Implements variable assignment evaluation
This commit is contained in:
parent
6185f755a4
commit
f6cf4d96dd
|
@ -11,7 +11,7 @@ BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s, Bou
|
|||
for (int i = 0; i < statements.size(); i++){
|
||||
boundStatements[i] = binder.BindStatement(statements[i]);
|
||||
}
|
||||
return new BoundScriptStatement(boundStatements);
|
||||
return new BoundScriptStatement(boundStatements, scriptScope->GetDeepestScope());
|
||||
}
|
||||
|
||||
Binder::~Binder() {
|
||||
|
|
|
@ -54,13 +54,19 @@ public:
|
|||
};
|
||||
|
||||
class BoundScriptStatement : public BoundBlockStatement{
|
||||
int _deepestScope;
|
||||
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{
|
||||
return BoundStatementKind ::Script;
|
||||
}
|
||||
|
||||
int GetDeepestScope(){
|
||||
return _deepestScope;
|
||||
}
|
||||
};
|
||||
|
||||
class BoundExpressionStatement : public BoundStatement{
|
||||
|
@ -98,6 +104,14 @@ public:
|
|||
BoundStatementKind GetKind() final{
|
||||
return BoundStatementKind ::Assignment;
|
||||
}
|
||||
|
||||
BoundVariableKey* GetKey(){
|
||||
return _key;
|
||||
}
|
||||
|
||||
BoundExpression* GetExpression(){
|
||||
return _expression;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_BOUNDSTATEMENT_HPP
|
||||
|
|
|
@ -28,6 +28,10 @@ public:
|
|||
BoundVariable* GetVariable(int scope, int identifier);
|
||||
VariableAssignment CreateExplicitLocal(int identifier, const ScriptType& type);
|
||||
VariableAssignment AssignVariable(int identifier, const ScriptType& type);
|
||||
|
||||
int GetDeepestScope(){
|
||||
return _deepestScope;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "EvaluationScope.hpp"
|
|
@ -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
|
|
@ -2,8 +2,10 @@
|
|||
#include "Evaluator.hpp"
|
||||
#include "EvaluationException.hpp"
|
||||
#include "../Script.hpp"
|
||||
#include "EvaluationScope/EvaluationScope.hpp"
|
||||
|
||||
void Evaluator::Evaluate(BoundScriptStatement *statement) {
|
||||
this->_evaluationScope = new EvaluationScope(this->_scriptData->_scriptVariables, statement->GetDeepestScope());
|
||||
EvaluateBlockStatement(statement);
|
||||
}
|
||||
|
||||
|
@ -12,6 +14,10 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) {
|
|||
case BoundStatementKind ::Script: throw; // Should never happen
|
||||
case BoundStatementKind ::Block: return this -> EvaluateBlockStatement((BoundBlockStatement*)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());
|
||||
}
|
||||
|
||||
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) {
|
||||
auto type = expression -> GetType();
|
||||
switch (type->GetClass()){
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "EvalValues/EvalValue.hpp"
|
||||
#include "EvalValues/NumericEvalValue.hpp"
|
||||
#include "EvalValues/StringEvalValue.hpp"
|
||||
|
||||
#include "EvaluationScope/EvaluationScope.hpp"
|
||||
|
||||
using namespace boost;
|
||||
|
||||
|
@ -17,10 +17,12 @@ class Evaluator {
|
|||
EvalValue* _result;
|
||||
|
||||
Script* _scriptData;
|
||||
EvaluationScope* _evaluationScope;
|
||||
|
||||
void EvaluateStatement(BoundStatement* statement);
|
||||
void EvaluateBlockStatement(BoundBlockStatement* statement);
|
||||
void EvaluateExpressionStatement(BoundExpressionStatement* statement);
|
||||
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
|
||||
|
||||
EvalValue* EvaluateExpression(BoundExpression* expression);
|
||||
NumericEvalValue* EvaluateIntegerExpression(BoundExpression* expression);
|
||||
|
@ -34,10 +36,17 @@ class Evaluator {
|
|||
NumericEvalValue* EvaluateIntegerUnary(BoundUnaryExpression* expression);
|
||||
BooleanEvalValue *EvaluateBooleanUnary(BoundUnaryExpression *expression);
|
||||
public:
|
||||
Evaluator(Script* script){
|
||||
explicit Evaluator(Script* script){
|
||||
_scriptData = script;
|
||||
_result = nullptr;
|
||||
_evaluationScope = nullptr;
|
||||
}
|
||||
|
||||
~Evaluator(){
|
||||
delete _result;
|
||||
delete _evaluationScope;
|
||||
}
|
||||
|
||||
void Evaluate(BoundScriptStatement* statement);
|
||||
|
||||
};
|
||||
|
|
|
@ -36,4 +36,4 @@ BooleanEvalValue *Evaluator::EvaluateBooleanUnary(BoundUnaryExpression *expressi
|
|||
case BoundUnaryOperation::Negation:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ Script::Script() {
|
|||
_evaluator = new Evaluator(this);
|
||||
_lastValue = nullptr;
|
||||
BoundScript = nullptr;
|
||||
_scriptVariables = new unordered_map<int, EvalValue*>(0);
|
||||
}
|
||||
|
||||
void Script::Evaluate() {
|
||||
|
@ -27,6 +28,8 @@ Script::~Script() {
|
|||
delete this -> BoundScript;
|
||||
delete this -> _lastValue;
|
||||
delete this -> _evaluator;
|
||||
this->_scriptVariables->clear();
|
||||
delete this->_scriptVariables;
|
||||
}
|
||||
|
||||
void Script::Parse(string script) {
|
||||
|
@ -43,7 +46,7 @@ void Script::Parse(string script) {
|
|||
auto bindScope = new BoundScope(&scriptScope);
|
||||
this->BoundScript = Binder::Bind(this, parseResult, bindScope);
|
||||
for (const auto& v : scriptScope){
|
||||
this->_scopeVariables.insert({v.first, nullptr});
|
||||
this->_scriptVariables -> insert({v.first, nullptr});
|
||||
delete v.second;
|
||||
}
|
||||
scriptScope.clear();
|
||||
|
|
|
@ -21,7 +21,7 @@ class Script {
|
|||
|
||||
EvalValue* _lastValue;
|
||||
Evaluator* _evaluator;
|
||||
unordered_map<int, EvalValue*> _scopeVariables;
|
||||
unordered_map<int, EvalValue*>* _scriptVariables;
|
||||
|
||||
explicit Script();
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
};
|
||||
|
||||
EvalValue* GetVariable(const string& key){
|
||||
return _scopeVariables.at(HashedString(key).GetHash());
|
||||
return _scriptVariables -> at(HashedString(key).GetHash());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@ TEST_CASE( "Create script variable", "[integration]" ) {
|
|||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto variable = script->GetVariable("foo");
|
||||
REQUIRE(variable == nullptr);
|
||||
script->Evaluate();
|
||||
variable = script->GetVariable("foo");
|
||||
REQUIRE(variable != nullptr);
|
||||
REQUIRE(variable->EvaluateBool());
|
||||
delete script;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue