@Override public Map<String, TypedAST> getChildren() { Map<String, TypedAST> children = new HashMap<>(); for (Case c : cases) { // is there a proper convention for names in children? children.put("match case: " + c.getTaggedTypeMatch(), c.getAST()); } if (defaultCase != null) { children.put("match default-case: " + defaultCase.getTaggedTypeMatch(), defaultCase.getAST()); } return children; }
/** * Helper method to simplify checking for a tag. Returns true if the given binding tag is present * in the list of cases. * * @param cases * @param binding * @return */ private boolean containsTagBinding(List<Case> cases, Type tagName) { for (Case c : cases) { // Found a match, this tag is present if (c.getTaggedTypeMatch().equals(tagName)) return true; } return false; }
private void checkAllCasesAreUnique() { // All tagged types must be unique Set<Type> caseSet = new HashSet<Type>(); for (Case c : cases) { if (c.isTyped()) caseSet.add(c.getTaggedTypeMatch()); } if (caseSet.size() != cases.size()) { ToolError.reportError(ErrorMessage.DUPLICATE_TAG, matchingOver); } }
/** * Checks that the tag we are matching over is a supertag of every tag in the case-list. * * <p>This ensures that each tag could actually have a match and that case is not unreachable * code. * * @param matchingOverTag */ private void checkStaticSubtags(TaggedInfo matchingOver) { for (Case c : cases) { TaggedInfo matchTarget = TaggedInfo.lookupTagByType(c.getTaggedTypeMatch()); // FIXME: if (!isSubtag(matchTarget, matchingOver)) { ToolError.reportError( ErrorMessage.UNMATCHABLE_CASE, this.matchingOver, matchingOver.getTagName(), matchTarget.getTagName()); } } }
private void checkSubtagsPreceedSupertags() { // A tag cannot be earlier than one of its subtags for (int i = 0; i < cases.size() - 1; i++) { Case beforeCase = cases.get(i); TaggedInfo beforeTag = TaggedInfo.lookupTagByType(beforeCase.getTaggedTypeMatch()); // FIXME: for (int j = i + 1; j < cases.size(); j++) { Case afterCase = cases.get(j); if (afterCase.isDefault()) break; TaggedInfo afterTag = TaggedInfo.lookupTagByType(afterCase.getTaggedTypeMatch()); // FIXME: // TagBinding afterBinding = TagBinding.get(afterCase.getTaggedTypeMatch()); if (afterTag != null && beforeTag != null && isSubtag(afterTag, beforeTag)) { ToolError.reportError( ErrorMessage.SUPERTAG_PRECEEDS_SUBTAG, matchingOver, beforeTag.getTagName(), afterTag.getTagName()); } } } }
private void checkAllCasesAreTagged(Environment env) { // All things we match over must be tagged types for (Case c : cases) { if (c.isDefault()) continue; Type tagName = c.getTaggedTypeMatch(); if (tagName instanceof UnresolvedType) { UnresolvedType ut = (UnresolvedType) tagName; // System.out.println("ut = " + ut.resolve(env)); } if (tagName instanceof TypeInv) { // TypeInv ti = (TypeInv) tagName; // System.out.println("ti = " + ti.resolve(env)); // tagName = ti.resolve(env); // if (tagName instanceof UnresolvedType) { // tagName = ((UnresolvedType) tagName).resolve(env); // } DO NOT UNCOMMENT THIS AS BREAKS CASES return; // FIXME: Assume TypeInv will sort itself out during runtime. } // System.out.println(tagName); // check type exists // TypeBinding type = env.lookupType(tagName.toString()); // FIXME: // if (type == null) { // ToolError.reportError(ErrorMessage.TYPE_NOT_DECLARED, this, tagName.toString()); // } // check it is tagged TaggedInfo info = TaggedInfo.lookupTagByType(tagName); // FIXME: if (info == null) { ToolError.reportError(ErrorMessage.TYPE_NOT_TAGGED, matchingOver, tagName.toString()); } } }
@Override public Value evaluate(EvaluationEnvironment env) { // TaggedInfo.resolveAll(env, this); Type mo = matchingOver.getType(); TaggedInfo matchingOverTag = TaggedInfo.lookupTagByType(mo); // FIXME: if (matchingOver instanceof Variable) { Variable w = (Variable) matchingOver; // ClassType wType = (ClassType) env.lookup(w.getName()).getType(); // System.out.println("wType = " + wType); // System.out.println("looked up = " + TaggedInfo.lookupTagByType(wType)); // System.out.println("but mot = " + matchingOverTag); matchingOverTag = ((Obj) env.lookup(w.getName()) .map(ib -> ib.getValue(env)) .orElseThrow(() -> new RuntimeException("Invalid matching over tag"))) .getTaggedInfo(); } // System.out.println("Evaluating match with matchingOver = " + matchingOver + " its class " + // matchingOver.getClass()); /* Variable v = (Variable) matchingOver; System.out.println("v.getType() = " + v.getType()); System.out.println("v.getName() = " + v.getName()); System.out.println(env); System.out.println(env.lookup(v.getName())); System.out.println("mo = " + mo + " and its class is " + mo.getClass()); System.out.println(env.lookup(v.getName()).getUse()); System.out.println(env.lookup(v.getName()).getValue(env)); TypeType ttmo = (TypeType) mo; System.out.println("ttmo.getName() is declared but not actual type = " + ttmo.getName()); TypeType tttmo = (TypeType) ((MetadataWrapper) v.typecheck(env, Optional.empty())).getInner(); System.out.println("v.type = " + tttmo.getName()); TaggedInfo.dumpall(env); */ // System.out.println("Evaluating match over tag: " + matchingOverTag + " with matchingOver = " // + matchingOver.getType()); if (matchingOver.getType() instanceof ClassType) { ClassType ct = (ClassType) matchingOver.getType(); // System.out.println("hmm = " + this.matchingOver.typecheck(env, Optional.empty())); // System.out.println("ct = " + ct.getName()); } // System.out.println("matchingOverTag (latest) = " + matchingOverTag); int cnt = 0; for (Case c : cases) { cnt++; // String caseTypeName = getTypeName(c.getAST()); // System.out.println("case "+ cnt + " = " + c); Type tt = c.getTaggedTypeMatch(); TaggedInfo caseTag; if (tt instanceof TypeInv) { TypeInv ti = (TypeInv) tt; // System.out.println("Processing TypeInv case: " + ti); // FIXME: In ECOOP2015Artifact, I am trying to tell the difference between winMod.Win and // bigWinMod.Win... Type ttti = ti.getInnerType(); String mbr = ti.getInvName(); if (ttti instanceof UnresolvedType) { Value objVal = env.lookup(((UnresolvedType) ttti).getName()).get().getValue(env); caseTag = ((Obj) objVal) .getIntEnv() .lookupBinding(mbr, HackForArtifactTaggedInfoBinding.class) .map(b -> b.getTaggedInfo()) .orElseThrow(() -> new RuntimeException("Invalid tag invocation")); } else { // tt = ti.resolve(env); TODO: is this valid? caseTag = TaggedInfo.lookupTagByType(tt); // FIXME: } } else { caseTag = TaggedInfo.lookupTagByType(tt); // FIXME: } // System.out.println("case " + cnt + " type = " + tt); // System.out.println("caseTag = " + caseTag); if (caseTag != null && isSubtag(matchingOverTag, caseTag)) { // We've got a match, evaluate this case // System.out.println("MAAAAATTTCH!"); return c.getAST().evaluate(env); } } // No match, evaluate the default case // System.out.println("DEFAULT: " + defaultCase.getAST().evaluate(env)); return defaultCase.getAST().evaluate(env); }