Skip to content

Commit 479bbe1

Browse files
committed
Draft default params
Add support for arrow functions Refactor Mark default params test n14 as flaky Initial implementation of default parameters
1 parent 4e4b5dd commit 479bbe1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+270
-42
lines changed

src/MoonSharp.Interpreter/Execution/InstructionFieldUsage.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ internal static InstructionFieldUsage GetFieldUsage(this OpCode op)
7070
case OpCode.Swap:
7171
case OpCode.Clean:
7272
case OpCode.CopyValue:
73+
case OpCode.JLclInit:
7374
return InstructionFieldUsage.NumVal | InstructionFieldUsage.NumVal2;
7475
case OpCode.Local:
7576
case OpCode.Upvalue:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using MoonSharp.Interpreter.Execution.Scopes;
4+
using MoonSharp.Interpreter.Tree;
45
using MoonSharp.Interpreter.Tree.Statements;
56

67
namespace MoonSharp.Interpreter.Execution
@@ -10,7 +11,6 @@ internal class BuildTimeScope
1011
List<BuildTimeScopeFrame> m_Frames = new List<BuildTimeScopeFrame>();
1112
List<IClosureBuilder> m_ClosureBuilders = new List<IClosureBuilder>();
1213

13-
1414
public void PushFunction(IClosureBuilder closureBuilder, bool hasVarArgs)
1515
{
1616
m_ClosureBuilders.Add(closureBuilder);

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using MoonSharp.Interpreter.Tree.Statements;
45

56
namespace MoonSharp.Interpreter.Execution.Scopes
@@ -8,13 +9,9 @@ internal class BuildTimeScopeBlock
89
{
910
internal BuildTimeScopeBlock Parent { get; private set; }
1011
internal List<BuildTimeScopeBlock> ChildNodes { get; private set; }
11-
1212
internal RuntimeScopeBlock ScopeBlock { get; private set; }
13-
1413
Dictionary<string, SymbolRef> m_DefinedNames = new Dictionary<string, SymbolRef>();
15-
16-
17-
14+
1815
internal void Rename(string name)
1916
{
2017
SymbolRef sref = m_DefinedNames[name];

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using MoonSharp.Interpreter.Tree.Statements;
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using MoonSharp.Interpreter.Tree.Statements;
24

35
namespace MoonSharp.Interpreter.Execution.Scopes
46
{

src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,5 +356,10 @@ public int Emit_Swap(int p1, int p2)
356356
return AppendInstruction(new Instruction() { OpCode = OpCode.Swap, NumVal = p1, NumVal2 = p2 });
357357
}
358358

359+
public int Emit_JLclInit(SymbolRef sym, int target)
360+
{
361+
if(sym.Type != SymbolRefType.Local) throw new InternalErrorException("Unexpected symbol type : {0}", sym);
362+
return AppendInstruction(new Instruction() { OpCode = OpCode.JLclInit, NumVal = target, NumVal2 = sym.Index });
363+
}
359364
}
360365
}

src/MoonSharp.Interpreter/Execution/VM/OpCode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,12 @@ internal enum OpCode
9090
IterPrep, // Prepares an iterator for execution
9191
IterUpd, // Updates the var part of an iterator
9292

93+
// Nil coalescing
9394
NilCoalescing,
9495
NilCoalescingInverse,
9596

97+
JLclInit, // Inits a param value if a default one is specified and not provided at callsite.
98+
9699
// Meta
97100
Invalid, // Crashes the executor with an unrecoverable NotImplementedException. This MUST always be the last opcode in enum
98101
}

src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ private DynValue Processing_Loop(int instructionPtr, bool canAwait = false)
306306
instructionPtr = ExecNilCoalescingAssignmentInverse(i, instructionPtr);
307307
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
308308
break;
309+
case OpCode.JLclInit:
310+
if(m_ValueStack[m_ExecutionStack.Peek().BasePointer + i.NumVal2].IsNotNil())
311+
instructionPtr = i.NumVal;
312+
break;
309313
case OpCode.Invalid:
310314
throw new NotImplementedException(string.Format("Invalid opcode : {0}", i.String));
311315
default:

