Implements basic numerical tables
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
ec2419bc7d
commit
081def0be0
|
@ -1,3 +1,5 @@
|
|||
#include <memory>
|
||||
|
||||
#include "Binder.hpp"
|
||||
#include <memory>
|
||||
|
||||
|
@ -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<ScriptType>(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<BoundExpression*>(expressions.size());
|
||||
shared_ptr<ScriptType> 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<ScriptType>(TypeClass::Nil);
|
||||
}
|
||||
auto keyType = std::make_shared<ScriptType>(TypeClass::Number);
|
||||
auto tableType = std::make_shared<TableScriptType>(keyType, valueType);
|
||||
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(), expression->GetLength());
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
#ifndef PORYGONLANG_BOUNDEXPRESSION_HPP
|
||||
#define PORYGONLANG_BOUNDEXPRESSION_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#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<BoundExpression*> _expressions;
|
||||
public:
|
||||
BoundNumericalTableExpression(vector<BoundExpression*> expressions, shared_ptr<ScriptType> 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<BoundExpression*> GetExpressions(){
|
||||
return _expressions;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //PORYGONLANG_BOUNDEXPRESSION_HPP
|
||||
|
|
|
@ -21,6 +21,7 @@ enum class DiagnosticCode{
|
|||
CantIndex,
|
||||
InvalidReturnType,
|
||||
ConditionNotABool,
|
||||
InvalidTableValueType,
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_DIAGNOSTICCODE_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<EvalValue> 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
|
||||
|
|
|
@ -49,6 +49,10 @@ public:
|
|||
shared_ptr<EvalValue> Clone() final{
|
||||
return make_shared<IntegerEvalValue>(_value);
|
||||
}
|
||||
|
||||
std::size_t GetHashCode() final{
|
||||
return std::hash<long>{}(_value);
|
||||
}
|
||||
};
|
||||
|
||||
class FloatEvalValue : public NumericEvalValue{
|
||||
|
@ -71,6 +75,10 @@ public:
|
|||
shared_ptr<EvalValue> Clone() final{
|
||||
return make_shared<FloatEvalValue>(_value);
|
||||
}
|
||||
|
||||
std::size_t GetHashCode() final{
|
||||
return std::hash<double >{}(_value);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_NUMERICEVALVALUE_HPP
|
||||
|
|
|
@ -14,11 +14,20 @@
|
|||
class ScriptFunctionEvalValue : public EvalValue{
|
||||
std::shared_ptr<BoundBlockStatement> _innerBlock;
|
||||
std::shared_ptr<FunctionScriptType> _type;
|
||||
std::size_t _hash;
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<FunctionScriptType> type, size_t hash)
|
||||
: _type(std::move(type))
|
||||
{
|
||||
_innerBlock = std::move(innerBlock);
|
||||
_hash = hash;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ScriptFunctionEvalValue(std::shared_ptr<BoundBlockStatement> innerBlock, std::shared_ptr<FunctionScriptType> type)
|
||||
: _type(std::move(type))
|
||||
{
|
||||
_innerBlock = std::move(innerBlock);
|
||||
_hash = rand();
|
||||
}
|
||||
|
||||
std::shared_ptr<ScriptType> GetType() final{
|
||||
|
@ -26,20 +35,25 @@ public:
|
|||
}
|
||||
|
||||
shared_ptr<EvalValue> Clone() final{
|
||||
return make_shared<ScriptFunctionEvalValue>(_innerBlock, _type);
|
||||
return shared_ptr<ScriptFunctionEvalValue>(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<BoundBlockStatement> GetInnerBlock(){
|
||||
return _innerBlock;
|
||||
}
|
||||
|
||||
std::size_t GetHashCode(){
|
||||
return _hash;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -9,11 +9,13 @@ using namespace std;
|
|||
|
||||
class StringEvalValue : public EvalValue{
|
||||
string _value;
|
||||
size_t _hash;
|
||||
std::shared_ptr<ScriptType> _type;
|
||||
public:
|
||||
explicit StringEvalValue(string s){
|
||||
_value = move(s);
|
||||
_type = std::make_shared<ScriptType>(TypeClass::String);
|
||||
_hash = std::hash<string>{}(_value);
|
||||
}
|
||||
|
||||
std::shared_ptr<ScriptType> 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<StringEvalValue>(_value);
|
||||
}
|
||||
|
||||
EvalValue* IndexValue(EvalValue* val) final{
|
||||
shared_ptr<EvalValue> 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<StringEvalValue>(string(1, _value[l]));
|
||||
}
|
||||
|
||||
std::size_t GetHashCode() final{
|
||||
return _hash;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "TableEvalValue.hpp"
|
|
@ -0,0 +1,51 @@
|
|||
#include <utility>
|
||||
|
||||
#ifndef PORYGONLANG_TABLEEVALVALUE_HPP
|
||||
#define PORYGONLANG_TABLEEVALVALUE_HPP
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
#include "EvalValue.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class TableEvalValue : public EvalValue {
|
||||
shared_ptr<unordered_map<size_t, shared_ptr<EvalValue>>> _table;
|
||||
shared_ptr<ScriptType> _type;
|
||||
size_t _hash;
|
||||
|
||||
explicit TableEvalValue(shared_ptr<unordered_map<size_t, shared_ptr<EvalValue>>> table, shared_ptr<ScriptType> type, size_t hash){
|
||||
_table = std::move(table);
|
||||
_type = std::move(type);
|
||||
_hash = hash;
|
||||
}
|
||||
public:
|
||||
explicit TableEvalValue(shared_ptr<unordered_map<size_t, shared_ptr<EvalValue>>> table, shared_ptr<ScriptType> type){
|
||||
_table = std::move(table);
|
||||
_type = std::move(type);
|
||||
_hash = rand();
|
||||
}
|
||||
|
||||
std::shared_ptr<ScriptType> GetType() final{
|
||||
return _type;
|
||||
}
|
||||
|
||||
size_t GetHashCode() final{
|
||||
return _hash;
|
||||
}
|
||||
|
||||
bool operator ==(EvalValue* b) final{
|
||||
return this -> _hash == b->GetHashCode();
|
||||
}
|
||||
|
||||
shared_ptr<EvalValue> Clone() final{
|
||||
return shared_ptr<EvalValue>(new TableEvalValue(_table, _type, _hash));
|
||||
}
|
||||
|
||||
shared_ptr<EvalValue> IndexValue(EvalValue* val) final{
|
||||
auto hash = val->GetHashCode();
|
||||
return this -> _table->at(hash);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //PORYGONLANG_TABLEEVALVALUE_HPP
|
|
@ -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<EvalValue> 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<NumericEvalValue> Evaluator::EvaluateIntegerExpression(BoundExpressio
|
|||
case BoundExpressionKind ::LiteralString:
|
||||
case BoundExpressionKind ::LiteralBool:
|
||||
case BoundExpressionKind ::Bad:
|
||||
case BoundExpressionKind::NumericalTable:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +139,7 @@ shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(BoundExpression *
|
|||
case BoundExpressionKind::LiteralInteger:
|
||||
case BoundExpressionKind::LiteralFloat:
|
||||
case BoundExpressionKind::LiteralString:
|
||||
case BoundExpressionKind::NumericalTable:
|
||||
throw;
|
||||
|
||||
}
|
||||
|
@ -156,6 +160,7 @@ shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(BoundExpression
|
|||
case BoundExpressionKind::LiteralFloat:
|
||||
case BoundExpressionKind::LiteralBool:
|
||||
case BoundExpressionKind::Unary:
|
||||
case BoundExpressionKind::NumericalTable:
|
||||
throw;
|
||||
|
||||
}
|
||||
|
@ -175,6 +180,19 @@ shared_ptr<EvalValue> Evaluator::EvaluateNilExpression(BoundExpression * express
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
shared_ptr<EvalValue> 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<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression* expression){
|
||||
|
@ -239,6 +257,18 @@ shared_ptr<EvalValue> Evaluator::EvaluateIndexExpression(BoundExpression *expres
|
|||
auto indexExpression = (BoundIndexExpression*)expression;
|
||||
auto index = this -> EvaluateExpression(indexExpression->GetIndexExpression());
|
||||
auto indexable = this -> EvaluateExpression(indexExpression->GetIndexableExpression());
|
||||
return shared_ptr<EvalValue>(indexable -> IndexValue(index.get()));
|
||||
return indexable -> IndexValue(index.get()) -> Clone();
|
||||
}
|
||||
|
||||
shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(BoundExpression *expression) {
|
||||
auto tableExpression = (BoundNumericalTableExpression*)expression;
|
||||
auto valueExpressions = tableExpression->GetExpressions();
|
||||
auto values = new unordered_map<size_t, shared_ptr<EvalValue>>(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<unordered_map<size_t, shared_ptr<EvalValue>>>(values);
|
||||
return make_shared<TableEvalValue>(valuesPointer, tableExpression->GetType());
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class Evaluator {
|
|||
shared_ptr<StringEvalValue> EvaluateStringExpression(BoundExpression* expression);
|
||||
shared_ptr<EvalValue> EvaluateFunctionExpression(BoundExpression *expression);
|
||||
shared_ptr<EvalValue>EvaluateNilExpression(BoundExpression *expression);
|
||||
shared_ptr<EvalValue>EvaluateTableExpression(BoundExpression *expression);
|
||||
|
||||
shared_ptr<NumericEvalValue> EvaluateIntegerBinary(BoundBinaryExpression* expression);
|
||||
shared_ptr<BooleanEvalValue> EvaluateBooleanBinary(BoundBinaryExpression *expression);
|
||||
|
@ -45,6 +46,7 @@ class Evaluator {
|
|||
shared_ptr<BooleanEvalValue> EvaluateBooleanUnary(BoundUnaryExpression *expression);
|
||||
shared_ptr<EvalValue> EvaluateFunctionCallExpression(BoundExpression *expression);
|
||||
shared_ptr<EvalValue> EvaluateIndexExpression(BoundExpression* expression);
|
||||
shared_ptr<EvalValue> EvaluateNumericTableExpression(BoundExpression* expression);
|
||||
|
||||
shared_ptr<EvalValue> GetVariable(BoundVariableExpression *expression);
|
||||
public:
|
||||
|
|
|
@ -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 '.':
|
||||
|
|
|
@ -23,6 +23,7 @@ enum class ParsedExpressionKind{
|
|||
Parenthesized,
|
||||
FunctionCall,
|
||||
Indexer,
|
||||
NumericalTable,
|
||||
};
|
||||
|
||||
class ParsedExpression {
|
||||
|
@ -270,5 +271,28 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class ParsedNumericalTableExpression : public ParsedExpression{
|
||||
vector<ParsedExpression*> _expressions;
|
||||
public:
|
||||
ParsedNumericalTableExpression(vector<ParsedExpression*> expressions, unsigned int start, unsigned int length)
|
||||
: ParsedExpression(start, length){
|
||||
_expressions = std::move(expressions);
|
||||
}
|
||||
|
||||
~ParsedNumericalTableExpression() final{
|
||||
for (auto s: _expressions){
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
vector<ParsedExpression*> GetExpressions(){
|
||||
return _expressions;
|
||||
}
|
||||
|
||||
ParsedExpressionKind GetKind() final{
|
||||
return ParsedExpressionKind::NumericalTable;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //PORYGONLANG_PARSEDEXPRESSION_HPP
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <utility>
|
||||
|
||||
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
#define PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
|
||||
|
|
|
@ -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<ParsedExpression*>{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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
|
||||
|
||||
IToken *PeekAt(int offset);
|
||||
|
||||
ParsedExpression *ParseTableExpression(IToken *current);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ enum class TokenKind{
|
|||
CloseParenthesis,
|
||||
OpenSquareBracket,
|
||||
CloseSquareBracket,
|
||||
OpenCurlyBracket,
|
||||
CloseCurlyBracket,
|
||||
|
||||
PeriodToken,
|
||||
CommaToken,
|
||||
|
|
|
@ -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> ScriptType::GetIndexedType(ScriptType *indexer) {
|
||||
if (_class == TypeClass::String){
|
||||
return new ScriptType(TypeClass::String);
|
||||
return make_shared<ScriptType>(TypeClass::String);
|
||||
}
|
||||
return new ScriptType(TypeClass::Error);
|
||||
return make_shared<ScriptType>(TypeClass::Error);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#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<ScriptType> GetIndexedType(ScriptType* indexer);
|
||||
};
|
||||
|
||||
class NumericScriptType : public ScriptType{
|
||||
|
@ -109,4 +104,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class TableScriptType : public ScriptType{
|
||||
shared_ptr<ScriptType> _keyType;
|
||||
shared_ptr<ScriptType> _valueType;
|
||||
// Consider adding a check whether the table actually contains a type if every key is static.
|
||||
public:
|
||||
TableScriptType(shared_ptr<ScriptType> keyType, shared_ptr<ScriptType> valueType) : ScriptType(TypeClass::Table){
|
||||
_keyType = std::move(keyType);
|
||||
_valueType = std::move(valueType);
|
||||
}
|
||||
|
||||
bool CanBeIndexedWith(ScriptType* indexer) final{
|
||||
return _keyType.get()->operator==(indexer);
|
||||
}
|
||||
|
||||
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
||||
return _valueType;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_SCRIPTTYPE_HPP
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#ifdef TESTS_BUILD
|
||||
#include <catch.hpp>
|
||||
#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
|
||||
|
Loading…
Reference in New Issue