Reworked modules, they now should bind properly
This commit is contained in:
parent
1caf8320b3
commit
98e5c1c136
|
@ -6,6 +6,7 @@ using Upsilon.BaseTypes;
|
||||||
using Upsilon.BaseTypes.Number;
|
using Upsilon.BaseTypes.Number;
|
||||||
using Upsilon.Binder.VariableSymbols;
|
using Upsilon.Binder.VariableSymbols;
|
||||||
using Upsilon.BoundTypes;
|
using Upsilon.BoundTypes;
|
||||||
|
using Upsilon.Evaluator;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
using Type = Upsilon.BaseTypes.Type;
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
|
@ -15,21 +16,26 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
private Diagnostics _diagnostics;
|
private Diagnostics _diagnostics;
|
||||||
public BoundScope Scope { get; private set; }
|
public BoundScope Scope { get; private set; }
|
||||||
|
private readonly Script _script;
|
||||||
|
|
||||||
private Dictionary<string, UnboundFunctionExpression> _unboundFunctions =
|
private Dictionary<string, UnboundFunctionExpression> _unboundFunctions =
|
||||||
new Dictionary<string, UnboundFunctionExpression>();
|
new Dictionary<string, UnboundFunctionExpression>();
|
||||||
|
|
||||||
public Binder(Diagnostics diagnostics, Dictionary<string, VariableSymbol> variables)
|
public Binder(Diagnostics diagnostics, Dictionary<string, VariableSymbol> variables, Script script)
|
||||||
{
|
{
|
||||||
_diagnostics = diagnostics;
|
_diagnostics = diagnostics;
|
||||||
|
_script = script;
|
||||||
Scope = new BoundScope(variables, null);
|
Scope = new BoundScope(variables, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Binder(){}
|
private Binder(Script script)
|
||||||
|
|
||||||
internal static Binder CreateWithSetScope(Diagnostics diagnostics, BoundScope scope)
|
|
||||||
{
|
{
|
||||||
return new Binder {_diagnostics = diagnostics, Scope = scope};
|
_script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Binder CreateWithSetScope(Diagnostics diagnostics, BoundScope scope, Script script)
|
||||||
|
{
|
||||||
|
return new Binder(script) {_diagnostics = diagnostics, Scope = scope};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -233,6 +239,24 @@ namespace Upsilon.Binder
|
||||||
_unboundFunctions.Remove(scriptFunction.Name);
|
_unboundFunctions.Remove(scriptFunction.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (string.Equals(function.Name, "require") && parameters.Count > 0)
|
||||||
|
{
|
||||||
|
var parameter = parameters[0];
|
||||||
|
if (parameter is BoundLiteralExpression be && be.Value.Type == Type.String)
|
||||||
|
{
|
||||||
|
var moduleName = be.Value.ToString();
|
||||||
|
var module = _script.Options.ModuleHandler.GetModule(_script, moduleName);
|
||||||
|
foreach (var moduleVariable in module.Scope.Variables)
|
||||||
|
{
|
||||||
|
if (moduleVariable.Value.Local)
|
||||||
|
continue;
|
||||||
|
Scope.Variables.Add(moduleVariable.Key, moduleVariable.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
returnType = function.ResultType;
|
returnType = function.ResultType;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace Upsilon.Evaluator
|
||||||
|
|
||||||
var staticBoundScope = options.OverrideStaticBoundScope ?? StaticScope.BoundScope;
|
var staticBoundScope = options.OverrideStaticBoundScope ?? StaticScope.BoundScope;
|
||||||
var boundScope = BoundScope.WithReadOnlyScope(staticBoundScope);
|
var boundScope = BoundScope.WithReadOnlyScope(staticBoundScope);
|
||||||
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, boundScope);
|
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, boundScope, this);
|
||||||
|
|
||||||
var staticScope = options.OverrideStaticScope ?? StaticScope.Scope;
|
var staticScope = options.OverrideStaticScope ?? StaticScope.Scope;
|
||||||
Scope = EvaluationScope.CreateWithGetOnlyParent(staticScope);
|
Scope = EvaluationScope.CreateWithGetOnlyParent(staticScope);
|
||||||
|
@ -45,7 +45,7 @@ namespace Upsilon.Evaluator
|
||||||
_scriptString = scriptString;
|
_scriptString = scriptString;
|
||||||
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
|
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
|
||||||
|
|
||||||
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope);
|
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope, this);
|
||||||
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
|
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
|
||||||
Scope = Evaluator.Scope;
|
Scope = Evaluator.Scope;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace Upsilon.Evaluator
|
||||||
_bound = boundScript;
|
_bound = boundScript;
|
||||||
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
|
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
|
||||||
|
|
||||||
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope);
|
Binder = Upsilon.Binder.Binder.CreateWithSetScope(Diagnostics, binder.Scope, this);
|
||||||
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
|
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, evaluator.Scope, this);
|
||||||
Scope = Evaluator.Scope;
|
Scope = Evaluator.Scope;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Upsilon.Binder;
|
||||||
|
using Upsilon.Evaluator;
|
||||||
|
|
||||||
|
namespace Upsilon
|
||||||
|
{
|
||||||
|
public class ModuleHandler
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, BoundScript> _cachedModules = new Dictionary<string, BoundScript>();
|
||||||
|
|
||||||
|
public virtual BoundScript GetModule(Script script, string name)
|
||||||
|
{
|
||||||
|
if (_cachedModules.TryGetValue(name, out var module))
|
||||||
|
return module;
|
||||||
|
|
||||||
|
var moduleScript = script.Options.ScriptLoader.LoadModule(name);
|
||||||
|
var parsed = Executor.ContinueWith(script, moduleScript);
|
||||||
|
module = parsed.Bind();
|
||||||
|
_cachedModules.Add(name, module);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ namespace Upsilon
|
||||||
|
|
||||||
public BoundScope OverrideStaticBoundScope { get; set; } = null;
|
public BoundScope OverrideStaticBoundScope { get; set; } = null;
|
||||||
public EvaluationScope OverrideStaticScope { get; set; } = null;
|
public EvaluationScope OverrideStaticScope { get; set; } = null;
|
||||||
public ScriptLoader ScriptLoader { get; set; } = null;
|
public ScriptLoader ScriptLoader { get; set; } = new ScriptLoader();
|
||||||
|
public ModuleHandler ModuleHandler { get; set; } = new ModuleHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,30 +41,15 @@ namespace Upsilon.StandardLibraries
|
||||||
return new PairsScriptIterator(table);
|
return new PairsScriptIterator(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<string, BoundScript> CachedBoundModules = new Dictionary<string, BoundScript>();
|
|
||||||
|
|
||||||
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.",
|
[StandardLibraryScriptFunction("require", "Loads a module from the module path, using the given script loader.",
|
||||||
true)]
|
true)]
|
||||||
public ScriptType Require(Script script, ScriptString fileName)
|
public ScriptType Require(Script script, ScriptString fileName)
|
||||||
{
|
{
|
||||||
var file = fileName.Value;
|
var file = fileName.Value;
|
||||||
var loader = script.Options.ScriptLoader;
|
var module = script.Options.ModuleHandler.GetModule(script, file);
|
||||||
if (loader != null)
|
var s = Executor.ContinueWith(script, module);
|
||||||
{
|
var val = s.Evaluate();
|
||||||
if (!CachedBoundModules.TryGetValue(file, out var boundScript))
|
return val != null ? val.ToScriptType() : new ScriptNull();
|
||||||
{
|
|
||||||
var loadedScript = loader.LoadModule(file);
|
|
||||||
boundScript = Executor.ParseInput(loadedScript).Bind();
|
|
||||||
CachedBoundModules.Add(file, boundScript);
|
|
||||||
}
|
|
||||||
var s = Executor.ContinueWith(script, boundScript);
|
|
||||||
var val = s.Evaluate();
|
|
||||||
if (val != null)
|
|
||||||
{
|
|
||||||
return val.ToScriptType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ScriptNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue