77import static wyil .lang .WyilFile .EXPR_arrayaccess ;
88import static wyil .lang .WyilFile .EXPR_arrayborrow ;
99import static wyil .lang .WyilFile .EXPR_dereference ;
10+ import static wyil .lang .WyilFile .EXPR_fielddereference ;
1011import static wyil .lang .WyilFile .EXPR_recordaccess ;
1112import static wyil .lang .WyilFile .EXPR_recordborrow ;
1213import static wyil .lang .WyilFile .EXPR_variablecopy ;
@@ -261,41 +262,43 @@ public Term constructAssert(Stmt.Assert stmt, Term condition) {
261262
262263 @ Override
263264 public Term constructAssign (Stmt .Assign stmt , List <Term > lhs , List <Term > rhs ) {
265+ boolean simple = isSimpleAssignment (stmt );
264266 //
265- // FIXME: es6 supports destructuring assignment which could be used here.
266- //
267- if (lhs .size () == 1 ) {
268- // Easy case
267+ if (lhs .size () == 1 && simple ) {
268+ // Easy case with no destructuring assignment (unless ES6)
269269 return new JavaScriptFile .Assignment (lhs .get (0 ), rhs .get (0 ));
270- } else if (isSimpleAssignment ( stmt ) ) {
270+ } else if (simple ) {
271271 // NOTE: what we know here is that there is no interference between the left and
272- // right-hand sides. Also, that we have no multi- assignment
272+ // right-hand sides. Also, that we have no destructuring assignment (unless ES6)
273273 ArrayList <Term > stmts = new ArrayList <>();
274274 for (int i =0 ;i !=lhs .size ();++i ) {
275275 stmts .add (new JavaScriptFile .Assignment (lhs .get (i ), rhs .get (i )));
276276 }
277277 return new Block (stmts );
278278 } else {
279279 // Harder case as have to workaround interference.
280- Tuple <Expr > exprs = stmt .getRightHandSide ();
280+ Tuple <LVal > lvals = stmt .getLeftHandSide ();
281+ // Contains set of rhs terms to evaluate first. These all have to be executed
282+ // before the lhs terms because of the potential for interference.
281283 ArrayList <Term > first = new ArrayList <>();
284+ // Contains set of assignments to evaluate afterwards.
282285 ArrayList <Term > second = new ArrayList <>();
283- //
284- for (int i =0 ,j =0 ;i !=exprs .size ();++i ) {
285- Expr e = exprs .get (i );
286- Tuple <Type > types = e .getTypes ();
286+ // Finally, handle assignents to lvals
287+ for (int i =0 ;i !=lvals .size ();++i ) {
288+ Type lv_t = lvals .get (i ).getType ();
287289 // Translate right-hand side
288290 VariableAccess tmp = new VariableAccess ("$" + (temporaryIndex ++));
289291 first .add (new VariableDeclaration (toConstKind (),tmp .getName (), rhs .get (i )));
290292 // Translate left-hand side
291- if (types == null ) {
293+ if (lv_t . shape () == 1 ) {
292294 // Unit assignment
293- second .add (new JavaScriptFile .Assignment (lhs .get (j ++ ), tmp ));
295+ second .add (new JavaScriptFile .Assignment (lhs .get (i ), tmp ));
294296 } else {
295297 // Multi-assignment
296- for (int k =0 ;k !=types .size ();++k ) {
297- Term t = new ArrayAccess (tmp ,new Constant (k ));
298- second .add (new JavaScriptFile .Assignment (lhs .get (j ++), t ));
298+ JavaScriptFile .ArrayInitialiser ai = (JavaScriptFile .ArrayInitialiser ) lhs .get (i );
299+ for (int k =0 ;k !=lv_t .shape ();++k ) {
300+ Term a = new ArrayAccess (tmp ,new Constant (k ));
301+ second .add (new JavaScriptFile .Assignment (ai .getElement (k ), a ));
299302 }
300303 }
301304 }
@@ -360,24 +363,7 @@ public Term constructNamedBlock(Stmt.NamedBlock stmt, List<Term> stmts) {
360363 }
361364
362365 @ Override
363- public Term constructReturn (Stmt .Return stmt , List <Term > returns ) {
364- Term rval ;
365- if (returns .size () == 0 ) {
366- rval = null ;
367- } else if (returns .size () == 1 ) {
368- // Easy case
369- rval = returns .get (0 );
370- } else {
371- //
372- if (allUnitExpressions (stmt .getReturns ())) {
373- // Easier as direct mapping between expressions.
374- rval = new JavaScriptFile .ArrayInitialiser (returns );
375- } else {
376- // FIXME: implement multiple expressions!!
377- throw new UnsupportedOperationException ();
378- }
379- }
380- //
366+ public Term constructReturn (Stmt .Return stmt , Term rval ) {
381367 return new Return (rval );
382368 }
383369
@@ -440,6 +426,11 @@ public Term constructRecordAccessLVal(Expr.RecordAccess expr, Term source) {
440426 return new JavaScriptFile .PropertyAccess (source , expr .getField ().toString ());
441427 }
442428
429+ @ Override
430+ public Term constructTupleInitialiserLVal (Expr .TupleInitialiser expr , List <Term > terms ) {
431+ return new JavaScriptFile .ArrayInitialiser (terms );
432+ }
433+
443434 @ Override
444435 public Term constructVariableAccessLVal (Expr .VariableAccess expr ) {
445436 String name = expr .getVariableDeclaration ().getName ().toString ();
@@ -693,9 +684,9 @@ public Term constructLambdaAccess(Expr.LambdaAccess expr) {
693684 // just assigning the name) is that it protects against potential name
694685 // clashes with local variables.
695686 Type .Callable ft = expr .getLink ().getTarget ().getType ();
696- Tuple < Type > params = ft .getParameters ();
687+ Type param = ft .getParameter ();
697688 //
698- for (int i =0 ;i !=params . size ();++i ) {
689+ for (int i =0 ;i !=param . shape ();++i ) {
699690 String v = "p" + i ;
700691 parameters .add (v );
701692 arguments .add (new VariableAccess (v ));
@@ -744,6 +735,11 @@ public Term constructRecordInitialiser(Expr.RecordInitialiser expr, List<Term> o
744735 return new Operator (Kind .NEW ,WY_RECORD (new JavaScriptFile .ObjectLiteral (fields )));
745736 }
746737
738+ @ Override
739+ public Term constructTupleInitialiser (Expr .TupleInitialiser expr , List <Term > operands ) {
740+ return new ArrayInitialiser (operands );
741+ }
742+
747743 @ Override
748744 public Term constructStaticVariableAccess (Expr .StaticVariableAccess expr ) {
749745 String name = toMangledName (expr .getLink ().getTarget ());
@@ -1759,33 +1755,32 @@ private boolean isSimpleAssignment(Stmt.Assign stmt) {
17591755 Tuple <LVal > lhs = stmt .getLeftHandSide ();
17601756 Tuple <Expr > rhs = stmt .getRightHandSide ();
17611757 //
1762- if (lhs .size () != rhs .size ()) {
1763- // Multi-assignment is present
1764- return false ;
1765- } else {
1766- Decl .Variable [] defs = new Decl .Variable [lhs .size ()];
1767- HashSet <Decl .Variable > uses = new HashSet <>();
1768- // Identify all defs and uses
1769- for (int i =0 ;i !=lhs .size ();++i ) {
1770- defs [i ] = extractDefinedVariable (lhs .get (i ));
1771- if (defs [i ] == null ) {
1772- // Couldn't tell what was being defined.
1773- return false ;
1774- }
1775- extractUsedVariables (lhs .get (i ),uses );
1776- extractUsedVariables (rhs .get (i ),uses );
1777-
1758+ Decl .Variable [] defs = new Decl .Variable [lhs .size ()];
1759+ HashSet <Decl .Variable > uses = new HashSet <>();
1760+ // Identify all defs and uses
1761+ for (int i =0 ;i !=lhs .size ();++i ) {
1762+ LVal lv = lhs .get (i );
1763+ if (lv instanceof Expr .TupleInitialiser && !jsFile .ES6 ()) {
1764+ // Prior to ES6 was no destructuring assignment
1765+ return false ;
17781766 }
1779- // Check for interference
1780- for (int i =0 ;i !=defs .length ;++i ) {
1781- if (uses .contains (defs [i ])) {
1782- // Interference detected
1783- return false ;
1784- }
1767+ defs [i ] = extractDefinedVariable (lhs .get (i ));
1768+ if (defs [i ] == null ) {
1769+ // Couldn't tell what was being defined.
1770+ return false ;
17851771 }
1786- //
1787- return true ;
1772+ extractUsedVariables ( lhs . get ( i ), uses );
1773+ extractUsedVariables ( rhs . get ( i ), uses ) ;
17881774 }
1775+ // Check for interference
1776+ for (int i =0 ;i !=defs .length ;++i ) {
1777+ if (uses .contains (defs [i ])) {
1778+ // Interference detected
1779+ return false ;
1780+ }
1781+ }
1782+ //
1783+ return true ;
17891784 }
17901785
17911786 private Decl .Variable extractDefinedVariable (LVal lval ) {
@@ -1795,6 +1790,7 @@ private Decl.Variable extractDefinedVariable(LVal lval) {
17951790 Expr .ArrayAccess e = (Expr .ArrayAccess ) lval ;
17961791 return extractDefinedVariable ((WyilFile .LVal ) e .getFirstOperand ());
17971792 }
1793+ case EXPR_fielddereference :
17981794 case EXPR_dereference : {
17991795 // NOTE: it's impossible to tell what variable is being defined through a
18001796 // dereference.
@@ -2019,23 +2015,6 @@ public static boolean hasOtherSubtypesBesidesNull(Type type, Class<? extends Typ
20192015 return false ;
20202016 }
20212017
2022- /**
2023- * Determine whether a sequence of expressions are all "unit" expressions (that
2024- * is, return a single value) or not.
2025- *
2026- * @param exprs
2027- * @return
2028- */
2029- private static boolean allUnitExpressions (Tuple <Expr > exprs ) {
2030- for (int i =0 ;i !=exprs .size ();++i ) {
2031- Tuple <Type > types = exprs .get (i ).getTypes ();
2032- if (types != null ) {
2033- return false ;
2034- }
2035- }
2036- return true ;
2037- }
2038-
20392018 /**
20402019 * Determine the appropriate mangled string for a given named declaration. This
20412020 * is critical to ensuring that overloaded declarations do not clash.
@@ -2051,12 +2030,12 @@ private String toMangledName(Decl.Named<?> decl) {
20512030 // Add type mangles for non-exported symbols
20522031 if (!exported && decl instanceof Decl .Method ) {
20532032 Decl .Method method = (Decl .Method ) decl ;
2054- Tuple < Type > parameters = method .getType ().getParameters ();
2033+ Type parameters = method .getType ().getParameter ();
20552034 Tuple <Identifier > lifetimes = method .getType ().getLifetimeParameters ();
20562035 name += getMangle (parameters , lifetimes );
20572036 } else if (!exported && decl instanceof Decl .Callable ) {
20582037 Decl .Callable callable = (Decl .Callable ) decl ;
2059- Tuple < Type > parameters = callable .getType ().getParameters ();
2038+ Type parameters = callable .getType ().getParameter ();
20602039 name += getMangle (parameters , new Tuple <>());
20612040 } else if (decl instanceof Decl .Type ) {
20622041 name += "$type" ;
@@ -2138,11 +2117,11 @@ private Term[] toLambdaArguments(Tuple<Decl.Variable> arguments) {
21382117 return results ;
21392118 }
21402119
2141- private String getMangle (Tuple < Type > types , Tuple <Identifier > lifetimes ) {
2142- if (types . size () == 0 ) {
2120+ private String getMangle (Type type , Tuple <Identifier > lifetimes ) {
2121+ if (type . shape () == 0 ) {
21432122 return "" ;
21442123 } else {
2145- return "$" + mangler .getMangle (types , lifetimes );
2124+ return "$" + mangler .getMangle (type , lifetimes );
21462125 }
21472126 }
21482127
0 commit comments