Skip to content

Commit 3ea993d

Browse files
authored
Merge pull request #19 from Librelancer/feat-hoisting
Feature: Hoisting
2 parents 2e6ee5f + 492f916 commit 3ea993d

40 files changed

+429
-101
lines changed

src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ public SymbolRef TryDefineLocal(string name)
103103
return m_Frames.Last().TryDefineLocal(name);
104104
}
105105

106+
public void BlockResolution(IEnumerable<SymbolRef> locals)
107+
{
108+
m_Frames.Last().BlockResolution(locals);
109+
}
110+
111+
public void UnblockResolution() => m_Frames.Last().UnblockResolution();
112+
113+
106114
public bool CurrentFunctionHasVarArgs()
107115
{
108116
return m_Frames.Last().HasVarArgs;

src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeBlock.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,25 @@ internal BuildTimeScopeBlock AddChild()
3434
return block;
3535
}
3636

37+
private HashSet<string> blockedNames = new HashSet<string>();
38+
internal void BlockResolution(IEnumerable<SymbolRef> locals)
39+
{
40+
foreach(var l in locals) {
41+
if (!m_DefinedNames.ContainsValue(l))
42+
throw new InternalErrorException("Tried to block resolution of local outside of block");
43+
blockedNames.Add(l.Name);
44+
}
45+
}
46+
47+
internal void UnblockResolution()
48+
{
49+
blockedNames.Clear();
50+
}
51+
52+
3753
internal SymbolRef Find(string name)
3854
{
55+
if (blockedNames.Contains(name)) return null;
3956
return m_DefinedNames.GetOrDefault(name);
4057
}
4158

src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeFrame.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ internal SymbolRef DefineLocal(string name)
6464
return m_ScopeTreeHead.Define(name);
6565
}
6666

67+
internal void BlockResolution(IEnumerable<SymbolRef> locals)
68+
{
69+
m_ScopeTreeHead.BlockResolution(locals);
70+
}
71+
72+
internal void UnblockResolution() => m_ScopeTreeHead.UnblockResolution();
73+
6774
internal SymbolRef TryDefineLocal(string name)
6875
{
6976
if (m_ScopeTreeHead.Find(name) != null)

src/MoonSharp.Interpreter/Tree/Expression_.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public virtual string GetFriendlyDebugName()
2222

2323
public abstract DynValue Eval(ScriptExecutionContext context);
2424

25+
public abstract void ResolveScope(ScriptLoadingContext lcontext);
26+
2527
public abstract bool EvalLiteral(out DynValue dv);
2628

2729
public void CompilePossibleLiteral(ByteCode bc)

src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public override DynValue Eval(ScriptExecutionContext context)
2525
return expression.Eval(context).ToScalar();
2626
}
2727

28+
public override void ResolveScope(ScriptLoadingContext lcontext)
29+
{
30+
expression.ResolveScope(lcontext);
31+
}
32+
2833
public override bool EvalLiteral(out DynValue dv)
2934
{
3035
if (expression.EvalLiteral(out dv))

src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,12 @@ public static OpCode OperatorToOpCode(Operator op)
360360
}
361361
}
362362

363+
public override void ResolveScope(ScriptLoadingContext lcontext)
364+
{
365+
m_Exp1.ResolveScope(lcontext);
366+
m_Exp2.ResolveScope(lcontext);
367+
}
368+
363369

364370
public override void Compile(Execution.VM.ByteCode bc)
365371
{

src/MoonSharp.Interpreter/Tree/Expressions/DynamicExprExpression.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ public DynamicExprExpression(Expression exp, ScriptLoadingContext lcontext)
1515
m_Exp = exp;
1616
}
1717

18+
public override void ResolveScope(ScriptLoadingContext lcontext)
19+
{
20+
m_Exp.ResolveScope(lcontext);
21+
}
1822

1923
public override DynValue Eval(ScriptExecutionContext context)
2024
{

src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ public Expression[] GetExpressions()
2020
return expressions.ToArray();
2121
}
2222

23+
public override void ResolveScope(ScriptLoadingContext lcontext)
24+
{
25+
foreach(var exp in expressions)
26+
exp.ResolveScope(lcontext);
27+
}
28+
2329
public override void Compile(Execution.VM.ByteCode bc)
2430
{
2531
foreach (var exp in expressions)

src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ public FunctionCallExpression(ScriptLoadingContext lcontext, Expression function
6565
}
6666
}
6767

