Implements variable assignment evaluation

This commit is contained in:
Deukhoofd 2019-05-29 14:55:03 +02:00
parent 6185f755a4
commit f6cf4d96dd
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
11 changed files with 104 additions and 8 deletions

View File

@ -11,7 +11,7 @@ BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s, Bou
for (int i = 0; i < statements.size(); i++){ for (int i = 0; i < statements.size(); i++){
boundStatements[i] = binder.BindStatement(statements[i]); boundStatements[i] = binder.BindStatement(statements[i]);
} }
return new BoundScriptStatement(boundStatements); return new BoundScriptStatement(boundStatements, scriptScope->GetDeepestScope());
} }
Binder::~Binder() { Binder::~Binder() {

View File

@ -54,13 +54,19 @@ public:
}; };
class BoundScriptStatement : public BoundBlockStatement{ class BoundScriptStatement : public BoundBlockStatement{
int _deepestScope;
public: public:
explicit BoundScriptStatement(vector<BoundStatement*> statements) : BoundBlockStatement(std::move(statements)){ explicit BoundScriptStatement(vector<BoundStatement*> statements, int deepestScope) : BoundBlockStatement(std::move(statements)){
_deepestScope = deepestScope;
} }
BoundStatementKind GetKind() final{ BoundStatementKind GetKind() final{
return BoundStatementKind ::Script; return BoundStatementKind ::Script;
} }
int GetDeepestScope(){
return _deepestScope;
}
}; };
class BoundExpressionStatement : public BoundStatement{ class BoundExpressionStatement : public BoundStatement{
@ -98,6 +104,14 @@ public:
BoundStatementKind GetKind() final{ BoundStatementKind GetKind() final{
return BoundStatementKind ::Assignment; return BoundStatementKind ::Assignment;
} }
BoundVariableKey* GetKey(){
return _key;
}
BoundExpression* GetExpression(){
return _expression;
}
}; };
#endif //PORYGONLANG_BOUNDSTATEMENT_HPP #endif //PORYGONLANG_BOUNDSTATEMENT_HPP

View File

@ -28,6 +28,10 @@ public:
BoundVariable* GetVariable(int scope, int identifier); BoundVariable* GetVariable(int scope, int identifier);
VariableAssignment CreateExplicitLocal(int identifier, const ScriptType& type); VariableAssignment CreateExplicitLocal(int identifier, const ScriptType& type);
VariableAssignment AssignVariable(int identifier, const ScriptType& type); VariableAssignment AssignVariable(int identifier, const ScriptType& type);
int GetDeepestScope(){
return _deepestScope;
}
}; };

View File

@ -0,0 +1,2 @@
#include "EvaluationScope.hpp"

View File

@ -0,0 +1,44 @@
#ifndef PORYGONLANG_EVALUATIONSCOPE_HPP
#define PORYGONLANG_EVALUATIONSCOPE_HPP
#include <unordered_map>
#include <vector>
#include "../EvalValues/EvalValue.hpp"
class EvaluationScope {
unordered_map<int, EvalValue*>* _scriptScope;
vector<unordered_map<int, EvalValue*>> _localScope;
public:
explicit EvaluationScope(unordered_map<int, EvalValue*>* scriptVariables, int deepestScope){
_scriptScope = scriptVariables;
_localScope = vector<unordered_map<int, EvalValue*>>(deepestScope);
}
~EvaluationScope(){
_localScope.clear();
}
void CreateVariable(int scope, int id, EvalValue* value){
if (scope == 0){
_scriptScope->insert_or_assign(id, value);
} else{
_localScope[scope - 1].insert({id, value});
}
}
void SetVariable(int scope, int id, EvalValue* value){
if (scope == 0){
_scriptScope->insert_or_assign(id, value);
} else{
_localScope[scope - 1][id] = value;
}
}
EvalValue* GetVariable(int scope, int id){
return _localScope[scope - 1][id];
}
};
#endif //PORYGONLANG_EVALUATIONSCOPE_HPP

View File

@ -2,8 +2,10 @@
#include "Evaluator.hpp" #include "Evaluator.hpp"
#include "EvaluationException.hpp" #include "EvaluationException.hpp"
#include "../Script.hpp" #include "../Script.hpp"
#include "EvaluationScope/EvaluationScope.hpp"
void Evaluator::Evaluate(BoundScriptStatement *statement) { void Evaluator::Evaluate(BoundScriptStatement *statement) {
this->_evaluationScope = new EvaluationScope(this->_scriptData->_scriptVariables, statement->GetDeepestScope());
EvaluateBlockStatement(statement); EvaluateBlockStatement(statement);
} }
@ -12,6 +14,10 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) {
case BoundStatementKind ::Script: throw; // Should never happen case BoundStatementKind ::Script: throw; // Should never happen
case BoundStatementKind ::Block: return this -> EvaluateBlockStatement((BoundBlockStatement*)statement); case BoundStatementKind ::Block: return this -> EvaluateBlockStatement((BoundBlockStatement*)statement);
case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement); case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement);
case BoundStatementKind ::Assignment: return this -> EvaluateAssignmentStatement((BoundAssignmentStatement*)statement);
case BoundStatementKind::Bad:
throw;
} }
} }
@ -28,6 +34,16 @@ void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement)
this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression()); this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression());
} }
void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement) {
auto value = this -> EvaluateExpression(statement->GetExpression());
auto key = statement->GetKey();
if (key->IsCreation()){
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value);
} else{
this->_evaluationScope->SetVariable(key->GetScopeId(), key->GetIdentifier(), value);
}
}
EvalValue *Evaluator::EvaluateExpression(BoundExpression *expression) { EvalValue *Evaluator::EvaluateExpression(BoundExpression *expression) {
auto type = expression -> GetType(); auto type = expression -> GetType();
switch (type->GetClass()){ switch (type->GetClass()){

View File

@ -9,7 +9,7 @@
#include "EvalValues/EvalValue.hpp" #include "EvalValues/EvalValue.hpp"
#include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
#include "EvaluationScope/EvaluationScope.hpp"
using namespace boost; using namespace boost;
@ -17,10 +17,12 @@ class Evaluator {
EvalValue* _result; EvalValue* _result;
Script* _scriptData; Script* _scriptData;
EvaluationScope* _evaluationScope;
void EvaluateStatement(BoundStatement* statement); void EvaluateStatement(BoundStatement* statement);
void EvaluateBlockStatement(BoundBlockStatement* statement); void EvaluateBlockStatement(BoundBlockStatement* statement);
void EvaluateExpressionStatement(BoundExpressionStatement* statement); void EvaluateExpressionStatement(BoundExpressionStatement* statement);
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
EvalValue* EvaluateExpression(BoundExpression* expression); EvalValue* EvaluateExpression(BoundExpression* expression);
NumericEvalValue* EvaluateIntegerExpression(BoundExpression* expression); NumericEvalValue* EvaluateIntegerExpression(BoundExpression* expression);
@ -34,10 +36,17 @@ class Evaluator {
NumericEvalValue* EvaluateIntegerUnary(BoundUnaryExpression* expression); NumericEvalValue* EvaluateIntegerUnary(BoundUnaryExpression* expression);
BooleanEvalValue *EvaluateBooleanUnary(BoundUnaryExpression *expression); BooleanEvalValue *EvaluateBooleanUnary(BoundUnaryExpression *expression);
public: public:
Evaluator(Script* script){ explicit Evaluator(Script* script){
_scriptData = script; _scriptData = script;
_result = nullptr; _result = nullptr;
_evaluationScope = nullptr;
} }
~Evaluator(){
delete _result;
delete _evaluationScope;
}
void Evaluate(BoundScriptStatement* statement); void Evaluate(BoundScriptStatement* statement);
}; };

View File

@ -36,4 +36,4 @@ BooleanEvalValue *Evaluator::EvaluateBooleanUnary(BoundUnaryExpression *expressi
case BoundUnaryOperation::Negation: case BoundUnaryOperation::Negation:
throw; throw;
} }
} }

View File

@ -16,6 +16,7 @@ Script::Script() {
_evaluator = new Evaluator(this); _evaluator = new Evaluator(this);
_lastValue = nullptr; _lastValue = nullptr;
BoundScript = nullptr; BoundScript = nullptr;
_scriptVariables = new unordered_map<int, EvalValue*>(0);
} }
void Script::Evaluate() { void Script::Evaluate() {
@ -27,6 +28,8 @@ Script::~Script() {
delete this -> BoundScript; delete this -> BoundScript;
delete this -> _lastValue; delete this -> _lastValue;
delete this -> _evaluator; delete this -> _evaluator;
this->_scriptVariables->clear();
delete this->_scriptVariables;
} }
void Script::Parse(string script) { void Script::Parse(string script) {
@ -43,7 +46,7 @@ void Script::Parse(string script) {
auto bindScope = new BoundScope(&scriptScope); auto bindScope = new BoundScope(&scriptScope);
this->BoundScript = Binder::Bind(this, parseResult, bindScope); this->BoundScript = Binder::Bind(this, parseResult, bindScope);
for (const auto& v : scriptScope){ for (const auto& v : scriptScope){
this->_scopeVariables.insert({v.first, nullptr}); this->_scriptVariables -> insert({v.first, nullptr});
delete v.second; delete v.second;
} }
scriptScope.clear(); scriptScope.clear();

View File

@ -21,7 +21,7 @@ class Script {
EvalValue* _lastValue; EvalValue* _lastValue;
Evaluator* _evaluator; Evaluator* _evaluator;
unordered_map<int, EvalValue*> _scopeVariables; unordered_map<int, EvalValue*>* _scriptVariables;
explicit Script(); explicit Script();
@ -40,7 +40,7 @@ public:
}; };
EvalValue* GetVariable(const string& key){ EvalValue* GetVariable(const string& key){
return _scopeVariables.at(HashedString(key).GetHash()); return _scriptVariables -> at(HashedString(key).GetHash());
} }
}; };

View File

@ -7,6 +7,10 @@ TEST_CASE( "Create script variable", "[integration]" ) {
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
auto variable = script->GetVariable("foo"); auto variable = script->GetVariable("foo");
REQUIRE(variable == nullptr); REQUIRE(variable == nullptr);
script->Evaluate();
variable = script->GetVariable("foo");
REQUIRE(variable != nullptr);
REQUIRE(variable->EvaluateBool());
delete script; delete script;
} }