void convertFreeVars(LambdaPtr x, EnvPtr env, const string &closureDataName, vector<string> &freeVars) { EnvPtr env2 = new Env(env); for (unsigned i = 0; i < x->formalArgs.size(); ++i) { FormalArgPtr arg = x->formalArgs[i]; addLocal(env2, arg->name, arg->name.ptr()); } if (x->formalVarArg.ptr()) { addLocal(env2, x->formalVarArg->name, x->formalVarArg->name.ptr()); } LambdaContext ctx(x->captureByRef, env, closureDataName, freeVars); convertFreeVars(x->body, env2, ctx); }
void initializeLambda(LambdaPtr x, EnvPtr env) { assert(!x->initialized); x->initialized = true; string lname = lambdaName(x); ostringstream ostr; ostr << "%closureData:" << lname; string closureDataName = ostr.str(); convertFreeVars(x, env, closureDataName, x->freeVars); getProcedureMonoTypes(x->mono, env, x->formalArgs, x->formalVarArg); if (x->freeVars.empty()) { initializeLambdaWithoutFreeVars(x, env, closureDataName, lname); } else { initializeLambdaWithFreeVars(x, env, closureDataName, lname); } }
void initializeLambda(LambdaPtr x, EnvPtr env) { assert(!x->initialized); x->initialized = true; int lambdaObjectIndex = nextLambdaObjectIndex(); ostringstream ostr; ostr << "%closureData" << lambdaObjectIndex; string closureDataName = ostr.str(); convertFreeVars(x, env, closureDataName, x->freeVars); if (x->freeVars.empty()) { initializeLambdaWithoutFreeVars(x, env); } else { initializeLambdaWithFreeVars( x, env, closureDataName, lambdaObjectIndex); } }
void convertFreeVars(ExprListPtr x, EnvPtr env, LambdaContext &ctx) { for (unsigned i = 0; i < x->size(); ++i) convertFreeVars(x->exprs[i], env, ctx); }
void convertFreeVars(ExprPtr &x, EnvPtr env, LambdaContext &ctx) { switch (x->exprKind) { case BOOL_LITERAL : case INT_LITERAL : case FLOAT_LITERAL : case CHAR_LITERAL : case STRING_LITERAL : case IDENTIFIER_LITERAL : break; case NAME_REF : { NameRef *y = (NameRef *)x.ptr(); bool isNonLocal = false; bool isGlobal = false; ObjectPtr z = lookupEnvEx(env, y->name, ctx.nonLocalEnv, isNonLocal, isGlobal); if (isNonLocal && !isGlobal) { if ((z->objKind == PVALUE) || (z->objKind == CVALUE)) { TypePtr t = typeOfValue(z); if (isStaticOrTupleOfStatics(t)) { ExprListPtr args = new ExprList(); args->add(new ObjectExpr(t.ptr())); CallPtr call = new Call(operator_expr_typeToRValue(), args); call->location = y->location; x = call.ptr(); } else { addFreeVar(ctx, y->name->str); IdentifierPtr a = new Identifier(ctx.closureDataName); a->location = y->location; NameRefPtr b = new NameRef(a); b->location = y->location; FieldRefPtr c = new FieldRef(b.ptr(), y->name); c->location = y->location; if (ctx.captureByRef) { vector<int> ops; ops.push_back(DEREFERENCE); ExprPtr d = new VariadicOp(ops, new ExprList(c.ptr())); d->location = y->location; x = d.ptr(); } else { x = c.ptr(); } } } else if ((z->objKind == MULTI_PVALUE) || (z->objKind == MULTI_CVALUE)) { vector<TypePtr> types = typesOfValues(z); bool allStatic = true; for (unsigned i = 0; i < types.size(); ++i) { if (!isStaticOrTupleOfStatics(types[i])) { allStatic = false; break; } } if (allStatic) { ExprListPtr args = new ExprList(); for (unsigned i = 0; i < types.size(); ++i) args->add(new ObjectExpr(types[i].ptr())); CallPtr call = new Call(operator_expr_typesToRValues(), args); call->location = y->location; x = call.ptr(); } else { addFreeVar(ctx, y->name->str); IdentifierPtr a = new Identifier(ctx.closureDataName); a->location = y->location; NameRefPtr b = new NameRef(a); b->location = y->location; FieldRefPtr c = new FieldRef(b.ptr(), y->name); c->location = y->location; if (ctx.captureByRef) { ExprPtr f = operator_expr_unpackMultiValuedFreeVarAndDereference(); CallPtr d = new Call(f, new ExprList()); d->parenArgs->add(c.ptr()); x = d.ptr(); } else { ExprPtr f = operator_expr_unpackMultiValuedFreeVar(); CallPtr d = new Call(f, new ExprList()); d->parenArgs->add(c.ptr()); x = d.ptr(); } } } } break; } case TUPLE : { Tuple *y = (Tuple *)x.ptr(); convertFreeVars(y->args, env, ctx); break; } case PAREN : { Paren *y = (Paren *)x.ptr(); convertFreeVars(y->args, env, ctx); break; } case INDEXING : { Indexing *y = (Indexing *)x.ptr(); convertFreeVars(y->expr, env, ctx); convertFreeVars(y->args, env, ctx); break; } case CALL : { Call *y = (Call *)x.ptr(); convertFreeVars(y->expr, env, ctx); convertFreeVars(y->parenArgs, env, ctx); convertFreeVars(y->lambdaArgs, env, ctx); break; } case FIELD_REF : { FieldRef *y = (FieldRef *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case STATIC_INDEXING : { StaticIndexing *y = (StaticIndexing *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case VARIADIC_OP : { VariadicOp *y = (VariadicOp *)x.ptr(); convertFreeVars(y->exprs, env, ctx); break; } case AND : { And *y = (And *)x.ptr(); convertFreeVars(y->expr1, env, ctx); convertFreeVars(y->expr2, env, ctx); break; } case OR : { Or *y = (Or *)x.ptr(); convertFreeVars(y->expr1, env, ctx); convertFreeVars(y->expr2, env, ctx); break; } case LAMBDA : { Lambda *y = (Lambda *)x.ptr(); EnvPtr env2 = new Env(env); for (unsigned i = 0; i < y->formalArgs.size(); ++i) addLocal(env2, y->formalArgs[i]->name, y->formalArgs[i]->name.ptr()); if (y->formalVarArg.ptr()) addLocal(env2, y->formalVarArg->name, y->formalVarArg->name.ptr()); convertFreeVars(y->body, env2, ctx); break; } case UNPACK : { Unpack *y = (Unpack *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case STATIC_EXPR : { StaticExpr *y = (StaticExpr *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case DISPATCH_EXPR : { DispatchExpr *y = (DispatchExpr *)x.ptr(); convertFreeVars(y->expr, env, ctx); break; } case EVAL_EXPR : { EvalExpr *eval = (EvalExpr *)x.ptr(); convertFreeVars(eval->args, env, ctx); break; } case FOREIGN_EXPR : case OBJECT_EXPR : case FILE_EXPR : case LINE_EXPR : case COLUMN_EXPR : case ARG_EXPR : break; } }
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); } }