68+
public override void ResolveScope(ScriptLoadingContext lcontext)
69+
{
70+
m_Function.ResolveScope(lcontext);
71+
foreach(var arg in m_Arguments)
72+
arg.ResolveScope(lcontext);
73+
}
74+
6875
public override void Compile(Execution.VM.ByteCode bc)
6976
{
7077
m_Function.Compile(bc);

src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,7 @@ private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSel
4646

4747
m_Annotations = lcontext.FunctionAnnotations.ToArray();
4848
lcontext.FunctionAnnotations = new List<Annotation>();
49-
50-
// create scope
51-
// This needs to be up here to allow for arguments to correctly close over ENV
52-
// Arguments, however, must come before any other local definitions to avoid closing
53-
// over uninitialised variables. (Note for hoisting).
54-
lcontext.Scope.PushFunction(this);
55-
56-
if (m_UsesGlobalEnv)
57-
{
58-
m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV);
59-
}
60-
else
61-
{
62-
lcontext.Scope.ForceEnvUpValue();
63-
}
64-
49+
6550
// Parse arguments
6651
// here lexer should be at the '(' or at the '|'
6752
//Token openRound = CheckTokenType(lcontext, isLambda ? TokenType.Lambda : TokenType.Brk_Open_Round);
@@ -97,24 +82,41 @@ private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSel
9782
// here lexer is at first token of body
9883

9984
m_Begin = openRound.GetSourceRefUpTo(lcontext.Lexer.Current);
100-
101-
102-
m_ParamNames = DefineArguments(paramnames, lcontext);
10385

104-
if(m_HasVarArgs) lcontext.Scope.SetHasVarArgs(); //Moved here
105-
10686
if(isLambda)
10787
m_Statement = CreateLambdaBody(lcontext, arrowFunc);
10888
else
10989
m_Statement = CreateBody(lcontext, openCurly);
11090

111-
m_StackFrame = lcontext.Scope.PopFunction();
11291

11392
lcontext.Source.Refs.Add(m_Begin);
11493
lcontext.Source.Refs.Add(m_End);
11594

11695
}
11796

97+
public override void ResolveScope(ScriptLoadingContext lcontext)
98+
{
99+
resolved = true;
100+
lcontext.Scope.PushFunction(this);
101+
102+
if (m_UsesGlobalEnv)
103+
{
104+
m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV);
105+
}
106+
else
107+
{
108+
lcontext.Scope.ForceEnvUpValue();
109+
}
110+
111+
m_ParamNames = DefineArguments(paramnames, lcontext);
112+
113+
if(m_HasVarArgs) lcontext.Scope.SetHasVarArgs(); //Moved here
114+
115+
m_Statement.ResolveScope(lcontext);
116+
117+
m_StackFrame = lcontext.Scope.PopFunction();
118+
}
119+
118120

119121
private Statement CreateLambdaBody(ScriptLoadingContext lcontext, bool arrowFunc)
120122
{
@@ -247,7 +249,7 @@ private SymbolRef[] DefineArguments(List<FunctionDefinitionStatement.FunctionPar
247249
{
248250
if (!names.Add(paramnames[i].Name))
249251
paramnames[i].Name = paramnames[i].Name + "@" + i.ToString();
250-
252+
paramnames[i].DefaultValue?.ResolveScope(lcontext);
251253
ret[i] = lcontext.Scope.DefineLocal(paramnames[i].Name);
252254
}
253255

@@ -281,8 +283,11 @@ public override DynValue Eval(ScriptExecutionContext context)
281283
throw new DynamicExpressionException("Dynamic Expressions cannot define new functions.");
282284
}
283285

286+
private bool resolved = false;
287+
284288
public int CompileBody(ByteCode bc, string friendlyName)
285289
{
290+
if (!resolved) throw new InternalErrorException("Function definition scope not resolved");
286291
//LoadingContext.Scope.PopFunction()
287292

288293
string funcName = friendlyName ?? ("<" + this.m_Begin.FormatLocation(bc.Script, true) + ">");

0 commit comments

Comments
 (0)