Files
Upsilon/Upsilon/Evaluator/Script.cs

141 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Upsilon.BaseTypes;
using Upsilon.Binder;
using Upsilon.Parser;
using Upsilon.StandardLibraries;
using Upsilon.Text;
using Upsilon.Utilities;
namespace Upsilon.Evaluator
{
public class Script : IDisposable
{
public SourceText ScriptString { get; }
private Evaluator Evaluator { get; }
private BlockStatementSyntax _parsed;
private BoundScript _bound;
public Diagnostics Diagnostics { get; }
private Binder.Binder Binder { get; }
private EvaluationScope Scope { get; }
public Script(string scriptString, BoundScope overrideBoundStaticScope = null,
EvaluationScope overrideStaticScope = null )
{
ScriptString = new SourceText(scriptString);
Diagnostics = new Diagnostics(ScriptString);
_parsed = Parser.Parser.Parse(scriptString, Diagnostics);
var staticBoundScope = overrideBoundStaticScope ?? StaticScope.BoundScope;
var boundScope = BoundScope.WithReadOnlyScope(staticBoundScope);
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, boundScope);
var staticScope = overrideStaticScope ?? StaticScope.Scope;
Scope = EvaluationScope.CreateWithGetOnlyParent(staticScope);
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, Scope);
}
private Script(string scriptString, Binder.Binder binder, Evaluator evaluator)
{
ScriptString = new SourceText(scriptString);
Diagnostics = new Diagnostics(ScriptString);
_parsed = Parser.Parser.Parse(scriptString, Diagnostics);
Binder = new Binder.Binder(Diagnostics, binder.Scope.Variables);
Evaluator = new Evaluator( Diagnostics, evaluator.Scope.Variables);
Scope = Evaluator.Scope;
}
public static Script ContinueWith(Script previousScript, string scriptString)
{
var s = new Script(scriptString, previousScript.Binder, previousScript.Evaluator);
return s;
}
public BoundScript Bind()
{
return _bound ?? (_bound = Binder.BindScript(_parsed));
}
public object Evaluate()
{
return Convert(Evaluator.Evaluate(Bind()));
}
public object EvaluateFunction(string functionName, object[] parameters = null)
{
var luaParameters = ImmutableArray.CreateBuilder<ScriptType>();
if (parameters != null)
{
foreach (var parameter in parameters)
{
luaParameters.Add(parameter.ToScriptType());
}
}
return Convert(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
}
private static T Convert<T>(ScriptType t)
{
if (typeof(T) == typeof(double))
return (T)(object)System.Convert.ToDouble(t.ToCSharpObject());
if (typeof(T) == typeof(long))
return (T)(object)System.Convert.ToInt64(t.ToCSharpObject());
return (T) t.ToCSharpObject();
}
private static object Convert(ScriptType t)
{
return t?.ToCSharpObject();
}
public T Evaluate<T>()
{
var bound = Bind();
var evaluate = Evaluator.Evaluate(bound);
return Convert<T>(evaluate);
}
public T EvaluateFunction<T>(string functionName, object[] parameters = null)
{
var luaParameters = ImmutableArray.CreateBuilder<ScriptType>();
if (parameters != null)
{
foreach (var parameter in parameters)
{
luaParameters.Add(parameter.ToScriptType());
}
}
return Convert<T>(Evaluator.Evaluate(Bind(), functionName, luaParameters.ToImmutable()));
}
public T GetVariable<T>(string variableName)
{
if (!Scope.TryGet(variableName, out var variable))
{
throw new NullReferenceException();
}
return Convert<T>(variable);
}
public bool HasVariable(string variableName)
{
return Scope.TryGet(variableName, out _);
}
public string PrettyPrintSyntaxTree()
{
return _parsed.Print();
}
public void Dispose()
{
Binder?.Dispose();
Evaluator?.Dispose();
Scope?.Dispose();
_parsed = null;
_bound = null;
}
}
}