StatementPtr desugarForStatement(ForPtr x, CompilerState* cst) { IdentifierPtr exprVar = Identifier::get("%expr", x->location); IdentifierPtr iterVar = Identifier::get("%iter", x->location); IdentifierPtr valueVar = Identifier::get("%value", x->location); BlockPtr block = new Block(); block->location = x->body->location; vector<StatementPtr> &bs = block->statements; BindingPtr exprBinding = new Binding(FORWARD, identV(exprVar), new ExprList(x->expr)); exprBinding->location = x->body->location; bs.push_back(exprBinding.ptr()); CallPtr iteratorCall = new Call(operator_expr_iterator(cst), new ExprList()); iteratorCall->location = x->body->location; ExprPtr exprName = new NameRef(exprVar); exprName->location = x->location; iteratorCall->parenArgs->add(exprName); BindingPtr iteratorBinding = new Binding(FORWARD, identV(iterVar), new ExprList(iteratorCall.ptr())); iteratorBinding->location = x->body->location; bs.push_back(iteratorBinding.ptr()); vector<StatementPtr> valueStatements; CallPtr nextValueCall = new Call(operator_expr_nextValue(cst), new ExprList()); nextValueCall->location = x->body->location; ExprPtr iterName = new NameRef(iterVar); iterName->location = x->body->location; nextValueCall->parenArgs->add(iterName); BindingPtr nextValueBinding = new Binding(VAR, identV(valueVar), new ExprList(nextValueCall.ptr())); nextValueBinding->location = x->body->location; valueStatements.push_back(nextValueBinding.ptr()); CallPtr hasValueCall = new Call(operator_expr_hasValueP(cst), new ExprList()); hasValueCall->location = x->body->location; ExprPtr valueName = new NameRef(valueVar); valueName->location = x->body->location; hasValueCall->parenArgs->add(valueName); CallPtr getValueCall = new Call(operator_expr_getValue(cst), new ExprList()); getValueCall->location = x->body->location; getValueCall->parenArgs->add(valueName); BlockPtr whileBody = new Block(); whileBody->location = x->body->location; vector<StatementPtr> &ws = whileBody->statements; ws.push_back(new Binding(FORWARD, identVtoFormalV(x->variables), new ExprList(getValueCall.ptr()))); ws.push_back(x->body); StatementPtr whileStmt = new While(valueStatements, hasValueCall.ptr(), whileBody.ptr()); whileStmt->location = x->location; bs.push_back(whileStmt); return block.ptr(); }
StatementPtr desugarSwitchStatement(SwitchPtr x, CompilerState* cst) { BlockPtr block = new Block(); block->location = x->location; block->statements.insert(block->statements.end(), x->exprStatements.begin(), x->exprStatements.end()); // %thing is the value being switched on IdentifierPtr thing = Identifier::get("%case", x->expr->location); NameRefPtr thingRef = new NameRef(thing); thingRef->location = x->expr->location; // initialize %case { BindingPtr b = new Binding(FORWARD, identV(thing), new ExprList(x->expr)); b->location = x->expr->location; block->statements.push_back(b.ptr()); } ExprPtr caseCallable = operator_expr_caseP(cst); StatementPtr root; StatementPtr *nextPtr = &root; // dispatch logic for (size_t i = 0; i < x->caseBlocks.size(); ++i) { CaseBlockPtr caseBlock = x->caseBlocks[i]; ExprListPtr caseArgs = new ExprList(thingRef.ptr()); ExprPtr caseCompareArgs = new Paren(caseBlock->caseLabels); caseCompareArgs->location = caseBlock->location; caseArgs->add(caseCompareArgs); ExprPtr condition = new Call(caseCallable, caseArgs); condition->location = caseBlock->location; IfPtr ifStmt = new If(condition, caseBlock->body); ifStmt->location = caseBlock->location; *nextPtr = ifStmt.ptr(); nextPtr = &(ifStmt->elsePart); } if (x->defaultCase.ptr()) *nextPtr = x->defaultCase; else *nextPtr = NULL; block->statements.push_back(root); return block.ptr(); }
static void jitStatements(llvm::ArrayRef<StatementPtr> statements) { if (statements.empty()) { return; } if (printAST) { for (size_t i = 0; i < statements.size(); ++i) { llvm::errs() << statements[i] << "\n"; } } IdentifierPtr fun = Identifier::get(newFunctionName()); BlockPtr funBody = new Block(statements); ExternalProcedurePtr entryProc = new ExternalProcedure(NULL, fun, PRIVATE, vector<ExternalArgPtr>(), false, NULL, funBody.ptr(), new ExprList()); entryProc->env = module->env; codegenBeforeRepl(module); try { codegenExternalProcedure(entryProc, true); } catch (std::exception) { return; } llvm::Function* ctor; llvm::Function* dtor; codegenAfterRepl(ctor, dtor); engine->runFunction(ctor, std::vector<llvm::GenericValue>()); void* dtorLlvmFun = engine->getPointerToFunction(dtor); typedef void (*PFN)(); atexit((PFN)(uintptr_t)dtorLlvmFun); engine->runFunction(entryProc->llvmFunc, std::vector<llvm::GenericValue>()); }
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(); }