Support for passing Script reference to functions. useful when options are required for function

This commit is contained in:
Deukhoofd 2018-11-30 11:31:45 +01:00
parent 3a3ed071d2
commit 9e27778af1
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 46 additions and 27 deletions

View File

@ -1,3 +1,5 @@
using Upsilon.Evaluator;
namespace Upsilon.BaseTypes.ScriptFunction
{
internal abstract class ScriptFunction : ScriptType
@ -13,6 +15,6 @@ namespace Upsilon.BaseTypes.ScriptFunction
return null;
}
public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables);
public abstract ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script);
}
}

View File

@ -1,26 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Upsilon.BaseTypes.UserData;
using Upsilon.Evaluator;
namespace Upsilon.BaseTypes.ScriptFunction
{
internal class ScriptMethodInfoFunction : ScriptFunction
{
public ScriptMethodInfoFunction(UserDataMethod method, object o, bool directTypeManipulation)
public ScriptMethodInfoFunction(UserDataMethod method, object o, bool directTypeManipulation, bool passScriptReference = false)
{
_method = method;
_object = o;
_directTypeManipulation = directTypeManipulation;
_passScriptReference = passScriptReference;
ReturnType = _method.ReturnType;
}
private readonly UserDataMethod _method;
private readonly object _object;
private readonly bool _directTypeManipulation;
private readonly bool _passScriptReference;
public System.Type ReturnType { get; }
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables)
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script)
{
var types = _directTypeManipulation
? variables.Select(x => x.GetType()).ToArray()
@ -32,9 +36,10 @@ namespace Upsilon.BaseTypes.ScriptFunction
$"No valid function found on type '{_object.GetType()}' with name '{_method.Name}' " +
$"and parameter types: {string.Join(", ", types.Select(x => $"'{x.Name}'"))}");
}
var objects = _directTypeManipulation
var objects = new List<object>();
objects.AddRange(_directTypeManipulation
? variables.Select(x => (object) x).ToList()
: variables.Select(x => x.ToCSharpObject()).ToList();
: variables.Select(x => x.ToCSharpObject()).ToList());
var pars = method.GetParameters();
if (pars.Length != objects.Count)
{

View File

@ -19,9 +19,9 @@ namespace Upsilon.BaseTypes.ScriptFunction
EvaluationScope = evaluationScope;
}
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables)
public override ScriptType Run(Diagnostics diagnostics, ScriptType[] variables, Script script)
{
var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope);
var innerEvaluator = new Evaluator.Evaluator(diagnostics, EvaluationScope, script);
for (var i = 0; i < Parameters.Length; i++)
{
var parameterVariable = Parameters[i];

View File

@ -1,5 +1,3 @@
using System.Collections;
using System.Collections.Generic;
using Upsilon.Evaluator;
using Upsilon.Text;

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Net.Http.Headers;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptFunction;
@ -14,6 +12,7 @@ namespace Upsilon.Evaluator
{
internal class Evaluator : IDisposable
{
private Script _script;
private Diagnostics _diagnostics;
private ScriptType _lastValue;
private ScriptType _returnValue;
@ -21,23 +20,28 @@ namespace Upsilon.Evaluator
private bool HasReturned { get; set; }
private bool HasBroken { get; set; }
internal Evaluator(Diagnostics diagnostics, Dictionary<string, ScriptType> variables)
internal Evaluator(Diagnostics diagnostics, Dictionary<string, ScriptType> variables, Script script)
{
_diagnostics = diagnostics;
_script = script;
Scope = new EvaluationScope(variables);
}
internal Evaluator(Diagnostics diagnostics, EvaluationScope parentScope)
internal Evaluator(Diagnostics diagnostics, EvaluationScope parentScope, Script script)
{
_diagnostics = diagnostics;
_script = script;
Scope = new EvaluationScope(parentScope);
}
private Evaluator(){}
internal static Evaluator CreateWithSetScope(Diagnostics diagnostics, EvaluationScope scope)
private Evaluator(Script script)
{
return new Evaluator {_diagnostics = diagnostics, Scope = scope};
_script = script;
}
internal static Evaluator CreateWithSetScope(Diagnostics diagnostics, EvaluationScope scope, Script script)
{
return new Evaluator(script) {_diagnostics = diagnostics, Scope = scope};
}
public void Dispose()
@ -63,7 +67,7 @@ namespace Upsilon.Evaluator
throw new ArgumentException(($"Function '{functionName}' could not be found"));
}
var function = (ScriptRuntimeFunction) statement;
var innerEvaluator = new Evaluator(_diagnostics, Scope);
var innerEvaluator = new Evaluator(_diagnostics, Scope, _script);
if (parameters != null)
{
for (var index = 0; index < parameters.Length; index++)
@ -267,7 +271,6 @@ namespace Upsilon.Evaluator
{
return ((ScriptNumber)left) + ((ScriptNumber)right);
}
goto default;
}
else if (left.Type == Type.String)
{
@ -442,7 +445,7 @@ namespace Upsilon.Evaluator
ls.Add(evaluate);
}
var val = function.Run(_diagnostics, ls.ToArray());
var val = function.Run(_diagnostics, ls.ToArray(), _script);
return val;
}
@ -456,7 +459,7 @@ namespace Upsilon.Evaluator
private ScriptType EvaluateTableExpression(BoundTableExpression e)
{
var tableScope = EvaluationScope.CreateWithGetOnlyParent(Scope);
var innerEvaluator = new Evaluator(_diagnostics, tableScope);
var innerEvaluator = new Evaluator(_diagnostics, tableScope, _script);
var currentPos = 1;
foreach (var boundStatement in e.Statements)
{
@ -541,7 +544,7 @@ namespace Upsilon.Evaluator
private void EvaluateNumericForStatement(BoundNumericForStatement e)
{
var innerEvaluator = new Evaluator(_diagnostics, Scope);
var innerEvaluator = new Evaluator(_diagnostics, Scope, _script);
var startVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStart);
innerEvaluator.Scope.CreateLocal(e.Variable, startVal);
var stopVal = (ScriptNumberLong)innerEvaluator.EvaluateExpression(e.BoundStop);
@ -574,7 +577,7 @@ namespace Upsilon.Evaluator
private void EvaluateGenericForStatement(BoundGenericForStatement e)
{
var innerEvaluator = new Evaluator(_diagnostics, Scope);
var innerEvaluator = new Evaluator(_diagnostics, Scope, _script);
var enumeratorObject = EvaluateExpression(e.BoundEnumerableExpression);
if (!(enumeratorObject is IIterable iterable))
{

View File

@ -34,7 +34,7 @@ namespace Upsilon.Evaluator
var staticScope = options.OverrideStaticScope ?? StaticScope.Scope;
Scope = EvaluationScope.CreateWithGetOnlyParent(staticScope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, Scope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, Scope, this);
}
private Script(string scriptString, Binder.Binder binder, Evaluator evaluator, ScriptOptions options)
@ -45,7 +45,7 @@ namespace Upsilon.Evaluator
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
Scope = Evaluator.Scope;
}

View File

@ -2,6 +2,7 @@ using System;
using Upsilon.BaseTypes;
using Upsilon.BaseTypes.Number;
using Upsilon.BaseTypes.ScriptTypeInterfaces;
using Upsilon.Evaluator;
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
@ -37,6 +38,13 @@ namespace Upsilon.StandardLibraries
return new PairsScriptIterator(table);
}
[StandardLibraryScriptFunction("require", true)]
public void Require(Script script, ScriptBoolean boolean, ScriptString message = null)
{
}
[StandardLibraryScriptFunction("tonumber")]
public ScriptNumber ToNumber(ScriptString obj)
{

View File

@ -17,7 +17,8 @@ namespace Upsilon.StandardLibraries
var attr = methodInfo.GetCustomAttribute<StandardLibraryScriptFunctionAttribute>();
if (attr != null)
{
dictionary.Add(attr.Name, new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this, true));
dictionary.Add(attr.Name,
new ScriptMethodInfoFunction(new UserDataMethod(methodInfo), this, true));
}
}

View File

@ -5,11 +5,13 @@ namespace Upsilon.StandardLibraries
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class StandardLibraryScriptFunctionAttribute : Attribute
{
public StandardLibraryScriptFunctionAttribute(string name)
public StandardLibraryScriptFunctionAttribute(string name, bool passScriptReference = false)
{
Name = name;
PassScriptReference = passScriptReference;
}
public string Name { get; }
public bool PassScriptReference { get; }
}
}