Skip to content

Commit 9149396

Browse files
committed
fixed scope management (duplicate let)
1 parent 760f217 commit 9149396

File tree

1 file changed

+52
-27
lines changed

1 file changed

+52
-27
lines changed

hscript/JsInterp.hx

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ class JsInterp extends Interp {
1313
public var properties : Map<String,Bool>;
1414

1515

16+
var localNames : Map<String,String>;
17+
1618
override function execute( expr : Expr ) : Dynamic {
1719
depth = 0;
18-
locals = new Map();
20+
localNames = new Map();
1921
var str = '(($$i) => ${exprValue(expr)})';
2022
var f : Dynamic -> Dynamic = js.Lib.eval(str);
2123
return f(this);
@@ -58,6 +60,8 @@ class JsInterp extends Interp {
5860
return '(() => {${exprJS(expr)}})()';
5961
case EMeta(_,_,e), ECheckType(e,_):
6062
return exprValue(e);
63+
case EFunction(_,_,name,_) if( name != null ):
64+
return '(() => {${exprJS(expr)}})()';
6165
default:
6266
return exprJS(expr);
6367
}
@@ -104,6 +108,17 @@ class JsInterp extends Interp {
104108
}
105109
}
106110

111+
function declLocal( n : String ) {
112+
if( !localNames.exists(n) ) {
113+
localNames.set(n, n);
114+
return n;
115+
}
116+
var c = 2;
117+
while( localNames.exists(n+c) ) c++;
118+
localNames.set(n, n+c);
119+
return n+c;
120+
}
121+
107122
function exprJS( expr : Expr ) : String {
108123
#if hscriptPos
109124
curExpr = expr;
@@ -117,8 +132,9 @@ class JsInterp extends Interp {
117132
case CString(s): '"'+escapeString(s)+'"';
118133
}
119134
case EIdent(v):
120-
if( locals.exists(v) )
121-
return v;
135+
var v2 = localNames.get(v);
136+
if( v2 != null )
137+
return v2;
122138
if( isContext(v) )
123139
return '$$i.ctx.$v';
124140
switch( v ) {
@@ -127,16 +143,16 @@ class JsInterp extends Interp {
127143
}
128144
return '$$i.resolve("$v")';
129145
case EVar(n, t, e):
130-
locals.set(n, null);
146+
n = declLocal(n);
131147
return e == null ? 'let $n' : 'let $n = ${exprValue(e)}';
132148
case EParent(e):
133149
return '(${exprValue(e)})';
134150
case EBlock(el):
135-
var old = locals.copy();
151+
var old = localNames.copy();
136152
// pre define name functions
137153
for( e in el )
138154
switch( Tools.expr(e) ) {
139-
case EFunction(_,_,name,_): locals.set(name,null);
155+
case EFunction(_,_,name,_): declLocal(name);
140156
default:
141157
}
142158
var buf = new StringBuf();
@@ -146,7 +162,7 @@ class JsInterp extends Interp {
146162
buf.add(";");
147163
}
148164
buf.add('}');
149-
locals = old;
165+
localNames = old;
150166
return buf.toString();
151167
case EField(e,f) if( !isProperty(f) ):
152168
return exprValue(e)+"."+f;
@@ -160,8 +176,8 @@ class JsInterp extends Interp {
160176
return '(${exprCond(e1)} $op ${exprCond(e2)})';
161177
case "=":
162178
switch( Tools.expr(e1) ) {
163-
case EIdent(id) if( locals.exists(id) ):
164-
return id+" = "+exprValue(e2);
179+
case EIdent(id) if( localNames.exists(id) ):
180+
return localNames.get(id)+" = "+exprValue(e2);
165181
case EIdent(id) if( isContext(id) ):
166182
return '$$i.ctx.$id = ${exprValue(e2)}';
167183
case EIdent(id):
@@ -176,8 +192,8 @@ class JsInterp extends Interp {
176192
case "+=","-=","*=","/=","%=","|=","&=","^=","<<=",">>=",">>>=":
177193
var aop = op.substr(0, op.length - 1);
178194
switch( Tools.expr(e1) ) {
179-
case EIdent(id) if( locals.exists(id) ):
180-
return id+" "+op+" "+exprValue(e2);
195+
case EIdent(id) if( localNames.exists(id) ):
196+
return localNames.get(id)+" "+op+" "+exprValue(e2);
181197
case EIdent(id) if( isContext(id) ):
182198
return '$$i.ctx.$id $op ${exprValue(e2)}';
183199
case EIdent(id):
@@ -204,7 +220,8 @@ class JsInterp extends Interp {
204220
return op+exprOp(e);
205221
case "++", "--":
206222
switch( Tools.expr(e) ) {
207-
case EIdent(id) if( locals.exists(id) ):
223+
case EIdent(id) if( localNames.exists(id) ):
224+
id = localNames.get(id);
208225
return prefix ? op + id : id + op;
209226
case EIdent(id) if( isContext(id) ):
210227
return prefix ? op + "$i.ctx."+id : "$i.ctx."+id + op;
@@ -216,9 +233,15 @@ class JsInterp extends Interp {
216233
return '(($$v) => ($$i.setVar("$id",$$v $op 1),$$v))($$i.resolve("$id"))';
217234
case EArray(e, index):
218235
var op = op.charAt(0);
219-
return '(($$a,$$idx) => { var $$v = $$i.getArray($$a,$$idx); $$i.setArray($$a,$$idx,$$v $op 1); return $$v; })(${exprValue(e)},${exprValue(index)})';
236+
var v = declLocal("$v");
237+
var str = '(($$a,$$idx) => { let $v = $$i.getArray($$a,$$idx); $$i.setArray($$a,$$idx,$v $op 1); return $v; })(${exprValue(e)},${exprValue(index)})';
238+
localNames.remove(v);
239+
return str;
220240
case EField(e, f):
221-
return '(($$o) => { var $$v = $$i.get($$o,"$f"); $$i.set($$o,"$f",$$v $op 1); return $$v; })(${exprValue(e)})';
241+
var v = declLocal("$v");
242+
var str = '(($$o) => { let $v = $$i.get($$o,"$f"); $$i.set($$o,"$f",$$v $op 1); return $v; })(${exprValue(e)})';
243+
localNames.remove(v);
244+
return str;
222245
default:
223246
error(EInvalidOp(op));
224247
}
@@ -241,7 +264,8 @@ class JsInterp extends Interp {
241264
if( isCtx )
242265
return '${exprValue(e)}(${args.join(',')})';
243266
return addPos('$$i.fcall2(${exprValue(eobj)},"$f",[${args.join(',')}])');
244-
case EIdent(id) if( locals.exists(id) ):
267+
case EIdent(id) if( localNames.exists(id) ):
268+
id = localNames.get(id);
245269
return '$id(${args.join(',')})';
246270
case EIdent(id) if( isContext(id) ):
247271
return '$$i.ctx.$id(${args.join(',')})';
@@ -255,12 +279,14 @@ class JsInterp extends Interp {
255279
case EWhile(cond, e):
256280
return 'while( ${exprValue(cond)} ) ${exprJS(e)}';
257281
case EFor(v, it, e):
258-
var prev = locals.exists(v);
259-
locals.set(v, null);
282+
v = declLocal(v);
260283
var block = exprJS(e);
261-
if( !prev ) locals.remove(v);
284+
localNames.remove(v);
262285
var iter = '$$i.makeIterator(${exprValue(it)})';
263-
return '{ var $$it = ${addPos(iter)}; while( $$it.hasNext() ) { var $v = $$it.next(); $block; } }';
286+
var it = declLocal("$it");
287+
var str = '{ let $it = ${addPos(iter)}; while( $it.hasNext() ) { let $v = $it.next(); $block; } }';
288+
localNames.remove(it);
289+
return str;
264290
case EBreak:
265291
return 'break';
266292
case EContinue:
@@ -295,10 +321,9 @@ class JsInterp extends Interp {
295321
case EThrow(e):
296322
return "throw "+exprValue(e);
297323
case ETry(e, v, t, ecatch):
298-
var prev = locals.exists(v);
299-
locals.set(v, null);
324+
v = declLocal(v);
300325
var ec = exprBlock(ecatch);
301-
if( !prev ) locals.remove(v);
326+
localNames.remove(v);
302327
return 'try ${exprBlock(e)} catch( $v ) $ec';
303328
case EObject(fl):
304329
var fields = [for( f in fl ) f.name+":"+exprValue(f.e)];
@@ -308,16 +333,16 @@ class JsInterp extends Interp {
308333
case EMeta(_, _, e), ECheckType(e,_):
309334
return exprJS(e);
310335
case EFunction(args, e, name, ret):
336+
var prev = localNames.copy();
311337
if( name != null )
312-
locals.set(name, null);
313-
var prev = locals.copy();
338+
declLocal(name);
314339
for( a in args )
315-
locals.set(a.name, null);
340+
localNames.set(a.name, a.name);
316341
var bl = exprBlock(e);
317-
locals = prev;
342+
localNames = prev;
318343
var fstr = 'function(${[for( a in args ) a.name].join(",")}) $bl';
319344
if( name != null )
320-
fstr = 'var $name = $$i.setVar("$name",$fstr)';
345+
fstr = 'let $name = $$i.setVar("$name",$fstr)';
321346
return fstr;
322347
case ESwitch(e, cases, defaultExpr):
323348
var checks = [for( c in cases ) 'if( ${[for( v in c.values ) '$$v == ${exprValue(v)}'].join(" || ")} ) return ${exprValue(handleRBC(c.expr))};'];

0 commit comments

Comments
 (0)