SymbolAstResult UnaryExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { AstUnaryOperator astOp = AstUnaryOperator::Not; switch (op) { case UnaryOperator::Not: astOp = AstUnaryOperator::Not; break; case UnaryOperator::Positive: astOp = AstUnaryOperator::Positive; break; case UnaryOperator::Negative: astOp = AstUnaryOperator::Negative; break; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(operand->GenerateAst(scope, context, state), context, exprs, exprStart, state); auto ast = make_shared<AstUnaryExpression>(); ast->op = astOp; ast->operand = exprs[0]; return result.ReplaceValue(ast); }
SymbolAstResult UnaryExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { AstDeclaration::Ptr astOp; switch (op) { case UnaryOperator::Not: astOp = scope->opNot; break; case UnaryOperator::Positive: astOp = scope->opPos; break; case UnaryOperator::Negative: astOp = scope->opNeg; break; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(operand->GenerateAst(scope, context, state), context, exprs, exprStart, state); auto stat = make_shared<AstExpressionStatement>(); auto invoke = make_shared<AstInvokeExpression>(); stat->expression = invoke; { auto ref = make_shared<AstReferenceExpression>(); ref->reference = astOp; invoke->function = ref; } { auto arg = make_shared<AstReferenceExpression>(); arg->reference = state; invoke->arguments.push_back(arg); } invoke->arguments.push_back(exprs[0]); auto lambda = Expression::GenerateContinuationLambdaAst(scope, context, state); invoke->arguments.push_back(lambda); auto ast = make_shared<AstReferenceExpression>(); ast->reference = lambda->arguments[1]; result.AppendStatement(stat); return result.ReplaceValue(ast, lambda); }
SymbolAstResult ListExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; for (auto element : elements) { result.MergeForExpression(element->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto ast = make_shared<AstNewArrayLiteralExpression>(); for (auto expr : exprs) { ast->elements.push_back(expr); } return result.ReplaceValue(ast); }
void SymbolAstResult::MergeForStatement(const SymbolAstResult& result, AstDeclaration::Ptr& state) { AppendStatement(result.statement); if (result.RequireCps()) { continuation = result.continuation; } if (continuation) { state = continuation->arguments[0]; } }
void SymbolAstResult::MergeForExpression(const SymbolAstResult& result, SymbolAstContext& context, vector<AstExpression::Ptr>& exprs, int& exprStart, AstDeclaration::Ptr& state) { if (result.RequireCps()) { auto block = make_shared<AstBlockStatement>(); for (int i = exprStart; (size_t)i < exprs.size(); i++) { auto var = make_shared<AstDeclarationStatement>(); { auto decl = make_shared<AstSymbolDeclaration>(); decl->composedName = T("$var") + context.GetUniquePostfix(); var->declaration = decl; auto declstat = make_shared<AstDeclarationStatement>(); declstat->declaration = decl; block->statements.push_back(declstat); auto assign = make_shared<AstAssignmentStatement>(); block->statements.push_back(assign); auto ref = make_shared<AstReferenceExpression>(); ref->reference = decl; assign->target = ref; assign->value = exprs[i]; } auto ref = make_shared<AstReferenceExpression>(); ref->reference = var->declaration; exprs[i] = ref; } block->statements.push_back(result.statement); if (continuation) { continuation->statement = block; } else { statement = block; } continuation = result.continuation; exprStart = exprs.size(); state = continuation->arguments[0]; } exprs.push_back(result.value); }
ast::AstAssembly::Ptr GenerateAst(SymbolAssembly::Ptr symbolAssembly) { auto assembly = make_shared<AstAssembly>(); auto scope = make_shared<SymbolAstScope>(); multimap<SymbolFunction::Ptr, SymbolFunction::Ptr> multipleDispatchChildren; map<SymbolFunction::Ptr, SymbolModule::Ptr> functionModules; map<SymbolFunction::Ptr, AstFunctionDeclaration::Ptr> functionAsts; GenerateStaticAst(symbolAssembly, assembly, scope, multipleDispatchChildren, functionModules, functionAsts); GenerateMultipleDispatchAsts(symbolAssembly, assembly, scope, multipleDispatchChildren, functionModules, functionAsts); for (auto fap : functionAsts) { auto func = fap.first; auto ast = fap.second; auto module = functionModules.find(func)->second; SymbolAstContext context; context.function = ast; context.continuation = ast->continuationArgument; auto itdecl = ast->arguments.begin(); if (func->cpsStateVariable) { context.createdVariables.push_back(func->cpsStateVariable); scope->readAsts.insert(make_pair(func->cpsStateVariable, ast->stateArgument)); } itdecl++; if (func->categorySignalVariable) { context.createdVariables.push_back(func->categorySignalVariable); scope->readAsts.insert(make_pair(func->categorySignalVariable, ast->signalArgument)); itdecl++; } if (func->cpsContinuationVariable) { context.createdVariables.push_back(func->cpsContinuationVariable); scope->readAsts.insert(make_pair(func->cpsContinuationVariable, ast->continuationArgument)); } if (func->resultVariable) { context.createdVariables.push_back(func->resultVariable); scope->readAsts.insert(make_pair(func->resultVariable, ast->resultVariable)); } for (auto arg : func->arguments) { if (auto var = dynamic_pointer_cast<VariableArgumentFragment>(arg.second)) { if (var->type == FunctionArgumentType::Argument) { continue; } else if (var->type == FunctionArgumentType::Assignable) { context.createdVariables.push_back(arg.first); scope->readAsts.insert(make_pair(arg.first, *itdecl++)); scope->writeAsts.insert(make_pair(arg.first, *itdecl++)); continue; } else if (var->type == FunctionArgumentType::Expression) { context.createdVariables.push_back(arg.first); scope->readAsts.insert(make_pair(arg.first, *itdecl++)); scope->writeAsts.insert(make_pair(arg.first, nullptr)); continue; } } context.createdVariables.push_back(arg.first); scope->readAsts.insert(make_pair(arg.first, *itdecl++)); if (auto func = dynamic_pointer_cast<FunctionArgumentFragment>(arg.second)) { auto ast = dynamic_pointer_cast<AstFunctionDeclaration>(func->declaration->GenerateAst(module)); scope->functionPrototypes.insert(make_pair(arg.first, ast)); } } { AstDeclaration::Ptr state = ast->arguments[0]; SymbolAstResult result = func->statement->GenerateBodyAst(scope, context, state, nullptr); result.MergeForStatement(Statement::GenerateExitAst(scope, context, state), state); ast->statement = result.statement; } { auto stat = make_shared<AstDeclarationStatement>(); stat->declaration = ast->resultVariable; if (auto block = dynamic_pointer_cast<AstBlockStatement>(ast->statement)) { block->statements.insert(block->statements.begin(), stat); } else { block = make_shared<AstBlockStatement>(); block->statements.push_back(stat); block->statements.push_back(ast->statement); ast->statement = block; } } if (!dynamic_pointer_cast<AstBlockStatement>(ast->statement)) { auto block = make_shared<AstBlockStatement>(); block->statements.push_back(ast->statement); ast->statement = block; } for (auto var : context.createdVariables) { scope->readAsts.erase(var); scope->writeAsts.erase(var); scope->functionPrototypes.erase(var); } } assembly->RoughlyOptimize(); assembly->SetParent(); return assembly; }
SymbolAstResult BinaryExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { AstDeclaration::Ptr astOp; switch (op) { case BinaryOperator::Concat: astOp = scope->opConcat; break; case BinaryOperator::Add: astOp = scope->opAdd; break; case BinaryOperator::Sub: astOp = scope->opSub; break; case BinaryOperator::Mul: astOp = scope->opMul; break; case BinaryOperator::Div: astOp = scope->opDiv; break; case BinaryOperator::IntDiv: astOp = scope->opIntDiv; break; case BinaryOperator::Mod: astOp = scope->opMod; break; case BinaryOperator::LT: astOp = scope->opLT; break; case BinaryOperator::GT: astOp = scope->opGT; break; case BinaryOperator::LE: astOp = scope->opLE; break; case BinaryOperator::GE: astOp = scope->opGE; break; case BinaryOperator::EQ: astOp = scope->opEQ; break; case BinaryOperator::NE: astOp = scope->opNE; break; case BinaryOperator::And: astOp = scope->opAnd; break; case BinaryOperator::Or: astOp = scope->opOr; break; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(first->GenerateAst(scope, context, state), context, exprs, exprStart, state); result.MergeForExpression(second->GenerateAst(scope, context, state), context, exprs, exprStart, state); auto stat = make_shared<AstExpressionStatement>(); auto invoke = make_shared<AstInvokeExpression>(); stat->expression = invoke; { auto ref = make_shared<AstReferenceExpression>(); ref->reference = astOp; invoke->function = ref; } { auto arg = make_shared<AstReferenceExpression>(); arg->reference = state; invoke->arguments.push_back(arg); } invoke->arguments.push_back(exprs[0]); invoke->arguments.push_back(exprs[1]); auto lambda = Expression::GenerateContinuationLambdaAst(scope, context, state); invoke->arguments.push_back(lambda); auto ast = make_shared<AstReferenceExpression>(); ast->reference = lambda->arguments[1]; result.AppendStatement(stat); return result.ReplaceValue(ast, lambda); }
SymbolAstResult InvokeExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { Expression::Ptr realFunction; Expression::List realArguments; bool invokeContinuation = false; if (auto ref = dynamic_pointer_cast<ReferenceExpression>(function)) { switch (ref->symbol->target) { case GrammarSymbolTarget::Invoke: { realFunction = arguments[0]; realArguments = dynamic_pointer_cast<ListExpression>(arguments[1])->elements; } break; case GrammarSymbolTarget::InvokeContinuation: { realFunction = arguments[0]; realArguments = dynamic_pointer_cast<ListExpression>(arguments[1])->elements; invokeContinuation = true; } break; case GrammarSymbolTarget::NewTypeOfFields: { SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; for (auto expr : dynamic_pointer_cast<ListExpression>(arguments[1])->elements) { result.MergeForExpression(expr->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto ast = make_shared<AstNewTypeExpression>(); ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[0])->symbol); ast->fields = exprs; return result.ReplaceValue(ast); } case GrammarSymbolTarget::NewArray: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstNewArrayExpression>(); ast->length = result.value; return result.ReplaceValue(ast); } case GrammarSymbolTarget::GetArrayItem: { SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; for (auto expr : arguments) { result.MergeForExpression(expr->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto ast = make_shared<AstArrayAccessExpression>(); ast->target = exprs[1]; ast->index = exprs[0]; return result.ReplaceValue(ast); } case GrammarSymbolTarget::GetArrayLength: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstArrayLengthExpression>(); ast->target = result.value; return result.ReplaceValue(ast); } case GrammarSymbolTarget::IsType: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstTestTypeExpression>(); ast->target = result.value; ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[1])->symbol); return result.ReplaceValue(ast); } case GrammarSymbolTarget::IsNotType: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto stat = make_shared<AstExpressionStatement>(); auto invoke = make_shared<AstInvokeExpression>(); stat->expression = invoke; { auto ref = make_shared<AstReferenceExpression>(); ref->reference = scope->opNot; invoke->function = ref; } { auto arg = make_shared<AstReferenceExpression>(); arg->reference = state; invoke->arguments.push_back(arg); } { auto arg = make_shared<AstTestTypeExpression>(); arg->target = result.value; arg->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[1])->symbol); invoke->arguments.push_back(arg); } auto lambda = Expression::GenerateContinuationLambdaAst(scope, context, state); invoke->arguments.push_back(lambda); auto ast = make_shared<AstReferenceExpression>(); ast->reference = lambda->arguments[1]; result.AppendStatement(stat); return result.ReplaceValue(ast, lambda); } case GrammarSymbolTarget::GetField: { SymbolAstResult result = arguments[1]->GenerateAst(scope, context, state); auto ast = make_shared<AstFieldAccessExpression>(); ast->target = result.value; ast->composedFieldName = dynamic_pointer_cast<ArgumentExpression>(arguments[0])->name->GetComposedName(); return result.ReplaceValue(ast); } } } if (!realFunction) { realFunction = function; realArguments = arguments; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(realFunction->GenerateAst(scope, context, state), context, exprs, exprStart, state); for (auto arg : realArguments) { result.MergeForExpression(arg->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto stat = make_shared<AstExpressionStatement>(); auto invoke = make_shared<AstInvokeExpression>(); stat->expression = invoke; auto it = exprs.begin(); invoke->function = *it++; { auto ref = make_shared<AstReferenceExpression>(); ref->reference = state; invoke->arguments.push_back(ref); } while (it != exprs.end()) { invoke->arguments.push_back(*it++); } if (invokeContinuation) { auto ast = make_shared<AstLiteralExpression>(); ast->literalName = AstLiteralName::Null; auto lambda = GenerateContinuationLambdaAst(scope, context, state); auto lambdaStat = make_shared<AstExpressionStatement>(); lambdaStat->expression = lambda; result.AppendStatement(stat); result.AppendStatement(lambdaStat); return result.ReplaceValue(ast, lambda); } else { auto lambda = GenerateContinuationLambdaAst(scope, context, state); invoke->arguments.push_back(lambda); auto ast = make_shared<AstReferenceExpression>(); ast->reference = lambda->arguments[1]; result.AppendStatement(stat); return result.ReplaceValue(ast, lambda); } }
SymbolAstResult BinaryExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { AstBinaryOperator astOp = AstBinaryOperator::Concat; switch (op) { case BinaryOperator::Concat: astOp = AstBinaryOperator::Concat; break; case BinaryOperator::Add: astOp = AstBinaryOperator::Add; break; case BinaryOperator::Sub: astOp = AstBinaryOperator::Sub; break; case BinaryOperator::Mul: astOp = AstBinaryOperator::Mul; break; case BinaryOperator::Div: astOp = AstBinaryOperator::Div; break; case BinaryOperator::IntDiv: astOp = AstBinaryOperator::IntDiv; break; case BinaryOperator::Mod: astOp = AstBinaryOperator::Mod; break; case BinaryOperator::LT: astOp = AstBinaryOperator::LT; break; case BinaryOperator::GT: astOp = AstBinaryOperator::GT; break; case BinaryOperator::LE: astOp = AstBinaryOperator::LE; break; case BinaryOperator::GE: astOp = AstBinaryOperator::GE; break; case BinaryOperator::EQ: astOp = AstBinaryOperator::EQ; break; case BinaryOperator::NE: astOp = AstBinaryOperator::NE; break; case BinaryOperator::And: astOp = AstBinaryOperator::And; break; case BinaryOperator::Or: astOp = AstBinaryOperator::Or; break; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(first->GenerateAst(scope, context, state), context, exprs, exprStart, state); result.MergeForExpression(second->GenerateAst(scope, context, state), context, exprs, exprStart, state); auto ast = make_shared<AstBinaryExpression>(); ast->op = astOp; ast->first = exprs[0]; ast->second = exprs[1]; return result.ReplaceValue(ast); }
SymbolAstResult InvokeExpression::GenerateAst(shared_ptr<SymbolAstScope> scope, SymbolAstContext& context, shared_ptr<ast::AstDeclaration> state) { Expression::Ptr func; Expression::List args; if (auto ref = dynamic_pointer_cast<ReferenceExpression>(function)) { switch (ref->symbol->target) { case GrammarSymbolTarget::Invoke: func = arguments[0]; break; case GrammarSymbolTarget::InvokeWith: func = arguments[0]; args = dynamic_pointer_cast<ListExpression>(arguments[1])->elements; break; case GrammarSymbolTarget::NewType: { auto ast = make_shared<AstNewTypeExpression>(); ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[0])->symbol, ast); return SymbolAstResult(ast); } case GrammarSymbolTarget::NewTypeOfFields: { SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; for (auto expr : dynamic_pointer_cast<ListExpression>(arguments[1])->elements) { result.MergeForExpression(expr->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto ast = make_shared<AstNewTypeExpression>(); ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[0])->symbol, ast); ast->fields = exprs; return result.ReplaceValue(ast); } case GrammarSymbolTarget::NewArray: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstNewArrayExpression>(); ast->length = result.value; return result.ReplaceValue(ast); } case GrammarSymbolTarget::GetArrayItem: { SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; for (auto expr : arguments) { result.MergeForExpression(expr->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto ast = make_shared<AstArrayAccessExpression>(); ast->target = exprs[1]; ast->index = exprs[0]; return result.ReplaceValue(ast); } case GrammarSymbolTarget::GetArrayLength: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstArrayLengthExpression>(); ast->target = result.value; return result.ReplaceValue(ast); } case GrammarSymbolTarget::IsType: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstTestTypeExpression>(); ast->target = result.value; ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[1])->symbol, ast); return result.ReplaceValue(ast); } case GrammarSymbolTarget::IsNotType: { SymbolAstResult result = arguments[0]->GenerateAst(scope, context, state); auto ast = make_shared<AstTestTypeExpression>(); ast->target = result.value; ast->type = scope->GetType(dynamic_pointer_cast<ReferenceExpression>(arguments[1])->symbol, ast); auto unary = make_shared<AstUnaryExpression>(); unary->op = AstUnaryOperator::Not; unary->operand = ast; return result.ReplaceValue(unary); } case GrammarSymbolTarget::GetField: { SymbolAstResult result = arguments[1]->GenerateAst(scope, context, state); auto ast = make_shared<AstFieldAccessExpression>(); ast->target = result.value; ast->composedFieldName = dynamic_pointer_cast<ArgumentExpression>(arguments[0])->name->GetComposedName(); return result.ReplaceValue(ast); } } } if (!func) { func = function; args = arguments; } SymbolAstResult result; vector<AstExpression::Ptr> exprs; int exprStart = 0; result.MergeForExpression(func->GenerateAst(scope, context, state), context, exprs, exprStart, state); for (auto arg : args) { result.MergeForExpression(arg->GenerateAst(scope, context, state), context, exprs, exprStart, state); } auto stat = make_shared<AstExpressionStatement>(); auto invoke = make_shared<AstInvokeExpression>(); stat->expression = invoke; auto it = exprs.begin(); invoke->function = *it++; { auto ref = make_shared<AstReferenceExpression>(); ref->reference = state; invoke->arguments.push_back(ref); } while (it != exprs.end()) { invoke->arguments.push_back(*it++); } auto lambda = GenerateContinuationLambdaAst(scope, context, state); invoke->arguments.push_back(lambda); auto ast = make_shared<AstReferenceExpression>(); ast->reference = lambda->arguments[1]; result.AppendStatement(stat); return result.ReplaceValue(ast, lambda); }