From 9c831134ae20f2eb94c7104557c035ef935de7d6 Mon Sep 17 00:00:00 2001 From: Felix Queissner Date: Mon, 10 Aug 2015 13:55:52 +0200 Subject: [PATCH] Adds method call support. Recursion is not supported, code is dieing by stack overflow :P --- trainscript/common.h | 6 ++++++ trainscript/file01.ts | 25 +++++++++++++++++++++--- trainscript/trainscript.y | 33 +++++++++++++++++++++++++++---- trainscript/tsvm.cpp | 2 +- trainscript/tsvm.hpp | 41 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/trainscript/common.h b/trainscript/common.h index ed5f0d3..eb602bc 100644 --- a/trainscript/common.h +++ b/trainscript/common.h @@ -65,5 +65,11 @@ struct MethodDeclaration MethodBody *body; }; +struct ExpressionList +{ + trainscript::Instruction *instruction; + ExpressionList *next; +}; + // Variable declaration diff --git a/trainscript/file01.ts b/trainscript/file01.ts index 623353d..b404f18 100644 --- a/trainscript/file01.ts +++ b/trainscript/file01.ts @@ -1,10 +1,16 @@ # Trainscript Test File -VAR global : INT; VAR v1' : REAL; VAR v2' : REAL; -PUB main(x : INT) → c : INT | m1:REAL, v1:REAL, m2:REAL, v2:REAL +# Execute some stuff +PUB main(x : INT) → c : INT + physics(); + factorial(2); + 42 → c; + +# Physics exercise with elastic collision +PRI physics() | m1:REAL, v1:REAL, m2:REAL, v2:REAL # Wagen 1 4.0 → m1; 1.2 → v1; @@ -16,4 +22,17 @@ PUB main(x : INT) → c : INT | m1:REAL, v1:REAL, m2:REAL, v2:REAL (((m1 - m2) * v1) + (2. * m2 * v2)) / (m1 + m2) → v1'; (((m2 - m1) * v2) + (2. * m1 * v1)) / (m1 + m2) → v2'; - 42 → c; +# Recursive test +PUB fibonacci(n : INT) → f : INT + #IF n = 0 + 0 → f; + #ELSEIF n = 1 + 1 → f; + #ELSE + fibonacci(n - 1) + fibonacci(n - 2) → f; + +PUB factorial(number : INT) → result : INT + #IF number <= 1 + 1 → result; + #ELSE + number * factorial(number - 1) → result; diff --git a/trainscript/trainscript.y b/trainscript/trainscript.y index c130a7a..cf9cca1 100644 --- a/trainscript/trainscript.y +++ b/trainscript/trainscript.y @@ -46,6 +46,7 @@ void yyerror(void *scanner, const char *s); MethodHeader methodHeader; trainscript::Instruction *instruction; LocalVariable *local; + ExpressionList *expressions; } %token TAB @@ -95,6 +96,8 @@ void yyerror(void *scanner, const char *s); %type instruction %type expression +%type expressionList + %start input %left PLUS MINUS MULTIPLY DIVIDE MODULO RARROW @@ -248,7 +251,15 @@ expression: | REAL { $$ = new ConstantExpression(mkvar($1)); } // | TEXT { $$ = new ConstantExpression(mkvar($1)); } | IDENTIFIER { $$ = new VariableExpression($1); } -| IDENTIFIER LBRACKET expressionList RBRACKET { $$ = nullptr; yyerror(nullptr, "missing instruction."); } +| IDENTIFIER LBRACKET expressionList RBRACKET { + auto *call = new MethodInvokeExpression($1); + auto *list = $3; + while(list) { + call->parameters.push_back(list->instruction); + list = list->next; + } + $$ = call; + } | LBRACKET expression RBRACKET { $$ = $2; } | expression PLUS expression { $$ = new ArithmeticExpression($1, $3); } | expression MINUS expression { $$ = new ArithmeticExpression($1, $3); } @@ -259,9 +270,23 @@ expression: ; expressionList: - %empty -| expression -| expressionList COMMA expression + %empty { $$ = nullptr; } +| expression { + $$ = new ExpressionList(); + $$->instruction = $1; + $$->next = nullptr; + } +| expressionList COMMA expression { + auto *list = new ExpressionList(); + list->instruction = $3; + list->next = nullptr; + + auto *it = $1; + while(it->next) { it = it->next; } + it->next = list; + $$ = $1; + + } ; variableDeclaration: diff --git a/trainscript/tsvm.cpp b/trainscript/tsvm.cpp index 4712f89..82ad58c 100644 --- a/trainscript/tsvm.cpp +++ b/trainscript/tsvm.cpp @@ -74,7 +74,7 @@ namespace trainscript Variable Method::invoke(std::vector arguments) { - LocalContext context; + LocalContext context(this->module); for(auto var : this->module->variables) { diff --git a/trainscript/tsvm.hpp b/trainscript/tsvm.hpp index bea879f..bb12bac 100644 --- a/trainscript/tsvm.hpp +++ b/trainscript/tsvm.hpp @@ -100,6 +100,15 @@ namespace trainscript public std::map { public: + Module * const module = nullptr; + + LocalContext(Module *mod) : + std::map(), + module(mod) + { + + } + int depth; LocalContext() : depth(0) { } @@ -289,6 +298,38 @@ namespace trainscript } }; + class MethodInvokeExpression : + public Instruction + { + public: + std::string methodName; + std::vector parameters; + + MethodInvokeExpression(std::string methodName) : + methodName(methodName) + { + + } + + Variable execute(LocalContext &context) const override + { + Method *method = context.module->method(this->methodName.c_str()); + if(method == nullptr) { + if(verbose) printf("method %s not found!\n", this->methodName.c_str()); + return Variable::Invalid; + } + + if(verbose) context.depth++; + std::vector vars(this->parameters.size()); + for(int i = 0; i < vars.size(); i++) { + vars[i] = this->parameters.at(i)->execute(context); + } + if(verbose) context.depth--; + + return method->invoke(vars); + } + }; + template class ArithmeticExpression : public Instruction