Rework evaluation to use shared pointers, fix bugs

This commit is contained in:
Deukhoofd 2019-06-01 21:38:39 +02:00
parent 4408cf00cd
commit 6206fef4c5
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
17 changed files with 122 additions and 133 deletions

View File

@ -90,7 +90,7 @@ VariableAssignment BoundScope::AssignVariable(int identifier, const std::shared_
} else{ } else{
// Assigning // Assigning
auto var = this->GetVariable(exists, identifier); auto var = this->GetVariable(exists, identifier);
if (var->GetType() != type){ if (var->GetType().get()->operator!=(type.get())){
return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr); return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr);
} }
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false)); return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false));

View File

@ -1,3 +1,5 @@
#include <utility>
#ifndef PORYGONLANG_BOUNDVARIABLE_HPP #ifndef PORYGONLANG_BOUNDVARIABLE_HPP
#define PORYGONLANG_BOUNDVARIABLE_HPP #define PORYGONLANG_BOUNDVARIABLE_HPP
@ -10,9 +12,7 @@ using namespace std;
class BoundVariable{ class BoundVariable{
std::shared_ptr<ScriptType> _type; std::shared_ptr<ScriptType> _type;
public: public:
explicit BoundVariable(std::shared_ptr<ScriptType> type) : _type(type){ explicit BoundVariable(std::shared_ptr<ScriptType> type) : _type(std::move(type)){
}
~BoundVariable(){
} }
std::shared_ptr<ScriptType> GetType(){ std::shared_ptr<ScriptType> GetType(){

View File

@ -5,68 +5,58 @@
#include "EvalValues/NumericEvalValue.hpp" #include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
NumericEvalValue* Evaluator::EvaluateIntegerBinary(BoundBinaryExpression *expression) { shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerBinary(BoundBinaryExpression *expression) {
NumericEvalValue* leftValue = this -> EvaluateIntegerExpression(expression->GetLeft()); auto leftValue = this -> EvaluateIntegerExpression(expression->GetLeft());
NumericEvalValue* rightValue = this -> EvaluateIntegerExpression(expression->GetRight()); auto rightValue = this -> EvaluateIntegerExpression(expression->GetRight());
NumericEvalValue* result; NumericEvalValue* result;
switch (expression->GetOperation()){ switch (expression->GetOperation()){
case BoundBinaryOperation ::Addition: case BoundBinaryOperation ::Addition:
result = leftValue -> operator+ (rightValue); result = leftValue.get() -> operator+ (rightValue.get());
break; break;
case BoundBinaryOperation::Subtraction: case BoundBinaryOperation::Subtraction:
result = leftValue -> operator- (rightValue); result = leftValue.get() -> operator- (rightValue.get());
break; break;
case BoundBinaryOperation::Multiplication: case BoundBinaryOperation::Multiplication:
result = leftValue -> operator* (rightValue); result = leftValue.get() -> operator* (rightValue.get());
break; break;
case BoundBinaryOperation::Division: case BoundBinaryOperation::Division:
result = leftValue -> operator/ (rightValue); result = leftValue.get() -> operator/ (rightValue.get());
break; break;
default: default:
delete leftValue;
delete rightValue;
throw EvaluationException("Can't evaluate operation to numeric"); throw EvaluationException("Can't evaluate operation to numeric");
} }
delete leftValue; return shared_ptr<NumericEvalValue>(result);
delete rightValue;
return result;
} }
BooleanEvalValue* Evaluator::EvaluateBooleanBinary(BoundBinaryExpression* expression){ shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanBinary(BoundBinaryExpression* expression){
switch (expression->GetOperation()){ switch (expression->GetOperation()){
case BoundBinaryOperation::Equality: case BoundBinaryOperation::Equality:
{ {
EvalValue* leftValue = this -> EvaluateExpression(expression->GetLeft()); auto leftValue = this -> EvaluateExpression(expression->GetLeft());
EvalValue* rightValue = this -> EvaluateExpression(expression->GetRight()); auto rightValue = this -> EvaluateExpression(expression->GetRight());
bool equals = leftValue->operator==(rightValue); bool equals = leftValue.get()->operator==(rightValue.get());
delete leftValue; return make_shared<BooleanEvalValue>(equals);
delete rightValue;
return new BooleanEvalValue(equals);
} }
case BoundBinaryOperation::Inequality: case BoundBinaryOperation::Inequality:
{ {
EvalValue* leftValue = this -> EvaluateExpression(expression->GetLeft()); auto leftValue = this -> EvaluateExpression(expression->GetLeft());
EvalValue* rightValue = this -> EvaluateExpression(expression->GetRight()); auto rightValue = this -> EvaluateExpression(expression->GetRight());
bool equals = leftValue->operator!=(rightValue); bool equals = leftValue.get()->operator!=(rightValue.get());
delete leftValue; return make_shared<BooleanEvalValue>(equals);
delete rightValue;
return new BooleanEvalValue(equals);
} }
case BoundBinaryOperation::LogicalAnd: case BoundBinaryOperation::LogicalAnd:
{ {
BooleanEvalValue* leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); auto leftValue = this -> EvaluateBoolExpression(expression->GetLeft());
if (!leftValue->EvaluateBool()) return leftValue; if (!leftValue->EvaluateBool()) return leftValue;
delete leftValue; auto rightValue = this -> EvaluateBoolExpression(expression->GetRight());
BooleanEvalValue* rightValue = this -> EvaluateBoolExpression(expression->GetRight());
return rightValue; return rightValue;
} }
case BoundBinaryOperation::LogicalOr: case BoundBinaryOperation::LogicalOr:
{ {
BooleanEvalValue* leftValue = this -> EvaluateBoolExpression(expression->GetLeft()); auto leftValue = this -> EvaluateBoolExpression(expression->GetLeft());
if (leftValue->EvaluateBool()) return leftValue; if (leftValue->EvaluateBool()) return leftValue;
delete leftValue; auto rightValue = this -> EvaluateBoolExpression(expression->GetRight());
BooleanEvalValue* rightValue = this -> EvaluateBoolExpression(expression->GetRight());
return rightValue; return rightValue;
} }
default: default:
@ -74,15 +64,13 @@ BooleanEvalValue* Evaluator::EvaluateBooleanBinary(BoundBinaryExpression* expres
} }
} }
StringEvalValue* Evaluator::EvaluateStringBinary(BoundBinaryExpression* expression){ shared_ptr<StringEvalValue> Evaluator::EvaluateStringBinary(BoundBinaryExpression* expression){
if (expression->GetOperation() != BoundBinaryOperation::Concatenation) if (expression->GetOperation() != BoundBinaryOperation::Concatenation)
throw; throw;
std::ostringstream strs; std::ostringstream strs;
auto left = this -> EvaluateStringExpression(expression->GetLeft()); auto left = this -> EvaluateStringExpression(expression->GetLeft());
strs << left->EvaluateString(); strs << left->EvaluateString();
delete left;
auto right = this -> EvaluateExpression(expression->GetRight()); auto right = this -> EvaluateExpression(expression->GetRight());
strs << right->EvaluateString(); strs << right->EvaluateString();
delete right; return make_shared<StringEvalValue>(strs.str());
return new StringEvalValue(strs.str());
} }

View File

@ -20,7 +20,7 @@ public:
return ! (this->operator==(b)); return ! (this->operator==(b));
} }
virtual EvalValue* Clone() = 0; virtual shared_ptr<EvalValue> Clone() = 0;
virtual long EvaluateInteger(){ virtual long EvaluateInteger(){
throw EvaluationException("Can't evaluate this EvalValue as integer."); throw EvaluationException("Can't evaluate this EvalValue as integer.");
@ -45,8 +45,8 @@ public:
_type = std::make_shared<ScriptType>(TypeClass::Bool); _type = std::make_shared<ScriptType>(TypeClass::Bool);
} }
EvalValue* Clone() final{ shared_ptr<EvalValue> Clone() final{
return new BooleanEvalValue(_value); return make_shared<BooleanEvalValue>(_value);
} }
std::shared_ptr<ScriptType> GetType() final{ std::shared_ptr<ScriptType> GetType() final{

View File

@ -48,8 +48,8 @@ public:
return strs.str(); return strs.str();
} }
EvalValue* Clone() final{ shared_ptr<EvalValue> Clone() final{
return new IntegerEvalValue(_value); return make_shared<IntegerEvalValue>(_value);
} }
}; };
@ -76,8 +76,8 @@ public:
return strs.str(); return strs.str();
} }
EvalValue* Clone() final{ shared_ptr<EvalValue> Clone() final{
return new FloatEvalValue(_value); return make_shared<FloatEvalValue>(_value);
} }
}; };

View File

@ -25,10 +25,11 @@ public:
return _type; return _type;
} }
EvalValue* Clone() final{ shared_ptr<EvalValue> Clone() final{
return new ScriptFunctionEvalValue(_innerBlock, _type); return make_shared<ScriptFunctionEvalValue>(_innerBlock, _type);
} }
bool operator ==(EvalValue* b) final{ bool operator ==(EvalValue* b) final{
if (b->GetType()->GetClass() != TypeClass::Function) if (b->GetType()->GetClass() != TypeClass::Function)
return false; return false;

View File

@ -29,8 +29,8 @@ public:
return _value; return _value;
} }
EvalValue* Clone() final{ shared_ptr<EvalValue> Clone() final{
return new StringEvalValue(_value); return make_shared<StringEvalValue>(_value);
} }
}; };

View File

@ -1,25 +1,22 @@
#include "EvaluationScope.hpp" #include "EvaluationScope.hpp"
#include <memory>
EvaluationScope::EvaluationScope(unordered_map<int, EvalValue *> *scriptVariables, int deepestScope) { EvaluationScope::EvaluationScope(unordered_map<int, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) {
_scriptScope = scriptVariables; _scriptScope = scriptVariables;
_localScope = vector<unordered_map<int, EvalValue*>>(deepestScope); _localScope = vector<unordered_map<int, shared_ptr<EvalValue>>>(deepestScope);
_currentScope = -1; _currentScope = -1;
} }
EvaluationScope::~EvaluationScope() { void EvaluationScope::CreateVariable(int scope, int id, shared_ptr<EvalValue> value) {
_localScope.clear();
}
void EvaluationScope::CreateVariable(int scope, int id, EvalValue *value) {
if (scope == 0){ if (scope == 0){
_scriptScope->insert_or_assign(id, value); _scriptScope->insert_or_assign(id, value);
} else{ } else{
_localScope[scope - 1].insert({id, value}); _localScope[scope - 1].insert_or_assign(id, value);
} }
} }
void EvaluationScope::SetVariable(int scope, int id, EvalValue *value) { void EvaluationScope::SetVariable(int scope, int id, shared_ptr<EvalValue> value) {
if (scope == 0){ if (scope == 0){
_scriptScope->insert_or_assign(id, value); _scriptScope->insert_or_assign(id, value);
} else{ } else{
@ -27,7 +24,7 @@ void EvaluationScope::SetVariable(int scope, int id, EvalValue *value) {
} }
} }
EvalValue *EvaluationScope::GetVariable(int scope, int id) { shared_ptr<EvalValue> EvaluationScope::GetVariable(int scope, int id) {
if (scope == 0){ if (scope == 0){
return _scriptScope->at(id); return _scriptScope->at(id);
} }
@ -40,9 +37,7 @@ void EvaluationScope::OuterScope() {
void EvaluationScope::InnerScope() { void EvaluationScope::InnerScope() {
auto scope = this->_localScope[_currentScope]; auto scope = this->_localScope[_currentScope];
for (auto v: scope){ scope.clear();
delete v.second;
}
_currentScope--; _currentScope--;
} }

View File

@ -7,18 +7,18 @@
#include "../EvalValues/EvalValue.hpp" #include "../EvalValues/EvalValue.hpp"
class EvaluationScope { class EvaluationScope {
unordered_map<int, EvalValue*>* _scriptScope; unordered_map<int, shared_ptr<EvalValue>>* _scriptScope;
vector<unordered_map<int, EvalValue*>> _localScope; vector<unordered_map<int, shared_ptr<EvalValue>>> _localScope;
int _currentScope; int _currentScope;
public: public:
explicit EvaluationScope(unordered_map<int, EvalValue*>* scriptVariables, int deepestScope); explicit EvaluationScope(unordered_map<int, shared_ptr<EvalValue>>* scriptVariables, int deepestScope);
~EvaluationScope(); ~EvaluationScope() = default;
void CreateVariable(int scope, int id, EvalValue* value); void CreateVariable(int scope, int id, shared_ptr<EvalValue> value);
void SetVariable(int scope, int id, EvalValue* value); void SetVariable(int scope, int id, shared_ptr<EvalValue> value);
void OuterScope(); void OuterScope();
void InnerScope(); void InnerScope();
EvalValue* GetVariable(int scope, int id); shared_ptr<EvalValue> GetVariable(int scope, int id);
}; };

View File

@ -1,10 +1,13 @@
#include <memory>
#include "Evaluator.hpp" #include "Evaluator.hpp"
#include "EvaluationException.hpp" #include "EvaluationException.hpp"
#include "../Script.hpp" #include "../Script.hpp"
#include "EvaluationScope/EvaluationScope.hpp" #include "EvaluationScope/EvaluationScope.hpp"
#include "EvalValues/ScriptFunctionEvalValue.hpp" #include "EvalValues/ScriptFunctionEvalValue.hpp"
using namespace std;
void Evaluator::Evaluate(BoundScriptStatement *statement) { void Evaluator::Evaluate(BoundScriptStatement *statement) {
this->_evaluationScope = new EvaluationScope(this->_scriptData->_scriptVariables, statement->GetDeepestScope()); this->_evaluationScope = new EvaluationScope(this->_scriptData->_scriptVariables, statement->GetDeepestScope());
EvaluateBlockStatement(statement); EvaluateBlockStatement(statement);
@ -32,8 +35,6 @@ void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement) {
} }
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) { void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
// Delete previously saved value.
delete this->_scriptData->_lastValue;
// Save new value // Save new value
this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression()); this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression());
} }
@ -52,7 +53,7 @@ void Evaluator::EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationSta
auto type = statement->GetType(); auto type = statement->GetType();
auto key = statement->GetKey(); auto key = statement->GetKey();
auto block = statement->GetBlock(); auto block = statement->GetBlock();
auto value = new ScriptFunctionEvalValue(block, type); auto value = make_shared<ScriptFunctionEvalValue>(block, type);
if (key->IsCreation()){ if (key->IsCreation()){
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value); this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), value);
} else{ } else{
@ -60,7 +61,7 @@ void Evaluator::EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationSta
} }
} }
EvalValue *Evaluator::EvaluateExpression(BoundExpression *expression) { shared_ptr<EvalValue> Evaluator::EvaluateExpression(BoundExpression *expression) {
auto type = expression -> GetType(); auto type = expression -> GetType();
switch (type->GetClass()){ switch (type->GetClass()){
case TypeClass ::Number: return this -> EvaluateIntegerExpression(expression); case TypeClass ::Number: return this -> EvaluateIntegerExpression(expression);
@ -72,18 +73,18 @@ EvalValue *Evaluator::EvaluateExpression(BoundExpression *expression) {
} }
} }
EvalValue* Evaluator::GetVariable(BoundVariableExpression* expression){ shared_ptr<EvalValue> Evaluator::GetVariable(BoundVariableExpression* expression){
return this->_evaluationScope->GetVariable(expression->GetScope(), expression->GetId())->Clone(); return this->_evaluationScope->GetVariable(expression->GetScope(), expression->GetId())->Clone();
} }
NumericEvalValue* Evaluator::EvaluateIntegerExpression(BoundExpression *expression) { shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(BoundExpression *expression) {
switch (expression->GetKind()){ switch (expression->GetKind()){
case BoundExpressionKind ::LiteralInteger: return new IntegerEvalValue(((BoundLiteralIntegerExpression*)expression)->GetValue()); case BoundExpressionKind ::LiteralInteger: return make_shared<IntegerEvalValue>(((BoundLiteralIntegerExpression*)expression)->GetValue());
case BoundExpressionKind ::LiteralFloat: return new FloatEvalValue(((BoundLiteralFloatExpression*)expression)->GetValue()); case BoundExpressionKind ::LiteralFloat: return make_shared<FloatEvalValue>(((BoundLiteralFloatExpression*)expression)->GetValue());
case BoundExpressionKind::Unary: return this -> EvaluateIntegerUnary((BoundUnaryExpression*)expression); case BoundExpressionKind::Unary: return this -> EvaluateIntegerUnary((BoundUnaryExpression*)expression);
case BoundExpressionKind ::Binary: return this -> EvaluateIntegerBinary((BoundBinaryExpression*)expression); case BoundExpressionKind ::Binary: return this -> EvaluateIntegerBinary((BoundBinaryExpression*)expression);
case BoundExpressionKind::Variable: return (NumericEvalValue*)this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable: return dynamic_pointer_cast<NumericEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
case BoundExpressionKind ::FunctionCall: return (NumericEvalValue*)this->EvaluateFunctionCallExpression(expression); case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind ::LiteralString: case BoundExpressionKind ::LiteralString:
case BoundExpressionKind ::LiteralBool: case BoundExpressionKind ::LiteralBool:
@ -92,13 +93,13 @@ NumericEvalValue* Evaluator::EvaluateIntegerExpression(BoundExpression *expressi
} }
} }
BooleanEvalValue* Evaluator::EvaluateBoolExpression(BoundExpression *expression) { shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind::LiteralBool: return new BooleanEvalValue(((BoundLiteralBoolExpression*)expression)->GetValue()); case BoundExpressionKind ::LiteralBool: return make_shared<BooleanEvalValue>(((BoundLiteralBoolExpression*)expression)->GetValue());
case BoundExpressionKind::Unary: return this -> EvaluateBooleanUnary((BoundUnaryExpression*)expression); case BoundExpressionKind::Unary: return this -> EvaluateBooleanUnary((BoundUnaryExpression*)expression);
case BoundExpressionKind::Binary: return this -> EvaluateBooleanBinary((BoundBinaryExpression*)expression); case BoundExpressionKind::Binary: return this -> EvaluateBooleanBinary((BoundBinaryExpression*)expression);
case BoundExpressionKind::Variable: return (BooleanEvalValue*)this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable: return dynamic_pointer_cast<BooleanEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
case BoundExpressionKind ::FunctionCall: return (BooleanEvalValue*)this->EvaluateFunctionCallExpression(expression); case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Bad: case BoundExpressionKind::Bad:
case BoundExpressionKind::LiteralInteger: case BoundExpressionKind::LiteralInteger:
@ -109,14 +110,14 @@ BooleanEvalValue* Evaluator::EvaluateBoolExpression(BoundExpression *expression)
} }
} }
StringEvalValue* Evaluator::EvaluateStringExpression(BoundExpression *expression) { shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(BoundExpression *expression) {
switch (expression->GetKind()) { switch (expression->GetKind()) {
case BoundExpressionKind::LiteralString: case BoundExpressionKind ::LiteralString:
return new StringEvalValue(((BoundLiteralStringExpression*)expression)->GetValue()); return make_shared<StringEvalValue>(((BoundLiteralStringExpression*)expression)->GetValue());
case BoundExpressionKind::Binary: case BoundExpressionKind::Binary:
return this -> EvaluateStringBinary((BoundBinaryExpression*)expression); return this -> EvaluateStringBinary((BoundBinaryExpression*)expression);
case BoundExpressionKind::Variable: return (StringEvalValue*)this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind::Variable: return dynamic_pointer_cast<StringEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
case BoundExpressionKind ::FunctionCall: return (StringEvalValue*)this->EvaluateFunctionCallExpression(expression); case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Bad: case BoundExpressionKind::Bad:
case BoundExpressionKind::LiteralInteger: case BoundExpressionKind::LiteralInteger:
@ -128,13 +129,13 @@ StringEvalValue* Evaluator::EvaluateStringExpression(BoundExpression *expression
} }
} }
EvalValue* Evaluator::EvaluateFunctionExpression(BoundExpression * expression){ shared_ptr<EvalValue> Evaluator::EvaluateFunctionExpression(BoundExpression * expression){
switch (expression->GetKind()){ switch (expression->GetKind()){
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression);
default: throw; default: throw;
} }
} }
EvalValue* Evaluator::EvaluateNilExpression(BoundExpression * expression){ shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(BoundExpression * expression){
switch (expression->GetKind()){ switch (expression->GetKind()){
case BoundExpressionKind ::FunctionCall: case BoundExpressionKind ::FunctionCall:
return this->EvaluateFunctionCallExpression(expression); return this->EvaluateFunctionCallExpression(expression);
@ -144,11 +145,11 @@ EvalValue* Evaluator::EvaluateNilExpression(BoundExpression * expression){
} }
EvalValue* Evaluator::EvaluateFunctionCallExpression(BoundExpression* expression){ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression* expression){
auto functionCall = (BoundFunctionCallExpression*)expression; auto functionCall = (BoundFunctionCallExpression*)expression;
auto function = (ScriptFunctionEvalValue*)this->EvaluateExpression(functionCall->GetFunctionExpression()); auto function = dynamic_pointer_cast<ScriptFunctionEvalValue>(this->EvaluateExpression(functionCall->GetFunctionExpression()));
auto boundParameters = functionCall->GetParameters(); auto boundParameters = functionCall->GetParameters();
auto parameters = vector<EvalValue*>(boundParameters.size()); auto parameters = vector<shared_ptr<EvalValue>>(boundParameters.size());
for (int i = 0; i < boundParameters.size(); i++){ for (int i = 0; i < boundParameters.size(); i++){
parameters[i] = this->EvaluateExpression(boundParameters[i]); parameters[i] = this->EvaluateExpression(boundParameters[i]);
} }

View File

@ -3,7 +3,6 @@
#define PORYGONLANG_EVALUATOR_HPP #define PORYGONLANG_EVALUATOR_HPP
#include <string> #include <string>
#include <boost/any.hpp>
#include "../Binder/BoundStatements/BoundStatement.hpp" #include "../Binder/BoundStatements/BoundStatement.hpp"
#include "../Script.hpp" #include "../Script.hpp"
#include "EvalValues/EvalValue.hpp" #include "EvalValues/EvalValue.hpp"
@ -12,10 +11,10 @@
#include "EvalValues/StringEvalValue.hpp" #include "EvalValues/StringEvalValue.hpp"
#include "EvaluationScope/EvaluationScope.hpp" #include "EvaluationScope/EvaluationScope.hpp"
using namespace boost; using namespace std;
class Evaluator { class Evaluator {
EvalValue* _result; shared_ptr<EvalValue> _result;
Script* _scriptData; Script* _scriptData;
EvaluationScope* _evaluationScope; EvaluationScope* _evaluationScope;
@ -25,31 +24,29 @@ class Evaluator {
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement); void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement); void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement);
EvalValue* EvaluateExpression(BoundExpression* expression); shared_ptr<EvalValue> EvaluateExpression(BoundExpression* expression);
NumericEvalValue* EvaluateIntegerExpression(BoundExpression* expression); shared_ptr<NumericEvalValue> EvaluateIntegerExpression(BoundExpression* expression);
BooleanEvalValue* EvaluateBoolExpression(BoundExpression* expression); shared_ptr<BooleanEvalValue> EvaluateBoolExpression(BoundExpression* expression);
StringEvalValue* EvaluateStringExpression(BoundExpression* expression); shared_ptr<StringEvalValue> EvaluateStringExpression(BoundExpression* expression);
EvalValue* EvaluateFunctionExpression(BoundExpression *expression); shared_ptr<EvalValue> EvaluateFunctionExpression(BoundExpression *expression);
EvalValue *EvaluateNilExpression(BoundExpression *expression); shared_ptr<EvalValue>EvaluateNilExpression(BoundExpression *expression);
NumericEvalValue* EvaluateIntegerBinary(BoundBinaryExpression* expression); shared_ptr<NumericEvalValue> EvaluateIntegerBinary(BoundBinaryExpression* expression);
BooleanEvalValue *EvaluateBooleanBinary(BoundBinaryExpression *expression); shared_ptr<BooleanEvalValue> EvaluateBooleanBinary(BoundBinaryExpression *expression);
StringEvalValue *EvaluateStringBinary(BoundBinaryExpression *expression); shared_ptr<StringEvalValue> EvaluateStringBinary(BoundBinaryExpression *expression);
NumericEvalValue* EvaluateIntegerUnary(BoundUnaryExpression* expression); shared_ptr<NumericEvalValue> EvaluateIntegerUnary(BoundUnaryExpression* expression);
BooleanEvalValue *EvaluateBooleanUnary(BoundUnaryExpression *expression); shared_ptr<BooleanEvalValue> EvaluateBooleanUnary(BoundUnaryExpression *expression);
EvalValue *EvaluateFunctionCallExpression(BoundExpression *expression); shared_ptr<EvalValue> EvaluateFunctionCallExpression(BoundExpression *expression);
EvalValue *GetVariable(BoundVariableExpression *expression); shared_ptr<EvalValue> GetVariable(BoundVariableExpression *expression);
public: public:
explicit Evaluator(Script* script){ explicit Evaluator(Script* script){
_scriptData = script; _scriptData = script;
_result = nullptr;
_evaluationScope = nullptr; _evaluationScope = nullptr;
} }
~Evaluator(){ ~Evaluator(){
delete _result;
delete _evaluationScope; delete _evaluationScope;
} }

View File

@ -4,19 +4,17 @@
#include "EvaluationException.hpp" #include "EvaluationException.hpp"
#include "../Script.hpp" #include "../Script.hpp"
NumericEvalValue *Evaluator::EvaluateIntegerUnary(BoundUnaryExpression *expression) { shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerUnary(BoundUnaryExpression *expression) {
switch (expression->GetOperation()){ switch (expression->GetOperation()){
case BoundUnaryOperation::Negation: case BoundUnaryOperation::Negation:
{ {
auto operandValue = EvaluateIntegerExpression(expression->GetOperand()); auto operandValue = EvaluateIntegerExpression(expression->GetOperand());
if (operandValue->IsFloat()){ if (operandValue->IsFloat()){
double f = operandValue->EvaluateFloat(); double f = operandValue->EvaluateFloat();
delete operandValue; return make_shared<FloatEvalValue>(-f);
return new FloatEvalValue(-f);
} else{ } else{
long l = operandValue->EvaluateInteger(); long l = operandValue->EvaluateInteger();
delete operandValue; return make_shared<IntegerEvalValue>(-l);
return new IntegerEvalValue(-l);
} }
} }
case BoundUnaryOperation::LogicalNegation: case BoundUnaryOperation::LogicalNegation:
@ -24,14 +22,13 @@ NumericEvalValue *Evaluator::EvaluateIntegerUnary(BoundUnaryExpression *expressi
} }
} }
BooleanEvalValue *Evaluator::EvaluateBooleanUnary(BoundUnaryExpression *expression) { shared_ptr<BooleanEvalValue> Evaluator::EvaluateBooleanUnary(BoundUnaryExpression *expression) {
switch (expression->GetOperation()){ switch (expression->GetOperation()){
case BoundUnaryOperation::LogicalNegation: case BoundUnaryOperation::LogicalNegation:
{ {
auto val = EvaluateBoolExpression(expression->GetOperand()); auto val = EvaluateBoolExpression(expression->GetOperand());
bool b = val->EvaluateBool(); bool b = val->EvaluateBool();
delete val; return make_shared<BooleanEvalValue>(!b);
return new BooleanEvalValue(!b);
} }
case BoundUnaryOperation::Negation: case BoundUnaryOperation::Negation:
throw; throw;

View File

@ -1,4 +1,5 @@
#include <algorithm>
#include "Parser.hpp" #include "Parser.hpp"
#include "ParsedStatements/ParsedStatement.hpp" #include "ParsedStatements/ParsedStatement.hpp"
#include "UnaryOperatorKind.hpp" #include "UnaryOperatorKind.hpp"
@ -65,7 +66,7 @@ ParsedStatement *Parser::ParseAssignment(IToken *current) {
return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> Value, expression, start, expression->GetEndPosition() - start); return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> Value, expression, start, expression->GetEndPosition() - start);
} }
ParsedStatement *Parser::ParseBlock(vector<TokenKind> endTokens) { ParsedStatement *Parser::ParseBlock(const vector<TokenKind>& endTokens) {
vector<ParsedStatement*> statements; vector<ParsedStatement*> statements;
while (true){ while (true){
auto next = this -> Next(); auto next = this -> Next();

View File

@ -1,9 +1,9 @@
#include <utility>
#ifndef PORYGONLANG_PARSER_HPP #ifndef PORYGONLANG_PARSER_HPP
#define PORYGONLANG_PARSER_HPP #define PORYGONLANG_PARSER_HPP
#include <utility>
#include <vector>
#include "ParsedStatements/ParsedStatement.hpp" #include "ParsedStatements/ParsedStatement.hpp"
#include "../Script.hpp" #include "../Script.hpp"
@ -27,7 +27,7 @@ class Parser {
ParsedStatement* ParseStatement(IToken* current); ParsedStatement* ParseStatement(IToken* current);
ParsedStatement* ParseAssignment(IToken* current); ParsedStatement* ParseAssignment(IToken* current);
ParsedStatement *ParseBlock(vector<TokenKind> endTokens); ParsedStatement *ParseBlock(const vector<TokenKind>& endTokens);
ParsedStatement* ParseFunctionDeclaration(IToken* current); ParsedStatement* ParseFunctionDeclaration(IToken* current);
ParsedExpression* ParseExpression(IToken* current); ParsedExpression* ParseExpression(IToken* current);

View File

@ -16,7 +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); _scriptVariables = new unordered_map<int, shared_ptr<EvalValue>>(0);
} }
void Script::Evaluate() { void Script::Evaluate() {
@ -26,11 +26,7 @@ void Script::Evaluate() {
Script::~Script() { Script::~Script() {
delete this -> Diagnostics; delete this -> Diagnostics;
delete this -> BoundScript; delete this -> BoundScript;
delete this -> _lastValue;
delete this -> _evaluator; delete this -> _evaluator;
for (auto v : *this->_scriptVariables){
delete v.second;
}
this->_scriptVariables->clear(); this->_scriptVariables->clear();
delete this->_scriptVariables; delete this->_scriptVariables;
} }
@ -58,7 +54,7 @@ void Script::Parse(string script) {
} }
EvalValue *Script::GetVariable(const string &key) { EvalValue *Script::GetVariable(const string &key) {
return _scriptVariables -> at(HashedString(key).GetHash()); return _scriptVariables -> at(HashedString(key).GetHash()).get();
} }
bool Script::HasVariable(const string &key) { bool Script::HasVariable(const string &key) {

View File

@ -19,9 +19,9 @@ using namespace std;
class Script { class Script {
friend class Evaluator; friend class Evaluator;
EvalValue* _lastValue; shared_ptr<EvalValue> _lastValue;
Evaluator* _evaluator; Evaluator* _evaluator;
unordered_map<int, EvalValue*>* _scriptVariables; unordered_map<int, shared_ptr<EvalValue>>* _scriptVariables;
explicit Script(); explicit Script();
@ -36,7 +36,7 @@ public:
void Evaluate(); void Evaluate();
EvalValue* GetLastValue(){ EvalValue* GetLastValue(){
return _lastValue; return _lastValue.get();
}; };
EvalValue* GetVariable(const string& key); EvalValue* GetVariable(const string& key);

View File

@ -25,4 +25,17 @@ TEST_CASE( "Define script function and call", "[integration]" ) {
delete script; delete script;
} }
TEST_CASE( "Define script function and call multiple times", "[integration]" ) {
Script* script = Script::Create("result = 0 function add(number a) result = result + a end add(1) add(4)");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto variable = script->GetVariable("add");
REQUIRE(variable != nullptr);
REQUIRE(variable->GetType()->GetClass() == TypeClass::Function);
auto result = script->GetVariable("result");
REQUIRE(result->GetType()->GetClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 5);
delete script;
}
#endif #endif