Rework evaluation to use shared pointers, fix bugs
This commit is contained in:
parent
4408cf00cd
commit
6206fef4c5
|
@ -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));
|
||||||
|
|
|
@ -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(){
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
|
@ -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{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue