Skip to content

Commit 75d6ee4

Browse files
author
dlsmith
committed
DynamicJava: Implemented qualified super expressions (parsing and type checking). Fixed misc parser bugs. The parser (driven by SourceChecker) can now handle all of the drjava, dynamicjava, plt, and javalanglevels source files.
git-svn-id: file:///tmp/test-svn/trunk@4829 fe72c1cf-3628-48e9-8b72-1c46755d3cff
1 parent 128dfa5 commit 75d6ee4

File tree

16 files changed

+145
-120
lines changed

16 files changed

+145
-120
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ public Iterable<LocalFunction> getLocalFunctions(String name, TypeSystem ts, Ite
2525
public LocalVariable getLocalVariable(String name, TypeSystem ts) { return null; }
2626
public String getPackage() { return ""; }
2727
public Type getReturnType() { return null; }
28-
public Type getSuperType(TypeSystem ts) { return null; }
2928
public DJClass getThis() { return null; }
3029
public DJClass getThis(String className) { return null; }
3130
public DJClass getTopLevelClass(String name, TypeSystem ts) throws AmbiguousNameException { return null; }

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,4 @@ private boolean hasMethod(String name, TypeSystem ts) {
142142
*/
143143
@Override public Iterable<Type> getDeclaredThrownTypes() { return IterUtil.empty(); }
144144

145-
/**
146-
* Return the type referenced by {@code super} in the current context, or {@code null}
147-
* if there is no such type (for example, in a static context).
148-
*/
149-
@Override public Type getSuperType(TypeSystem ts) { return _c.immediateSuperclass(); }
150-
151145
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ public class CompositeException extends InterpreterException {
1212
private final SizedIterable<InterpreterException> _exceptions;
1313

1414
public CompositeException(Iterable<? extends InterpreterException> exceptions) {
15+
super(extractCause(exceptions));
1516
_exceptions = IterUtil.snapshot(exceptions);
1617
}
18+
19+
private static InterpreterException extractCause(Iterable<? extends InterpreterException> exceptions) {
20+
return IterUtil.isEmpty(exceptions) ? null : IterUtil.first(exceptions);
21+
}
1722

1823
public void printUserMessage(PrintWriter out) {
1924
out.println(_exceptions.size() + " errors:");

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,6 @@ public DJClass getThis(String className) {
208208
return _next.getThis(className);
209209
}
210210

211-
/**
212-
* Return the type referenced by {@code super} in the current context, or {@code null}
213-
* if there is no such type (for example, in a static context).
214-
*/
215-
public Type getSuperType(TypeSystem ts) {
216-
return _next.getSuperType(ts);
217-
}
218-
219211
/**
220212
* The expected type of a {@code return} statement in the given context, or {@code null}
221213
* if {@code return} statements should not appear here.

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

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ public void checkConstructorCall(ConstructorCall node) {
183183
Iterable<Type> targs = IterUtil.empty();
184184

185185
Type type;
186-
if (node.isSuper()) { type = context.getSuperType(ts); }
186+
if (node.isSuper()) { type = context.getThis().immediateSuperclass(); }
187187
else { type = SymbolUtil.thisType(context.getThis()); }
188188
if (type == null) {
189189
throw new IllegalArgumentException("Can't check a ConstructorCall in this context");
@@ -373,24 +373,28 @@ else if (ts.containsClass(classType, memberName.image())) {
373373
else { return setType(node, SymbolUtil.typeOfPrimitiveClass(node.getType())); }
374374
}
375375

376-
/**
377-
* Visits a ThisExpression
378-
* @return The type of this, according to the context.
379-
*/
380-
@Override public Type visit(ThisExpression node) {
381-
String name = node.getClassName();
382-
DJClass thisC;
383-
if (name.equals("")) {
384-
thisC = context.getThis();
385-
if (thisC == null) { throw new ExecutionError("this.undefined", node); }
376+
private DJClass resolveThis(Option<String> outerName, Node node) {
377+
DJClass result;
378+
if (outerName.isNone()) {
379+
result = context.getThis();
380+
if (result == null) { throw new ExecutionError("this.undefined", node); }
386381
}
387382
else {
388-
thisC = context.getThis(name);
389-
if (thisC == null) {
390-
setErrorStrings(node, name);
383+
result = context.getThis(outerName.unwrap());
384+
if (result == null) {
385+
setErrorStrings(node, outerName.unwrap());
391386
throw new ExecutionError("undefined.class", node);
392387
}
393388
}
389+
return result;
390+
}
391+
392+
/**
393+
* Visits a ThisExpression
394+
* @return The type of this, according to the context.
395+
*/
396+
@Override public Type visit(ThisExpression node) {
397+
DJClass thisC = resolveThis(node.getClassName(), node);
394398
setDJClass(node, thisC);
395399
return setType(node, SymbolUtil.thisType(thisC));
396400
}
@@ -473,7 +477,8 @@ else if (ts.containsClass(classType, memberName.image())) {
473477
* @return The type of the expression
474478
*/
475479
@Override public Type visit(SuperFieldAccess node) {
476-
Type t = context.getSuperType(ts);
480+
DJClass c = resolveThis(node.getClassName(), node);
481+
Type t = c.immediateSuperclass();
477482
if (t == null) {
478483
throw new ExecutionError("super.undefined", node);
479484
}
@@ -483,7 +488,7 @@ else if (ts.containsClass(classType, memberName.image())) {
483488
FieldReference ref = ts.lookupField(obj, node.getFieldName());
484489
// TODO: Check accessibility of field
485490
setField(node, ref.field());
486-
setDJClass(node, context.getThis());
491+
setDJClass(node, c);
487492
setVariableType(node, ref.type());
488493
Type result = ts.capture(ref.type());
489494
addRuntimeCheck(node, result, ref.field().type());
@@ -639,7 +644,8 @@ else if (ts.containsClass(classType, memberName.image())) {
639644
* @return The type of the expression
640645
*/
641646
@Override public Type visit(SuperMethodCall node) {
642-
Type t = context.getSuperType(ts);
647+
DJClass c = resolveThis(node.getClassName(), node);
648+
Type t = c.immediateSuperclass();
643649
if (t == null) {
644650
throw new ExecutionError("super.undefined", node);
645651
}
@@ -660,7 +666,7 @@ else if (ts.containsClass(classType, memberName.image())) {
660666
checkThrownExceptions(inv.thrown(), node);
661667
node.setArguments(CollectUtil.makeList(inv.args()));
662668
setMethod(node, inv.method());
663-
setDJClass(node, context.getThis());
669+
setDJClass(node, c);
664670
Type result = ts.capture(inv.returnType());
665671
debug.logValue("Type of method call " + node.getMethodName(), ts.wrap(result));
666672
addRuntimeCheck(node, result, inv.method().returnType());

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ private boolean isLocalFunction(String name) {
7979
else { return super.getThis(className); }
8080
}
8181

82-
@Override public Type getSuperType(TypeSystem ts) {
83-
if (isStatic()) { return null; }
84-
else { return super.getSuperType(ts); }
85-
}
86-
8782
@Override public Type getReturnType() {
8883
if (_f instanceof LocalFunction) { return ((LocalFunction) _f).returnType(); }
8984
else if (_f instanceof DJMethod) { return ((DJMethod) _f).returnType(); }

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,6 @@ public interface TypeContext {
135135
*/
136136
public DJClass getThis(String className);
137137

138-
/**
139-
* Return the type referenced by {@code super} in the current context, or {@code null}
140-
* if there is no such type (for example, in a static context).
141-
*/
142-
public Type getSuperType(TypeSystem ts);
143-
144138
/**
145139
* The expected type of a {@code return} statement in the given context, or {@code null}
146140
* if {@code return} statements should not appear here.

dynamicjava/src/edu/rice/cs/dynamicjava/sourcechecker/SourceChecker.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ public static void main(String... args) {
110110
new SourceChecker(opt).check(sources, cp);
111111
System.out.println("Completed checking successfully.");
112112
}
113-
catch (InterpreterException e) { e.printUserMessage(new PrintWriter(System.out, true)); }
113+
catch (InterpreterException e) {
114+
debug.log(e);
115+
e.printUserMessage(new PrintWriter(System.out, true));
116+
}
114117
}
115118

116119
}

dynamicjava/src/edu/rice/cs/dynamicjava/symbol/DJClass.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import edu.rice.cs.dynamicjava.symbol.type.Type;
44
import edu.rice.cs.dynamicjava.symbol.type.VariableType;
5+
import edu.rice.cs.plt.tuple.Option;
56

67
/** Represents a class declaration. */
78
public interface DJClass {
@@ -39,7 +40,7 @@ public interface DJClass {
3940

4041
/** List the declared supertypes of this class */
4142
public Iterable<Type> declaredSupertypes();
42-
43+
4344
public Iterable<DJField> declaredFields();
4445

4546
public Iterable<DJConstructor> declaredConstructors();

dynamicjava/src/koala/dynamicjava/parser/grammar.jj

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ public class Parser {
276276

277277
@Override public Primary dotThis(Option<List<TypeName>> targs, Token t) throws ParseException {
278278
if (targs.isNone()) {
279-
return new ExpressionPrimary(new ThisExpression(ids(), _range(this, t)));
279+
Option<String> cn = Option.some(TreeUtilities.listToName(ids()));
280+
return new ExpressionPrimary(new ThisExpression(cn, _range(this, t)));
280281
}
281282
else { return _throwParseException("Unexpected type arguments"); }
282283
}
@@ -480,7 +481,7 @@ public class Parser {
480481
class ThisExpressionPrimary extends CompletedPrimary {
481482
public ThisExpressionPrimary(Token t) { super(_range(t, t)); }
482483
public Expression asExpression() {
483-
return new ThisExpression(new LinkedList<IdentifierToken>(), getSourceInfo());
484+
return new ThisExpression(Option.<String>none(), getSourceInfo());
484485
}
485486
@Override public Primary withArgs(List<Expression> args, Token last) {
486487
return new ConstructorCallPrimary(new ConstructorCall(null, args, false, _range(this, last)));
@@ -511,8 +512,9 @@ public class Parser {
511512
_ids = ids;
512513
}
513514
@Override public Primary dotId(Option<List<TypeName>> targs, Token id) {
514-
if (targs.isNone()) { return new SuperFieldAccessPrimary(_ids, id, _range(this, id)); }
515-
else { return new PartialSuperMethodCallPrimary(_ids, targs, id, _range(this, id)); }
515+
Option<String> cn = (_ids == null) ? Option.<String>none() : Option.some(TreeUtilities.listToName(_ids));
516+
if (targs.isNone()) { return new SuperFieldAccessPrimary(cn, id, _range(this, id)); }
517+
else { return new PartialSuperMethodCallPrimary(cn, targs, id, _range(this, id)); }
516518
}
517519
@Override public Primary withArgs(List<Expression> args, Token last) {
518520
Expression outer = null;
@@ -548,20 +550,18 @@ public class Parser {
548550
* method arguments.
549551
*/
550552
class SuperFieldAccessPrimary extends CompletedPrimary {
551-
private final List<IdentifierToken> _className; // may be null
553+
private final Option<String> _className;
552554
private final String _name;
553-
public SuperFieldAccessPrimary(List<IdentifierToken> className, Token id, SourceInfo si) {
555+
public SuperFieldAccessPrimary(Option<String> className, Token id, SourceInfo si) {
554556
super(si);
555557
_className = className;
556558
_name = id.image;
557559
}
558560
public Expression asExpression() throws ParseException {
559-
if (_className != null) { return _throwParseException("Qualified super field accesses are not yet supported"); }
560-
return new SuperFieldAccess(_name, getSourceInfo());
561+
return new SuperFieldAccess(_className, _name, getSourceInfo());
561562
}
562563
@Override public Primary withArgs(List<Expression> args, Token last) throws ParseException {
563-
if (_className != null) { return _throwParseException("Qualified super method calls are not yet supported"); }
564-
return new ExpressionPrimary(new SuperMethodCall(_name, args, _range(this, last)));
564+
return new ExpressionPrimary(new SuperMethodCall(_className, _name, args, _range(this, last)));
565565
}
566566
}
567567

@@ -570,21 +570,24 @@ public class Parser {
570570
* a method name.
571571
*/
572572
class PartialSuperMethodCallPrimary extends Primary {
573-
private final List<IdentifierToken> _className; // may be null
573+
private final Option<String> _className;
574574
private final Option<List<TypeName>> _targs;
575575
private final String _name;
576-
PartialSuperMethodCallPrimary(List<IdentifierToken> className, Option<List<TypeName>> targs, Token id,
576+
PartialSuperMethodCallPrimary(Option<String> className, Option<List<TypeName>> targs, Token id,
577577
SourceInfo si) {
578578
super(si);
579579
_className = className;
580580
_targs = targs;
581581
_name = id.image;
582582
}
583583
@Override public Primary withArgs(List<Expression> args, Token last) throws ParseException {
584-
if (_className != null) { _throwParseException("Qualified super method calls are not yet supported"); }
585584
SourceInfo si = _range(this, last);
586-
if (_targs.isNone()) { return new ExpressionPrimary(new SuperMethodCall(_name, args, si)); }
587-
else { return new ExpressionPrimary(new PolymorphicSuperMethodCall(_name, args, _targs.unwrap(), si)); }
585+
if (_targs.isNone()) {
586+
return new ExpressionPrimary(new SuperMethodCall(_className, _name, args, si));
587+
}
588+
else {
589+
return new ExpressionPrimary(new PolymorphicSuperMethodCall(_className, _name, args, _targs.unwrap(), si));
590+
}
588591
}
589592
}
590593

@@ -1721,7 +1724,7 @@ PARSER_END(Parser)
17211724
( "[" "]" { dim++; } )*
17221725
[ "throws" exceptions=ReferenceTypeNameList() ]
17231726
(
1724-
LOOKAHEAD({ !level.equals(DeclType.INTERFACE_MEMBER) }) body=block()
1727+
body=block()
17251728
| ";"
17261729
)
17271730
{
@@ -1748,11 +1751,11 @@ PARSER_END(Parser)
17481751
}
17491752

17501753
if (typeParameters == null) {
1751-
return new MethodDeclaration(mods, typ, id.image, params, exceptions, body, _range(mods, body));
1754+
return new MethodDeclaration(mods, typ, id.image, params, exceptions, body, _range(mods, token));
17521755
}
17531756
else {
17541757
return new PolymorphicMethodDeclaration(mods, typ, id.image, params, exceptions, body, typeParameters,
1755-
_range(mods, body));
1758+
_range(mods, token));
17561759
}
17571760
}
17581761
}
@@ -1985,6 +1988,7 @@ PARSER_END(Parser)
19851988
node = unmodifiedTypeDeclaration(mods, DeclType.INTERFACE_MEMBER)
19861989
| LOOKAHEAD(methodLookahead()) node=unmodifiedMethodDeclaration(mods, DeclType.INTERFACE_MEMBER)
19871990
| LOOKAHEAD(variableLookahead()) list=unmodifiedVariableDeclaration(mods, DeclType.INTERFACE_MEMBER)
1991+
| ";"
19881992
)
19891993
{
19901994
if (node != null) { list.add(node); }
@@ -2051,8 +2055,7 @@ PARSER_END(Parser)
20512055
}
20522056
{
20532057
[ consts = enumConstants() ]
2054-
";"
2055-
( ns = classBodyDeclaration() { decls.addAll(ns); } )*
2058+
[";" ( ns = classBodyDeclaration() { decls.addAll(ns); } )* ]
20562059
{
20572060
return new EnumDeclaration.EnumBody((consts==null) ? new LinkedList<EnumDeclaration.EnumConstant>() : consts,
20582061
decls);

0 commit comments

Comments
 (0)