src/MoonSharp.Interpreter/Tree/Expression_.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ internal static List<Expression> ExprListAfterFirstExpr(ScriptLoadingContext lco
5252

5353
return exps;
5454
}
55-
56-
55+
5756
internal static List<Expression> ExprList(ScriptLoadingContext lcontext)
5857
{
5958
List<Expression> exps = new List<Expression>();
@@ -78,8 +77,7 @@ internal static Expression Expr(ScriptLoadingContext lcontext)
7877

7978
internal static Expression SubExpr(ScriptLoadingContext lcontext, bool isPrimary, bool binaryChainInProgress = false)
8079
{
81-
Expression e = null;
82-
80+
Expression e;
8381
Token T = lcontext.Lexer.Current;
8482

8583
if (T.IsUnaryOperator())
@@ -202,7 +200,7 @@ internal static Expression SimpleExp(ScriptLoadingContext lcontext)
202200
lcontext.Lexer.Next();
203201
}
204202
lcontext.Lexer.Next();
205-
bool arrowLambda = lcontext.Lexer.Current.Type == TokenType.Arrow;
203+
bool arrowLambda = lcontext.Lexer.Current.Type == TokenType.Arrow || lcontext.Lexer.PeekNext().Type == TokenType.Arrow;
206204
lcontext.Lexer.RestorePos();
207205
if (arrowLambda)
208206
return new FunctionDefinitionExpression(lcontext, false, true);
@@ -222,11 +220,11 @@ internal static Expression SimpleExp(ScriptLoadingContext lcontext)
222220
/// <returns></returns>
223221
internal static Expression PrimaryExp(ScriptLoadingContext lcontext)
224222
{
225-
if (lcontext.Lexer.PeekNext().Type == TokenType.Arrow &&
226-
lcontext.Lexer.Current.Type == TokenType.Name)
223+
if (lcontext.Lexer.PeekNext().Type == TokenType.Arrow && lcontext.Lexer.Current.Type == TokenType.Name)
227224
{
228225
return new FunctionDefinitionExpression(lcontext, false, true);
229226
}
227+
230228
Expression e = PrefixExp(lcontext);
231229

232230
while (true)

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ class FunctionCallExpression : Expression
1111
Expression m_Function;
1212
string m_Name;
1313
string m_DebugErr;
14-
1514
internal SourceRef SourceRef { get; private set; }
1615

17-
1816
public FunctionCallExpression(ScriptLoadingContext lcontext, Expression function, Token thisCallName)
1917
: base(lcontext)
2018
{

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

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class FunctionDefinitionExpression : Expression, IClosureBuilder
2424
SymbolRef m_Env;
2525

2626
SourceRef m_Begin, m_End;
27-
27+
private ScriptLoadingContext lcontext;
28+
List<FunctionDefinitionStatement.FunctionParamRef> paramnames;
2829

2930
public FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool usesGlobalEnv)
3031
: this(lcontext, false, usesGlobalEnv, false)
@@ -33,26 +34,26 @@ public FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool usesGlob
3334
public FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSelfParam, bool isLambda)
3435
: this(lcontext, pushSelfParam, false, isLambda)
3536
{ }
36-
37-
37+
3838
private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSelfParam, bool usesGlobalEnv, bool isLambda)
3939
: base(lcontext)
4040
{
41+
this.lcontext = lcontext;
42+
4143
if (m_UsesGlobalEnv = usesGlobalEnv)
4244
CheckTokenType(lcontext, TokenType.Function);
4345

4446
// here lexer should be at the '(' or at the '|'
4547
//Token openRound = CheckTokenType(lcontext, isLambda ? TokenType.Lambda : TokenType.Brk_Open_Round);
4648

4749
Token openRound;
48-
List<string> paramnames;
4950
bool openCurly = false;
5051
if (isLambda)
5152
{
5253
openRound = lcontext.Lexer.Current;
5354
lcontext.Lexer.Next();
5455
if (openRound.Type == TokenType.Name)
55-
paramnames = new List<string>(new[] {openRound.Text});
56+
paramnames = new List<FunctionDefinitionStatement.FunctionParamRef>(new FunctionDefinitionStatement.FunctionParamRef[] {new FunctionDefinitionStatement.FunctionParamRef(openRound.Text)});
5657
else
5758
paramnames = BuildParamList(lcontext, pushSelfParam, openRound);
5859
}
@@ -150,33 +151,61 @@ private Statement CreateBody(ScriptLoadingContext lcontext, bool openCurly)
150151
return s;
151152
}
152153

