diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 749c34b..d21b70b 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -1,3 +1,5 @@ +#include + #include "Binder.hpp" #include @@ -174,6 +176,8 @@ BoundExpression* Binder::BindExpression(ParsedExpression* expression){ case ParsedExpressionKind ::Indexer: return this->BindIndexExpression((IndexExpression*)expression); + case ParsedExpressionKind::NumericalTable: + return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression); case ParsedExpressionKind ::Bad: return new BoundBadExpression(expression->GetStartPosition(), expression-> GetLength()); @@ -386,7 +390,29 @@ BoundExpression *Binder::BindIndexExpression(IndexExpression *expression) { index->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } - auto resultType = shared_ptr(indexer->GetType()->GetIndexedType(index->GetType().get())); + auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); } +BoundExpression* Binder::BindNumericalTableExpression(ParsedNumericalTableExpression* expression){ + auto expressions = expression->GetExpressions(); + auto boundExpressions = vector(expressions.size()); + shared_ptr valueType = nullptr; + if (!boundExpressions.empty()){ + boundExpressions[0] = this -> BindExpression(expressions[0]); + valueType = boundExpressions[0] -> GetType(); + for (int i = 1; i < expressions.size(); i++){ + boundExpressions[i] = this -> BindExpression(expressions[i]); + if (boundExpressions[i] -> GetType().get()->operator!=(valueType.get())){ + this->_scriptData->Diagnostics->LogError(DiagnosticCode::InvalidTableValueType, boundExpressions[i]->GetStartPosition(), + boundExpressions[i]->GetLength()); + } + } + } + if (valueType == nullptr){ + valueType = std::make_shared(TypeClass::Nil); + } + auto keyType = std::make_shared(TypeClass::Number); + auto tableType = std::make_shared(keyType, valueType); + return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength()); +} \ No newline at end of file diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index 3cdc6bc..bdeba8f 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -28,6 +28,7 @@ class Binder { BoundExpression *BindUnaryOperator(UnaryExpression *expression); BoundExpression *BindFunctionCall(FunctionCallExpression *expression); BoundExpression *BindIndexExpression(IndexExpression *expression); + BoundExpression *BindNumericalTableExpression(ParsedNumericalTableExpression *expression); public: static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s, BoundScope* scriptScope); diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index b7532eb..bf9796f 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -1,15 +1,10 @@ -#include - -#include - -#include - #ifndef PORYGONLANG_BOUNDEXPRESSION_HPP #define PORYGONLANG_BOUNDEXPRESSION_HPP #include #include +#include #include "../../ScriptType.hpp" #include "../BoundOperators.hpp" #include "../BoundVariables/BoundVariableKey.hpp" @@ -29,6 +24,7 @@ enum class BoundExpressionKind{ Binary, FunctionCall, Index, + NumericalTable, }; class BoundExpression{ @@ -276,5 +272,28 @@ public: } }; +class BoundNumericalTableExpression : public BoundExpression{ + vector _expressions; +public: + BoundNumericalTableExpression(vector expressions, shared_ptr type, unsigned int start, unsigned int length) + : BoundExpression(start, length, type){ + _expressions = std::move(expressions); + } + + ~BoundNumericalTableExpression(){ + for (auto e: _expressions){ + delete e; + } + } + + BoundExpressionKind GetKind() final{ + return BoundExpressionKind ::NumericalTable; + } + + vector GetExpressions(){ + return _expressions; + } +}; + #endif //PORYGONLANG_BOUNDEXPRESSION_HPP diff --git a/src/Diagnostics/DiagnosticCode.hpp b/src/Diagnostics/DiagnosticCode.hpp index c7df63f..4d38bbd 100644 --- a/src/Diagnostics/DiagnosticCode.hpp +++ b/src/Diagnostics/DiagnosticCode.hpp @@ -21,6 +21,7 @@ enum class DiagnosticCode{ CantIndex, InvalidReturnType, ConditionNotABool, + InvalidTableValueType, }; #endif //PORYGONLANG_DIAGNOSTICCODE_HPP diff --git a/src/Evaluator/EvalValues/EvalValue.hpp b/src/Evaluator/EvalValues/EvalValue.hpp index ddd1237..f3a1f4b 100644 --- a/src/Evaluator/EvalValues/EvalValue.hpp +++ b/src/Evaluator/EvalValues/EvalValue.hpp @@ -35,7 +35,9 @@ public: throw EvaluationException("Can't evaluate this EvalValue as string."); } - virtual EvalValue* IndexValue(EvalValue* val){ + virtual std::size_t GetHashCode() = 0; + + virtual shared_ptr IndexValue(EvalValue* val){ throw EvaluationException("Can't index this EvalValue"); } }; @@ -66,6 +68,10 @@ public: return false; return this->EvaluateBool() == b->EvaluateBool(); }; + + std::size_t GetHashCode() final{ + return _value; + } }; #endif //PORYGONLANG_EVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/NumericEvalValue.hpp b/src/Evaluator/EvalValues/NumericEvalValue.hpp index 602a87b..21991b4 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.hpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.hpp @@ -49,6 +49,10 @@ public: shared_ptr Clone() final{ return make_shared(_value); } + + std::size_t GetHashCode() final{ + return std::hash{}(_value); + } }; class FloatEvalValue : public NumericEvalValue{ @@ -71,6 +75,10 @@ public: shared_ptr Clone() final{ return make_shared(_value); } + + std::size_t GetHashCode() final{ + return std::hash{}(_value); + } }; #endif //PORYGONLANG_NUMERICEVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp b/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp index e04fc99..c53e910 100644 --- a/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp +++ b/src/Evaluator/EvalValues/ScriptFunctionEvalValue.hpp @@ -14,11 +14,20 @@ class ScriptFunctionEvalValue : public EvalValue{ std::shared_ptr _innerBlock; std::shared_ptr _type; + std::size_t _hash; + explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, std::shared_ptr type, size_t hash) + : _type(std::move(type)) + { + _innerBlock = std::move(innerBlock); + _hash = hash; + } + public: explicit ScriptFunctionEvalValue(std::shared_ptr innerBlock, std::shared_ptr type) : _type(std::move(type)) { _innerBlock = std::move(innerBlock); + _hash = rand(); } std::shared_ptr GetType() final{ @@ -26,20 +35,25 @@ public: } shared_ptr Clone() final{ - return make_shared(_innerBlock, _type); + return shared_ptr(new ScriptFunctionEvalValue(_innerBlock, _type, _hash)); } bool operator ==(EvalValue* b) final{ if (b->GetType()->GetClass() != TypeClass::Function) return false; - return this->_innerBlock == ((ScriptFunctionEvalValue*)b)->_innerBlock; + return this->_hash == ((ScriptFunctionEvalValue*)b)->_hash; }; std::shared_ptr GetInnerBlock(){ return _innerBlock; } + std::size_t GetHashCode(){ + return _hash; + } + + }; diff --git a/src/Evaluator/EvalValues/StringEvalValue.hpp b/src/Evaluator/EvalValues/StringEvalValue.hpp index d052768..c673d9c 100644 --- a/src/Evaluator/EvalValues/StringEvalValue.hpp +++ b/src/Evaluator/EvalValues/StringEvalValue.hpp @@ -9,11 +9,13 @@ using namespace std; class StringEvalValue : public EvalValue{ string _value; + size_t _hash; std::shared_ptr _type; public: explicit StringEvalValue(string s){ _value = move(s); _type = std::make_shared(TypeClass::String); + _hash = std::hash{}(_value); } std::shared_ptr GetType() final{ @@ -22,7 +24,7 @@ public: bool operator ==(EvalValue* b) final{ if (b->GetType()->GetClass() != TypeClass::String) return false; - return this->_value == *b->EvaluateString(); + return this->_hash == b->GetHashCode(); }; string* EvaluateString() final{ @@ -33,10 +35,14 @@ public: return make_shared(_value); } - EvalValue* IndexValue(EvalValue* val) final{ + shared_ptr IndexValue(EvalValue* val) final{ // Porygon is 1-indexed, so we convert to that. auto l = val->EvaluateInteger() - 1; - return new StringEvalValue(string(1, _value[l])); + return make_shared(string(1, _value[l])); + } + + std::size_t GetHashCode() final{ + return _hash; } }; diff --git a/src/Evaluator/EvalValues/TableEvalValue.cpp b/src/Evaluator/EvalValues/TableEvalValue.cpp new file mode 100644 index 0000000..4f08c93 --- /dev/null +++ b/src/Evaluator/EvalValues/TableEvalValue.cpp @@ -0,0 +1,2 @@ + +#include "TableEvalValue.hpp" diff --git a/src/Evaluator/EvalValues/TableEvalValue.hpp b/src/Evaluator/EvalValues/TableEvalValue.hpp new file mode 100644 index 0000000..d18f739 --- /dev/null +++ b/src/Evaluator/EvalValues/TableEvalValue.hpp @@ -0,0 +1,51 @@ +#include + +#ifndef PORYGONLANG_TABLEEVALVALUE_HPP +#define PORYGONLANG_TABLEEVALVALUE_HPP +#include +#include +#include "EvalValue.hpp" + +using namespace std; + +class TableEvalValue : public EvalValue { + shared_ptr>> _table; + shared_ptr _type; + size_t _hash; + + explicit TableEvalValue(shared_ptr>> table, shared_ptr type, size_t hash){ + _table = std::move(table); + _type = std::move(type); + _hash = hash; + } +public: + explicit TableEvalValue(shared_ptr>> table, shared_ptr type){ + _table = std::move(table); + _type = std::move(type); + _hash = rand(); + } + + std::shared_ptr GetType() final{ + return _type; + } + + size_t GetHashCode() final{ + return _hash; + } + + bool operator ==(EvalValue* b) final{ + return this -> _hash == b->GetHashCode(); + } + + shared_ptr Clone() final{ + return shared_ptr(new TableEvalValue(_table, _type, _hash)); + } + + shared_ptr IndexValue(EvalValue* val) final{ + auto hash = val->GetHashCode(); + return this -> _table->at(hash); + } +}; + + +#endif //PORYGONLANG_TABLEEVALVALUE_HPP diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 999ee2f..d7adaf0 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -5,6 +5,7 @@ #include "../Script.hpp" #include "EvaluationScope/EvaluationScope.hpp" #include "EvalValues/ScriptFunctionEvalValue.hpp" +#include "EvalValues/TableEvalValue.hpp" using namespace std; @@ -97,6 +98,7 @@ shared_ptr Evaluator::EvaluateExpression(BoundExpression *expression) case TypeClass ::String: return this -> EvaluateStringExpression(expression); case TypeClass ::Function: return this->EvaluateFunctionExpression(expression); case TypeClass ::Nil: return this->EvaluateNilExpression(expression); + case TypeClass ::Table: return this-> EvaluateTableExpression(expression); default: throw; } } @@ -119,6 +121,7 @@ shared_ptr Evaluator::EvaluateIntegerExpression(BoundExpressio case BoundExpressionKind ::LiteralString: case BoundExpressionKind ::LiteralBool: case BoundExpressionKind ::Bad: + case BoundExpressionKind::NumericalTable: throw; } } @@ -136,6 +139,7 @@ shared_ptr Evaluator::EvaluateBoolExpression(BoundExpression * case BoundExpressionKind::LiteralInteger: case BoundExpressionKind::LiteralFloat: case BoundExpressionKind::LiteralString: + case BoundExpressionKind::NumericalTable: throw; } @@ -156,6 +160,7 @@ shared_ptr Evaluator::EvaluateStringExpression(BoundExpression case BoundExpressionKind::LiteralFloat: case BoundExpressionKind::LiteralBool: case BoundExpressionKind::Unary: + case BoundExpressionKind::NumericalTable: throw; } @@ -175,6 +180,19 @@ shared_ptr Evaluator::EvaluateNilExpression(BoundExpression * express return nullptr; } } +shared_ptr Evaluator::EvaluateTableExpression(BoundExpression * expression){ + switch (expression->GetKind()){ + case BoundExpressionKind ::FunctionCall: + return this->EvaluateFunctionCallExpression(expression); + case BoundExpressionKind ::Variable: return this->GetVariable((BoundVariableExpression*)expression); + case BoundExpressionKind ::Index: return this->EvaluateIndexExpression(expression); + case BoundExpressionKind ::NumericalTable: return this-> EvaluateNumericTableExpression(expression); + default: + return nullptr; + } +} + + shared_ptr Evaluator::EvaluateFunctionCallExpression(BoundExpression* expression){ @@ -239,6 +257,18 @@ shared_ptr Evaluator::EvaluateIndexExpression(BoundExpression *expres auto indexExpression = (BoundIndexExpression*)expression; auto index = this -> EvaluateExpression(indexExpression->GetIndexExpression()); auto indexable = this -> EvaluateExpression(indexExpression->GetIndexableExpression()); - return shared_ptr(indexable -> IndexValue(index.get())); + return indexable -> IndexValue(index.get()) -> Clone(); +} + +shared_ptr Evaluator::EvaluateNumericTableExpression(BoundExpression *expression) { + auto tableExpression = (BoundNumericalTableExpression*)expression; + auto valueExpressions = tableExpression->GetExpressions(); + auto values = new unordered_map>(valueExpressions.size()); + for (int i = 0; i < valueExpressions.size(); i++){ + auto val = this -> EvaluateExpression(valueExpressions[i]); + values -> insert({i + 1, val}); + } + auto valuesPointer = shared_ptr>>(values); + return make_shared(valuesPointer, tableExpression->GetType()); } diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index af5e37c..46880a7 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -36,6 +36,7 @@ class Evaluator { shared_ptr EvaluateStringExpression(BoundExpression* expression); shared_ptr EvaluateFunctionExpression(BoundExpression *expression); shared_ptrEvaluateNilExpression(BoundExpression *expression); + shared_ptrEvaluateTableExpression(BoundExpression *expression); shared_ptr EvaluateIntegerBinary(BoundBinaryExpression* expression); shared_ptr EvaluateBooleanBinary(BoundBinaryExpression *expression); @@ -45,6 +46,7 @@ class Evaluator { shared_ptr EvaluateBooleanUnary(BoundUnaryExpression *expression); shared_ptr EvaluateFunctionCallExpression(BoundExpression *expression); shared_ptr EvaluateIndexExpression(BoundExpression* expression); + shared_ptr EvaluateNumericTableExpression(BoundExpression* expression); shared_ptr GetVariable(BoundVariableExpression *expression); public: diff --git a/src/Parser/Lexer.cpp b/src/Parser/Lexer.cpp index 2f3999c..8629944 100644 --- a/src/Parser/Lexer.cpp +++ b/src/Parser/Lexer.cpp @@ -69,6 +69,10 @@ IToken* Lexer::LexNext(char c){ return new SimpleToken(TokenKind::OpenSquareBracket, this -> _position - 1, 1); case ']': return new SimpleToken(TokenKind::CloseSquareBracket, this -> _position - 1, 1); + case '{': + return new SimpleToken(TokenKind::OpenCurlyBracket, this -> _position - 1, 1); + case '}': + return new SimpleToken(TokenKind::CloseCurlyBracket, this -> _position - 1, 1); case ',': return new SimpleToken(TokenKind::CommaToken, this -> _position - 1, 1); case '.': diff --git a/src/Parser/ParsedExpressions/ParsedExpression.hpp b/src/Parser/ParsedExpressions/ParsedExpression.hpp index 299903c..0e2a523 100644 --- a/src/Parser/ParsedExpressions/ParsedExpression.hpp +++ b/src/Parser/ParsedExpressions/ParsedExpression.hpp @@ -23,6 +23,7 @@ enum class ParsedExpressionKind{ Parenthesized, FunctionCall, Indexer, + NumericalTable, }; class ParsedExpression { @@ -270,5 +271,28 @@ public: } }; +class ParsedNumericalTableExpression : public ParsedExpression{ + vector _expressions; +public: + ParsedNumericalTableExpression(vector expressions, unsigned int start, unsigned int length) + : ParsedExpression(start, length){ + _expressions = std::move(expressions); + } + + ~ParsedNumericalTableExpression() final{ + for (auto s: _expressions){ + delete s; + } + } + + vector GetExpressions(){ + return _expressions; + } + + ParsedExpressionKind GetKind() final{ + return ParsedExpressionKind::NumericalTable; + } +}; + #endif //PORYGONLANG_PARSEDEXPRESSION_HPP diff --git a/src/Parser/ParsedStatements/ParsedStatement.hpp b/src/Parser/ParsedStatements/ParsedStatement.hpp index d75e3df..6bd13fc 100644 --- a/src/Parser/ParsedStatements/ParsedStatement.hpp +++ b/src/Parser/ParsedStatements/ParsedStatement.hpp @@ -1,3 +1,5 @@ +#include + #ifndef PORYGONLANG_PARSEDSTATEMENT_HPP #define PORYGONLANG_PARSEDSTATEMENT_HPP diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 0f69275..0928d2a 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -307,6 +307,7 @@ ParsedExpression *Parser::ParsePrimaryExpression(IToken *current) { case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current); case TokenKind ::Identifier: return new VariableExpression((IdentifierToken*)current); case TokenKind ::OpenParenthesis: return this -> ParseParenthesizedExpression(current); + case TokenKind ::OpenCurlyBracket: return this -> ParseTableExpression(current); // If we find a bad token here, we should have already logged it in the lexer, so don't log another error. case TokenKind ::BadToken: return new BadExpression(current->GetStartPosition(), current->GetLength()); default: @@ -365,5 +366,41 @@ ParsedExpression* Parser::ParseIndexExpression(ParsedExpression* indexingExpress return new IndexExpression(indexingExpression, indexExpression, start, closeBracket->GetEndPosition() - start); } - +ParsedExpression* Parser::ParseTableExpression(IToken* current){ + if (this -> Peek() -> GetKind() == TokenKind::CloseCurlyBracket){ + this -> Next(); + auto start = current->GetStartPosition(); + return new ParsedNumericalTableExpression({}, start, this -> Peek()->GetEndPosition() - start); + } + 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 (firstItem->GetKind() == ParsedStatementKind::Expression && + (this->Peek()->GetKind() == TokenKind::CommaToken )){ + auto expr = ((ParsedExpressionStatement*)firstItem)->GetExpression(); + auto expressions = vector{expr}; + auto n = this -> Next(); // consume the comma + bool hasErrors = false; + while (n->GetKind() != TokenKind::CloseCurlyBracket){ + auto expression = this->ParseExpression(this->Next()); + expressions.push_back(expression); + n = this->Next(); + if (n->GetKind() != TokenKind::CommaToken && n->GetKind() != TokenKind ::CloseCurlyBracket && !hasErrors){ + this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, n->GetStartPosition(), n->GetLength()); + hasErrors = true; + } + } + auto start = current->GetStartPosition(); + if (hasErrors){ + return new BadExpression(start, n->GetEndPosition() - start); + } + return new ParsedNumericalTableExpression(expressions, start, n->GetEndPosition() - start); + } + // Otherwise we have a more complex table, which can be defined by a block + else { + auto block = (ParsedBlockStatement*)this -> ParseBlock({TokenKind ::CloseCurlyBracket}); + auto statements = block->GetStatements(); + statements.insert(statements.begin(), firstItem); + throw "not implemented TODO"; + } +} diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp index 618cda3..684dea7 100644 --- a/src/Parser/Parser.hpp +++ b/src/Parser/Parser.hpp @@ -49,6 +49,8 @@ public: IToken *PeekAt(int offset); + + ParsedExpression *ParseTableExpression(IToken *current); }; diff --git a/src/Parser/TokenKind.hpp b/src/Parser/TokenKind.hpp index a98a4a6..9473a39 100644 --- a/src/Parser/TokenKind.hpp +++ b/src/Parser/TokenKind.hpp @@ -22,6 +22,8 @@ enum class TokenKind{ CloseParenthesis, OpenSquareBracket, CloseSquareBracket, + OpenCurlyBracket, + CloseCurlyBracket, PeriodToken, CommaToken, diff --git a/src/ScriptType.cpp b/src/ScriptType.cpp index e1124b2..dcadf01 100644 --- a/src/ScriptType.cpp +++ b/src/ScriptType.cpp @@ -5,9 +5,9 @@ bool ScriptType::CanBeIndexedWith(ScriptType *indexer) { return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat(); } -ScriptType *ScriptType::GetIndexedType(ScriptType *indexer) { +shared_ptr ScriptType::GetIndexedType(ScriptType *indexer) { if (_class == TypeClass::String){ - return new ScriptType(TypeClass::String); + return make_shared(TypeClass::String); } - return new ScriptType(TypeClass::Error); + return make_shared(TypeClass::Error); } diff --git a/src/ScriptType.hpp b/src/ScriptType.hpp index 50269d0..6b92a1e 100644 --- a/src/ScriptType.hpp +++ b/src/ScriptType.hpp @@ -1,8 +1,3 @@ -#include - -#include - -#include #ifndef PORYGONLANG_SCRIPTTYPE_HPP #define PORYGONLANG_SCRIPTTYPE_HPP @@ -55,7 +50,7 @@ public: virtual bool CanBeIndexedWith(ScriptType* indexer); - virtual ScriptType* GetIndexedType(ScriptType* indexer); + virtual shared_ptr GetIndexedType(ScriptType* indexer); }; class NumericScriptType : public ScriptType{ @@ -109,4 +104,24 @@ public: } }; +class TableScriptType : public ScriptType{ + shared_ptr _keyType; + shared_ptr _valueType; + // Consider adding a check whether the table actually contains a type if every key is static. +public: + TableScriptType(shared_ptr keyType, shared_ptr valueType) : ScriptType(TypeClass::Table){ + _keyType = std::move(keyType); + _valueType = std::move(valueType); + } + + bool CanBeIndexedWith(ScriptType* indexer) final{ + return _keyType.get()->operator==(indexer); + } + + shared_ptr GetIndexedType(ScriptType* indexer) final{ + return _valueType; + } + +}; + #endif //PORYGONLANG_SCRIPTTYPE_HPP diff --git a/tests/integration/Tables.cpp b/tests/integration/Tables.cpp new file mode 100644 index 0000000..0a2364a --- /dev/null +++ b/tests/integration/Tables.cpp @@ -0,0 +1,48 @@ +#ifdef TESTS_BUILD +#include +#include "../src/Script.hpp" + +TEST_CASE( "Create empty table", "[integration]" ) { + Script* script = Script::Create("table = {}"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto variable = script->GetVariable("table"); + REQUIRE(variable != nullptr); + delete script; +} + +TEST_CASE( "Create simple integer table", "[integration]" ) { + Script* script = Script::Create("table = {100, 50, 20, 5, -100, 50+50}"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto variable = script->GetVariable("table"); + REQUIRE(variable != nullptr); + delete script; +} + +TEST_CASE( "Create simple string table", "[integration]" ) { + Script* script = Script::Create("table = {'bla', 'test', 'foo', 'bar'}"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto variable = script->GetVariable("table"); + REQUIRE(variable != nullptr); + delete script; +} + +TEST_CASE( "Index string table", "[integration]" ) { + Script* script = Script::Create( + R"( +table = {'bla', 'test', 'foo', 'bar'} +result = table[3] +)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto variable = script->GetVariable("result"); + REQUIRE(variable != nullptr); + REQUIRE(*variable->EvaluateString() == "foo"); + delete script; +} + + +#endif +