Reworked modules, they now should bind properly

This commit is contained in:
Deukhoofd 2018-12-07 13:49:51 +01:00
parent 1caf8320b3
commit 98e5c1c136
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
5 changed files with 61 additions and 28 deletions

View File

@ -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;

View File

@ -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;
} }

23
Upsilon/ModuleHandler.cs Normal file
View File

@ -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;
}
}
}

View File

@ -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();
} }
} }

View File

@ -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();
} }