diff --git a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs index 9b30517d..560e95dd 100644 --- a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs +++ b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs @@ -103,6 +103,14 @@ public SymbolRef TryDefineLocal(string name) return m_Frames.Last().TryDefineLocal(name); } + public void BlockResolution(IEnumerable locals) + { + m_Frames.Last().BlockResolution(locals); + } + + public void UnblockResolution() => m_Frames.Last().UnblockResolution(); + + public bool CurrentFunctionHasVarArgs() { return m_Frames.Last().HasVarArgs; diff --git a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeBlock.cs b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeBlock.cs index 630635f2..ac5b91b6 100644 --- a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeBlock.cs +++ b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeBlock.cs @@ -34,8 +34,25 @@ internal BuildTimeScopeBlock AddChild() return block; } + private HashSet blockedNames = new HashSet(); + internal void BlockResolution(IEnumerable locals) + { + foreach(var l in locals) { + if (!m_DefinedNames.ContainsValue(l)) + throw new InternalErrorException("Tried to block resolution of local outside of block"); + blockedNames.Add(l.Name); + } + } + + internal void UnblockResolution() + { + blockedNames.Clear(); + } + + internal SymbolRef Find(string name) { + if (blockedNames.Contains(name)) return null; return m_DefinedNames.GetOrDefault(name); } diff --git a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeFrame.cs b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeFrame.cs index 73d0a763..94c96561 100644 --- a/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeFrame.cs +++ b/src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScopeFrame.cs @@ -64,6 +64,13 @@ internal SymbolRef DefineLocal(string name) return m_ScopeTreeHead.Define(name); } + internal void BlockResolution(IEnumerable locals) + { + m_ScopeTreeHead.BlockResolution(locals); + } + + internal void UnblockResolution() => m_ScopeTreeHead.UnblockResolution(); + internal SymbolRef TryDefineLocal(string name) { if (m_ScopeTreeHead.Find(name) != null) diff --git a/src/MoonSharp.Interpreter/Tree/Expression_.cs b/src/MoonSharp.Interpreter/Tree/Expression_.cs index 5d70f469..09b94024 100644 --- a/src/MoonSharp.Interpreter/Tree/Expression_.cs +++ b/src/MoonSharp.Interpreter/Tree/Expression_.cs @@ -22,6 +22,8 @@ public virtual string GetFriendlyDebugName() public abstract DynValue Eval(ScriptExecutionContext context); + public abstract void ResolveScope(ScriptLoadingContext lcontext); + public abstract bool EvalLiteral(out DynValue dv); public void CompilePossibleLiteral(ByteCode bc) diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs index 821cd214..b7b49873 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs @@ -25,6 +25,11 @@ public override DynValue Eval(ScriptExecutionContext context) return expression.Eval(context).ToScalar(); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + expression.ResolveScope(lcontext); + } + public override bool EvalLiteral(out DynValue dv) { if (expression.EvalLiteral(out dv)) diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs index 2b2e85f1..a31699f4 100755 --- a/src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs @@ -360,6 +360,12 @@ public static OpCode OperatorToOpCode(Operator op) } } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Exp1.ResolveScope(lcontext); + m_Exp2.ResolveScope(lcontext); + } + public override void Compile(Execution.VM.ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/DynamicExprExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/DynamicExprExpression.cs index 46f6359e..17389d75 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/DynamicExprExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/DynamicExprExpression.cs @@ -15,6 +15,10 @@ public DynamicExprExpression(Expression exp, ScriptLoadingContext lcontext) m_Exp = exp; } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Exp.ResolveScope(lcontext); + } public override DynValue Eval(ScriptExecutionContext context) { diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs index 81c63e1c..33d10f35 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs @@ -20,6 +20,12 @@ public Expression[] GetExpressions() return expressions.ToArray(); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + foreach(var exp in expressions) + exp.ResolveScope(lcontext); + } + public override void Compile(Execution.VM.ByteCode bc) { foreach (var exp in expressions) diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs index 52e81715..99948a70 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs @@ -65,6 +65,13 @@ public FunctionCallExpression(ScriptLoadingContext lcontext, Expression function } } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Function.ResolveScope(lcontext); + foreach(var arg in m_Arguments) + arg.ResolveScope(lcontext); + } + public override void Compile(Execution.VM.ByteCode bc) { m_Function.Compile(bc); diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs index d95f2d71..db884c5a 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs @@ -46,22 +46,7 @@ private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSel m_Annotations = lcontext.FunctionAnnotations.ToArray(); lcontext.FunctionAnnotations = new List(); - - // create scope - // This needs to be up here to allow for arguments to correctly close over ENV - // Arguments, however, must come before any other local definitions to avoid closing - // over uninitialised variables. (Note for hoisting). - lcontext.Scope.PushFunction(this); - - if (m_UsesGlobalEnv) - { - m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV); - } - else - { - lcontext.Scope.ForceEnvUpValue(); - } - + // Parse arguments // here lexer should be at the '(' or at the '|' //Token openRound = CheckTokenType(lcontext, isLambda ? TokenType.Lambda : TokenType.Brk_Open_Round); @@ -97,24 +82,41 @@ private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSel // here lexer is at first token of body m_Begin = openRound.GetSourceRefUpTo(lcontext.Lexer.Current); - - - m_ParamNames = DefineArguments(paramnames, lcontext); - if(m_HasVarArgs) lcontext.Scope.SetHasVarArgs(); //Moved here - if(isLambda) m_Statement = CreateLambdaBody(lcontext, arrowFunc); else m_Statement = CreateBody(lcontext, openCurly); - m_StackFrame = lcontext.Scope.PopFunction(); lcontext.Source.Refs.Add(m_Begin); lcontext.Source.Refs.Add(m_End); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + resolved = true; + lcontext.Scope.PushFunction(this); + + if (m_UsesGlobalEnv) + { + m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV); + } + else + { + lcontext.Scope.ForceEnvUpValue(); + } + + m_ParamNames = DefineArguments(paramnames, lcontext); + + if(m_HasVarArgs) lcontext.Scope.SetHasVarArgs(); //Moved here + + m_Statement.ResolveScope(lcontext); + + m_StackFrame = lcontext.Scope.PopFunction(); + } + private Statement CreateLambdaBody(ScriptLoadingContext lcontext, bool arrowFunc) { @@ -247,7 +249,7 @@ private SymbolRef[] DefineArguments(List"); diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs index ff337eee..d46e7397 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs @@ -67,6 +67,12 @@ public IndexExpression(Expression baseExp, Token nameToken, bool nilCheck, Scrip } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_BaseExp.ResolveScope(lcontext); + m_IndexExp?.ResolveScope(lcontext); + } + public override void Compile(ByteCode bc) { m_BaseExp.Compile(bc); diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs index b3be4e80..a5c67534 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs @@ -54,6 +54,11 @@ public LiteralExpression(ScriptLoadingContext lcontext, Token t) lcontext.Lexer.Next(); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + //No-op + } + public override void Compile(Execution.VM.ByteCode bc) { bc.Emit_Literal(m_Value); diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs index 899c28d6..c47c3020 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs @@ -9,7 +9,8 @@ class SymbolRefExpression : Expression, IVariable { SymbolRef m_Ref; string m_VarName; - + private Token T; + private bool inc = false; private bool dec = false; @@ -20,22 +21,7 @@ public SymbolRefExpression(Token T, ScriptLoadingContext lcontext) : base(lcontext) { m_VarName = T.Text; - - if (T.Type == TokenType.VarArgs) - { - m_Ref = lcontext.Scope.Find(WellKnownSymbols.VARARGS); - - if (!lcontext.Scope.CurrentFunctionHasVarArgs()) - throw new SyntaxErrorException(T, "cannot use '...' outside a vararg function"); - - if (lcontext.IsDynamicExpression) - throw new DynamicExpressionException("cannot use '...' in a dynamic expression."); - } - else - { - if (!lcontext.IsDynamicExpression) - m_Ref = lcontext.Scope.Find(m_VarName); - } + this.T = T; lcontext.Lexer.Next(); //inc/dec expr @@ -51,6 +37,27 @@ public SymbolRefExpression(Token T, ScriptLoadingContext lcontext) } } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + if (m_Ref == null) { + if (T.Type == TokenType.VarArgs) + { + m_Ref = lcontext.Scope.Find(WellKnownSymbols.VARARGS); + + if (!lcontext.Scope.CurrentFunctionHasVarArgs()) + throw new SyntaxErrorException(T, "cannot use '...' outside a vararg function"); + + if (lcontext.IsDynamicExpression) + throw new DynamicExpressionException("cannot use '...' in a dynamic expression."); + } + else + { + if (!lcontext.IsDynamicExpression) + m_Ref = lcontext.Scope.Find(m_VarName); + } + } + } + public SymbolRefExpression(ScriptLoadingContext lcontext, SymbolRef refr) : base(lcontext) { diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs b/src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs index 6c87aa77..6b3be816 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs @@ -172,6 +172,19 @@ public bool TryGetLiteral(out DynValue dv) return true; } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + foreach (var kvp in m_CtorArgs) + { + kvp.Key.ResolveScope(lcontext); + kvp.Value.ResolveScope(lcontext); + } + foreach (var p in m_PositionalValues) + { + p.ResolveScope(lcontext); + } + } + public override void Compile(Execution.VM.ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/TemplatedStringExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/TemplatedStringExpression.cs index 22ee054f..7725c19f 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/TemplatedStringExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/TemplatedStringExpression.cs @@ -49,6 +49,12 @@ public override void Compile(ByteCode bc) bc.Emit_StrFormat(arguments.Count); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + foreach(var exp in arguments) + exp.ResolveScope(lcontext); + } + public override DynValue Eval(ScriptExecutionContext context) { return DynValue.NewString(string.Format(formatString, arguments.Select(x => diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/TernaryExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/TernaryExpression.cs index 422a8e80..c1e10291 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/TernaryExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/TernaryExpression.cs @@ -39,6 +39,13 @@ public override void Compile(ByteCode bc) } } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + condition.ResolveScope(lcontext); + exp1.ResolveScope(lcontext); + exp2.ResolveScope(lcontext); + } + public override DynValue Eval(ScriptExecutionContext context) { if (condition.Eval(context).CastToBool()) diff --git a/src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs b/src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs index 2234cf38..442ce024 100644 --- a/src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs +++ b/src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs @@ -81,6 +81,11 @@ public override void Compile(ByteCode bc) } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Exp.ResolveScope(lcontext); + } + public override DynValue Eval(ScriptExecutionContext context) { DynValue v = m_Exp.Eval(context).ToScalar(); diff --git a/src/MoonSharp.Interpreter/Tree/Fast_Interface/Loader_Fast.cs b/src/MoonSharp.Interpreter/Tree/Fast_Interface/Loader_Fast.cs index 2cb5ce3d..f3eeac05 100644 --- a/src/MoonSharp.Interpreter/Tree/Fast_Interface/Loader_Fast.cs +++ b/src/MoonSharp.Interpreter/Tree/Fast_Interface/Loader_Fast.cs @@ -19,7 +19,11 @@ internal static DynamicExprExpression LoadDynamicExpr(Script script, SourceCode Expression exp; using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation)) + { exp = Expression.Expr(lcontext); + lcontext.Scope = new BuildTimeScope(); + exp.ResolveScope(lcontext); + } return new DynamicExprExpression(exp, lcontext); } @@ -35,7 +39,6 @@ private static ScriptLoadingContext CreateLoadingContext(Script script, SourceCo { return new ScriptLoadingContext(script) { - Scope = new BuildTimeScope(), Source = source, Lexer = new Lexer(source.SourceID, source.Code, true, script.Options.Syntax != ScriptSyntax.Lua, script.Options.Syntax == ScriptSyntax.CLike, script.Options.Directives), Syntax = script.Options.Syntax @@ -52,7 +55,11 @@ internal static int LoadChunk(Script script, SourceCode source, ByteCode bytecod Statement stat; using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation)) + { stat = new ChunkStatement(lcontext); + lcontext.Scope = new BuildTimeScope(); + stat.ResolveScope(lcontext); + } int beginIp = -1; @@ -91,7 +98,11 @@ internal static int LoadFunction(Script script, SourceCode source, ByteCode byte FunctionDefinitionExpression fnx; using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation)) + { fnx = new FunctionDefinitionExpression(lcontext, usesGlobalEnv); + lcontext.Scope = new BuildTimeScope(); + fnx.ResolveScope(lcontext); + } int beginIp = -1; diff --git a/src/MoonSharp.Interpreter/Tree/Statement.cs b/src/MoonSharp.Interpreter/Tree/Statement.cs index c19cee0b..7b0abb0f 100644 --- a/src/MoonSharp.Interpreter/Tree/Statement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statement.cs @@ -21,6 +21,8 @@ protected IVariable CheckVar(ScriptLoadingContext lcontext, Expression firstExpr return v; } + public abstract void ResolveScope(ScriptLoadingContext lcontext); + static void ProcessDirective(ScriptLoadingContext lcontext) { var str = lcontext.Lexer.Current.Text; diff --git a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs index 3e2ebf52..ff2b7e74 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs @@ -10,7 +10,8 @@ namespace MoonSharp.Interpreter.Tree.Statements { class AssignmentStatement : Statement { - List m_LValues = new List(); + List m_LValues; + List localNames; List m_RValues; SourceRef m_Ref; @@ -22,14 +23,14 @@ class AssignmentStatement : Statement public AssignmentStatement(ScriptLoadingContext lcontext, Token startToken) : base(lcontext) { - List names = new List(); + localNames = new List(); Token first = startToken; while (true) { Token name = CheckTokenType(lcontext, TokenType.Name); - names.Add(name.Text); + localNames.Add(name.Text); if (lcontext.Lexer.Current.Type != TokenType.Comma) break; @@ -56,16 +57,11 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Token startToken) } else { - if (names.Count > 0) + if (localNames.Count > 0) m_RValues = new List(new Expression[] { new LiteralExpression(lcontext, DynValue.Nil) }); } - foreach (string name in names) - { - var localVar = lcontext.Scope.TryDefineLocal(name); - var symbol = new SymbolRefExpression(lcontext, localVar); - m_LValues.Add(symbol); - } + Token last = lcontext.Lexer.Current; m_Ref = first.GetSourceRefUpTo(last); @@ -73,10 +69,37 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Token startToken) } + public void DefineLocals(ScriptLoadingContext lcontext) + { + if (localNames != null) + { + m_LValues = new List(); + foreach (string name in localNames) + { + var localVar = lcontext.Scope.TryDefineLocal(name); + var symbol = new SymbolRefExpression(lcontext, localVar); + m_LValues.Add(symbol); + } + } + } + + public override void ResolveScope(ScriptLoadingContext lcontext) + { + foreach(var l in m_LValues)((Expression)l).ResolveScope(lcontext); + if (localNames != null) // local definitions can't reference themselves + { + lcontext.Scope.BlockResolution(m_LValues.Select(x => ((SymbolRefExpression)x).Symbol)); + } + if(m_RValues != null) + foreach(var r in m_RValues) r.ResolveScope(lcontext); + if(localNames != null) lcontext.Scope.UnblockResolution(); + } + public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpression, Token first) : base(lcontext) { + m_LValues = new List(); m_LValues.Add(CheckVar(lcontext, firstExpression)); while (lcontext.Lexer.Current.Type == TokenType.Comma) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs index 66c6be2d..9d7685cc 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs @@ -16,6 +16,10 @@ public BreakStatement(ScriptLoadingContext lcontext) lcontext.Source.Refs.Add(m_Ref); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + //no-op + } public override void Compile(ByteCode bc) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/CStyleForStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/CStyleForStatement.cs index 37c499a5..d46b6ef3 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/CStyleForStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/CStyleForStatement.cs @@ -21,10 +21,11 @@ class CStyleForStatement : Statement, IBlockStatement private RuntimeScopeBlock iteratorFrame; public SourceRef End => refEnd; + + private string localDefName; public CStyleForStatement(ScriptLoadingContext lcontext, Token forTok) : base(lcontext) { - lcontext.Scope.PushBlock(); //Init if (lcontext.Lexer.Current.Type != TokenType.SemiColon) { @@ -32,11 +33,10 @@ public CStyleForStatement(ScriptLoadingContext lcontext, Token forTok) : base(lc { isDefLocal = true; lcontext.Lexer.Next(); - var lcl = lcontext.Scope.TryDefineLocal(CheckTokenType(lcontext, TokenType.Name).Text); + localDefName = CheckTokenType(lcontext, TokenType.Name).Text; CheckTokenType(lcontext, TokenType.Op_Assignment); initExpression = Expression.Expr(lcontext); CheckTokenType(lcontext, TokenType.SemiColon); - initAssignee = new SymbolRefExpression(lcontext, lcl); } else { @@ -75,7 +75,6 @@ public CStyleForStatement(ScriptLoadingContext lcontext, Token forTok) : base(lc CheckTokenType(lcontext, TokenType.Brk_Close_Round); refBegin = forTok.GetSourceRef(lcontext.Lexer.Current); - lcontext.Scope.PushBlock(); if (lcontext.Lexer.Current.Type == TokenType.Brk_Open_Curly) { lcontext.Lexer.Next(); @@ -86,12 +85,28 @@ public CStyleForStatement(ScriptLoadingContext lcontext, Token forTok) : base(lc { refEnd = CheckTokenType(lcontext, TokenType.SemiColon).GetSourceRef(); } - stackFrame = lcontext.Scope.PopBlock(); - iteratorFrame = lcontext.Scope.PopBlock(); + lcontext.Source.Refs.Add(refBegin); lcontext.Source.Refs.Add(refEnd); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + if (isDefLocal) { + var lcl = lcontext.Scope.TryDefineLocal(localDefName); + initAssignee = new SymbolRefExpression(lcontext, lcl); + } + (initAssignee as Expression)?.ResolveScope(lcontext); + initExpression?.ResolveScope(lcontext); + condition?.ResolveScope(lcontext); + modify?.ResolveScope(lcontext); + lcontext.Scope.PushBlock(); + block.ResolveScope(lcontext); + stackFrame = lcontext.Scope.PopBlock(); + iteratorFrame = lcontext.Scope.PopBlock(); + } + public override void Compile(ByteCode bc) { //TODO: There are scope issues which mean we have to copy diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ChunkStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ChunkStatement.cs index c51104a8..c0da8055 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ChunkStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ChunkStatement.cs @@ -1,4 +1,5 @@ -using MoonSharp.Interpreter.Execution; +using System; +using MoonSharp.Interpreter.Execution; using MoonSharp.Interpreter.Execution.VM; namespace MoonSharp.Interpreter.Tree.Statements @@ -14,18 +15,24 @@ class ChunkStatement : Statement, IClosureBuilder public ChunkStatement(ScriptLoadingContext lcontext) : base(lcontext) { - lcontext.Scope.PushFunction(this); - lcontext.Scope.SetHasVarArgs(); - m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV); - m_VarArgs = lcontext.Scope.DefineLocal(WellKnownSymbols.VARARGS); - m_Block = new CompositeStatement(lcontext, BlockEndType.Normal); if (lcontext.Lexer.Current.Type != TokenType.Eof) throw new SyntaxErrorException(lcontext.Lexer.Current, " expected near '{0}'", lcontext.Lexer.Current.Text); + + annotations = lcontext.ChunkAnnotations.ToArray(); + } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushFunction(this); + lcontext.Scope.SetHasVarArgs(); + m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV); + m_VarArgs = lcontext.Scope.DefineLocal(WellKnownSymbols.VARARGS); + + m_Block.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopFunction(); - annotations = lcontext.ChunkAnnotations.ToArray(); } diff --git a/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs index f60e056f..e31760b6 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs @@ -39,6 +39,50 @@ public CompositeStatement(ScriptLoadingContext lcontext, BlockEndType endType) lcontext.Lexer.Next(); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + if (lcontext.Syntax == ScriptSyntax.CLike) + { + //Perform declaration hoisting. + //Define all locals upfront, then bring function definitions up + List reordered = new List(m_Statements.Count); + foreach (var s in m_Statements) + { + if (s is AssignmentStatement a) + { + a.DefineLocals(lcontext); + reordered.Add(a); + } + else if (s is FunctionDefinitionStatement fd) + { + fd.DefineLocals(lcontext); + if(fd.CanHoist) + reordered.Insert(0, fd); + else + reordered.Add(fd); + } + else + { + reordered.Add(s); + } + } + m_Statements = reordered; + foreach(var s in m_Statements) s.ResolveScope(lcontext); + + } + else + { + foreach (var s in m_Statements) + { + if(s is AssignmentStatement a) a.DefineLocals(lcontext); + if(s is FunctionDefinitionStatement fd) fd.DefineLocals(lcontext); + s.ResolveScope(lcontext); + } + + } + + } + public override void Compile(Execution.VM.ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ContinueStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ContinueStatement.cs index 82bc8aa2..51248b7d 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ContinueStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ContinueStatement.cs @@ -16,6 +16,10 @@ public ContinueStatement(ScriptLoadingContext lcontext) lcontext.Source.Refs.Add(m_Ref); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + //No-op + } public override void Compile(ByteCode bc) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/DoBlockStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/DoBlockStatement.cs index 742e5386..175790c0 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/DoBlockStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/DoBlockStatement.cs @@ -16,7 +16,6 @@ class DoBlockStatement : Statement, IBlockStatement public DoBlockStatement(ScriptLoadingContext lcontext) : base(lcontext) { - lcontext.Scope.PushBlock(); m_Do = CheckTokenType(lcontext, TokenType.Do).GetSourceRef(); @@ -36,12 +35,18 @@ public DoBlockStatement(ScriptLoadingContext lcontext) m_Block = new CompositeStatement(lcontext, BlockEndType.Normal); m_End = CheckTokenType(lcontext, TokenType.End).GetSourceRef(); } - m_StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(m_Do); lcontext.Source.Refs.Add(m_End); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + m_Block.ResolveScope(lcontext); + m_Condition?.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } public override void Compile(Execution.VM.ByteCode bc) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/EmptyStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/EmptyStatement.cs index b0076749..6ffdd54d 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/EmptyStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/EmptyStatement.cs @@ -9,6 +9,11 @@ public EmptyStatement(ScriptLoadingContext lcontext) { } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + //No-op + } + public override void Compile(Execution.VM.ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs index d792da37..61284555 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs @@ -17,12 +17,14 @@ class ForEachLoopStatement : Statement Statement m_Block; SourceRef m_RefFor, m_RefEnd; + private List names; + public ForEachLoopStatement(ScriptLoadingContext lcontext, Token firstNameToken, Token forToken, bool paren) : base(lcontext) { // for namelist in explist do block end | - List names = new List(); + names = new List(); names.Add(firstNameToken.Text); while (lcontext.Lexer.Current.Type == TokenType.Comma) @@ -35,20 +37,9 @@ public ForEachLoopStatement(ScriptLoadingContext lcontext, Token firstNameToken, CheckTokenType(lcontext, TokenType.In); m_RValues = new ExprListExpression(Expression.ExprList(lcontext), lcontext); - - lcontext.Scope.PushBlock(); - m_Names = names - .Select(n => lcontext.Scope.TryDefineLocal(n)) - .ToArray(); - - m_NameExps = m_Names - .Select(s => new SymbolRefExpression(lcontext, s)) - .Cast() - .ToArray(); if (paren) CheckTokenType(lcontext, TokenType.Brk_Close_Round); - if (lcontext.Syntax == ScriptSyntax.Lua || lcontext.Lexer.Current.Type == TokenType.Do) { m_RefFor = forToken.GetSourceRef(CheckTokenType(lcontext, TokenType.Do)); @@ -71,12 +62,29 @@ public ForEachLoopStatement(ScriptLoadingContext lcontext, Token firstNameToken, m_RefEnd = CheckTokenType(lcontext, TokenType.SemiColon).GetSourceRef(); } - m_StackFrame = lcontext.Scope.PopBlock(); + lcontext.Source.Refs.Add(m_RefFor); lcontext.Source.Refs.Add(m_RefEnd); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + m_Names = names + .Select(n => lcontext.Scope.TryDefineLocal(n)) + .ToArray(); + + m_NameExps = m_Names + .Select(s => new SymbolRefExpression(lcontext, s)) + .Cast() + .ToArray(); + + m_RValues?.ResolveScope(lcontext); + m_Block.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } + public override void Compile(ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs index 4a92ff58..3c412ca4 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs @@ -14,6 +14,7 @@ class ForLoopStatement : Statement, IBlockStatement SymbolRef m_VarName; Expression m_Start, m_End, m_Step; SourceRef m_RefFor, m_RefEnd; + private Token nameToken; public SourceRef End => m_RefEnd; @@ -39,8 +40,7 @@ public ForLoopStatement(ScriptLoadingContext lcontext, Token nameToken, Token fo m_Step = new LiteralExpression(lcontext, DynValue.NewNumber(1)); } - lcontext.Scope.PushBlock(); - m_VarName = lcontext.Scope.DefineLocal(nameToken.Text); + this.nameToken = nameToken; if (paren) CheckTokenType(lcontext, TokenType.Brk_Close_Round); if (lcontext.Syntax == ScriptSyntax.Lua || lcontext.Lexer.Current.Type == TokenType.Do) @@ -65,10 +65,20 @@ public ForLoopStatement(ScriptLoadingContext lcontext, Token nameToken, Token fo m_RefEnd = CheckTokenType(lcontext, TokenType.SemiColon).GetSourceRef(); } - m_StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(m_RefFor); lcontext.Source.Refs.Add(m_RefEnd); - } + } + + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Start.ResolveScope(lcontext); + m_End.ResolveScope(lcontext); + m_Step.ResolveScope(lcontext); + lcontext.Scope.PushBlock(); + m_VarName = lcontext.Scope.DefineLocal(nameToken.Text); + m_InnerBlock.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } public override void Compile(ByteCode bc) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs index e9f36557..6a82d639 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs @@ -14,6 +14,7 @@ class ForRangeStatement : Statement, IBlockStatement SymbolRef m_VarName; Expression m_Start, m_End, m_Step; SourceRef m_RefFor, m_RefEnd; + private Token nameToken; public SourceRef End => m_RefEnd; @@ -27,8 +28,8 @@ public ForRangeStatement(ScriptLoadingContext lcontext, Token nameToken, Token f m_End = new LiteralExpression(lcontext, DynValue.NewNumber(endNumber)); m_Step = new LiteralExpression(lcontext, DynValue.NewNumber(startNumber > endNumber ? -1 : 1)); if (paren) CheckTokenType(lcontext, TokenType.Brk_Close_Round); - lcontext.Scope.PushBlock(); - m_VarName = lcontext.Scope.DefineLocal(nameToken.Text); + this.nameToken = nameToken; + if (lcontext.Syntax == ScriptSyntax.Lua || lcontext.Lexer.Current.Type == TokenType.Do) { m_RefFor = forToken.GetSourceRef(CheckTokenType(lcontext, TokenType.Do)); @@ -50,11 +51,18 @@ public ForRangeStatement(ScriptLoadingContext lcontext, Token nameToken, Token f else m_RefEnd = CheckTokenType(lcontext, TokenType.SemiColon).GetSourceRef(); } - m_StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(m_RefFor); lcontext.Source.Refs.Add(m_RefEnd); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + m_VarName = lcontext.Scope.DefineLocal(nameToken.Text); + m_InnerBlock.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } + public override void Compile(ByteCode bc) { bc.PushSourceRef(m_RefFor); diff --git a/src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs index 68c3b8d8..16a30e2f 100755 --- a/src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs @@ -16,6 +16,11 @@ public FunctionCallStatement(ScriptLoadingContext lcontext, FunctionCallExpressi lcontext.Source.Refs.Add(m_FunctionCallExpression.SourceRef); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_FunctionCallExpression.ResolveScope(lcontext); + } + public override void Compile(ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs index 27e2ace3..8c65777d 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs @@ -42,6 +42,11 @@ internal class FunctionRef List m_TableAccessors; FunctionDefinitionExpression m_FuncDef; + private string m_FuncDefName; + private string m_FuncLookupSymbol; + + public bool CanHoist => m_MethodName == null || m_Local; + public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, Token localToken) : base(lcontext) { @@ -54,7 +59,7 @@ public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, To if (m_Local) { - m_FuncSymbol = lcontext.Scope.TryDefineLocal(name.Text); + m_FuncDefName = name.Text; m_FriendlyName = string.Format("{0} (local)", name.Text); m_SourceRef = funcKeyword.GetSourceRef(name); } @@ -63,8 +68,8 @@ public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, To string firstName = name.Text; m_SourceRef = funcKeyword.GetSourceRef(name); + m_FuncLookupSymbol = firstName; - m_FuncSymbol = lcontext.Scope.Find(firstName); m_FriendlyName = firstName; if (lcontext.Lexer.Current.Type != TokenType.Brk_Open_Round) @@ -109,6 +114,23 @@ public FunctionDefinitionStatement(ScriptLoadingContext lcontext, bool local, To lcontext.Source.Refs.Add(m_SourceRef); } + public void DefineLocals(ScriptLoadingContext lcontext) + { + if (m_FuncDefName != null) + { + m_FuncSymbol = lcontext.Scope.TryDefineLocal(m_FuncDefName); + } + } + + public override void ResolveScope(ScriptLoadingContext lcontext) + { + if (m_FuncSymbol == null) + { + m_FuncSymbol = lcontext.Scope.Find(m_FuncLookupSymbol); + } + m_FuncDef.ResolveScope(lcontext); + } + public override void Compile(Execution.VM.ByteCode bc) { using (bc.EnterSource(m_SourceRef)) @@ -129,7 +151,7 @@ public override void Compile(Execution.VM.ByteCode bc) } } } - + private int SetMethod(Execution.VM.ByteCode bc) { int cnt = 0; diff --git a/src/MoonSharp.Interpreter/Tree/Statements/GotoStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/GotoStatement.cs index 2b79685a..4449ff6d 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/GotoStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/GotoStatement.cs @@ -26,7 +26,10 @@ public GotoStatement(ScriptLoadingContext lcontext) SourceRef = GotoToken.GetSourceRef(name); Label = name.Text; + } + public override void ResolveScope(ScriptLoadingContext lcontext) + { lcontext.Scope.RegisterGoto(this); } diff --git a/src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs index bbd496fe..6deaf813 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs @@ -42,7 +42,6 @@ public IfStatement(ScriptLoadingContext lcontext) IfBlock CreateIfBlock(ScriptLoadingContext lcontext, out bool cstyle, out bool endBlock) { Token type = CheckTokenType(lcontext, TokenType.If, TokenType.ElseIf); - lcontext.Scope.PushBlock(); var ifblock = new IfBlock(); ifblock.Exp = Expression.Expr(lcontext); cstyle = false; @@ -87,7 +86,6 @@ IfBlock CreateIfBlock(ScriptLoadingContext lcontext, out bool cstyle, out bool e cstyle = true; } } - ifblock.StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(ifblock.Source); return ifblock; } @@ -96,9 +94,6 @@ IfBlock CreateIfBlock(ScriptLoadingContext lcontext, out bool cstyle, out bool e IfBlock CreateElseBlock(ScriptLoadingContext lcontext, bool cstyle) { Token type = CheckTokenType(lcontext, TokenType.Else); - - lcontext.Scope.PushBlock(); - var ifblock = new IfBlock(); if (cstyle) { @@ -123,11 +118,27 @@ IfBlock CreateElseBlock(ScriptLoadingContext lcontext, bool cstyle) ifblock.Block = new CompositeStatement(lcontext, BlockEndType.Normal); m_End = CheckTokenType(lcontext, TokenType.End).GetSourceRef(); } - ifblock.StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(ifblock.Source); return ifblock; } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + foreach (var block in m_Ifs) + { + lcontext.Scope.PushBlock(); + block.Exp?.ResolveScope(lcontext); + block.Block?.ResolveScope(lcontext); + block.StackFrame = lcontext.Scope.PopBlock(); + } + if (m_Else != null) + { + lcontext.Scope.PushBlock(); + m_Else.Block?.ResolveScope(lcontext); + m_Else.StackFrame = lcontext.Scope.PopBlock(); + } + } + public override void Compile(Execution.VM.ByteCode bc) { diff --git a/src/MoonSharp.Interpreter/Tree/Statements/LabelStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/LabelStatement.cs index f6a28037..87949e89 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/LabelStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/LabelStatement.cs @@ -35,7 +35,10 @@ public LabelStatement(ScriptLoadingContext lcontext) SourceRef = NameToken.GetSourceRef(); Label = NameToken.Text; + } + public override void ResolveScope(ScriptLoadingContext lcontext) + { lcontext.Scope.DefineLabel(this); } diff --git a/src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs index 87cc7f36..a9fa75a7 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs @@ -19,7 +19,6 @@ public RepeatStatement(ScriptLoadingContext lcontext) { m_Repeat = CheckTokenType(lcontext, TokenType.Repeat).GetSourceRef(); - lcontext.Scope.PushBlock(); bool openCurly = lcontext.Syntax != ScriptSyntax.Lua && lcontext.Lexer.Current.Type == TokenType.Brk_Open_Curly; if (openCurly) lcontext.Lexer.Next(); @@ -30,11 +29,18 @@ public RepeatStatement(ScriptLoadingContext lcontext) m_Condition = Expression.Expr(lcontext); m_Until = until.GetSourceRefUpTo(lcontext.Lexer.Current); - m_StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(m_Repeat); lcontext.Source.Refs.Add(m_Until); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + m_Block.ResolveScope(lcontext); + m_Condition.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } + public override void Compile(ByteCode bc) { Loop L = new Loop() diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs index b24262e3..b7681752 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs @@ -18,8 +18,10 @@ public ReturnStatement(ScriptLoadingContext lcontext, Expression e, SourceRef sr lcontext.Source.Refs.Add(sref); } - - + public override void ResolveScope(ScriptLoadingContext lcontext) + { + m_Expression?.ResolveScope(lcontext); + } public ReturnStatement(ScriptLoadingContext lcontext) : base(lcontext) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs index cba73a69..632c4a1a 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs @@ -24,7 +24,7 @@ public WhileStatement(ScriptLoadingContext lcontext) m_Start = whileTk.GetSourceRefUpTo(lcontext.Lexer.Current); - lcontext.Scope.PushBlock(); + if (lcontext.Syntax != ScriptSyntax.Lua && lcontext.Lexer.Current.Type != TokenType.Do && @@ -44,12 +44,19 @@ public WhileStatement(ScriptLoadingContext lcontext) m_End = CheckTokenTypeEx(lcontext, TokenType.End, TokenType.Brk_Close_Curly).GetSourceRef(); } - m_StackFrame = lcontext.Scope.PopBlock(); lcontext.Source.Refs.Add(m_Start); lcontext.Source.Refs.Add(m_End); } + public override void ResolveScope(ScriptLoadingContext lcontext) + { + lcontext.Scope.PushBlock(); + m_Condition.ResolveScope(lcontext); + m_Block.ResolveScope(lcontext); + m_StackFrame = lcontext.Scope.PopBlock(); + } + public override void Compile(ByteCode bc) { diff --git a/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.lua b/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.lua new file mode 100644 index 00000000..cc25eb1b --- /dev/null +++ b/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.lua @@ -0,0 +1,6 @@ +f(); +//This will be hoisted to the top of the block. +function f() +{ + print("hello world!"); +} \ No newline at end of file diff --git a/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.txt b/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.txt new file mode 100644 index 00000000..bc7774a7 --- /dev/null +++ b/src/MoonSharp.Tests/EndToEnd/CLike/SyntaxCLike/Functions/17-call-hoisted.txt @@ -0,0 +1 @@ +hello world! \ No newline at end of file