@@ -24,7 +24,8 @@ class FunctionDefinitionExpression : Expression, IClosureBuilder
24
24
SymbolRef m_Env ;
25
25
26
26
SourceRef m_Begin , m_End ;
27
-
27
+ private ScriptLoadingContext lcontext ;
28
+ List < FunctionDefinitionStatement . FunctionParamRef > paramnames ;
28
29
29
30
public FunctionDefinitionExpression ( ScriptLoadingContext lcontext , bool usesGlobalEnv )
30
31
: this ( lcontext , false , usesGlobalEnv , false )
@@ -33,26 +34,43 @@ public FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool usesGlob
33
34
public FunctionDefinitionExpression ( ScriptLoadingContext lcontext , bool pushSelfParam , bool isLambda )
34
35
: this ( lcontext , pushSelfParam , false , isLambda )
35
36
{ }
36
-
37
-
37
+
38
38
private FunctionDefinitionExpression ( ScriptLoadingContext lcontext , bool pushSelfParam , bool usesGlobalEnv , bool isLambda )
39
39
: base ( lcontext )
40
40
{
41
+ this . lcontext = lcontext ;
42
+
41
43
if ( m_UsesGlobalEnv = usesGlobalEnv )
42
44
CheckTokenType ( lcontext , TokenType . Function ) ;
43
45
46
+
47
+ // create scope
48
+ // This needs to be up here to allow for arguments to correctly close over ENV
49
+ // Arguments, however, must come before any other local definitions to avoid closing
50
+ // over uninitialised variables. (Note for hoisting).
51
+ lcontext . Scope . PushFunction ( this ) ;
52
+
53
+ if ( m_UsesGlobalEnv )
54
+ {
55
+ m_Env = lcontext . Scope . DefineLocal ( WellKnownSymbols . ENV ) ;
56
+ }
57
+ else
58
+ {
59
+ lcontext . Scope . ForceEnvUpValue ( ) ;
60
+ }
61
+
62
+ // Parse arguments
44
63
// here lexer should be at the '(' or at the '|'
45
64
//Token openRound = CheckTokenType(lcontext, isLambda ? TokenType.Lambda : TokenType.Brk_Open_Round);
46
65
47
66
Token openRound ;
48
- List < string > paramnames ;
49
67
bool openCurly = false ;
50
68
if ( isLambda )
51
69
{
52
70
openRound = lcontext . Lexer . Current ;
53
71
lcontext . Lexer . Next ( ) ;
54
72
if ( openRound . Type == TokenType . Name )
55
- paramnames = new List < string > ( new [ ] { openRound . Text } ) ;
73
+ paramnames = new List < FunctionDefinitionStatement . FunctionParamRef > ( new FunctionDefinitionStatement . FunctionParamRef [ ] { new FunctionDefinitionStatement . FunctionParamRef ( openRound . Text ) } ) ;
56
74
else
57
75
paramnames = BuildParamList ( lcontext , pushSelfParam , openRound ) ;
58
76
}
@@ -77,19 +95,10 @@ private FunctionDefinitionExpression(ScriptLoadingContext lcontext, bool pushSel
77
95
78
96
m_Begin = openRound . GetSourceRefUpTo ( lcontext . Lexer . Current ) ;
79
97
80
- // create scope
81
- lcontext . Scope . PushFunction ( this , m_HasVarArgs ) ;
82
-
83
- if ( m_UsesGlobalEnv )
84
- {
85
- m_Env = lcontext . Scope . DefineLocal ( WellKnownSymbols . ENV ) ;
86
- }
87
- else
88
- {
89
- lcontext . Scope . ForceEnvUpValue ( ) ;
90
- }
91
98
92
99
m_ParamNames = DefineArguments ( paramnames , lcontext ) ;
100
+
101
+ if ( m_HasVarArgs ) lcontext . Scope . SetHasVarArgs ( ) ; //Moved here
93
102
94
103
if ( isLambda )
95
104
m_Statement = CreateLambdaBody ( lcontext , arrowFunc ) ;
@@ -150,33 +159,61 @@ private Statement CreateBody(ScriptLoadingContext lcontext, bool openCurly)
150
159
return s ;
151
160
}
152
161
153
- private List < string > BuildParamList ( ScriptLoadingContext lcontext , bool pushSelfParam , Token openBracketToken )
162
+ private List < FunctionDefinitionStatement . FunctionParamRef > BuildParamList ( ScriptLoadingContext lcontext , bool pushSelfParam , Token openBracketToken )
154
163
{
155
164
TokenType closeToken = openBracketToken . Type == TokenType . Lambda ? TokenType . Lambda : TokenType . Brk_Close_Round ;
156
165
157
- List < string > paramnames = new List < string > ( ) ;
166
+ List < FunctionDefinitionStatement . FunctionParamRef > paramnames = new List < FunctionDefinitionStatement . FunctionParamRef > ( ) ;
158
167
159
168
// method decls with ':' must push an implicit 'self' param
160
169
if ( pushSelfParam )
161
- paramnames . Add ( lcontext . Syntax == ScriptSyntax . CLike ? "this" : "self" ) ;
170
+ paramnames . Add ( lcontext . Syntax == ScriptSyntax . CLike ? new FunctionDefinitionStatement . FunctionParamRef ( "this" ) : new FunctionDefinitionStatement . FunctionParamRef ( "self" ) ) ;
162
171
172
+ bool parsingDefaultParams = false ;
163
173
while ( lcontext . Lexer . Current . Type != closeToken )
164
174
{
165
175
Token t = lcontext . Lexer . Current ;
176
+ bool nextAfterParamDeclr = true ;
166
177
167
178
if ( t . Type == TokenType . Name )
168
179
{
169
- paramnames . Add ( t . Text ) ;
180
+ string paramName = t . Text ;
181
+
182
+ if ( lcontext . Lexer . PeekNext ( ) . Type == TokenType . Op_Assignment )
183
+ {
184
+ parsingDefaultParams = true ;
185
+ lcontext . Lexer . Next ( ) ;
186
+ lcontext . Lexer . Next ( ) ;
187
+ Expression defaultVal = Expr ( lcontext ) ;
188
+ nextAfterParamDeclr = false ;
189
+
190
+ paramnames . Add ( new FunctionDefinitionStatement . FunctionParamRef ( paramName , defaultVal ) ) ;
191
+ }
192
+ else
193
+ {
194
+ if ( parsingDefaultParams )
195
+ {
196
+ throw new SyntaxErrorException ( t , "after first parameter with default value a parameter without default value cannot be declared" , t . Text )
197
+ {
198
+ IsPrematureStreamTermination = ( t . Type == TokenType . Eof )
199
+ } ;
200
+ }
201
+
202
+ paramnames . Add ( new FunctionDefinitionStatement . FunctionParamRef ( paramName ) ) ;
203
+ }
170
204
}
171
205
else if ( t . Type == TokenType . VarArgs )
172
206
{
173
207
m_HasVarArgs = true ;
174
- paramnames . Add ( WellKnownSymbols . VARARGS ) ;
208
+ paramnames . Add ( new FunctionDefinitionStatement . FunctionParamRef ( WellKnownSymbols . VARARGS ) ) ;
175
209
}
176
210
else
177
211
UnexpectedTokenType ( t ) ;
178
212
179
- lcontext . Lexer . Next ( ) ;
213
+ if ( nextAfterParamDeclr )
214
+ {
215
+ lcontext . Lexer . Next ( ) ;
216
+ }
180
217
181
218
t = lcontext . Lexer . Current ;
182
219
@@ -197,18 +234,18 @@ private List<string> BuildParamList(ScriptLoadingContext lcontext, bool pushSelf
197
234
return paramnames ;
198
235
}
199
236
200
- private SymbolRef [ ] DefineArguments ( List < string > paramnames , ScriptLoadingContext lcontext )
237
+ private SymbolRef [ ] DefineArguments ( List < FunctionDefinitionStatement . FunctionParamRef > paramnames , ScriptLoadingContext lcontext )
201
238
{
202
239
HashSet < string > names = new HashSet < string > ( ) ;
203
240
204
241
SymbolRef [ ] ret = new SymbolRef [ paramnames . Count ] ;
205
242
206
243
for ( int i = paramnames . Count - 1 ; i >= 0 ; i -- )
207
244
{
208
- if ( ! names . Add ( paramnames [ i ] ) )
209
- paramnames [ i ] = paramnames [ i ] + "@" + i . ToString ( ) ;
245
+ if ( ! names . Add ( paramnames [ i ] . Name ) )
246
+ paramnames [ i ] . Name = paramnames [ i ] . Name + "@" + i . ToString ( ) ;
210
247
211
- ret [ i ] = lcontext . Scope . DefineLocal ( paramnames [ i ] ) ;
248
+ ret [ i ] = lcontext . Scope . DefineLocal ( paramnames [ i ] . Name ) ;
212
249
}
213
250
214
251
return ret ;
@@ -243,6 +280,8 @@ public override DynValue Eval(ScriptExecutionContext context)
243
280
244
281
public int CompileBody ( ByteCode bc , string friendlyName )
245
282
{
283
+ //LoadingContext.Scope.PopFunction()
284
+
246
285
string funcName = friendlyName ?? ( "<" + this . m_Begin . FormatLocation ( bc . Script , true ) + ">" ) ;
247
286
248
287
bc . PushSourceRef ( m_Begin ) ;
@@ -265,8 +304,25 @@ public int CompileBody(ByteCode bc, string friendlyName)
265
304
}
266
305
267
306
if ( m_ParamNames . Length > 0 )
307
+ {
268
308
bc . Emit_Args ( m_ParamNames ) ;
269
309
310
+ for ( int i = 0 ; i < m_ParamNames . Length ; i ++ )
311
+ {
312
+ FunctionDefinitionStatement . FunctionParamRef fr = paramnames [ i ] ;
313
+ SymbolRef sr = m_ParamNames [ i ] ;
314
+
315
+ if ( fr . DefaultValue != null )
316
+ {
317
+ var jp = bc . Emit_JLclInit ( sr , - 1 ) ;
318
+ fr . DefaultValue . CompilePossibleLiteral ( bc ) ;
319
+ new SymbolRefExpression ( lcontext , sr ) . CompileAssignment ( bc , Operator . NotAnOperator , 0 , 0 ) ;
320
+ bc . Emit_Pop ( ) ;
321
+ bc . SetNumVal ( jp , bc . GetJumpPointForNextInstruction ( ) ) ;
322
+ }
323
+ }
324
+ }
325
+
270
326
m_Statement . Compile ( bc ) ;
271
327
272
328
bc . PopSourceRef ( ) ;
0 commit comments