private Node buildSJSessionTypeCast(SJSessionTypeCast stc) throws SemanticException { SJTypeNode tn = disambiguateSJTypeNode(this, stc.sessionType()); SJSessionType st = tn.type(); if (stc instanceof SJAmbiguousCast) { SJNoAliasExprExt naee = getSJNoAliasExprExt(stc); Position pos = stc.position(); Expr e = stc.expr(); if (st instanceof SJBeginType) { stc = sjnf.SJChannelCast(pos, e, tn); } else { stc = sjnf.SJSessionCast(pos, e, tn); } stc = (SJSessionTypeCast) buildAndCheckTypes(this, stc); stc = (SJSessionTypeCast) SJNoAliasExprBuilder.setSJNoAliasExprExt( sjef, stc, naee.isNoAlias(), naee.isFinal(), naee.fields(), naee.locals(), naee.arrayAccesses()); } else { stc = stc.sessionType(tn); } stc = (SJSessionTypeCast) setSJTypeableExt(sjef, stc, st); return stc; }
private Expr buildNewArray(Position pos, List contents) { NewArray na = sjnf.makeSocketsArray(pos, contents.size()); ArrayInit ai = sjnf.ArrayInit(pos, contents); na = na.init(ai).dims(Collections.emptyList()).additionalDims(1); return na; }
// FIXME: does not integrate with recursive session method calls: recursionEnter/Exit and also // recurse do not match the control flow of recursive calls, and hence runtime type monitoring // does not work. private Node translateSJRecursion(SJRecursion r, QQ qq) // recursionEnter inserted by node factory, but translation is finished here.. { SJSessionOperationExt soe = getSJSessionOperationExt(r); Position pos = r.position(); Collection<Object> mapping = new LinkedList<Object>(); String bname = getRecursionBooleanName(soe.targetNames(), r.label()); mapping.add(bname); mapping.add(bname); String translation = "for (boolean %s = true; %s; ) { }"; For f = (For) qq.parseStmt(translation, mapping.toArray()); mapping.clear(); r = (SJRecursion) r.inits(f.inits()); r = (SJRecursion) r.cond(f.cond()); List stmts = new LinkedList(); stmts.addAll(r.body().statements()); translation = "%s = %E;"; mapping.add(bname); mapping.add(((Eval) stmts.remove(0)).expr()); // Factor out constant. Eval e = (Eval) qq.parseStmt(translation, mapping.toArray()); stmts.add(0, e); r = (SJRecursion) r.body(sjnf.Block(pos, stmts)); /*// Appending the recursion-exit hook. // Disabled to support delegation from within recursion scopes (socket will be null on recursion-exit). List<Local> targets = new LinkedList<Local>(); // FIXME: should be SJLocalSockets. for (String sjname : soe.targetNames()) // Unicast optimisation for SJRecursionExit is done within the NodeFactory method - this pass comes after SJUnicastOptimiser. { targets.add(sjnf.Local(pos, sjnf.Id(pos, sjname))); // Would it be bad to instead alias the recursionEnter targets? } SJRecursionExit re = sjnf.SJRecursionExit(pos, targets); // Problem: the sockets argument array is not yet filled (for other (internal) basic operations, this was done earlier by SJSessionOperationParser)... re = (SJRecursionExit) SJVariableParser.parseSJSessionOperation(this, re); // ...Current fix: use those routines form those earlier passes. re = (SJRecursionExit) SJSessionOperationParser.fixSJBasicOperationArguments(this, re);*/ // return sjnf.Block(pos, r, sjnf.Eval(pos, re)); return sjnf.Block(pos, r); }
private Node translateSJInbranch(SJInbranch ib, QQ qq) { StringBuilder translation = new StringBuilder("{ "); Collection<Object> mapping = new LinkedList<Object>(); String labVar = UniqueID.newID(SJ_INBRANCH_LABEL_FIELD_PREFIX); translation.append("%T %s = %E; "); mapping.add(qq.parseType(SJ_LABEL_CLASS)); mapping.add(labVar); mapping.add(ib.inlabel()); for (Iterator<SJInbranchCase> i = ib.branchCases().iterator(); i.hasNext(); ) { SJInbranchCase ibc = i.next(); translation.append("if (%s.equals(%E)) { %LS } "); mapping.add(labVar); mapping.add(sjnf.StringLit(ib.position(), ibc.label().labelValue())); mapping.add(ibc.statements()); if (i.hasNext()) { translation.append("else "); } } translation.append("else { throw new SJIOException(\"Unexpected inbranch label: \" + %s); }"); mapping.add(labVar); // FIXME: need a final else case to better handle, if runtime monitoring is disabled, // non-sj-compatibility mode and in case of malicious peers. translation.append('}'); return qq.parseStmt(translation.toString(), mapping.toArray()); }
/** * @author Raymond * <p>Also does SJSessionTypeCasts and SJFormals. */ public class SJProtocolDeclTypeBuilder extends ContextVisitor { private SJTypeSystem sjts = (SJTypeSystem) typeSystem(); private SJNodeFactory sjnf = (SJNodeFactory) nodeFactory(); private SJExtFactory sjef = sjnf.extFactory(); /** */ public SJProtocolDeclTypeBuilder(Job job, TypeSystem ts, NodeFactory nf) { super(job, ts, nf); } protected NodeVisitor enterCall(Node parent, Node n) throws SemanticException { return this; } protected Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException { if (n instanceof VarInit) { if (n instanceof FieldDecl) { n = buildFieldDecl((FieldDecl) n); } else // if (n instanceof LocalDecl) { n = buildLocalDecl((LocalDecl) n); } } else if (n instanceof SJSessionTypeCast) { n = buildSJSessionTypeCast((SJSessionTypeCast) n); } else if (n instanceof Formal) { n = buildFormal((Formal) n); } return n; } private Node buildFieldDecl(FieldDecl fd) throws SemanticException { Type t = fd.declType(); if (t.isSubtype(SJ_PROTOCOL_TYPE)) { if (!(fd instanceof SJFieldProtocolDecl)) { throw new SemanticException( "[SJProtocolDeclTypeBuilder] Protocols may only be declared using the protocol keyword: " + fd); } SJTypeNode tn = disambiguateSJTypeNode(this, ((SJProtocolDecl) fd).sessionType()); SJSessionType st = tn.type(); String sjname = fd.name(); // Should match that given by SJVariable.sjname. SJFieldInstance fi = (SJFieldInstance) fd.fieldInstance(); SJFieldProtocolInstance fpi = sjts.SJFieldProtocolInstance((SJFieldInstance) fd.fieldInstance(), st, sjname); fpi.setConstantValue( fi .constantValue()); // Currently, constant checker not run on custom nodes/type // objects. (Previously done by SJNoAliasTypeBuilder.) fd = fd.fieldInstance(fpi); fd = (FieldDecl) setSJProtocolDeclExt((SJProtocolDecl) fd, tn, sjname); updateSJFieldInstance(fi, fpi); } return fd; } private Node buildLocalDecl(LocalDecl ld) throws SemanticException { Type t = ld.declType(); SJLocalInstance li = (SJLocalInstance) ld.localInstance(); // SJNamedInstance ni = null; if (t.isSubtype(SJ_PROTOCOL_TYPE)) // Mostly the same as for LocalDecl. { if (!(ld instanceof SJLocalProtocolDecl)) { throw new SemanticException( "[SJProtocolDeclTypeBuilder] Protocols may only be declared using the protocol keyword: " + ld); } SJTypeNode tn = disambiguateSJTypeNode(this, ((SJProtocolDecl) ld).sessionType()); SJSessionType st = tn.type(); String sjname = ld.name(); // Should match that given by SJVariable.sjname. ld = ld.localInstance(sjts.SJLocalProtocolInstance(li, st, sjname)); ld = (LocalDecl) setSJProtocolDeclExt((SJProtocolDecl) ld, tn, sjname); } return ld; } private SJProtocolDecl setSJProtocolDeclExt(SJProtocolDecl pd, SJTypeNode tn, String sjname) { pd = pd.sessionType(tn); pd = (SJProtocolDecl) setSJNamedExt(sjef, pd, tn.type(), sjname); return pd; } private Node buildSJSessionTypeCast(SJSessionTypeCast stc) throws SemanticException { SJTypeNode tn = disambiguateSJTypeNode(this, stc.sessionType()); SJSessionType st = tn.type(); if (stc instanceof SJAmbiguousCast) { SJNoAliasExprExt naee = getSJNoAliasExprExt(stc); Position pos = stc.position(); Expr e = stc.expr(); if (st instanceof SJBeginType) { stc = sjnf.SJChannelCast(pos, e, tn); } else { stc = sjnf.SJSessionCast(pos, e, tn); } stc = (SJSessionTypeCast) buildAndCheckTypes(this, stc); stc = (SJSessionTypeCast) SJNoAliasExprBuilder.setSJNoAliasExprExt( sjef, stc, naee.isNoAlias(), naee.isFinal(), naee.fields(), naee.locals(), naee.arrayAccesses()); } else { stc = stc.sessionType(tn); } stc = (SJSessionTypeCast) setSJTypeableExt(sjef, stc, st); return stc; } private Node buildFormal(Formal f) throws SemanticException // Based on buildLocalDecl. { Type t = f.declType(); SJLocalInstance li = (SJLocalInstance) f.localInstance(); if (t.isSubtype(SJ_ABSTRACT_CHANNEL_TYPE)) { if (!(f instanceof SJFormal)) { throw new SemanticException( "[SJProtocolDeclTypeBuilder] Session socket parameters should be declared by their session type: " + f); } SJTypeNode tn = disambiguateSJTypeNode(this, ((SJFormal) f).sessionType()); SJSessionType st = tn.type(); String sjname = f.name(); // Should match that given by SJVariable.sjname. f = f.localInstance(sjts.SJLocalProtocolInstance(li, st, sjname)); f = setSJFormalExt((SJFormal) f, tn, sjname); } return f; } private Formal setSJFormalExt( SJFormal f, SJTypeNode tn, String sjname) // Based on setSJProtocolDeclExt { f = f.sessionType(tn); f = (SJFormal) setSJNamedExt(sjef, f, tn.type(), sjname); return f; } }