void convertFreeVars(StatementPtr x, EnvPtr env, LambdaContext &ctx) { switch (x->stmtKind) { case BLOCK : { Block *y = (Block *)x.ptr(); if (!y->desugared) y->desugared = desugarBlock(y); for (unsigned i = 0; i < y->desugared->statements.size(); ++i) { StatementPtr z = y->desugared->statements[i]; if (z->stmtKind == BINDING) { Binding *a = (Binding *)z.ptr(); convertFreeVars(a->values, env, ctx); EnvPtr env2 = new Env(env); for (unsigned j = 0; j < a->names.size(); ++j) addLocal(env2, a->names[j], a->names[j].ptr()); env = env2; } else { convertFreeVars(z, env, ctx); } } break; } case LABEL : case BINDING : { break; } case ASSIGNMENT : { Assignment *y = (Assignment *)x.ptr(); convertFreeVars(y->left, env, ctx); convertFreeVars(y->right, env, ctx); break; } case INIT_ASSIGNMENT : { InitAssignment *y = (InitAssignment *)x.ptr(); convertFreeVars(y->left, env, ctx); convertFreeVars(y->right, env, ctx); break; } case UPDATE_ASSIGNMENT : { UpdateAssignment *y = (UpdateAssignment *)x.ptr(); convertFreeVars(y->left, env, ctx); convertFreeVars(y->right, env, ctx); break; } case GOTO : { break; } case RETURN : { Return *y = (Return *)x.ptr(); convertFreeVars(y->values, env, ctx); break; } case IF : { If *y = (If *)x.ptr(); convertFreeVars(y->condition, env, ctx); convertFreeVars(y->thenPart, env, ctx); if (y->elsePart.ptr()) convertFreeVars(y->elsePart, env, ctx); break; } case SWITCH : { Switch *y = (Switch *)x.ptr(); convertFreeVars(y->expr, env, ctx); for (unsigned i = 0; i < y->caseBlocks.size(); ++i) { CaseBlockPtr z = y->caseBlocks[i]; convertFreeVars(z->caseLabels, env, ctx); convertFreeVars(z->body, env, ctx); } if (y->defaultCase.ptr()) convertFreeVars(y->defaultCase, env, ctx); break; } case EVAL_STATEMENT : { EvalStatement *eval = (EvalStatement *)x.ptr(); convertFreeVars(eval->args, env, ctx); break; } case EXPR_STATEMENT : { ExprStatement *y = (ExprStatement *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case WHILE : { While *y = (While *)x.ptr(); convertFreeVars(y->condition, env, ctx); convertFreeVars(y->body, env, ctx); break; } case BREAK : case CONTINUE : { break; } case FOR : { For *y = (For *)x.ptr(); convertFreeVars(y->expr, env, ctx); EnvPtr env2 = new Env(env); for (unsigned j = 0; j < y->variables.size(); ++j) addLocal(env2, y->variables[j], y->variables[j].ptr()); convertFreeVars(y->body, env2, ctx); break; } case FOREIGN_STATEMENT : { break; } case TRY : { Try *y = (Try *)x.ptr(); convertFreeVars(y->tryBlock, env, ctx); for (unsigned i = 0; i < y->catchBlocks.size(); ++i) { EnvPtr env2 = new Env(env); addLocal(env2, y->catchBlocks[i]->exceptionVar, y->catchBlocks[i]->exceptionVar.ptr() ); if (y->catchBlocks[i]->exceptionType.ptr()) convertFreeVars(y->catchBlocks[i]->exceptionType, env, ctx); convertFreeVars(y->catchBlocks[i]->body, env2, ctx); } break; } case THROW : { Throw *y = (Throw *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case STATIC_FOR : { StaticFor *y = (StaticFor *)x.ptr(); convertFreeVars(y->values, env, ctx); EnvPtr env2 = new Env(env); addLocal(env2, y->variable, y->variable.ptr()); convertFreeVars(y->body, env2, ctx); break; } case FINALLY : { Finally *y = (Finally *)x.ptr(); convertFreeVars(y->body, env, ctx); break; } case ONERROR : { OnError *y = (OnError *)x.ptr(); convertFreeVars(y->body, env, ctx); break; } case UNREACHABLE : break; default : assert(false); } }
StatementPtr clone(StatementPtr x) { StatementPtr out; switch (x->stmtKind) { case BLOCK : { Block *y = (Block *)x.ptr(); BlockPtr z = new Block(); clone(y->statements, z->statements); out = z.ptr(); break; } case LABEL : { Label *y = (Label *)x.ptr(); out = new Label(y->name); break; } case BINDING : { Binding *y = (Binding *)x.ptr(); vector<FormalArgPtr> args; vector<PatternVar> patternVars; vector<ObjectPtr> patternTypes; clone(y->args, args); clone(y->patternVars, patternVars); clone(y->patternTypes, patternTypes); out = new Binding(y->bindingKind, patternVars, patternTypes, cloneOpt(y->predicate), args, clone(y->values), y->hasVarArg); break; } case ASSIGNMENT : { Assignment *y = (Assignment *)x.ptr(); out = new Assignment(clone(y->left), clone(y->right)); break; } case INIT_ASSIGNMENT : { InitAssignment *y = (InitAssignment *)x.ptr(); out = new InitAssignment(clone(y->left), clone(y->right)); break; } case VARIADIC_ASSIGNMENT : { VariadicAssignment *y = (VariadicAssignment *)x.ptr(); out = new VariadicAssignment(y->op, clone(y->exprs)); break; } case GOTO : { Goto *y = (Goto *)x.ptr(); out = new Goto(y->labelName); break; } case RETURN : { Return *y = (Return *)x.ptr(); out = new Return(y->returnKind, clone(y->values)); break; } case IF : { If *y = (If *)x.ptr(); vector<StatementPtr> conditionStatements; clone(y->conditionStatements, conditionStatements); out = new If(conditionStatements, clone(y->condition), clone(y->thenPart), cloneOpt(y->elsePart)); break; } case SWITCH : { Switch *y = (Switch *)x.ptr(); vector<StatementPtr> exprStatements; clone(y->exprStatements, exprStatements); vector<CaseBlockPtr> caseBlocks; clone(y->caseBlocks, caseBlocks); out = new Switch(exprStatements, clone(y->expr), caseBlocks, cloneOpt(y->defaultCase)); break; } case EXPR_STATEMENT : { ExprStatement *y = (ExprStatement *)x.ptr(); out = new ExprStatement(clone(y->expr)); break; } case WHILE : { While *y = (While *)x.ptr(); vector<StatementPtr> conditionStatements; clone(y->conditionStatements, conditionStatements); out = new While(conditionStatements, clone(y->condition), clone(y->body)); break; } case BREAK : { out = new Break(); break; } case CONTINUE : { out = new Continue(); break; } case FOR : { For *y = (For *)x.ptr(); vector<IdentifierPtr> variables; clone(y->variables, variables); out = new For(variables, clone(y->expr), clone(y->body)); break; } case FOREIGN_STATEMENT : { out = x; break; } case TRY : { Try *y = (Try *)x.ptr(); vector<CatchPtr> catchBlocks; clone(y->catchBlocks, catchBlocks); out = new Try(clone(y->tryBlock), catchBlocks); break; } case THROW : { Throw *y = (Throw *)x.ptr(); Throw *outThrow = new Throw(cloneOpt(y->expr), cloneOpt(y->context)); // this is weird part: in certain situations // clone is called after desugar, and desugaredExpr is modified after desugar outThrow->desugaredExpr = cloneOpt(y->desugaredExpr); outThrow->desugaredContext = cloneOpt(y->desugaredContext); out = outThrow; break; } case STATIC_FOR : { StaticFor *y = (StaticFor *)x.ptr(); out = new StaticFor(y->variable, clone(y->values), clone(y->body)); break; } case FINALLY : { Finally *y = (Finally *)x.ptr(); out = new Finally(clone(y->body)); break; } case ONERROR : { OnError *y = (OnError *)x.ptr(); out = new OnError(clone(y->body)); break; } case UNREACHABLE : { out = new Unreachable(); break; } case EVAL_STATEMENT : { EvalStatement *eval = (EvalStatement *)x.ptr(); out = new EvalStatement(eval->args); break; } case STATIC_ASSERT_STATEMENT : { StaticAssertStatement *staticAssert = (StaticAssertStatement *)x.ptr(); out = new StaticAssertStatement(clone(staticAssert->cond), clone(staticAssert->message)); break; } default : assert(false); } out->location = x->location; return out; }
StatementPtr desugarCatchBlocks(llvm::ArrayRef<CatchPtr> catchBlocks, CompilerState* cst) { assert(!catchBlocks.empty()); Location firstCatchLocation = catchBlocks.front()->location; IdentifierPtr expVar = Identifier::get("%exp", firstCatchLocation); CallPtr activeException = new Call(primitive_expr_activeException(cst), new ExprList()); activeException->location = firstCatchLocation; BindingPtr expBinding = new Binding(VAR, identVtoFormalV(vector<IdentifierPtr>(1, expVar)), new ExprList(activeException.ptr())); expBinding->location = firstCatchLocation; bool lastWasAny = false; IfPtr lastIf; StatementPtr result; for (size_t i = 0; i < catchBlocks.size(); ++i) { CatchPtr x = catchBlocks[i]; if (lastWasAny) error(x, "unreachable catch block"); if (x->exceptionType.ptr()) { ExprListPtr asTypeArgs = new ExprList(x->exceptionType); ExprPtr expVarName = new NameRef(expVar); expVarName->location = x->exceptionVar->location; asTypeArgs->add(expVarName); CallPtr cond = new Call(operator_expr_exceptionIsP(cst), asTypeArgs); cond->location = x->exceptionType->location; BlockPtr block = new Block(); block->location = x->location; vector<IdentifierPtr> identifiers; makeExceptionVars(identifiers, x); CallPtr getter = new Call(operator_expr_exceptionAs(cst), asTypeArgs); getter->location = x->exceptionVar->location; BindingPtr binding = new Binding(VAR, identVtoFormalV(identifiers), new ExprList(getter.ptr())); binding->location = x->exceptionVar->location; BindingPtr exceptionVarForRethrow = new Binding(REF, identVtoFormalV(vector<IdentifierPtr>(1, Identifier::get("%exception", x->location))), new ExprList(new NameRef(Identifier::get(x->exceptionVar->str, x->location)))); exceptionVarForRethrow->location = x->exceptionVar->location; block->statements.push_back(binding.ptr()); block->statements.push_back(exceptionVarForRethrow.ptr()); block->statements.push_back(x->body); IfPtr ifStatement = new If(cond.ptr(), block.ptr()); ifStatement->location = x->location; if (!result) result = ifStatement.ptr(); if (lastIf.ptr()) lastIf->elsePart = ifStatement.ptr(); lastIf = ifStatement; } else { BlockPtr block = new Block(); block->location = x->location; vector<IdentifierPtr> identifiers; makeExceptionVars(identifiers, x); ExprListPtr asAnyArgs = new ExprList(new NameRef(expVar)); CallPtr getter = new Call(operator_expr_exceptionAsAny(cst), asAnyArgs); getter->location = x->exceptionVar->location; BindingPtr binding = new Binding(VAR, identVtoFormalV(identifiers), new ExprList(getter.ptr())); binding->location = x->exceptionVar->location; BindingPtr exceptionVarForRethrow = new Binding(REF, identVtoFormalV(vector<IdentifierPtr>(1, Identifier::get("%exception", x->location))), new ExprList(new NameRef(Identifier::get(x->exceptionVar->str, x->location)))); exceptionVarForRethrow->location = x->exceptionVar->location; block->statements.push_back(binding.ptr()); block->statements.push_back(exceptionVarForRethrow.ptr()); block->statements.push_back(x->body); if (!result) result = block.ptr(); if (lastIf.ptr()) lastIf->elsePart = block.ptr(); lastWasAny = true; lastIf = NULL; } } assert(result.ptr()); if (!lastWasAny) { assert(lastIf.ptr()); BlockPtr block = new Block(); block->location = firstCatchLocation; ExprPtr expVarName = new NameRef(expVar); expVarName->location = firstCatchLocation; ExprListPtr continueArgs = new ExprList(expVarName); CallPtr continueException = new Call(operator_expr_continueException(cst), continueArgs); continueException->location = firstCatchLocation; StatementPtr stmt = new ExprStatement(continueException.ptr()); stmt->location = firstCatchLocation; block->statements.push_back(stmt); block->statements.push_back(new Unreachable()); lastIf->elsePart = block.ptr(); } BlockPtr block = new Block(); block->location = firstCatchLocation; block->statements.push_back(expBinding.ptr()); block->statements.push_back(result.ptr()); return block.ptr(); }