135 lines
5.2 KiB
C#

using System;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Binder;
using Upsilon.Binder.VariableSymbols;
using Upsilon.BoundTypes;
using Upsilon.Evaluator;
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
namespace Upsilon.StandardLibraries
{
internal class BasicFunctions : ScriptLibrary
{
[ScriptFunction("assert", "Asserts that the parameter passed is true. Throws an exception if it is not true. " +
"Can take a message to show in the exception, otherwise throws with message \"assertion failed!\"",
directScriptManipulation: true)]
public void Assert(ScriptBoolean boolean)
{
if (!boolean)
{
Error(new ScriptString("assertion failed!"));
}
}
public void Assert(ScriptBoolean boolean, ScriptString message)
{
if (!boolean)
{
Error(message);
}
}
[ScriptFunction("error", "Throw an exception with given error message",
directScriptManipulation: true)]
public void Error(ScriptString message)
{
throw new Exception(message.Value);
}
[ScriptFunction("ipairs", "Iterates over an iterable variable, like a table, until it encounters a nil value.",
directScriptManipulation: true, overrideReturnType: typeof(BasicFunctions), overrideReturnMethod: nameof(PairsBindHandler))]
public UpTillNullPairsScriptIterator UpTillNullPairs(IIterable table)
{
return new UpTillNullPairsScriptIterator(table);
}
[ScriptFunction("pairs", "Iterates over an iterable variable, like a table, skipping all nil values.",
directScriptManipulation: true, overrideReturnType: typeof(BasicFunctions), overrideReturnMethod: nameof(PairsBindHandler))]
public PairsScriptIterator Pairs(IIterable table)
{
return new PairsScriptIterator(table);
}
private static TypeContainer PairsBindHandler(BoundExpression[] variableSymbols)
{
if (variableSymbols.Length != 1)
return BaseTypes.Type.Unknown;
var parameter = variableSymbols[0];
return parameter.ValueType;
}
[ScriptFunction("print", "Prints a message to the action given in the script options", passScriptReference: true,
directScriptManipulation: true)]
public void Print(Script script, ScriptType message)
{
script.Options.PrintResult.Invoke(message.ToCSharpObject().ToString());
}
[ScriptFunction("require", "Loads a module from the module path, using the given script loader.",
true, true)]
public ScriptType Require(Script script, ScriptString fileName)
{
var file = fileName.Value;
var module = script.Options.ModuleHandler.GetModule(script, file);
if (module == null)
{
throw new Exception($"Unable to load module {file} at path {script.Options.ScriptLoader.ModulesPath}");
}
var s = Executor.ContinueWith(script, module);
var val = s.Evaluate();
return val != null ? val.ToScriptType() : new ScriptNull();
}
[ScriptFunction("tonumber", "Parses a string to a number.", directScriptManipulation: true)]
public ScriptNumber ToNumber(ScriptString obj)
{
var str = obj.Value;
if (str.Contains("."))
{
return new ScriptNumberDouble(double.Parse(str));
}
else
{
return new ScriptNumberLong(long.Parse(str));
}
}
[ScriptFunction("tostring", "Returns the string value of the given object.", directScriptManipulation: true)]
public ScriptString ToString(ScriptType obj)
{
return new ScriptString(obj.ToString());
}
[ScriptFunction("type", "Returns the type of the given object as a string.", directScriptManipulation: true)]
public ScriptString Type(ScriptType obj)
{
return new ScriptString(obj.Type.ToString());
}
[ScriptFunction("cast", "Casts an object to a given type.", directScriptManipulation: true,
overrideReturnType: typeof(BasicFunctions), overrideReturnMethod: nameof(CastBindHelper))]
public ScriptType Cast(ScriptType obj, ScriptString typeName)
{
return obj;
}
private static TypeContainer CastBindHelper(BoundExpression[] expressions)
{
if (expressions.Length != 2)
return BaseTypes.Type.Unknown;
var typeNameExpression = expressions[1];
if (!(typeNameExpression is BoundLiteralExpression literal) || literal.ValueType != BaseTypes.Type.String)
return BaseTypes.Type.Unknown;
var boundType = BoundTypeHandler.GetTypeDefinition(((ScriptString) literal.Value));
if (boundType == null)
return BaseTypes.Type.Unknown;
return boundType.ScriptType;
}
}
}