Implements complex tables
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
ba4fe888fa
commit
c022c91777
|
@ -1,6 +1,6 @@
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "Binder.hpp"
|
#include "Binder.hpp"
|
||||||
|
#include "../TableScriptType.hpp"
|
||||||
|
#include "BoundExpressions/BoundTableExpression.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s, BoundScope* scriptScope) {
|
BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s, BoundScope* scriptScope) {
|
||||||
|
@ -71,7 +71,7 @@ std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s){
|
||||||
switch (s.GetHash()){
|
switch (s.GetHash()){
|
||||||
case HashedString::ConstHash("number"): return std::make_shared<NumericScriptType>(false, false);
|
case HashedString::ConstHash("number"): return std::make_shared<NumericScriptType>(false, false);
|
||||||
case HashedString::ConstHash("bool"): return std::make_shared<ScriptType>(TypeClass::Bool);
|
case HashedString::ConstHash("bool"): return std::make_shared<ScriptType>(TypeClass::Bool);
|
||||||
case HashedString::ConstHash("string"): return std::make_shared<ScriptType>(TypeClass::String);
|
case HashedString::ConstHash("string"): return std::make_shared<StringScriptType>(false, 0);
|
||||||
default: return std::make_shared<ScriptType>(TypeClass::Error); // todo: change to userdata
|
default: return std::make_shared<ScriptType>(TypeClass::Error); // todo: change to userdata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,8 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){
|
||||||
return this->BindIndexExpression((IndexExpression*)expression);
|
return this->BindIndexExpression((IndexExpression*)expression);
|
||||||
case ParsedExpressionKind::NumericalTable:
|
case ParsedExpressionKind::NumericalTable:
|
||||||
return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression);
|
return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression);
|
||||||
|
case ParsedExpressionKind ::Table:
|
||||||
|
return this -> BindTableExpression((ParsedTableExpression*)expression);
|
||||||
|
|
||||||
case ParsedExpressionKind ::Bad:
|
case ParsedExpressionKind ::Bad:
|
||||||
return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength());
|
return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength());
|
||||||
|
@ -220,7 +222,8 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
|
||||||
expression->GetStartPosition(), expression->GetLength());
|
expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
} else if (boundLeftType->GetClass() == TypeClass::String){
|
} else if (boundLeftType->GetClass() == TypeClass::String){
|
||||||
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, std::make_shared<ScriptType>(TypeClass::String),
|
return new BoundBinaryExpression(boundLeft, boundRight, BoundBinaryOperation::Concatenation, std::make_shared<StringScriptType>(false,
|
||||||
|
0),
|
||||||
expression->GetStartPosition(), expression->GetLength());
|
expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -412,7 +415,19 @@ BoundExpression* Binder::BindNumericalTableExpression(ParsedNumericalTableExpres
|
||||||
if (valueType == nullptr){
|
if (valueType == nullptr){
|
||||||
valueType = std::make_shared<ScriptType>(TypeClass::Nil);
|
valueType = std::make_shared<ScriptType>(TypeClass::Nil);
|
||||||
}
|
}
|
||||||
auto keyType = std::make_shared<ScriptType>(TypeClass::Number);
|
auto tableType = std::make_shared<NumericalTableScriptType>(valueType);
|
||||||
auto tableType = std::make_shared<TableScriptType>(keyType, valueType);
|
|
||||||
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength());
|
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundExpression *Binder::BindTableExpression(ParsedTableExpression *expression) {
|
||||||
|
auto tableScope = new unordered_map<int, BoundVariable*>();
|
||||||
|
auto innerScope = new BoundScope(tableScope);
|
||||||
|
auto currentScope = this -> _scope;
|
||||||
|
this -> _scope = innerScope;
|
||||||
|
auto block = this -> BindBlockStatement(expression -> GetBlock());
|
||||||
|
this -> _scope = currentScope;
|
||||||
|
|
||||||
|
auto tableType = shared_ptr<TableScriptType>(new TableScriptType(tableScope, innerScope->GetDeepestScope()));
|
||||||
|
|
||||||
|
return new BoundTableExpression((BoundBlockStatement*)block, tableType, expression->GetStartPosition(), expression->GetLength());
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "BoundStatements/BoundStatement.hpp"
|
#include "BoundStatements/BoundStatement.hpp"
|
||||||
#include "../Script.hpp"
|
#include "../Script.hpp"
|
||||||
#include "BoundVariables/BoundScope.hpp"
|
#include "BoundVariables/BoundScope.hpp"
|
||||||
|
#include "../Parser/ParsedExpressions/ParsedTableExpression.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Binder {
|
class Binder {
|
||||||
|
@ -29,6 +31,7 @@ class Binder {
|
||||||
BoundExpression *BindFunctionCall(FunctionCallExpression *expression);
|
BoundExpression *BindFunctionCall(FunctionCallExpression *expression);
|
||||||
BoundExpression *BindIndexExpression(IndexExpression *expression);
|
BoundExpression *BindIndexExpression(IndexExpression *expression);
|
||||||
BoundExpression *BindNumericalTableExpression(ParsedNumericalTableExpression *expression);
|
BoundExpression *BindNumericalTableExpression(ParsedNumericalTableExpression *expression);
|
||||||
|
BoundExpression *BindTableExpression(ParsedTableExpression * expression);
|
||||||
public:
|
public:
|
||||||
static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s, BoundScope* scriptScope);
|
static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s, BoundScope* scriptScope);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ enum class BoundExpressionKind{
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
Index,
|
Index,
|
||||||
NumericalTable,
|
NumericalTable,
|
||||||
|
Table,
|
||||||
};
|
};
|
||||||
|
|
||||||
class BoundExpression{
|
class BoundExpression{
|
||||||
|
@ -102,7 +103,7 @@ class BoundLiteralStringExpression : public BoundExpression{
|
||||||
string _value;
|
string _value;
|
||||||
public:
|
public:
|
||||||
BoundLiteralStringExpression(string value, unsigned int start, unsigned int length)
|
BoundLiteralStringExpression(string value, unsigned int start, unsigned int length)
|
||||||
: BoundExpression(start, length, make_shared<ScriptType>(TypeClass::String)){
|
: BoundExpression(start, length, make_shared<StringScriptType>(true, HashedString::ConstHash(value.c_str()))){
|
||||||
_value = std::move(value);
|
_value = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,11 +277,11 @@ class BoundNumericalTableExpression : public BoundExpression{
|
||||||
vector<BoundExpression*> _expressions;
|
vector<BoundExpression*> _expressions;
|
||||||
public:
|
public:
|
||||||
BoundNumericalTableExpression(vector<BoundExpression*> expressions, shared_ptr<ScriptType> type, unsigned int start, unsigned int length)
|
BoundNumericalTableExpression(vector<BoundExpression*> expressions, shared_ptr<ScriptType> type, unsigned int start, unsigned int length)
|
||||||
: BoundExpression(start, length, type){
|
: BoundExpression(start, length, std::move(type)){
|
||||||
_expressions = std::move(expressions);
|
_expressions = std::move(expressions);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BoundNumericalTableExpression(){
|
~BoundNumericalTableExpression() final{
|
||||||
for (auto e: _expressions){
|
for (auto e: _expressions){
|
||||||
delete e;
|
delete e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORYGONLANG_BOUNDTABLEEXPRESSION_HPP
|
||||||
|
#define PORYGONLANG_BOUNDTABLEEXPRESSION_HPP
|
||||||
|
|
||||||
|
#include "../BoundStatements/BoundStatement.hpp"
|
||||||
|
|
||||||
|
class BoundTableExpression : public BoundExpression{
|
||||||
|
BoundBlockStatement* _block;
|
||||||
|
public:
|
||||||
|
BoundTableExpression(BoundBlockStatement* block, shared_ptr<ScriptType> type, unsigned int start, unsigned int length)
|
||||||
|
: BoundExpression(start, length, std::move(type)){
|
||||||
|
_block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BoundTableExpression() final{
|
||||||
|
delete _block;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundExpressionKind GetKind() final{
|
||||||
|
return BoundExpressionKind ::Table;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundBlockStatement* GetBlock(){
|
||||||
|
return _block;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "BoundExpression.hpp"
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_BOUNDTABLEEXPRESSION_HPP
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "BoundScope.hpp"
|
#include "BoundScope.hpp"
|
||||||
|
|
||||||
BoundScope::BoundScope(unordered_map<int, BoundVariable *> *scriptScope) {
|
BoundScope::BoundScope(unordered_map<int, BoundVariable *> *tableScope) {
|
||||||
_scriptScope = scriptScope;
|
_tableScope = tableScope;
|
||||||
_currentScope = 1;
|
_currentScope = 1;
|
||||||
_deepestScope = 1;
|
_deepestScope = 1;
|
||||||
auto localUpmostScope = new unordered_map<int, BoundVariable*>();
|
auto localUpmostScope = new unordered_map<int, BoundVariable*>();
|
||||||
|
@ -41,8 +41,8 @@ void BoundScope::GoOuterScope() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int BoundScope::Exists(int key) {
|
int BoundScope::Exists(int key) {
|
||||||
auto found = this -> _scriptScope -> find(key);
|
auto found = this -> _tableScope -> find(key);
|
||||||
if (found != _scriptScope -> end()){
|
if (found != _tableScope -> end()){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (int i = _currentScope - 1; i >= 0; i--){
|
for (int i = _currentScope - 1; i >= 0; i--){
|
||||||
|
@ -57,8 +57,8 @@ int BoundScope::Exists(int key) {
|
||||||
|
|
||||||
BoundVariable *BoundScope::GetVariable(int scope, int identifier) {
|
BoundVariable *BoundScope::GetVariable(int scope, int identifier) {
|
||||||
if (scope == 0){
|
if (scope == 0){
|
||||||
auto find = this -> _scriptScope->find(identifier);
|
auto find = this -> _tableScope->find(identifier);
|
||||||
if (find != _scriptScope->end()){
|
if (find != _tableScope->end()){
|
||||||
return find -> second;
|
return find -> second;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -85,7 +85,7 @@ VariableAssignment BoundScope::AssignVariable(int identifier, const std::shared_
|
||||||
int exists = this->Exists(identifier);
|
int exists = this->Exists(identifier);
|
||||||
if (exists == -1){
|
if (exists == -1){
|
||||||
// Creation
|
// Creation
|
||||||
_scriptScope->insert({identifier, new BoundVariable(type)});
|
_tableScope->insert({identifier, new BoundVariable(type)});
|
||||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true));
|
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true));
|
||||||
} else{
|
} else{
|
||||||
// Assigning
|
// Assigning
|
||||||
|
|
|
@ -14,12 +14,12 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class BoundScope {
|
class BoundScope {
|
||||||
unordered_map<int, BoundVariable*>* _scriptScope;
|
unordered_map<int, BoundVariable*>* _tableScope;
|
||||||
vector<unordered_map<int, BoundVariable*>*> _localScope;
|
vector<unordered_map<int, BoundVariable*>*> _localScope;
|
||||||
int _currentScope;
|
int _currentScope;
|
||||||
int _deepestScope;
|
int _deepestScope;
|
||||||
public:
|
public:
|
||||||
explicit BoundScope(unordered_map<int, BoundVariable*> *scriptScope);
|
explicit BoundScope(unordered_map<int, BoundVariable*> *tableScope);
|
||||||
~BoundScope();
|
~BoundScope();
|
||||||
|
|
||||||
void GoInnerScope();
|
void GoInnerScope();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "EvalValue.hpp"
|
#include "EvalValue.hpp"
|
||||||
|
#include "../../Utilities/HashedString.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -14,8 +15,8 @@ class StringEvalValue : public EvalValue{
|
||||||
public:
|
public:
|
||||||
explicit StringEvalValue(string s){
|
explicit StringEvalValue(string s){
|
||||||
_value = move(s);
|
_value = move(s);
|
||||||
_type = std::make_shared<ScriptType>(TypeClass::String);
|
_hash = HashedString::ConstHash (_value.c_str());
|
||||||
_hash = std::hash<string>{}(_value);
|
_type = std::make_shared<StringScriptType>(true, _hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ScriptType> GetType() final{
|
std::shared_ptr<ScriptType> GetType() final{
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_TABLEEVALVALUE_HPP
|
#ifndef PORYGONLANG_TABLEEVALVALUE_HPP
|
||||||
#define PORYGONLANG_TABLEEVALVALUE_HPP
|
#define PORYGONLANG_TABLEEVALVALUE_HPP
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -45,6 +43,11 @@ public:
|
||||||
auto hash = val->GetHashCode();
|
auto hash = val->GetHashCode();
|
||||||
return this -> _table->at(hash);
|
return this -> _table->at(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> IndexValue(const char* val){
|
||||||
|
auto hash = HashedString::ConstHash(val);
|
||||||
|
return this -> _table -> at(hash);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "EvaluationScope.hpp"
|
#include "EvaluationScope.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
EvaluationScope::EvaluationScope(unordered_map<int, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) {
|
EvaluationScope::EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope) {
|
||||||
_scriptScope = scriptVariables;
|
_scriptScope = scriptVariables;
|
||||||
_localScope = vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>>(deepestScope);
|
_localScope = vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>>(deepestScope);
|
||||||
for (int i = 0; i < deepestScope; i++){
|
for (int i = 0; i < deepestScope; i++){
|
||||||
|
@ -42,6 +42,7 @@ EvaluationScope* EvaluationScope::CreateBranchingScope(int index){
|
||||||
for (int i = 0; i < index; i++){
|
for (int i = 0; i < index; i++){
|
||||||
scope->_localScope[i] = this->_localScope[i];
|
scope->_localScope[i] = this->_localScope[i];
|
||||||
}
|
}
|
||||||
|
scope->_currentScope = index;
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +50,11 @@ void EvaluationScope::OuterScope() {
|
||||||
_currentScope++;
|
_currentScope++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvaluationScope::InnerScope() {
|
void EvaluationScope::InnerScope(bool clearScope) {
|
||||||
|
if (clearScope){
|
||||||
auto scope = this->_localScope[_currentScope];
|
auto scope = this->_localScope[_currentScope];
|
||||||
scope->clear();
|
scope->clear();
|
||||||
|
}
|
||||||
_currentScope--;
|
_currentScope--;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,17 @@
|
||||||
#include "../EvalValues/EvalValue.hpp"
|
#include "../EvalValues/EvalValue.hpp"
|
||||||
|
|
||||||
class EvaluationScope {
|
class EvaluationScope {
|
||||||
unordered_map<int, shared_ptr<EvalValue>>* _scriptScope;
|
unordered_map<size_t, shared_ptr<EvalValue>>* _scriptScope;
|
||||||
vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>> _localScope;
|
vector<shared_ptr<unordered_map<int, shared_ptr<EvalValue>>>> _localScope;
|
||||||
int _currentScope;
|
int _currentScope;
|
||||||
public:
|
public:
|
||||||
explicit EvaluationScope(unordered_map<int, shared_ptr<EvalValue>>* scriptVariables, int deepestScope);
|
explicit EvaluationScope(unordered_map<size_t, shared_ptr<EvalValue>>* scriptVariables, int deepestScope);
|
||||||
~EvaluationScope() = default;
|
~EvaluationScope() = default;
|
||||||
|
|
||||||
void CreateVariable(int scope, int id, const shared_ptr<EvalValue>& value);
|
void CreateVariable(int scope, int id, const shared_ptr<EvalValue>& value);
|
||||||
void SetVariable(int scope, int id, const shared_ptr<EvalValue>& value);
|
void SetVariable(int scope, int id, const shared_ptr<EvalValue>& value);
|
||||||
void OuterScope();
|
void OuterScope();
|
||||||
void InnerScope();
|
void InnerScope(bool clearScope = true);
|
||||||
shared_ptr<EvalValue> GetVariable(int scope, int id);
|
shared_ptr<EvalValue> GetVariable(int scope, int id);
|
||||||
|
|
||||||
EvaluationScope* CreateBranchingScope(int index);
|
EvaluationScope* CreateBranchingScope(int index);
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
#include "EvaluationScope/EvaluationScope.hpp"
|
#include "EvaluationScope/EvaluationScope.hpp"
|
||||||
#include "EvalValues/ScriptFunctionEvalValue.hpp"
|
#include "EvalValues/ScriptFunctionEvalValue.hpp"
|
||||||
#include "EvalValues/TableEvalValue.hpp"
|
#include "EvalValues/TableEvalValue.hpp"
|
||||||
|
#include "../Binder/BoundExpressions/BoundTableExpression.hpp"
|
||||||
|
#include "../TableScriptType.hpp"
|
||||||
|
|
||||||
using namespace std;
|
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, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Evaluator::EvaluateStatement(BoundStatement *statement) {
|
void Evaluator::EvaluateStatement(BoundStatement *statement) {
|
||||||
|
@ -19,7 +21,7 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) {
|
||||||
return;
|
return;
|
||||||
switch (statement->GetKind()){
|
switch (statement->GetKind()){
|
||||||
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, true);
|
||||||
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 ::Assignment: return this -> EvaluateAssignmentStatement((BoundAssignmentStatement*)statement);
|
||||||
case BoundStatementKind ::FunctionDeclaration: return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement*)statement);
|
case BoundStatementKind ::FunctionDeclaration: return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement*)statement);
|
||||||
|
@ -31,14 +33,14 @@ void Evaluator::EvaluateStatement(BoundStatement *statement) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement) {
|
void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope) {
|
||||||
this->_evaluationScope->OuterScope();
|
this->_evaluationScope->OuterScope();
|
||||||
for (auto s: statement->GetStatements()){
|
for (auto s: statement->GetStatements()){
|
||||||
this -> EvaluateStatement(s);
|
this -> EvaluateStatement(s);
|
||||||
if (this->_hasReturned)
|
if (this->_hasReturned)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->_evaluationScope->InnerScope();
|
this->_evaluationScope->InnerScope(clearScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
|
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
|
||||||
|
@ -122,6 +124,7 @@ shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(BoundExpressio
|
||||||
case BoundExpressionKind ::LiteralBool:
|
case BoundExpressionKind ::LiteralBool:
|
||||||
case BoundExpressionKind ::Bad:
|
case BoundExpressionKind ::Bad:
|
||||||
case BoundExpressionKind::NumericalTable:
|
case BoundExpressionKind::NumericalTable:
|
||||||
|
case BoundExpressionKind::Table:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,6 +143,7 @@ shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(BoundExpression *
|
||||||
case BoundExpressionKind::LiteralFloat:
|
case BoundExpressionKind::LiteralFloat:
|
||||||
case BoundExpressionKind::LiteralString:
|
case BoundExpressionKind::LiteralString:
|
||||||
case BoundExpressionKind::NumericalTable:
|
case BoundExpressionKind::NumericalTable:
|
||||||
|
case BoundExpressionKind::Table:
|
||||||
throw;
|
throw;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -161,6 +165,7 @@ shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(BoundExpression
|
||||||
case BoundExpressionKind::LiteralBool:
|
case BoundExpressionKind::LiteralBool:
|
||||||
case BoundExpressionKind::Unary:
|
case BoundExpressionKind::Unary:
|
||||||
case BoundExpressionKind::NumericalTable:
|
case BoundExpressionKind::NumericalTable:
|
||||||
|
case BoundExpressionKind::Table:
|
||||||
throw;
|
throw;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -187,8 +192,9 @@ shared_ptr<EvalValue> Evaluator::EvaluateTableExpression(BoundExpression * expre
|
||||||
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression);
|
case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression);
|
||||||
case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression);
|
case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression);
|
||||||
case BoundExpressionKind ::NumericalTable: return this-> EvaluateNumericTableExpression(expression);
|
case BoundExpressionKind ::NumericalTable: return this-> EvaluateNumericTableExpression(expression);
|
||||||
|
case BoundExpressionKind ::Table: return this -> EvaluateComplexTableExpression(expression);
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +228,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
||||||
auto key = parameterKeys.at(i);
|
auto key = parameterKeys.at(i);
|
||||||
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
||||||
}
|
}
|
||||||
this->_evaluationScope->OuterScope();
|
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
|
||||||
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
|
||||||
|
|
||||||
delete this->_evaluationScope;
|
delete this->_evaluationScope;
|
||||||
this->_evaluationScope = originalScope;
|
this->_evaluationScope = originalScope;
|
||||||
|
@ -237,6 +242,12 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
|
||||||
auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType());
|
auto type = std::dynamic_pointer_cast<FunctionScriptType>(function->GetType());
|
||||||
auto parameterTypes = type->GetParameterTypes();
|
auto parameterTypes = type->GetParameterTypes();
|
||||||
auto parameterKeys = type->GetParameterKeys();
|
auto parameterKeys = type->GetParameterKeys();
|
||||||
|
|
||||||
|
auto scope = type -> GetScopeIndex();
|
||||||
|
auto originalScope = this->_evaluationScope;
|
||||||
|
auto functionScope = this->_evaluationScope->CreateBranchingScope(scope);
|
||||||
|
this->_evaluationScope = functionScope;
|
||||||
|
|
||||||
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
|
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++){
|
||||||
auto parameter = parameters[i];
|
auto parameter = parameters[i];
|
||||||
auto requiredType = parameterTypes.at(i);
|
auto requiredType = parameterTypes.at(i);
|
||||||
|
@ -246,7 +257,9 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunction(ScriptFunctionEvalValue *funct
|
||||||
auto key = parameterKeys.at(i);
|
auto key = parameterKeys.at(i);
|
||||||
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
this->_evaluationScope->CreateVariable(key->GetScopeId(), key->GetIdentifier(), parameter->Clone());
|
||||||
}
|
}
|
||||||
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
this->EvaluateBlockStatement(function->GetInnerBlock().get(), true);
|
||||||
|
delete this->_evaluationScope;
|
||||||
|
this->_evaluationScope = originalScope;
|
||||||
this->_hasReturned = false;
|
this->_hasReturned = false;
|
||||||
auto r = this -> _returnValue;
|
auto r = this -> _returnValue;
|
||||||
this -> _returnValue = nullptr;
|
this -> _returnValue = nullptr;
|
||||||
|
@ -272,3 +285,18 @@ shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(BoundExpression
|
||||||
return make_shared<TableEvalValue>(valuesPointer, tableExpression->GetType());
|
return make_shared<TableEvalValue>(valuesPointer, tableExpression->GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> Evaluator::EvaluateComplexTableExpression(BoundExpression *expression) {
|
||||||
|
auto tableExpression = (BoundTableExpression*)expression;
|
||||||
|
auto type = dynamic_pointer_cast<TableScriptType>(tableExpression->GetType());
|
||||||
|
auto declaredVars = type -> GetValues();
|
||||||
|
auto variables = make_shared<unordered_map<size_t, shared_ptr<EvalValue>>>(declaredVars->size());
|
||||||
|
for (auto i : *declaredVars){
|
||||||
|
variables->insert({i.first, nullptr});
|
||||||
|
}
|
||||||
|
auto evaluator = new EvaluationScope(variables.get(), type -> GetDeepestScope());
|
||||||
|
auto currentEvaluator = this -> _evaluationScope;
|
||||||
|
this -> _evaluationScope = evaluator;
|
||||||
|
this -> EvaluateBlockStatement(tableExpression->GetBlock(), false);
|
||||||
|
this -> _evaluationScope = currentEvaluator;
|
||||||
|
return shared_ptr<TableEvalValue>(new TableEvalValue(variables, tableExpression->GetType()));
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Evaluator {
|
||||||
EvaluationScope* _evaluationScope;
|
EvaluationScope* _evaluationScope;
|
||||||
|
|
||||||
void EvaluateStatement(BoundStatement* statement);
|
void EvaluateStatement(BoundStatement* statement);
|
||||||
void EvaluateBlockStatement(BoundBlockStatement* statement);
|
void EvaluateBlockStatement(BoundBlockStatement* statement, bool clearScope);
|
||||||
void EvaluateExpressionStatement(BoundExpressionStatement* statement);
|
void EvaluateExpressionStatement(BoundExpressionStatement* statement);
|
||||||
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
|
void EvaluateAssignmentStatement(BoundAssignmentStatement* statement);
|
||||||
void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement);
|
void EvaluateFunctionDeclarationStatement(BoundFunctionDeclarationStatement *statement);
|
||||||
|
@ -67,6 +67,8 @@ public:
|
||||||
EvalValue* GetLastValue(){
|
EvalValue* GetLastValue(){
|
||||||
return _lastValue.get();
|
return _lastValue.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> EvaluateComplexTableExpression(BoundExpression *expression);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum class ParsedExpressionKind{
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
Indexer,
|
Indexer,
|
||||||
NumericalTable,
|
NumericalTable,
|
||||||
|
Table,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParsedExpression {
|
class ParsedExpression {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
#ifndef PORYGONLANG_PARSEDTABLEEXPRESSION_HPP
|
||||||
|
#define PORYGONLANG_PARSEDTABLEEXPRESSION_HPP
|
||||||
|
|
||||||
|
#include "ParsedExpression.hpp"
|
||||||
|
#include "../ParsedStatements/ParsedStatement.hpp"
|
||||||
|
|
||||||
|
class ParsedTableExpression : public ParsedExpression{
|
||||||
|
ParsedBlockStatement* _block;
|
||||||
|
public:
|
||||||
|
ParsedTableExpression(ParsedBlockStatement* block, unsigned int start, unsigned int length)
|
||||||
|
: ParsedExpression(start, length){
|
||||||
|
_block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ParsedTableExpression() final{
|
||||||
|
delete _block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParsedBlockStatement* GetBlock(){
|
||||||
|
return _block;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParsedExpressionKind GetKind() final{
|
||||||
|
return ParsedExpressionKind::Table;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "ParsedExpression.hpp"
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_PARSEDTABLEEXPRESSION_HPP
|
|
@ -5,6 +5,7 @@
|
||||||
#include "UnaryOperatorKind.hpp"
|
#include "UnaryOperatorKind.hpp"
|
||||||
#include "BinaryOperatorKind.hpp"
|
#include "BinaryOperatorKind.hpp"
|
||||||
#include "TypedVariableIdentifier.hpp"
|
#include "TypedVariableIdentifier.hpp"
|
||||||
|
#include "ParsedExpressions/ParsedTableExpression.hpp"
|
||||||
|
|
||||||
|
|
||||||
ParsedScriptStatement* Parser::Parse() {
|
ParsedScriptStatement* Parser::Parse() {
|
||||||
|
@ -372,6 +373,7 @@ ParsedExpression* Parser::ParseTableExpression(IToken* current){
|
||||||
auto start = current->GetStartPosition();
|
auto start = current->GetStartPosition();
|
||||||
return new ParsedNumericalTableExpression({}, start, this -> Peek()->GetEndPosition() - start);
|
return new ParsedNumericalTableExpression({}, start, this -> Peek()->GetEndPosition() - start);
|
||||||
}
|
}
|
||||||
|
auto start = current->GetStartPosition();
|
||||||
auto firstItem = this->ParseStatement(this -> Next());
|
auto firstItem = this->ParseStatement(this -> Next());
|
||||||
// If the first item is an expression, and is followed by a comma, we're dealing with a simple {1, 2, 3} kind of array
|
// If the first item is an expression, and is followed by a comma, we're dealing with a simple {1, 2, 3} kind of array
|
||||||
if (firstItem->GetKind() == ParsedStatementKind::Expression &&
|
if (firstItem->GetKind() == ParsedStatementKind::Expression &&
|
||||||
|
@ -389,7 +391,6 @@ ParsedExpression* Parser::ParseTableExpression(IToken* current){
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto start = current->GetStartPosition();
|
|
||||||
if (hasErrors){
|
if (hasErrors){
|
||||||
return new BadExpression(start, n->GetEndPosition() - start);
|
return new BadExpression(start, n->GetEndPosition() - start);
|
||||||
}
|
}
|
||||||
|
@ -400,7 +401,8 @@ ParsedExpression* Parser::ParseTableExpression(IToken* current){
|
||||||
auto block = (ParsedBlockStatement*)this -> ParseBlock({TokenKind ::CloseCurlyBracket});
|
auto block = (ParsedBlockStatement*)this -> ParseBlock({TokenKind ::CloseCurlyBracket});
|
||||||
auto statements = block->GetStatements();
|
auto statements = block->GetStatements();
|
||||||
statements->insert(statements->begin(), firstItem);
|
statements->insert(statements->begin(), firstItem);
|
||||||
throw "not implemented TODO";
|
auto closeToken = this -> PeekAt(-1);
|
||||||
|
return new ParsedTableExpression(block, start, closeToken->GetEndPosition() - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ Script::Script() {
|
||||||
Diagnostics = new DiagnosticsHolder();
|
Diagnostics = new DiagnosticsHolder();
|
||||||
_evaluator = new Evaluator(this);
|
_evaluator = new Evaluator(this);
|
||||||
_boundScript = nullptr;
|
_boundScript = nullptr;
|
||||||
_scriptVariables = new unordered_map<int, shared_ptr<EvalValue>>(0);
|
_scriptVariables = new unordered_map<size_t, shared_ptr<EvalValue>>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::Evaluate() {
|
void Script::Evaluate() {
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Script {
|
||||||
friend class Evaluator;
|
friend class Evaluator;
|
||||||
|
|
||||||
Evaluator* _evaluator;
|
Evaluator* _evaluator;
|
||||||
unordered_map<int, shared_ptr<EvalValue>>* _scriptVariables;
|
unordered_map<size_t, shared_ptr<EvalValue>>* _scriptVariables;
|
||||||
BoundScriptStatement* _boundScript;
|
BoundScriptStatement* _boundScript;
|
||||||
shared_ptr<ScriptType> _returnType;
|
shared_ptr<ScriptType> _returnType;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Binder/BoundVariables/BoundVariableKey.hpp"
|
#include "Binder/BoundVariables/BoundVariableKey.hpp"
|
||||||
|
#include "Utilities/HashedString.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -73,6 +74,24 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StringScriptType : public ScriptType{
|
||||||
|
bool _isKnownAtBind;
|
||||||
|
int _hashValue;
|
||||||
|
public:
|
||||||
|
explicit StringScriptType(bool knownAtBind, int hashValue): ScriptType(TypeClass::String){
|
||||||
|
_isKnownAtBind = knownAtBind;
|
||||||
|
_hashValue = hashValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsKnownAtBind(){
|
||||||
|
return _isKnownAtBind;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetHashValue(){
|
||||||
|
return _hashValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class FunctionScriptType : public ScriptType{
|
class FunctionScriptType : public ScriptType{
|
||||||
shared_ptr<ScriptType> _returnType;
|
shared_ptr<ScriptType> _returnType;
|
||||||
vector<shared_ptr<ScriptType>> _parameterTypes;
|
vector<shared_ptr<ScriptType>> _parameterTypes;
|
||||||
|
@ -104,24 +123,22 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TableScriptType : public ScriptType{
|
class NumericalTableScriptType : public ScriptType{
|
||||||
shared_ptr<ScriptType> _keyType;
|
|
||||||
shared_ptr<ScriptType> _valueType;
|
shared_ptr<ScriptType> _valueType;
|
||||||
// Consider adding a check whether the table actually contains a type if every key is static.
|
// Consider adding a check whether the table actually contains a type if every key is static.
|
||||||
public:
|
public:
|
||||||
TableScriptType(shared_ptr<ScriptType> keyType, shared_ptr<ScriptType> valueType) : ScriptType(TypeClass::Table){
|
explicit NumericalTableScriptType(shared_ptr<ScriptType> valueType) : ScriptType(TypeClass::Table){
|
||||||
_keyType = std::move(keyType);
|
|
||||||
_valueType = std::move(valueType);
|
_valueType = std::move(valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanBeIndexedWith(ScriptType* indexer) final{
|
bool CanBeIndexedWith(ScriptType* indexer) final{
|
||||||
return _keyType.get()->operator==(indexer);
|
return indexer->GetClass() == TypeClass ::Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
||||||
return _valueType;
|
return _valueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //PORYGONLANG_SCRIPTTYPE_HPP
|
#endif //PORYGONLANG_SCRIPTTYPE_HPP
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
#ifndef PORYGONLANG_TABLESCRIPTTYPE_HPP
|
||||||
|
#define PORYGONLANG_TABLESCRIPTTYPE_HPP
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "Binder/BoundVariables/BoundVariable.hpp"
|
||||||
|
|
||||||
|
class TableScriptType : public ScriptType{
|
||||||
|
unordered_map<int, BoundVariable*>* _values;
|
||||||
|
int _deepestScope;
|
||||||
|
public:
|
||||||
|
explicit TableScriptType(unordered_map<int, BoundVariable*>* values, int deepestScope) : ScriptType(TypeClass::Table){
|
||||||
|
_values = values;
|
||||||
|
_deepestScope = deepestScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TableScriptType() final{
|
||||||
|
for (auto i : *_values){
|
||||||
|
delete i.second;
|
||||||
|
}
|
||||||
|
delete _values;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanBeIndexedWith(ScriptType* indexer) final{
|
||||||
|
return indexer->GetClass() == TypeClass ::String;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
||||||
|
auto stringKey = (StringScriptType*)indexer;
|
||||||
|
if (stringKey->IsKnownAtBind()){
|
||||||
|
return _values-> at(stringKey->GetHashValue())->GetType();
|
||||||
|
}
|
||||||
|
throw "TODO: indexing with dynamic keys";
|
||||||
|
}
|
||||||
|
|
||||||
|
unordered_map<int, BoundVariable*>* GetValues(){
|
||||||
|
return _values;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetDeepestScope(){
|
||||||
|
return _deepestScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "ScriptType.hpp"
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_TABLESCRIPTTYPE_HPP
|
|
@ -1,6 +1,7 @@
|
||||||
#ifdef TESTS_BUILD
|
#ifdef TESTS_BUILD
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "../src/Script.hpp"
|
#include "../src/Script.hpp"
|
||||||
|
#include "../../src/Evaluator/EvalValues/TableEvalValue.hpp"
|
||||||
|
|
||||||
TEST_CASE( "Create empty table", "[integration]" ) {
|
TEST_CASE( "Create empty table", "[integration]" ) {
|
||||||
Script* script = Script::Create("table = {}");
|
Script* script = Script::Create("table = {}");
|
||||||
|
@ -43,6 +44,24 @@ result = table[3]
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Create complex table", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(
|
||||||
|
R"(
|
||||||
|
table = {
|
||||||
|
foo = 'test'
|
||||||
|
bar = 100
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
script->Evaluate();
|
||||||
|
auto variable = script->GetVariable("table");
|
||||||
|
REQUIRE(variable != nullptr);
|
||||||
|
auto table = (TableEvalValue*)variable;
|
||||||
|
CHECK(*table->IndexValue("foo")->EvaluateString() == "test");
|
||||||
|
CHECK(table->IndexValue("bar")->EvaluateInteger() == 100);
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -44,5 +44,22 @@ TEST_CASE( "Create local variable and use", "[integration]" ) {
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Local variables in upmost scope persist", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(R"(
|
||||||
|
result = 0
|
||||||
|
local foo = 0
|
||||||
|
function bar()
|
||||||
|
foo = foo + 1
|
||||||
|
result = foo
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
script->Evaluate();
|
||||||
|
script -> CallFunction("bar", {});
|
||||||
|
script -> CallFunction("bar", {});
|
||||||
|
auto variable = script->GetVariable("result");
|
||||||
|
REQUIRE(variable != nullptr);
|
||||||
|
CHECK(variable->EvaluateInteger() == 2);
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue