Implemented generic for loops
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
cfd558b718
commit
d86e9ba8ae
|
@ -46,6 +46,8 @@ namespace Porygon::Binder {
|
|||
return this->BindConditionalStatement(statement);
|
||||
case ParsedStatementKind::NumericalFor:
|
||||
return this->BindNumericalForStatement(statement);
|
||||
case ParsedStatementKind::GenericFor:
|
||||
return this -> BindGenericForStatement(statement);
|
||||
case ParsedStatementKind::Bad:
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
|
@ -105,7 +107,7 @@ namespace Porygon::Binder {
|
|||
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
||||
}
|
||||
|
||||
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s) {
|
||||
std::shared_ptr<ScriptType> ParseTypeIdentifier(const HashedString& s) {
|
||||
auto hash = s.GetHash();
|
||||
switch (hash) {
|
||||
case HashedString::ConstHash("number"):
|
||||
|
@ -253,6 +255,46 @@ namespace Porygon::Binder {
|
|||
return new BoundNumericalForStatement(variableKey.GetKey(), start, end, step, block);
|
||||
}
|
||||
|
||||
BoundStatement *Binder::BindGenericForStatement(const ParsedStatement *statement) {
|
||||
auto genericFor = (ParsedGenericForStatement*) statement;
|
||||
auto boundIterator = BindExpression(genericFor -> GetIteratorExpression());
|
||||
const auto& itType = boundIterator -> GetType();
|
||||
if (!itType -> CanBeIterated()){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantIterateExpression, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
auto keyType = itType -> GetIteratorKeyType();
|
||||
auto keyIdentifier = genericFor -> GetKeyIdentifier();
|
||||
this -> _scope -> GoInnerScope();
|
||||
auto keyVariableAssignment = this -> _scope -> CreateExplicitLocal(keyIdentifier, keyType);
|
||||
if (keyVariableAssignment.GetResult() != VariableAssignmentResult::Ok){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
auto keyVariable = keyVariableAssignment.GetKey();
|
||||
|
||||
auto valueIdentifier = genericFor -> GetValueIdentifier();
|
||||
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
||||
BoundVariableKey* valueVariable = nullptr;
|
||||
if (isValueVariableDefined){
|
||||
auto valueType = itType -> GetIndexedType(keyType.get());
|
||||
auto valueVariableAssignment = this -> _scope -> CreateExplicitLocal(valueIdentifier, valueType);
|
||||
if (valueVariableAssignment.GetResult() != VariableAssignmentResult::Ok){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
valueVariable = valueVariableAssignment.GetKey();
|
||||
}
|
||||
auto boundBlock = this -> BindBlockStatement(genericFor -> GetBlock());
|
||||
|
||||
this -> _scope -> GoOuterScope();
|
||||
|
||||
return new BoundGenericForStatement(keyVariable, valueVariable, boundIterator, boundBlock);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Expressions //
|
||||
/////////////////
|
||||
|
@ -629,5 +671,4 @@ namespace Porygon::Binder {
|
|||
return new BoundTableExpression((BoundBlockStatement *) block, tableType, expression->GetStartPosition(),
|
||||
expression->GetLength());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace Porygon::Binder {
|
|||
BoundStatement *BindReturnStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindConditionalStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindNumericalForStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindGenericForStatement(const ParsedStatement *statement);
|
||||
|
||||
// Expressions
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace Porygon::Binder {
|
|||
Return,
|
||||
Conditional,
|
||||
NumericalFor,
|
||||
GenericFor,
|
||||
};
|
||||
|
||||
class BoundStatement {
|
||||
|
@ -247,6 +248,48 @@ namespace Porygon::Binder {
|
|||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
class BoundGenericForStatement : public BoundStatement {
|
||||
const BoundVariableKey* _keyIdentifier;
|
||||
const BoundVariableKey* _valueIdentifier;
|
||||
const BoundExpression* _iterator;
|
||||
|
||||
const BoundStatement *_block;
|
||||
public:
|
||||
explicit BoundGenericForStatement(const BoundVariableKey *keyIdentifier,
|
||||
const BoundVariableKey *valueIdentifier,
|
||||
const BoundExpression *iterator, const BoundStatement *block)
|
||||
: _keyIdentifier(keyIdentifier), _valueIdentifier(valueIdentifier), _iterator(iterator), _block(block) {
|
||||
}
|
||||
|
||||
~BoundGenericForStatement() final {
|
||||
delete _keyIdentifier;
|
||||
delete _valueIdentifier;
|
||||
delete _iterator;
|
||||
delete _block;
|
||||
}
|
||||
|
||||
const BoundStatementKind GetKind() const final {
|
||||
return BoundStatementKind::GenericFor;
|
||||
}
|
||||
|
||||
const BoundVariableKey* GetKeyIdentifier() const{
|
||||
return _keyIdentifier;
|
||||
}
|
||||
|
||||
const BoundVariableKey* GetValueIdentifier() const{
|
||||
return _valueIdentifier;
|
||||
}
|
||||
|
||||
const BoundExpression* GetIterator() const{
|
||||
return _iterator;
|
||||
}
|
||||
|
||||
const BoundStatement* GetBlock() const{
|
||||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ namespace Porygon::Diagnostics {
|
|||
InvalidTypeName,
|
||||
UserDataFieldNoGetter,
|
||||
UserDataFieldNoSetter,
|
||||
NumericalForArgumentNotANumber
|
||||
NumericalForArgumentNotANumber,
|
||||
CantIterateExpression
|
||||
};
|
||||
}
|
||||
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
||||
|
|
|
@ -69,6 +69,7 @@ std::string SeverityToString(DiagnosticSeverity s){
|
|||
case DiagnosticSeverity::Info: return "Info";
|
||||
case DiagnosticSeverity::Warning: return "Warning";
|
||||
case DiagnosticSeverity::Error: return "Error";
|
||||
default: throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,17 @@
|
|||
#ifndef PORYGONLANG_EVALVALUE_HPP
|
||||
#define PORYGONLANG_EVALVALUE_HPP
|
||||
|
||||
#include "../../ScriptType.hpp"
|
||||
#include "../EvaluationException.hpp"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include "../../ScriptType.hpp"
|
||||
#include "../EvaluationException.hpp"
|
||||
namespace Porygon::Evaluation{
|
||||
class EvalValue;
|
||||
class Iterator;
|
||||
}
|
||||
#include "../Iterator/Iterator.hpp"
|
||||
|
||||
|
||||
namespace Porygon::Evaluation {
|
||||
class EvalValue {
|
||||
|
@ -54,6 +60,10 @@ namespace Porygon::Evaluation {
|
|||
virtual void SetIndexValue(EvalValue *key, const shared_ptr<EvalValue> &value) const {
|
||||
throw EvaluationException("Can't index this EvalValue");
|
||||
}
|
||||
|
||||
virtual Iterator * GetKeyIterator() const{
|
||||
throw EvaluationException("Can't iterate over this EvalValue");
|
||||
}
|
||||
};
|
||||
|
||||
class BooleanEvalValue : public EvalValue {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#include "TableEvalValue.hpp"
|
||||
#include "../Iterator/SimpleKeyIterator.hpp"
|
||||
|
||||
Porygon::Evaluation::Iterator * Porygon::Evaluation::TableEvalValue::GetKeyIterator() const {
|
||||
return new TableKeyIterator(this);
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
#ifndef PORYGONLANG_TABLEEVALVALUE_HPP
|
||||
#define PORYGONLANG_TABLEEVALVALUE_HPP
|
||||
#include <utility>
|
||||
|
@ -8,18 +9,20 @@ using namespace std;
|
|||
|
||||
namespace Porygon::Evaluation {
|
||||
class TableEvalValue : public EvalValue {
|
||||
shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> _table;
|
||||
size_t _hash;
|
||||
const shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> _table;
|
||||
const size_t _hash;
|
||||
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table, size_t hash) {
|
||||
_table = std::move(table);
|
||||
_hash = hash;
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table, size_t hash)
|
||||
: _table(std::move(table)),
|
||||
_hash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table) {
|
||||
_table = std::move(table);
|
||||
_hash = rand();
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table) :
|
||||
_table(std::move(table)),
|
||||
_hash(rand())
|
||||
{
|
||||
}
|
||||
|
||||
const TypeClass GetTypeClass() const final {
|
||||
|
@ -57,6 +60,8 @@ namespace Porygon::Evaluation {
|
|||
this->_table->at(Utilities::HashedString::CreateLookup(hash)) = value;
|
||||
}
|
||||
|
||||
Iterator * GetKeyIterator() const final;
|
||||
|
||||
const _Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> GetTableIterator() const{
|
||||
return _table->cbegin();
|
||||
};
|
||||
|
|
|
@ -45,6 +45,8 @@ namespace Porygon::Evaluation {
|
|||
return this->EvaluateConditionalStatement((BoundConditionalStatement *) statement);
|
||||
case BoundStatementKind::NumericalFor:
|
||||
return this->EvaluateNumericalForStatement((BoundNumericalForStatement*)statement);
|
||||
case BoundStatementKind::GenericFor:
|
||||
return this-> EvaluateGenericForStatement((BoundGenericForStatement*)statement);
|
||||
|
||||
case BoundStatementKind::Bad:
|
||||
throw;
|
||||
|
@ -151,6 +153,32 @@ namespace Porygon::Evaluation {
|
|||
}
|
||||
}
|
||||
|
||||
void Evaluator::EvaluateGenericForStatement(const BoundGenericForStatement *statement) {
|
||||
auto iteratorVal = EvaluateExpression(statement -> GetIterator());
|
||||
auto iterator = iteratorVal -> GetKeyIterator();
|
||||
auto keyVariable = statement ->GetKeyIdentifier();
|
||||
auto valueVariable = statement ->GetValueIdentifier();
|
||||
|
||||
this -> _evaluationScope -> CreateVariable(keyVariable, nullptr);
|
||||
if (valueVariable != nullptr)
|
||||
this -> _evaluationScope -> CreateVariable(valueVariable, nullptr);
|
||||
auto block = (BoundBlockStatement*)statement -> GetBlock();
|
||||
|
||||
while (iterator->MoveNext()){
|
||||
auto currentKey = iterator->GetCurrent();
|
||||
this -> _evaluationScope -> SetVariable(keyVariable, currentKey);
|
||||
if (valueVariable != nullptr){
|
||||
auto currentValue = iteratorVal -> IndexValue(currentKey.get());
|
||||
this -> _evaluationScope -> SetVariable(valueVariable, currentValue);
|
||||
}
|
||||
this -> EvaluateBlockStatement(block);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Expressions //
|
||||
/////////////////
|
||||
|
||||
const shared_ptr<EvalValue> Evaluator::EvaluateExpression(const BoundExpression *expression) {
|
||||
auto type = expression->GetType();
|
||||
switch (type->GetClass()) {
|
||||
|
@ -425,5 +453,4 @@ namespace Porygon::Evaluation {
|
|||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ namespace Porygon::Evaluation{
|
|||
void EvaluateReturnStatement(const BoundReturnStatement *statement);
|
||||
void EvaluateConditionalStatement(const BoundConditionalStatement *statement);
|
||||
void EvaluateNumericalForStatement(const BoundNumericalForStatement *statement);
|
||||
void EvaluateGenericForStatement(const BoundGenericForStatement *statement);
|
||||
|
||||
const shared_ptr<EvalValue> EvaluateExpression(const BoundExpression *expression);
|
||||
const shared_ptr<NumericEvalValue> EvaluateIntegerExpression(const BoundExpression *expression);
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <memory>
|
||||
#include "../EvalValues/EvalValue.hpp"
|
||||
#include "../EvalValues/TableEvalValue.hpp"
|
||||
#include "../EvalValues/StringEvalValue.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -17,26 +15,6 @@ namespace Porygon::Evaluation{
|
|||
virtual void Reset() = 0;
|
||||
};
|
||||
|
||||
class TableKeyIterator : Iterator{
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _iterator;
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _end;
|
||||
public:
|
||||
TableKeyIterator(shared_ptr<TableEvalValue> table)
|
||||
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
|
||||
|
||||
shared_ptr<EvalValue> GetCurrent() final{
|
||||
return make_shared<StringEvalValue>(*_iterator->first.GetString());
|
||||
}
|
||||
|
||||
bool MoveNext() final{
|
||||
std::advance(_iterator, 1);
|
||||
return _iterator != _end;
|
||||
}
|
||||
|
||||
void Reset(){
|
||||
throw EvaluationException("Can't reset table key iterator");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
#include "SimpleKeyIterator.hpp"
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
#ifndef PORYGONLANG_SIMPLEKEYITERATOR_HPP
|
||||
#define PORYGONLANG_SIMPLEKEYITERATOR_HPP
|
||||
|
||||
#include "Iterator.hpp"
|
||||
#include "../EvalValues/TableEvalValue.hpp"
|
||||
#include "../EvalValues/StringEvalValue.hpp"
|
||||
|
||||
namespace Porygon::Evaluation{
|
||||
class TableKeyIterator : public Iterator{
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _iterator;
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _end;
|
||||
bool _hasStarted = false;
|
||||
public:
|
||||
explicit TableKeyIterator(const TableEvalValue* table)
|
||||
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
|
||||
|
||||
shared_ptr<EvalValue> GetCurrent() final{
|
||||
return make_shared<StringEvalValue>(*_iterator->first.GetString());
|
||||
}
|
||||
|
||||
bool MoveNext() final{
|
||||
if (_hasStarted){
|
||||
std::advance(_iterator, 1);
|
||||
} else{
|
||||
_hasStarted = true;
|
||||
}
|
||||
return _iterator != _end;
|
||||
}
|
||||
|
||||
void Reset(){
|
||||
throw EvaluationException("Can't reset table key iterator");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif //PORYGONLANG_SIMPLEKEYITERATOR_HPP
|
|
@ -21,7 +21,8 @@ namespace Porygon::Parser {
|
|||
FunctionDeclaration,
|
||||
Return,
|
||||
Conditional,
|
||||
NumericalFor
|
||||
NumericalFor,
|
||||
GenericFor
|
||||
};
|
||||
|
||||
class ParsedStatement {
|
||||
|
@ -129,7 +130,7 @@ namespace Porygon::Parser {
|
|||
const vector<TypedVariableIdentifier *> _parameters;
|
||||
const ParsedBlockStatement *_block;
|
||||
public:
|
||||
ParsedFunctionDeclarationStatement(HashedString identifier, vector<TypedVariableIdentifier *> parameters,
|
||||
ParsedFunctionDeclarationStatement(const HashedString& identifier, vector<TypedVariableIdentifier *> parameters,
|
||||
ParsedBlockStatement *block,
|
||||
unsigned int start, unsigned int length)
|
||||
: ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)),
|
||||
|
@ -164,7 +165,7 @@ namespace Porygon::Parser {
|
|||
const HashedString _identifier;
|
||||
const ParsedExpression *_expression;
|
||||
public:
|
||||
ParsedAssignmentStatement(bool local, const HashedString identifier, ParsedExpression *expression,
|
||||
ParsedAssignmentStatement(bool local, const HashedString& identifier, ParsedExpression *expression,
|
||||
unsigned int start, unsigned int length)
|
||||
: ParsedStatement(start, length), _local(local), _identifier(identifier), _expression(expression) {
|
||||
}
|
||||
|
@ -288,7 +289,7 @@ namespace Porygon::Parser {
|
|||
const ParsedExpression *_step;
|
||||
const ParsedStatement *_block;
|
||||
public:
|
||||
ParsedNumericalForStatement(const HashedString identifier, const ParsedExpression *start,
|
||||
ParsedNumericalForStatement(const HashedString& identifier, const ParsedExpression *start,
|
||||
const ParsedExpression *end, const ParsedExpression *step, const ParsedStatement *block,
|
||||
unsigned int startPos, unsigned int length)
|
||||
: ParsedStatement(startPos, length), _identifier(identifier), _start(start), _end(end), _step(step), _block(block) {
|
||||
|
@ -326,5 +327,43 @@ namespace Porygon::Parser {
|
|||
}
|
||||
};
|
||||
|
||||
class ParsedGenericForStatement : public ParsedStatement{
|
||||
const HashedString _keyIdentifier;
|
||||
const HashedString _valueIdentifier;
|
||||
const ParsedExpression* _iteratorExpression;
|
||||
const ParsedStatement* _block;
|
||||
public:
|
||||
ParsedGenericForStatement(const HashedString& keyIdentifier, const HashedString& valueIdentifier,
|
||||
const ParsedExpression *iteratorExpression, const ParsedStatement *block,
|
||||
unsigned int start, unsigned int length)
|
||||
: ParsedStatement(start, length), _keyIdentifier(keyIdentifier), _valueIdentifier(valueIdentifier),
|
||||
_iteratorExpression(iteratorExpression), _block(block) {}
|
||||
|
||||
~ParsedGenericForStatement() final{
|
||||
delete _iteratorExpression;
|
||||
delete _block;
|
||||
}
|
||||
|
||||
const ParsedStatementKind GetKind() const final {
|
||||
return ParsedStatementKind::GenericFor;
|
||||
}
|
||||
|
||||
const HashedString GetKeyIdentifier() const{
|
||||
return _keyIdentifier;
|
||||
}
|
||||
|
||||
const HashedString GetValueIdentifier() const{
|
||||
return _valueIdentifier;
|
||||
}
|
||||
|
||||
const ParsedExpression* GetIteratorExpression() const{
|
||||
return _iteratorExpression;
|
||||
}
|
||||
|
||||
const ParsedStatement* GetBlock() const{
|
||||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif //PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
|
|
|
@ -267,7 +267,47 @@ namespace Porygon::Parser {
|
|||
}
|
||||
|
||||
ParsedStatement *Parser::ParseGenericForStatement(const IToken *current) {
|
||||
return nullptr;
|
||||
auto keyIdentifier = ((IdentifierToken*) current)->GetValue();
|
||||
IdentifierToken* valueIdentifierToken = nullptr;
|
||||
bool hasErrors = false;
|
||||
auto next = this -> Next();
|
||||
if (next -> GetKind() == TokenKind::CommaToken){
|
||||
next = this -> Next();
|
||||
if (next->GetKind() != TokenKind::Identifier){
|
||||
hasErrors = true;
|
||||
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
|
||||
next->GetLength());
|
||||
} else{
|
||||
valueIdentifierToken = (IdentifierToken*) next;
|
||||
next = this -> Next();
|
||||
}
|
||||
}
|
||||
if (next->GetKind() != TokenKind::InKeyword && !hasErrors){
|
||||
hasErrors = true;
|
||||
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
|
||||
next->GetLength());
|
||||
}
|
||||
auto expression = this -> ParseExpression(this -> Next());
|
||||
next = this -> Next();
|
||||
if (next -> GetKind() != TokenKind::DoKeyword && !hasErrors){
|
||||
hasErrors = true;
|
||||
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedToken, next->GetStartPosition(),
|
||||
next->GetLength());
|
||||
}
|
||||
auto block = this -> ParseBlock({TokenKind ::EndKeyword});
|
||||
auto startPos = current->GetStartPosition();
|
||||
if (hasErrors){
|
||||
return new ParsedBadStatement(startPos, block -> GetEndPosition() - startPos);
|
||||
} else{
|
||||
auto valueIdentifier = HashedString::CreateLookup(0);
|
||||
if (valueIdentifierToken != nullptr){
|
||||
return new ParsedGenericForStatement(keyIdentifier, valueIdentifierToken -> GetValue(), expression, block,
|
||||
startPos, block -> GetEndPosition() - startPos);
|
||||
} else{
|
||||
return new ParsedGenericForStatement(keyIdentifier, HashedString::CreateLookup(0), expression, block,
|
||||
startPos, block -> GetEndPosition() - startPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////
|
||||
|
|
|
@ -61,7 +61,14 @@ namespace Porygon{
|
|||
|
||||
virtual const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const;
|
||||
virtual const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const{
|
||||
throw "Shouldn't be possible";
|
||||
throw "This type told the binder it can be indexed, but it does not implement the resulting type.";
|
||||
}
|
||||
|
||||
virtual const bool CanBeIterated() const{
|
||||
return false;
|
||||
}
|
||||
virtual shared_ptr<ScriptType> GetIteratorKeyType() const{
|
||||
throw "This type told the binder it can be iterated, but it does not implement the resulting type.";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -161,12 +168,22 @@ namespace Porygon{
|
|||
}
|
||||
|
||||
const bool CanBeIndexedWith(ScriptType* indexer) const final{
|
||||
return indexer->GetClass() == TypeClass ::Number;
|
||||
if (indexer -> GetClass() != TypeClass::Number)
|
||||
return false;
|
||||
auto num =(NumericScriptType*)indexer;
|
||||
return !(num->IsAwareOfFloat() && num->IsFloat());
|
||||
}
|
||||
|
||||
const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{
|
||||
return _valueType;
|
||||
}
|
||||
|
||||
const bool CanBeIterated() const final{
|
||||
return true;
|
||||
}
|
||||
shared_ptr<ScriptType> GetIteratorKeyType() const final{
|
||||
return make_shared<StringScriptType>(false, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ namespace Porygon{
|
|||
const int GetLocalVariableCount() const{
|
||||
return _localVariableCount;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -60,5 +60,35 @@ end
|
|||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "Generic for loop over simple numerical table, get keys", "[integration]" ) {
|
||||
auto script = Script::Create(uR"(
|
||||
local table = {1, 3, 5, 7, 9}
|
||||
result = ""
|
||||
for i in table do
|
||||
result = result + i
|
||||
end
|
||||
)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto var = script->GetVariable(u"result");
|
||||
REQUIRE(var->EvaluateString() == u"12345");
|
||||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "Generic for loop over simple numerical table, get values", "[integration]" ) {
|
||||
auto script = Script::Create(uR"(
|
||||
local table = {1, 3, 5, 7, 9}
|
||||
result = ""
|
||||
for i,v in table do
|
||||
result = result + v
|
||||
end
|
||||
)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto var = script->GetVariable(u"result");
|
||||
REQUIRE(var->EvaluateString() == u"13579");
|
||||
delete script;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue