Skip to content

Commit eef3210

Browse files
author
dlsmith
committed
DynamicJava: fixed broken final variable mutation check (was allowing some incorrect code and rejecting good code) internal failures when constructing error messages are more cleanly handled
git-svn-id: file:///tmp/test-svn/trunk@5080 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent 17b59cf commit eef3210

File tree

14 files changed

+34
-121
lines changed

14 files changed

+34
-121
lines changed

dynamicjava/src/edu/rice/cs/dynamicjava/DynamicJava.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static void main(String... args) throws IOException {
3333
catch (InterpreterException e) { e.printUserMessage(); debug.log(e); }
3434
catch (RuntimeException e) {
3535
System.out.println("INTERNAL ERROR: Uncaught exception");
36-
e.printStackTrace();
36+
e.printStackTrace(System.out);
3737
}
3838
System.out.println();
3939
}

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/BaseContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public Iterable<LocalFunction> getLocalFunctions(String name, TypeSystem ts, Ite
3737
public TypeContext importStaticMembers(DJClass c) { throw new UnsupportedOperationException(); }
3838
public TypeContext importTopLevelClass(DJClass c) { throw new UnsupportedOperationException(); }
3939
public TypeContext importTopLevelClasses(String pkg) { throw new UnsupportedOperationException(); }
40+
public boolean inConstructorBody() { return false; }
4041
public boolean localFunctionExists(String name, TypeSystem ts) { return false; }
4142
public boolean localVariableExists(String name, TypeSystem ts) { return false; }
4243
public String makeAnonymousClassName() { throw new UnsupportedOperationException(); }

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/ClassChecker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@ else if (!mods.isAbstract() && node.getBody() == null) {
263263
@Override public Void visit(ConstructorDeclaration node) {
264264
DJConstructor k = getConstructor(node);
265265
if (_c.isAnonymous() || !_c.declaredName().equals(node.getName())) {
266-
setErrorStrings(node, SymbolUtil.shortName(_c));
267-
throw new ExecutionError("constructor.name");
266+
setErrorStrings(node, node.getName());
267+
throw new ExecutionError("constructor.name", node);
268268
}
269269

270270
TypeContext sigContext = new FunctionSignatureContext(_bodyContext, k);

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/ClassContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ private boolean hasMethod(String name, TypeSystem ts) {
141141
else { return super.getThis(expected, ts); }
142142
}
143143

144+
@Override public boolean inConstructorBody() { return false; }
145+
144146
/**
145147
* The expected type of a {@code return} statement in the given context, or {@code null}
146148
* if {@code return} statements should not appear here.

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/DelegatingContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ public DJClass getThis(String className) {
210210

211211
public DJClass getThis(Type expected, TypeSystem ts) { return _next.getThis(expected, ts); }
212212

213+
public boolean inConstructorBody() { return _next.inConstructorBody(); }
214+
213215
/**
214216
* The expected type of a {@code return} statement in the given context, or {@code null}
215217
* if {@code return} statements should not appear here.

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/ExpressionChecker.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,12 @@ private class ExpressionVisitor extends AbstractVisitor<Type> implements Lambda<
343343
Expression resolvedExp = (Expression) resolved;
344344
resolvedExp.acceptVisitor(this);
345345
setTranslation(node, resolvedExp);
346-
// VARIABLE_TYPE and TYPE properties are important in the enclosing context; others
347-
// (such as FIELD) are not, and need not be copied to the AmbiguousName
346+
// VARIABLE_TYPE, TYPE, FIELD, and VARIABLE properties are important in the enclosing context;
347+
// others are not, and need not be copied to the AmbiguousName
348348
if (hasVariableType(resolvedExp)) { setVariableType(node, getVariableType(resolvedExp)); }
349349
if (hasValue(resolvedExp)) { setValue(node, getValue(resolvedExp)); }
350+
if (hasField(resolvedExp)) { setField(node, getField(resolvedExp)); }
351+
if (hasVariable(resolvedExp)) { setVariable(node, getVariable(resolvedExp)); }
350352
return setType(node, getType(resolvedExp));
351353
}
352354
}
@@ -1654,9 +1656,15 @@ private Type handleBooleanExpression(BinaryExpression node) {
16541656
if (!hasVariableType(left)) {
16551657
throw new ExecutionError("left.expression", node);
16561658
}
1657-
if (hasVariable(left) && getVariable(left).isFinal() ||
1658-
hasField(left) && getField(left).isFinal()) {
1659-
throw new ExecutionError("cannot.modify", node);
1659+
if (!context.inConstructorBody()) {
1660+
if (hasVariable(left) && getVariable(left).isFinal()) {
1661+
setErrorStrings(node, getVariable(left).declaredName());
1662+
throw new ExecutionError("cannot.modify", node);
1663+
}
1664+
else if (hasField(left) && getField(left).isFinal()) {
1665+
setErrorStrings(node, getField(left).declaredName());
1666+
throw new ExecutionError("cannot.modify", node);
1667+
}
16601668
}
16611669

16621670
Type target = getVariableType(left);

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/FunctionContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ private boolean isLocalFunction(String name) {
8484
else { return super.getThis(expected, ts); }
8585
}
8686

87+
@Override public boolean inConstructorBody() { return _f instanceof DJConstructor; }
88+
8789
@Override public Type getReturnType() {
8890
if (_f instanceof LocalFunction) { return ((LocalFunction) _f).returnType(); }
8991
else if (_f instanceof DJMethod) { return ((DJMethod) _f).returnType(); }

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/StatementChecker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ private ClassType resolveClassName(String name, Node node) {
253253
catch (InvalidTypeArgumentException e) { throw new RuntimeException("can't create raw type"); }
254254
catch (UnmatchedLookupException e) {
255255
setErrorStrings(node, piece);
256-
if (e.matches() > 1) { throw new ExecutionError("ambiguous.inner.class"); }
256+
if (e.matches() > 1) { throw new ExecutionError("ambiguous.inner.class", node); }
257257
else { throw new ExecutionError("no.such.inner.class", node); }
258258
}
259259
}

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/TopLevelContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ protected TypeContext duplicate(TypeContext next) {
349349

350350
@Override public DJClass getThis(Type expected, TypeSystem ts) { return null; }
351351

352+
@Override public boolean inConstructorBody() { return false; }
353+
352354
/**
353355
* The expected type of a {@code return} statement in the given context, or {@code null}
354356
* if {@code return} statements should not appear here.

dynamicjava/src/edu/rice/cs/dynamicjava/interpreter/TypeContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ public interface TypeContext {
141141
*/
142142
public DJClass getThis(Type expected, TypeSystem ts);
143143

144+
/** Whether this is immediately within a constructor body. */
145+
public boolean inConstructorBody();
146+
144147
/**
145148
* The expected type of a {@code return} statement in the given context, or {@code null}
146149
* if {@code return} statements should not appear here.

0 commit comments

Comments
 (0)