Adds method call support. Recursion is not supported, code is dieing by stack overflow :P

This commit is contained in:
Felix Queissner 2015-08-10 13:55:52 +02:00
parent 5ab82917fa
commit 9c831134ae
5 changed files with 99 additions and 8 deletions

View file

@ -65,5 +65,11 @@ struct MethodDeclaration
MethodBody *body;
};
struct ExpressionList
{
trainscript::Instruction *instruction;
ExpressionList *next;
};
// Variable declaration

View file

@ -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;

View file

@ -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> instruction
%type <instruction> expression
%type <expressions> 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<trainscript::ops::add>($1, $3); }
| expression MINUS expression { $$ = new ArithmeticExpression<trainscript::ops::subtract>($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:

View file

@ -74,7 +74,7 @@ namespace trainscript
Variable Method::invoke(std::vector<Variable> arguments)
{
LocalContext context;
LocalContext context(this->module);
for(auto var : this->module->variables)
{

View file

@ -100,6 +100,15 @@ namespace trainscript
public std::map<std::string, Variable*>
{
public:
Module * const module = nullptr;
LocalContext(Module *mod) :
std::map<std::string, Variable*>(),
module(mod)
{
}
int depth;
LocalContext() : depth(0) { }
@ -289,6 +298,38 @@ namespace trainscript
}
};
class MethodInvokeExpression :
public Instruction
{
public:
std::string methodName;
std::vector<Instruction*> 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<Variable> 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<Variable (*OP)(Variable, Variable)>
class ArithmeticExpression :
public Instruction