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 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); }