Adds method call support. Recursion is not supported, code is dieing by stack overflow :P
This commit is contained in:
parent
5ab82917fa
commit
9c831134ae
5 changed files with 99 additions and 8 deletions
|
@ -65,5 +65,11 @@ struct MethodDeclaration
|
|||
MethodBody *body;
|
||||
};
|
||||
|
||||
struct ExpressionList
|
||||
{
|
||||
trainscript::Instruction *instruction;
|
||||
ExpressionList *next;
|
||||
};
|
||||
|
||||
// Variable declaration
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue