00001
00005 package edu.mit.csail.sdg.squander.spec;
00006
00007 import static edu.mit.csail.sdg.squander.parser.JFSLParser.FRAME_ALL;
00008 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_AND;
00009 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_BIT_AND_OR_INTERSECTION;
00010 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_BIT_NOT_OR_TRANSPOSE;
00011 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_BIT_OR;
00012 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_BIT_XOR;
00013 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_CLOSURE;
00014 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_DIFFERENCE;
00015 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_DIVIDE;
00016 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_EQ;
00017 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_EQUIV;
00018 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_GEQ;
00019 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_GT;
00020 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_IMPLIES;
00021 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_INTERSECTION;
00022 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_LEQ;
00023 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_LT;
00024 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_MINUS;
00025 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_MINUS_OR_DIFFERENCE;
00026 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_MOD;
00027 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_NEQ;
00028 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_NEQUIV;
00029 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_NOT;
00030 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_NSET_SUBSET;
00031 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_OR;
00032 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_PLUS;
00033 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_PLUS_OR_UNION;
00034 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_RELATIONAL_COMPOSE;
00035 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_RELATIONAL_OVERRIDE;
00036 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_ALL;
00037 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_COMPREHENSION;
00038 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_EXISTS;
00039 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_LONE;
00040 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_NO;
00041 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_NUM;
00042 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_ONE;
00043 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_SOME;
00044 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_SUBSET;
00045 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SET_SUM;
00046 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SHL;
00047 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_SHR;
00048 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_TIMES;
00049 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_TRANSPOSE;
00050 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_UNION;
00051 import static edu.mit.csail.sdg.squander.parser.JFSLParser.OP_USHR;
00052
00053 import java.lang.reflect.Array;
00054 import java.util.ArrayList;
00055 import java.util.Arrays;
00056 import java.util.LinkedList;
00057 import java.util.List;
00058
00059 import edu.mit.csail.sdg.squander.parser.JFSLParser;
00060 import edu.mit.csail.sdg.squander.parser.JFSLParserException;
00061 import edu.mit.csail.sdg.squander.parser.JFSLParser.Decision;
00062 import edu.mit.csail.sdg.squander.parser.JFSLParser.Node;
00063 import edu.mit.csail.sdg.squander.spec.JType.Factory;
00064 import edu.mit.csail.sdg.squander.spec.JType.Unary;
00065 import edu.mit.csail.sdg.squander.spec.constant.ConstRel;
00066 import edu.mit.csail.sdg.squander.spec.constant.ConstRels;
00067 import edu.mit.csail.sdg.squander.utils.ReflectionUtils;
00068
00069
00099 public class TypeChecker extends Visitor<JType, NameSpace> {
00100
00101 protected final JavaScene scene;
00102
00107 private ClassSpec clsSpec;
00108
00116 public TypeChecker(JavaScene scene) {
00117 this.scene = scene;
00118 }
00119
00126 public void setClsSpecForSpecField(ClassSpec clsSpec) {
00127 this.clsSpec = clsSpec;
00128 }
00129
00130 @Override
00131 protected void validate(Node tree, JType type) {
00132 super.validate(tree, type);
00133 tree.setJType(type);
00134 }
00135
00136
00137
00138
00139
00140 protected void checkSubtype(String expr, JType sub, JType supr) throws TypeCheckException {
00141 checkArity(expr, sub, supr);
00142 for (int i = 0; i < sub.arity(); i++) {
00143 Unary t1 = supr.projection(i);
00144 Unary t2 = sub.projection(i);
00145 if (!t1.isAssignableFrom(t2) && !t2.isAssignableFrom(t1))
00146 throw new IncompatibleTypesException(sub, supr, i, expr);
00147 }
00148 }
00149
00150 protected void checkJoin(JType primary, JType rest) throws TypeCheckException {
00151 JType.Unary t1 = primary.projection(primary.arity() - 1);
00152 JType.Unary t2 = rest.projection(0);
00153 if (!t1.isAssignableFrom(t2) && !t2.isAssignableFrom(t1))
00154 throw new IncompatibleTypesException(t1, t2, -1, "");
00155 }
00156
00157 protected void checkArity(String inExpr, JType ... expressions) throws TypeCheckException {
00158 int i = -1;
00159 for (JType expr : expressions) {
00160 if (i == -1)
00161 i = expr.arity();
00162 else if (i != expr.arity())
00163 throw new ArityMismatchException(i, expr.arity(), Arrays.toString(expressions) + "\nin expression " + inExpr);
00164 }
00165 }
00166
00167 protected void checkBoolean(JType expr, Node node) throws TypeCheckException {
00168 if (!expr.isBoolean())
00169 throw new TypeCheckException("expected a boolean expression, actual: " + expr,
00170 node.toStringTree());
00171 }
00172
00173 protected void checkInteger(JType expr, Node node) throws TypeCheckException {
00174 if (!expr.isInteger())
00175 throw new TypeCheckException("expected an integer expression, actual: " + expr,
00176 node.toStringTree());
00177 }
00178
00179 protected void checkUnary(JType expr, Node node) throws TypeCheckException {
00180 if (expr.arity() != 1)
00181 throw new TypeCheckException("expected a unary type, actual: " + expr,
00182 node.toStringTree());
00183 }
00184
00189 @Override
00190 protected JType visitArgument(NameSpace env, int i) {
00191 JMethod root = env.method();
00192 if (root == null) throw new TypeCheckException("no parameters in the context");
00193 if (i >= 0 && i < root.paramTypes().size())
00194 return root.paramTypes().get(i);
00195 else
00196 throw new TypeCheckException("procedure has no " + i + "th argument");
00197 }
00198
00199 @Override
00200 protected JType visitBracket(NameSpace env, JType primary, Node tree) {
00201 final Node selector = child(tree);
00202 final JType expr = visit(env, selector);
00203
00204 env = env.addScope(primary.range());
00205
00206
00207 if (primary.arity() == 1 && env.inArray()) {
00208 tree.setFlag(true);
00209 checkInteger(expr, selector);
00210 return Factory.instance.newJType(env.scope().domain().clazz().getComponentType());
00211 } else {
00212 tree.setFlag(false);
00213 return expr.join(primary);
00214 }
00215 }
00216
00217 @Override
00218 protected JType visitJoin(NameSpace env, JType primary, Node tree) {
00219 JType rest = visit(env.addScope(primary.range()), child(tree));
00220 checkJoin(primary, rest);
00221 return primary.join(rest);
00222 }
00223
00224 @Override
00225 protected JType visitJoinReflexive(NameSpace env, JType primary, Node tree) {
00226 final JType relation = visit(env.addScope(primary.range()), child(tree));
00227
00228 if (relation.arity() != 2)
00229 throw new TypeCheckException("reflexive transitive join expects a relation of arity 2",
00230 tree.toStringTree());
00231
00232 return primary.union(primary.join(relation));
00233 }
00234
00235 @Override
00236 protected JType visitMethodCall(NameSpace env, JType receiver, String name, Node arguments) {
00237 throw new RuntimeException("method calls not supported");
00238 }
00239
00240 @Override
00241 protected JType visitBinary(NameSpace env, Node tree, int op, Node leftTree, Node rightTree) {
00242 final JType result;
00243 final JType left = visit(env, leftTree);
00244 final JType right = visit(env, rightTree);
00245
00246 final String expr = leftTree.toStringTree() + op + rightTree.toStringTree();
00247
00248 switch (op) {
00249 case OP_SHL:
00250 case OP_SHR:
00251 case OP_USHR:
00252 case OP_PLUS:
00253 case OP_MINUS:
00254 case OP_TIMES:
00255 case OP_DIVIDE:
00256 case OP_MOD:
00257 case OP_BIT_XOR:
00258 case OP_BIT_OR:
00259 checkInteger(left, leftTree);
00260 checkInteger(right, rightTree);
00261 result = Factory.instance.integerType();
00262 break;
00263
00264 case OP_LT:
00265 case OP_GT:
00266 case OP_LEQ:
00267 case OP_GEQ:
00268 checkInteger(left, leftTree);
00269 checkInteger(right, rightTree);
00270 result = Factory.instance.booleanType();
00271 break;
00272
00273 case OP_OR:
00274 case OP_AND:
00275 case OP_EQUIV:
00276 case OP_NEQUIV:
00277 case OP_IMPLIES:
00278 checkBoolean(left, leftTree);
00279 checkBoolean(right, rightTree);
00280 result = Factory.instance.booleanType();
00281 break;
00282
00283 case OP_EQ:
00284 case OP_NEQ:
00285 checkSubtype(expr, right, left);
00286 result = Factory.instance.booleanType();
00287 break;
00288 case OP_SET_SUBSET:
00289 case OP_NSET_SUBSET:
00290 checkSubtype(expr, left, right);
00291 result = Factory.instance.booleanType();
00292 break;
00293
00294 case OP_RELATIONAL_OVERRIDE:
00295 result = left.union(right);
00296 break;
00297 case OP_RELATIONAL_COMPOSE:
00298 result = left.product(right);
00299 break;
00300
00301 case OP_INTERSECTION:
00302 result = left.intersection(right);
00303 break;
00304 case OP_UNION:
00305 result = left.union(right);
00306 break;
00307 case OP_DIFFERENCE:
00308 result = left.difference(right);
00309 break;
00310
00311 case OP_PLUS_OR_UNION:
00312 if (left.isInteger() && right.isInteger())
00313 tree.setFlag(true);
00314 else
00315 tree.setFlag(false);
00316 result = tree.flag() ? Factory.instance.integerType() : left.union(right);
00317 break;
00318 case OP_MINUS_OR_DIFFERENCE:
00319 if (left.isInteger() && right.isInteger())
00320 tree.setFlag(true);
00321 else
00322 tree.setFlag(false);
00323 result = tree.flag() ? Factory.instance.integerType() : left.difference(right);
00324 break;
00325 case OP_BIT_AND_OR_INTERSECTION:
00326 if (left.isInteger() && right.isInteger())
00327 tree.setFlag(true);
00328 else
00329 tree.setFlag(false);
00330 result = tree.flag() ? Factory.instance.integerType() : left.intersection(right);
00331 break;
00332 default:
00333 result = null;
00334 }
00335
00336 return result;
00337 }
00338
00339 @Override
00340 protected JType visitConditional(NameSpace env, Node condTree, Node leftTree, Node rightTree) {
00341 JType cond = visit(env, condTree);
00342 JType left = visit(env, leftTree);
00343 JType right = visit(env, rightTree);
00344 checkBoolean(cond, condTree);
00345 return left.union(right);
00346 }
00347
00348 @Override
00349 protected JType visitDecimal(NameSpace env, int i) {
00350 return Factory.instance.integerType();
00351 }
00352
00353 @Override
00354 protected JType visitString(NameSpace env, String s) {
00355 return Factory.instance.newJType(String.class);
00356 }
00357
00358 @Override
00359 protected JType visitFalse(NameSpace env) {
00360 return Factory.instance.booleanType();
00361 }
00362
00363 @Override
00364 protected JType visitNull(NameSpace env) {
00365 return Factory.instance.newJType(Null.class);
00366 }
00367
00368 @Override
00369 protected JType visitOld(NameSpace env, Node sub) {
00370 return visit(env, sub);
00371 }
00372
00373 @Override
00374 protected JType visitQuantification(NameSpace env, int op, List<String> names, List<String> mults, List<Node> sets, Node expr) {
00375 final List<JType> decls = new ArrayList<JType>();
00376 for (int i = 0; i < names.size(); i++) {
00377 JType type = visit(env, sets.get(i));
00378 decls.add(type);
00379 checkUnary(type, sets.get(i));
00380 env = env.addLocal(names.get(i), type.domain());
00381 }
00382
00383 switch (op) {
00384 case OP_SET_ALL:
00385 case OP_SET_EXISTS:
00386 case OP_SET_SOME:
00387 case OP_SET_ONE:
00388 case OP_SET_LONE:
00389 case OP_SET_NO:
00390 checkBoolean(visit(env, expr), expr);
00391 return Factory.instance.booleanType();
00392 case OP_SET_NUM:
00393 checkBoolean(visit(env, expr), expr);
00394 return Factory.instance.integerType();
00395 case OP_SET_SUM:
00396 checkInteger(visit(env, expr), expr);
00397 return Factory.instance.integerType();
00398 case OP_SET_COMPREHENSION:
00399 checkBoolean(visit(env, expr), expr);
00400 JType type = decls.get(0);
00401 for (int i = 1; i < decls.size(); i++)
00402 type = type.product(decls.get(i));
00403 return type;
00404 default:
00405 return null;
00406 }
00407 }
00408
00409 @Override
00410 protected JType visitReturn(NameSpace env) {
00411 return env.method().returnType();
00412 }
00413
00414 @Override
00415 protected JType visitThrow(NameSpace env) {
00416 throw new UnsupportedOperationException();
00417 }
00418
00419 @Override
00420 protected JType visitSuper(NameSpace env) {
00421 throw new UnsupportedOperationException();
00422 }
00423
00424 @Override
00425 protected JType visitThis(NameSpace env) {
00426 JType type = env.declarer();
00427 JMethod m = env.method();
00428 if (m != null && m.isStatic())
00429 throw new TypeCheckException("no \"this\" variable in the context");
00430 return type;
00431 }
00432
00433 @Override
00434 protected JType visitTrue(NameSpace env) {
00435 return Factory.instance.booleanType();
00436 }
00437
00438 @Override
00439 protected JType visitUnary(NameSpace env, Node tree, int op, Node expr) {
00440 final JType sub = visit(env, expr);
00441 final JType result;
00442
00443 switch (op) {
00444 case OP_PLUS:
00445 case OP_MINUS:
00446 checkInteger(sub, expr);
00447 result = sub;
00448 break;
00449 case OP_NOT:
00450 checkBoolean(sub, expr);
00451 result = sub;
00452 break;
00453
00454 case OP_SET_SOME:
00455 case OP_SET_NO:
00456 case OP_SET_ONE:
00457 case OP_SET_LONE:
00458 result = Factory.instance.booleanType();
00459 break;
00460 case OP_SET_NUM:
00461 result = Factory.instance.integerType();
00462 break;
00463
00464 case OP_SET_SUM:
00465 checkInteger(sub, expr);
00466 result = Factory.instance.integerType();
00467 break;
00468
00469 case OP_CLOSURE:
00470 result = sub;
00471 break;
00472 case OP_TRANSPOSE:
00473 result = sub.transpose();
00474 break;
00475
00476 case OP_BIT_NOT_OR_TRANSPOSE:
00477 if (sub.isInteger())
00478 tree.setFlag(true);
00479 else
00480 tree.setFlag(false);
00481 result = tree.flag() ? Factory.instance.integerType() : sub.transpose();
00482 break;
00483 default:
00484 result = null;
00485 }
00486
00487 return result;
00488 }
00489
00490 @Override
00491 protected JType visitFieldDeclaration(NameSpace env, Node ident, int op, Node set, Node frame, Node constraint) {
00492
00493 JType declType = visit(env, set);
00494 String fldName = asText(ident);
00495 if (clsSpec != null) {
00496 clsSpec.addSpecField(JField.newSpecField(fldName, getFldOwner(fldName), clsSpec.jtype(), declType));
00497 }
00498
00499
00500 if (frame != null) visit(env, frame);
00501
00502
00503 if (constraint != null) checkBoolean(visit(env, constraint), constraint);
00504
00505
00506 return Factory.instance.booleanType();
00507 }
00508
00509 private JType.Unary getFldOwner(String fldName) {
00510 Unary declarer = clsSpec.jtype();
00511
00512 List<Class<?>> parents = new LinkedList<Class<?>>();
00513 parents.addAll(ReflectionUtils.getImmParents(clsSpec.clz()));
00514 while (!parents.isEmpty()) {
00515 Class<?> p = parents.remove(0);
00516 JType.Unary jp = Factory.instance.newJType(p, clsSpec.typeParams());
00517 if (scene.ensureClass(jp).hasSpecField(fldName))
00518 declarer = jp;
00519 parents.addAll(ReflectionUtils.getImmParents(p));
00520 }
00521 return declarer;
00522 }
00523
00524 @Override
00525 protected JType visitCastExpression(NameSpace env, Node type, Node sub) {
00526 visit(env, sub);
00527 return visit(env, type);
00528 }
00529
00530 @Override
00531 protected JType visitFieldRelation(NameSpace env, Node type, Node ident) {
00532 final JType expr = visit(env, type);
00533 final JType result = resolveField(env.addScope(expr.range()), ident);
00534 return result;
00535 }
00536
00537 @Override
00538 protected JType visitFrame(NameSpace env, List<JType> joins, List<Node> fields, List<JType> selectors, List<JType> lowers, List<JType> uppers) {
00539 for (int i = 0; i < joins.size(); i++) {
00540 final Node field = fields.get(i);
00541 final JType type = joins.get(i);
00542 if (type.arity() != 1)
00543 throw new TypeCheckException("frame location LHS expression has arity greater than 1: " + type + " " + field.toStringTree());
00544
00545 if (field.getType() == FRAME_ALL) {
00546 field.setJType(type);
00547 } else {
00548 JType selector = resolveField(env.addScope(type.range()), field);
00549 if (selector == null)
00550 throw new TypeCheckException("frame location selector cannot be resolved");
00551 JType sub = selectors.get(i);
00552 if (sub != null) {
00553 if (!sub.isSubtypeOf(selector.domain()))
00554 throw new TypeCheckException("frame instance selector should be of type "
00555 + selector.domain() + "; actual instance selector type: " + sub);
00556 }
00557 JType lower = lowers.get(i);
00558 if (lower != null) {
00559 JType dom = selector;
00560 if (!lower.isSubtypeOf(dom))
00561 throw new TypeCheckException("frame lower bound should be of type "
00562 + dom + "; actual instance selector type: " + lower);
00563 }
00564 JType upper = uppers.get(i);
00565 if (upper != null) {
00566 JType dom = selector.projectionFromTo(1, selector.arity() - 1);
00567 if (!upper.isSubtypeOf(dom))
00568 throw new TypeCheckException("frame upper bound should be of type "
00569 + dom + "; actual instance selector type: " + upper);
00570 }
00571 }
00572 }
00573 return Factory.instance.booleanType();
00574 }
00575
00576 @Override
00577 protected JType visitArrayType(NameSpace env, Node base) {
00578 final JType sub = visit(env, base);
00579 checkUnary(sub, base);
00580 return Factory.instance.newJType(Array.newInstance(sub.domain().clazz(), 0).getClass());
00581 }
00582
00583 @Override
00584 protected JType visitBooleanType(NameSpace env) {
00585 return Factory.instance.booleanType();
00586 }
00587
00588 @Override
00589 protected JType visitIntegralType(NameSpace env) {
00590 return Factory.instance.integerType();
00591 }
00592
00593 @Override
00594 protected JType visitRefType(NameSpace env, Node source, List<Node> idents) {
00595 StringBuilder sb = new StringBuilder();
00596 boolean first = true;
00597 for (Node node : idents) {
00598 if (first)
00599 first = false;
00600 else
00601 sb.append('.');
00602 sb.append(asText(node));
00603 }
00604 JType t = resolveType(env, sb.toString());
00605 scene.ensureClass(t.range());
00606 return t;
00607 }
00608
00609
00624 @Override
00625 public JType visitAmbiguous(NameSpace env, List<Node> idents) {
00626 int i = 0;
00627 StringBuilder sb = new StringBuilder();
00628 sb.append(asText(idents.get(0)));
00629 JType primary = visitName(env, idents.get(0));
00630
00631
00632 if (primary == null) {
00633 while (primary == null && i < idents.size() - 1) {
00634 i++;
00635 idents.get(i).setDecision(Decision.FRAGMENT);
00636 sb.append(".").append(asText(idents.get(i)));
00637 primary = resolveType(env, sb.toString());
00638 }
00639 if (primary != null) {
00640 idents.get(0).setDecision(Decision.TYPE);
00641 } else {
00642 throw new RuntimeException("unresolved string: " + sb);
00643 }
00644 }
00645
00646 idents.get(0).jtype = primary;
00647 if (i < idents.size() - 1 && idents.get(i+1).token.getType() == JFSLParser.TYPE_PARAMETERS) {
00648 Node nextChild = idents.get(i+1);
00649 JType.Unary[] typeParams = visitTypeParams(env, nextChild);
00650 idents.get(0).jtype = setTypeParams(primary, typeParams);
00651 nextChild.setDecision(Decision.FRAGMENT);
00652 i++;
00653 }
00654 scene.ensureClass(idents.get(0).jtype.range());
00655
00656
00657 if (i == idents.size() - 1)
00658 return idents.get(0).jtype;
00659 else {
00660
00661 NameSpace extended = env.addScope(primary.range());
00662 List<Node> rest = idents.subList(i + 1, idents.size());
00663 JType selector = visitAmbiguous(extended, rest);
00664 try {
00665 return primary.join(selector);
00666 } catch (AssertionError e) {
00667 String msg = e.getMessage();
00668 msg = msg + "\nlhs = " + idents.get(0).toStringTree() + "\nrhs = " + print(rest);
00669 JFSLParserException ex = new JFSLParserException(msg, e);
00670 throw ex;
00671 }
00672 }
00673
00674 }
00675
00676 private String print(List<Node> rest) {
00677 String ret = "";
00678 for (Node n : rest) {
00679 ret = ret + n.toStringTree() + " JOIN ";
00680 }
00681 return ret.substring(0, ret.length() - 6);
00682 }
00683
00684 private JType setTypeParams(JType primary, JType.Unary[] typeParams) {
00685 List<Unary> result = new ArrayList<Unary>(primary.arity());
00686 for (int i = 0; i < primary.arity(); i++) {
00687 Unary t = primary.projection(i);
00688 if (i == primary.arity() - 1)
00689 result.add(Factory.instance.newJType(t.clazz(), typeParams));
00690 else
00691 result.add(t);
00692 }
00693 return Factory.instance.newJType(result);
00694 }
00695
00696 private JType.Unary[] visitTypeParams(NameSpace env, Node node) {
00697 List<Node> children = children(node);
00698 JType.Unary[] result = new JType.Unary[children.size()];
00699 int idx = 0;
00700 for (Node n : children) {
00701 result[idx++] = (Unary) visit(env, n);
00702 }
00703 return result;
00704 }
00705
00706 @Override
00707 public JType visitName(NameSpace env, Node ident) {
00708 String text = asText(ident);
00709
00710
00711 JType localType = env.findLocal(text);
00712 if (localType != null) {
00713 ident.setDecision(Decision.LOCAL);
00714 return localType;
00715 }
00716
00717
00718 JType fieldType = resolveField(env, ident);
00719 if (fieldType != null)
00720 return fieldType;
00721
00722
00723 JType type = resolveType(env, text);
00724 if (type != null) {
00725 assert type.isUnary();
00726 ident.setDecision(Decision.TYPE);
00727 scene.ensureClass(type.range());
00728 return type;
00729 }
00730
00731
00732 ConstRel constRel = ConstRels.findRel(text);
00733 if (constRel != null) {
00734 ident.setDecision(Decision.CONST);
00735 return constRel.type();
00736 }
00737
00738 return null;
00739 }
00740
00741 public static void main(String[] args) {
00742
00743 }
00744
00748 private JType resolveField(NameSpace env, Node tree) {
00749 String text = asText(tree);
00750 JField field = env.findField(text, scene);
00751 if (field != null) {
00752 tree.setDecision(Decision.GLOBAL);
00753 tree.field = field;
00754
00755 JType value = field.type();
00756 if (field.isStatic())
00757 return value;
00758 else
00759 return field.declaringType().product(value);
00760 }
00761 return null;
00762 }
00763
00764 private JType resolveType(NameSpace env, String name) {
00765 if (env.declarer() == null || env.declarer().arity() > 1)
00766 return null;
00767 JType.Unary parent = env.declarer().domain();
00768 Class<?> candidate;
00769
00770
00771
00772 candidate = getClass(name);
00773
00774 if (candidate == null && parent.clazz().getPackage() != null)
00775 candidate = getClass(parent.clazz().getPackage().getName() + "." + name);
00776
00777 if (candidate == null)
00778 candidate = getClass(parent.clazz().getName() + "$" + name);
00779
00780 Class<?> sc = parent.clazz().getSuperclass();
00781 while (candidate == null && sc != null) {
00782 candidate = getClass(sc.getName() + "$" + name);
00783 sc = sc.getSuperclass();
00784 }
00785
00786 if (candidate == null)
00787 if (parent.clazz().getSimpleName().equals(name))
00788 candidate = parent.clazz();
00789
00790 if (candidate == null)
00791 if (parent.clazz().getDeclaringClass() != null)
00792 candidate = getClass(parent.clazz().getDeclaringClass().getName() + "$" + name);
00793
00794 if (candidate == null)
00795 candidate = getClass("java.lang." + name);
00796
00797 if (candidate != null) {
00798
00799 return Factory.instance.newJType(candidate);
00800 }
00801
00802
00803 return null;
00804 }
00805
00806 private Class<?> getClass(String name) {
00807 try {
00808 return Class.forName(name);
00809 } catch (ClassNotFoundException e) {
00810 return null;
00811 }
00812 }
00813
00814 }