153-
private List<string> BuildParamList(ScriptLoadingContext lcontext, bool pushSelfParam, Token openBracketToken)
154+
private List<FunctionDefinitionStatement.FunctionParamRef> BuildParamList(ScriptLoadingContext lcontext, bool pushSelfParam, Token openBracketToken)
154155
{
155156
TokenType closeToken = openBracketToken.Type == TokenType.Lambda ? TokenType.Lambda : TokenType.Brk_Close_Round;
156157

157-
List<string> paramnames = new List<string>();
158+
List<FunctionDefinitionStatement.FunctionParamRef> paramnames = new List<FunctionDefinitionStatement.FunctionParamRef>();
158159

159160
// method decls with ':' must push an implicit 'self' param
160161
if (pushSelfParam)
161-
paramnames.Add(lcontext.Syntax == ScriptSyntax.CLike ? "this" : "self");
162+
paramnames.Add(lcontext.Syntax == ScriptSyntax.CLike ? new FunctionDefinitionStatement.FunctionParamRef("this") : new FunctionDefinitionStatement.FunctionParamRef("self"));
162163

164+
bool parsingDefaultParams = false;
163165
while (lcontext.Lexer.Current.Type != closeToken)
164166
{
165167
Token t = lcontext.Lexer.Current;
168+
bool nextAfterParamDeclr = true;
166169

167170
if (t.Type == TokenType.Name)
168171
{
169-
paramnames.Add(t.Text);
172+
string paramName = t.Text;
173+
174+
if (lcontext.Lexer.PeekNext().Type == TokenType.Op_Assignment)
175+
{
176+
parsingDefaultParams = true;
177+
lcontext.Lexer.Next();
178+
lcontext.Lexer.Next();
179+
Expression defaultVal = Expr(lcontext);
180+
nextAfterParamDeclr = false;
181+
182+
paramnames.Add(new FunctionDefinitionStatement.FunctionParamRef(paramName, defaultVal));
183+
}
184+
else
185+
{
186+
if (parsingDefaultParams)
187+
{
188+
throw new SyntaxErrorException(t, "after first parameter with default value a parameter without default value cannot be declared", t.Text)
189+
{
190+
IsPrematureStreamTermination = (t.Type == TokenType.Eof)
191+
};
192+
}
193+
194+
paramnames.Add(new FunctionDefinitionStatement.FunctionParamRef(paramName));
195+
}
170196
}
171197
else if (t.Type == TokenType.VarArgs)
172198
{
173199
m_HasVarArgs = true;
174-
paramnames.Add(WellKnownSymbols.VARARGS);
200+
paramnames.Add(new FunctionDefinitionStatement.FunctionParamRef(WellKnownSymbols.VARARGS));
175201
}
176202
else
177203
UnexpectedTokenType(t);
178204

179-
lcontext.Lexer.Next();
205+
if (nextAfterParamDeclr)
206+
{
207+
lcontext.Lexer.Next();
208+
}
180209

181210
t = lcontext.Lexer.Current;
182211

@@ -197,18 +226,18 @@ private List<string> BuildParamList(ScriptLoadingContext lcontext, bool pushSelf
197226
return paramnames;
198227
}
199228

200-
private SymbolRef[] DefineArguments(List<string> paramnames, ScriptLoadingContext lcontext)
229+
private SymbolRef[] DefineArguments(List<FunctionDefinitionStatement.FunctionParamRef> paramnames, ScriptLoadingContext lcontext)
201230
{
202231
HashSet<string> names = new HashSet<string>();
203232

204233
SymbolRef[] ret = new SymbolRef[paramnames.Count];
205234

206235
for (int i = paramnames.Count - 1; i >= 0; i--)
207236
{
208-
if (!names.Add(paramnames[i]))
209-
paramnames[i] = paramnames[i] + "@" + i.ToString();
237+
if (!names.Add(paramnames[i].Name))
238+
paramnames[i].Name = paramnames[i].Name + "@" + i.ToString();
210239

211-
ret[i] = lcontext.Scope.DefineLocal(paramnames[i]);
240+
ret[i] = lcontext.Scope.DefineLocal(paramnames[i].Name);
212241
}
213242

214243
return ret;
@@ -243,6 +272,8 @@ public override DynValue Eval(ScriptExecutionContext context)
243272

244273
public int CompileBody(ByteCode bc, string friendlyName)
245274
{
275+
//LoadingContext.Scope.PopFunction()
276+
246277
string funcName = friendlyName ?? ("<" + this.m_Begin.FormatLocation(bc.Script, true) + ">");
247278

248279
bc.PushSourceRef(m_Begin);
@@ -265,8 +296,25 @@ public int CompileBody(ByteCode bc, string friendlyName)
265296
}
266297

267298
if (m_ParamNames.Length > 0)
299+
{
268300
bc.Emit_Args(m_ParamNames);
269301

302+
for (int i = 0; i < m_ParamNames.Length; i++)
303+
{
304+
FunctionDefinitionStatement.FunctionParamRef fr = paramnames[i];
305+
SymbolRef sr = m_ParamNames[i];
306+
307+
if (fr.DefaultValue != null)
308+
{
309+
var jp = bc.Emit_JLclInit(sr, -1);
310+
fr.DefaultValue.CompilePossibleLiteral(bc);
311+
new SymbolRefExpression(lcontext, sr).CompileAssignment(bc, Operator.NotAnOperator, 0, 0);
312+
bc.Emit_Pop();
313+
bc.SetNumVal(jp, bc.GetJumpPointForNextInstruction());
314+
}
315+
}
316+
}
317+
270318
m_Statement.Compile(bc);
271319

272320
bc.PopSourceRef();

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class IndexExpression : Expression, IVariable
1010
Expression m_BaseExp;
1111
Expression m_IndexExp;
1212
string m_Name;
13-
private Token nameToken;
1413
private bool inc;
1514
private bool dec;
1615
private bool nilCheck;
@@ -125,7 +124,7 @@ public void CompileAssignment(ByteCode bc, Operator op, int stackofs, int tuplei
125124
{
126125
if (isLength)
127126
{
128-
throw new SyntaxErrorException(nameToken, "Cannot assign to readonly property .length");
127+
throw new SyntaxErrorException(null, "Cannot assign to readonly property .length");
129128
}
130129
if (op != Operator.NotAnOperator)
131130
{

src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -851,9 +851,7 @@ private Token ReadHashBang(int fromLine, int fromCol)
851851
private Token ReadCMultilineComment(int fromLine, int fromCol)
852852
{
853853
StringBuilder text = new StringBuilder(32);
854-
855-
bool extraneousFound = false;
856-
854+
857855
for (char c = CursorChar(); ; c = CursorCharNext())
858856
{
859857
if (c == '\r') continue;
@@ -894,7 +892,6 @@ private Token ReadComment(int fromLine, int fromCol)
894892
}
895893
else if (c == '\n')
896894
{
897-
extraneousFound = true;
898895
CursorCharNext();
899896
return CreateToken(TokenType.Comment, fromLine, fromCol, text.ToString());
900897
}

src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using MoonSharp.Interpreter.Debugging;
45
using MoonSharp.Interpreter.Execution;
56

@@ -145,6 +146,7 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres
145146
else {
146147
CheckTokenType(lcontext, TokenType.Op_Assignment);
147148
}
149+
148150
m_RValues = Expression.ExprList(lcontext);
149151
}
150152

0 commit comments

Comments
 (0)