Skip to content

Commit 05165ac

Browse files
committed
Merge branch 'feature/975-tuples' into develop
2 parents cfbf115 + 6bb6951 commit 05165ac

33 files changed

+239
-1914
lines changed

src/main/java/wyjs/io/JavaScriptFileWriter.java

Lines changed: 0 additions & 1747 deletions
This file was deleted.

src/main/java/wyjs/tasks/JavaScriptCompiler.java

Lines changed: 61 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static wyil.lang.WyilFile.EXPR_arrayaccess;
88
import static wyil.lang.WyilFile.EXPR_arrayborrow;
99
import static wyil.lang.WyilFile.EXPR_dereference;
10+
import static wyil.lang.WyilFile.EXPR_fielddereference;
1011
import static wyil.lang.WyilFile.EXPR_recordaccess;
1112
import static wyil.lang.WyilFile.EXPR_recordborrow;
1213
import 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

Comments
 (0)