Implements indexing with period identifier style (``foo.bar``)
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
d06b04cae9
commit
d91caa7f32
|
@ -73,15 +73,21 @@ BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement
|
||||||
|
|
||||||
BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) {
|
BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) {
|
||||||
auto s = (ParsedIndexAssignmentStatement*) statement;
|
auto s = (ParsedIndexAssignmentStatement*) statement;
|
||||||
auto boundIndexExpression = this -> BindIndexExpression((IndexExpression*)s->GetIndexExpression(), true);
|
auto indexExp = s -> GetIndexExpression();
|
||||||
|
const BoundExpression* indexable;
|
||||||
|
if (indexExp->GetKind() == ParsedExpressionKind::Indexer){
|
||||||
|
indexable = this -> BindIndexExpression((IndexExpression*)indexExp, true);
|
||||||
|
} else{
|
||||||
|
indexable = this -> BindPeriodIndexExpression((PeriodIndexExpression*)indexExp, true);
|
||||||
|
}
|
||||||
auto valueExpression = this -> BindExpression(s->GetValueExpression());
|
auto valueExpression = this -> BindExpression(s->GetValueExpression());
|
||||||
auto boundIndexType = boundIndexExpression -> GetType();
|
auto boundIndexType = indexable -> GetType();
|
||||||
if (boundIndexType ->GetClass() != TypeClass ::Error && boundIndexType->operator!=(valueExpression->GetType().get())){
|
if (boundIndexType ->GetClass() != TypeClass ::Error && boundIndexType->operator!=(valueExpression->GetType().get())){
|
||||||
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength());
|
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength());
|
||||||
return new BoundBadStatement();
|
return new BoundBadStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundIndexAssignmentStatement(boundIndexExpression, valueExpression);
|
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s){
|
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s){
|
||||||
|
@ -209,6 +215,8 @@ BoundExpression* Binder::BindExpression(const ParsedExpression* expression){
|
||||||
|
|
||||||
case ParsedExpressionKind ::Indexer:
|
case ParsedExpressionKind ::Indexer:
|
||||||
return this->BindIndexExpression((IndexExpression*)expression, false);
|
return this->BindIndexExpression((IndexExpression*)expression, false);
|
||||||
|
case ParsedExpressionKind::PeriodIndexer:
|
||||||
|
return this -> BindPeriodIndexExpression((PeriodIndexExpression*)expression, false);
|
||||||
case ParsedExpressionKind::NumericalTable:
|
case ParsedExpressionKind::NumericalTable:
|
||||||
return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression);
|
return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression);
|
||||||
case ParsedExpressionKind ::Table:
|
case ParsedExpressionKind ::Table:
|
||||||
|
@ -449,6 +457,37 @@ BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression,
|
||||||
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength());
|
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundExpression* Binder::BindPeriodIndexExpression(const PeriodIndexExpression* expression, bool setter){
|
||||||
|
auto indexer = this->BindExpression(expression->GetIndexer());
|
||||||
|
const auto& identifier = expression->GetIndex();
|
||||||
|
const auto& indexerType = indexer -> GetType();
|
||||||
|
if (!indexerType -> CanBeIndexedWithIdentifier(identifier.GetHash())){
|
||||||
|
this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, expression->GetStartPosition(),
|
||||||
|
expression->GetLength());
|
||||||
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
|
}
|
||||||
|
if (indexerType -> GetClass() == TypeClass::UserData){
|
||||||
|
auto field = dynamic_pointer_cast<UserDataScriptType>(indexerType) -> GetField(identifier . GetHash());
|
||||||
|
if (!setter){
|
||||||
|
if (!field->HasGetter()){
|
||||||
|
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, expression->GetStartPosition(),
|
||||||
|
expression->GetLength());
|
||||||
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
if (!field->HasSetter()){
|
||||||
|
this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, expression->GetStartPosition(),
|
||||||
|
expression->GetLength());
|
||||||
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resultType = indexer->GetType()->GetIndexedType(identifier . GetHash());
|
||||||
|
return new BoundPeriodIndexExpression(indexer, identifier, resultType, expression->GetStartPosition(), expression->GetLength());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTableExpression* expression){
|
BoundExpression* Binder::BindNumericalTableExpression(const ParsedNumericalTableExpression* expression){
|
||||||
auto expressions = expression->GetExpressions();
|
auto expressions = expression->GetExpressions();
|
||||||
auto boundExpressions = vector<BoundExpression*>(expressions-> size());
|
auto boundExpressions = vector<BoundExpression*>(expressions-> size());
|
||||||
|
|
|
@ -36,6 +36,7 @@ class Binder {
|
||||||
public:
|
public:
|
||||||
static BoundScriptStatement* Bind(Script* script, const ParsedScriptStatement* s, BoundScope* scriptScope);
|
static BoundScriptStatement* Bind(Script* script, const ParsedScriptStatement* s, BoundScope* scriptScope);
|
||||||
|
|
||||||
|
BoundExpression *BindPeriodIndexExpression(const PeriodIndexExpression *expression, bool setter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum class BoundExpressionKind{
|
||||||
Binary,
|
Binary,
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
Index,
|
Index,
|
||||||
|
PeriodIndex,
|
||||||
NumericalTable,
|
NumericalTable,
|
||||||
Table,
|
Table,
|
||||||
};
|
};
|
||||||
|
@ -279,6 +280,31 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BoundPeriodIndexExpression : public BoundExpression {
|
||||||
|
BoundExpression* _indexableExpression;
|
||||||
|
HashedString _index;
|
||||||
|
public:
|
||||||
|
BoundPeriodIndexExpression(BoundExpression* indexableExpression, HashedString index, shared_ptr<ScriptType> result,
|
||||||
|
unsigned int start, unsigned int length)
|
||||||
|
: BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression), _index(index) {}
|
||||||
|
|
||||||
|
~BoundPeriodIndexExpression() final{
|
||||||
|
delete _indexableExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoundExpressionKind GetKind() const final{
|
||||||
|
return BoundExpressionKind ::PeriodIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoundExpression* GetIndexableExpression() const{
|
||||||
|
return _indexableExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HashedString GetIndex() const{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class BoundNumericalTableExpression : public BoundExpression{
|
class BoundNumericalTableExpression : public BoundExpression{
|
||||||
const vector<BoundExpression*> _expressions;
|
const vector<BoundExpression*> _expressions;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -129,7 +129,7 @@ class BoundIndexAssignmentStatement : public BoundStatement{
|
||||||
const BoundExpression* _indexExpression;
|
const BoundExpression* _indexExpression;
|
||||||
const BoundExpression* _valueExpression;
|
const BoundExpression* _valueExpression;
|
||||||
public:
|
public:
|
||||||
BoundIndexAssignmentStatement(BoundExpression* index, BoundExpression* value)
|
BoundIndexAssignmentStatement(const BoundExpression* index, BoundExpression* value)
|
||||||
: _indexExpression(index), _valueExpression(value)
|
: _indexExpression(index), _valueExpression(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ public:
|
||||||
throw EvaluationException("Can't index this EvalValue");
|
throw EvaluationException("Can't index this EvalValue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual shared_ptr<EvalValue> IndexValue(uint32_t hash){
|
||||||
|
throw EvaluationException("Can't index this EvalValue");
|
||||||
|
}
|
||||||
|
|
||||||
virtual void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value){
|
virtual void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value){
|
||||||
throw EvaluationException("Can't index this EvalValue");
|
throw EvaluationException("Can't index this EvalValue");
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ public:
|
||||||
return this -> _table->at(hash);
|
return this -> _table->at(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> IndexValue(uint32_t hash) final{
|
||||||
|
return this -> _table->at(hash);
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<EvalValue> IndexValue(const char* val){
|
shared_ptr<EvalValue> IndexValue(const char* val){
|
||||||
auto hash = HashedString::ConstHash(val);
|
auto hash = HashedString::ConstHash(val);
|
||||||
return this -> _table -> at(hash);
|
return this -> _table -> at(hash);
|
||||||
|
|
|
@ -135,6 +135,7 @@ shared_ptr<NumericEvalValue> Evaluator::EvaluateIntegerExpression(const BoundExp
|
||||||
case BoundExpressionKind::Variable: return dynamic_pointer_cast<NumericEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
case BoundExpressionKind::Variable: return dynamic_pointer_cast<NumericEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
||||||
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
||||||
case BoundExpressionKind ::Index: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateIndexExpression(expression));
|
case BoundExpressionKind ::Index: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluateIndexExpression(expression));
|
||||||
|
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<NumericEvalValue>(this->EvaluatePeriodIndexExpression(expression));
|
||||||
|
|
||||||
case BoundExpressionKind ::LiteralString:
|
case BoundExpressionKind ::LiteralString:
|
||||||
case BoundExpressionKind ::LiteralBool:
|
case BoundExpressionKind ::LiteralBool:
|
||||||
|
@ -153,6 +154,7 @@ shared_ptr<BooleanEvalValue> Evaluator::EvaluateBoolExpression(const BoundExpres
|
||||||
case BoundExpressionKind::Variable: return dynamic_pointer_cast<BooleanEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
case BoundExpressionKind::Variable: return dynamic_pointer_cast<BooleanEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
||||||
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
||||||
case BoundExpressionKind ::Index: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateIndexExpression(expression));
|
case BoundExpressionKind ::Index: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluateIndexExpression(expression));
|
||||||
|
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<BooleanEvalValue>(this->EvaluatePeriodIndexExpression(expression));
|
||||||
|
|
||||||
case BoundExpressionKind::Bad:
|
case BoundExpressionKind::Bad:
|
||||||
case BoundExpressionKind::LiteralInteger:
|
case BoundExpressionKind::LiteralInteger:
|
||||||
|
@ -174,6 +176,7 @@ shared_ptr<StringEvalValue> Evaluator::EvaluateStringExpression(const BoundExpre
|
||||||
case BoundExpressionKind::Variable: return dynamic_pointer_cast<StringEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
case BoundExpressionKind::Variable: return dynamic_pointer_cast<StringEvalValue>(this->GetVariable((BoundVariableExpression*)expression));
|
||||||
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
case BoundExpressionKind ::FunctionCall: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateFunctionCallExpression(expression));
|
||||||
case BoundExpressionKind ::Index: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateIndexExpression(expression));
|
case BoundExpressionKind ::Index: return dynamic_pointer_cast<StringEvalValue>(this->EvaluateIndexExpression(expression));
|
||||||
|
case BoundExpressionKind ::PeriodIndex: return dynamic_pointer_cast<StringEvalValue>(this->EvaluatePeriodIndexExpression(expression));
|
||||||
|
|
||||||
case BoundExpressionKind::Bad:
|
case BoundExpressionKind::Bad:
|
||||||
case BoundExpressionKind::LiteralInteger:
|
case BoundExpressionKind::LiteralInteger:
|
||||||
|
@ -191,6 +194,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionExpression(const BoundExpressio
|
||||||
switch (expression->GetKind()){
|
switch (expression->GetKind()){
|
||||||
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 ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression);
|
||||||
default: throw;
|
default: throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,6 +214,7 @@ shared_ptr<EvalValue> Evaluator::EvaluateTableExpression(const BoundExpression *
|
||||||
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);
|
case BoundExpressionKind ::Table: return this -> EvaluateComplexTableExpression(expression);
|
||||||
|
case BoundExpressionKind ::PeriodIndex: return this->EvaluatePeriodIndexExpression(expression);
|
||||||
default:
|
default:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
@ -276,6 +281,13 @@ shared_ptr<EvalValue> Evaluator::EvaluateIndexExpression(const BoundExpression *
|
||||||
return indexable -> IndexValue(index.get()) -> Clone();
|
return indexable -> IndexValue(index.get()) -> Clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> Evaluator::EvaluatePeriodIndexExpression(const BoundExpression *expression) {
|
||||||
|
auto indexExpression = (BoundPeriodIndexExpression*)expression;
|
||||||
|
auto index = indexExpression -> GetIndex().GetHash();
|
||||||
|
auto indexable = this -> EvaluateExpression(indexExpression->GetIndexableExpression());
|
||||||
|
return indexable -> IndexValue(index) -> Clone();
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
|
shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
|
||||||
auto tableExpression = (BoundNumericalTableExpression*)expression;
|
auto tableExpression = (BoundNumericalTableExpression*)expression;
|
||||||
auto valueExpressions = tableExpression->GetExpressions();
|
auto valueExpressions = tableExpression->GetExpressions();
|
||||||
|
|
|
@ -47,6 +47,7 @@ class Evaluator {
|
||||||
shared_ptr<BooleanEvalValue> EvaluateBooleanUnary(const BoundUnaryExpression *expression);
|
shared_ptr<BooleanEvalValue> EvaluateBooleanUnary(const BoundUnaryExpression *expression);
|
||||||
shared_ptr<EvalValue> EvaluateFunctionCallExpression(const BoundExpression *expression);
|
shared_ptr<EvalValue> EvaluateFunctionCallExpression(const BoundExpression *expression);
|
||||||
shared_ptr<EvalValue> EvaluateIndexExpression(const BoundExpression* expression);
|
shared_ptr<EvalValue> EvaluateIndexExpression(const BoundExpression* expression);
|
||||||
|
shared_ptr<EvalValue> EvaluatePeriodIndexExpression(const BoundExpression* expression);
|
||||||
shared_ptr<EvalValue> EvaluateNumericTableExpression(const BoundExpression* expression);
|
shared_ptr<EvalValue> EvaluateNumericTableExpression(const BoundExpression* expression);
|
||||||
shared_ptr<EvalValue> EvaluateComplexTableExpression(const BoundExpression *expression);
|
shared_ptr<EvalValue> EvaluateComplexTableExpression(const BoundExpression *expression);
|
||||||
shared_ptr<EvalValue> EvaluateUserDataExpression(const BoundExpression *expression);
|
shared_ptr<EvalValue> EvaluateUserDataExpression(const BoundExpression *expression);
|
||||||
|
|
|
@ -25,6 +25,7 @@ enum class ParsedExpressionKind{
|
||||||
Parenthesized,
|
Parenthesized,
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
Indexer,
|
Indexer,
|
||||||
|
PeriodIndexer,
|
||||||
NumericalTable,
|
NumericalTable,
|
||||||
Table,
|
Table,
|
||||||
};
|
};
|
||||||
|
@ -287,6 +288,34 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PeriodIndexExpression : public ParsedExpression{
|
||||||
|
const ParsedExpression* _indexerExpression;
|
||||||
|
const HashedString _index;
|
||||||
|
public:
|
||||||
|
PeriodIndexExpression(ParsedExpression* indexer, HashedString index, unsigned int start, unsigned int length)
|
||||||
|
:ParsedExpression(start, length),
|
||||||
|
_indexerExpression(indexer), _index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~PeriodIndexExpression() final{
|
||||||
|
delete _indexerExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParsedExpressionKind GetKind() const final{
|
||||||
|
return ParsedExpressionKind::PeriodIndexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ParsedExpression* GetIndexer() const{
|
||||||
|
return _indexerExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HashedString& GetIndex() const{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class ParsedNumericalTableExpression : public ParsedExpression{
|
class ParsedNumericalTableExpression : public ParsedExpression{
|
||||||
vector<const ParsedExpression*> _expressions;
|
vector<const ParsedExpression*> _expressions;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -46,7 +46,9 @@ ParsedStatement* Parser::ParseStatement(const IToken* current){
|
||||||
return ParseVariableAssignment(current);
|
return ParseVariableAssignment(current);
|
||||||
}
|
}
|
||||||
auto expression = this -> ParseExpression(current);
|
auto expression = this -> ParseExpression(current);
|
||||||
if (expression->GetKind() == ParsedExpressionKind::Indexer && this -> Peek()->GetKind() == TokenKind::AssignmentToken){
|
auto expKind = expression -> GetKind();
|
||||||
|
if ((expKind == ParsedExpressionKind::Indexer || expKind == ParsedExpressionKind::PeriodIndexer)
|
||||||
|
&& this -> Peek()->GetKind() == TokenKind::AssignmentToken){
|
||||||
return this -> ParseIndexAssignment(expression);
|
return this -> ParseIndexAssignment(expression);
|
||||||
}
|
}
|
||||||
return new ParsedExpressionStatement(expression);
|
return new ParsedExpressionStatement(expression);
|
||||||
|
@ -206,7 +208,7 @@ ParsedExpression* Parser::ParseExpression(const IToken* current){
|
||||||
} else if (peekKind == TokenKind::OpenSquareBracket){
|
} else if (peekKind == TokenKind::OpenSquareBracket){
|
||||||
expression = this->ParseIndexExpression(expression);
|
expression = this->ParseIndexExpression(expression);
|
||||||
} else {
|
} else {
|
||||||
//TODO: index period expression
|
expression = this -> ParsePeriodIndexExpression(expression);
|
||||||
}
|
}
|
||||||
if (this -> _position >= this->_tokens.size())
|
if (this -> _position >= this->_tokens.size())
|
||||||
break;
|
break;
|
||||||
|
@ -379,6 +381,18 @@ ParsedExpression* Parser::ParseIndexExpression(ParsedExpression* indexingExpress
|
||||||
return new IndexExpression(indexingExpression, indexExpression, start, closeBracket->GetEndPosition() - start);
|
return new IndexExpression(indexingExpression, indexExpression, start, closeBracket->GetEndPosition() - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParsedExpression* Parser::ParsePeriodIndexExpression(ParsedExpression* indexingExpression){
|
||||||
|
this->Next(); // consume '.' token
|
||||||
|
auto identifier = this -> Next();
|
||||||
|
if (identifier->GetKind() != TokenKind::Identifier){
|
||||||
|
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength());
|
||||||
|
return new BadExpression(indexingExpression->GetStartPosition(), identifier->GetEndPosition() - indexingExpression->GetStartPosition());
|
||||||
|
}
|
||||||
|
auto start = indexingExpression->GetStartPosition();
|
||||||
|
return new PeriodIndexExpression(indexingExpression, ((IdentifierToken*)identifier)->GetValue(), start, identifier->GetEndPosition() - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ParsedExpression* Parser::ParseTableExpression(const IToken* current){
|
ParsedExpression* Parser::ParseTableExpression(const IToken* current){
|
||||||
if (this -> Peek() -> GetKind() == TokenKind::CloseCurlyBracket){
|
if (this -> Peek() -> GetKind() == TokenKind::CloseCurlyBracket){
|
||||||
this -> Next();
|
this -> Next();
|
||||||
|
|
|
@ -41,6 +41,7 @@ class Parser {
|
||||||
|
|
||||||
ParsedExpression* ParseFunctionCallExpression(ParsedExpression* functionExpression);
|
ParsedExpression* ParseFunctionCallExpression(ParsedExpression* functionExpression);
|
||||||
ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression);
|
ParsedExpression *ParseIndexExpression(ParsedExpression *indexingExpression);
|
||||||
|
ParsedExpression *ParsePeriodIndexExpression(ParsedExpression *indexingExpression);
|
||||||
ParsedExpression *ParseTableExpression(const IToken *current);
|
ParsedExpression *ParseTableExpression(const IToken *current);
|
||||||
public:
|
public:
|
||||||
ParsedScriptStatement* Parse();
|
ParsedScriptStatement* Parse();
|
||||||
|
@ -49,6 +50,7 @@ public:
|
||||||
_position = 0;
|
_position = 0;
|
||||||
ScriptData = scriptData;
|
ScriptData = scriptData;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "Script.hpp"
|
#include "Script.hpp"
|
||||||
|
|
||||||
bool ScriptType::CanBeIndexedWith(ScriptType *indexer) {
|
const bool ScriptType::CanBeIndexedWith(ScriptType *indexer) const{
|
||||||
// String type is the only simple script type we want to
|
// String type is the only simple script type we want to
|
||||||
return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat();
|
return _class == TypeClass::String && indexer->_class == TypeClass::Number && !((NumericScriptType*)indexer)->IsFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ScriptType> ScriptType::GetIndexedType(ScriptType *indexer) {
|
const shared_ptr<ScriptType> ScriptType::GetIndexedType(ScriptType *indexer) const{
|
||||||
if (_class == TypeClass::String){
|
if (_class == TypeClass::String){
|
||||||
return make_shared<ScriptType>(TypeClass::String);
|
return make_shared<ScriptType>(TypeClass::String);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_SCRIPTTYPE_HPP
|
#ifndef PORYGONLANG_SCRIPTTYPE_HPP
|
||||||
#define PORYGONLANG_SCRIPTTYPE_HPP
|
#define PORYGONLANG_SCRIPTTYPE_HPP
|
||||||
|
@ -30,28 +32,34 @@ public:
|
||||||
|
|
||||||
virtual ~ScriptType() = default;
|
virtual ~ScriptType() = default;
|
||||||
|
|
||||||
const TypeClass GetClass(){
|
const TypeClass GetClass() const{
|
||||||
return _class;
|
return _class;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool operator ==(const ScriptType& b){
|
virtual bool operator ==(const ScriptType& b) const{
|
||||||
return _class == b._class;
|
return _class == b._class;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool operator ==(ScriptType* b){
|
virtual bool operator ==(ScriptType* b) const{
|
||||||
return _class == b->_class;
|
return _class == b->_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool operator !=(const ScriptType& b){
|
virtual bool operator !=(const ScriptType& b) const{
|
||||||
return ! (operator==(b));
|
return ! (operator==(b));
|
||||||
}
|
}
|
||||||
virtual bool operator !=(ScriptType* b){
|
virtual bool operator !=(ScriptType* b) const{
|
||||||
return ! (operator==(b));
|
return ! (operator==(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool CanBeIndexedWith(ScriptType* indexer);
|
virtual const bool CanBeIndexedWith(ScriptType* indexer) const;
|
||||||
|
virtual const bool CanBeIndexedWithIdentifier(uint32_t hash) const{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer);
|
virtual const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const;
|
||||||
|
virtual const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const{
|
||||||
|
throw "Shouldn't be possible";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NumericScriptType : public ScriptType{
|
class NumericScriptType : public ScriptType{
|
||||||
|
@ -65,11 +73,11 @@ public:
|
||||||
_isFloat = isFloat;
|
_isFloat = isFloat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAwareOfFloat(){
|
const bool IsAwareOfFloat() const{
|
||||||
return _awareOfFloat;
|
return _awareOfFloat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFloat(){
|
const bool IsFloat() const{
|
||||||
return _isFloat;
|
return _isFloat;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -83,11 +91,11 @@ public:
|
||||||
_hashValue = hashValue;
|
_hashValue = hashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsKnownAtBind(){
|
const bool IsKnownAtBind() const{
|
||||||
return _isKnownAtBind;
|
return _isKnownAtBind;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetHashValue(){
|
const uint32_t GetHashValue() const{
|
||||||
return _hashValue;
|
return _hashValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -106,23 +114,23 @@ public:
|
||||||
_parameterKeys = std::move(parameterKeys);
|
_parameterKeys = std::move(parameterKeys);
|
||||||
_scopeIndex = scopeIndex;
|
_scopeIndex = scopeIndex;
|
||||||
}
|
}
|
||||||
shared_ptr<ScriptType> GetReturnType(){
|
const shared_ptr<ScriptType> GetReturnType() const{
|
||||||
return _returnType;
|
return _returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetReturnType(shared_ptr<ScriptType> t){
|
void SetReturnType(shared_ptr<ScriptType> t){
|
||||||
_returnType = t;
|
_returnType = std::move(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<shared_ptr<ScriptType>> GetParameterTypes(){
|
const vector<shared_ptr<ScriptType>> GetParameterTypes() const{
|
||||||
return _parameterTypes;
|
return _parameterTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<shared_ptr<BoundVariableKey>> GetParameterKeys(){
|
const vector<shared_ptr<BoundVariableKey>> GetParameterKeys() const{
|
||||||
return _parameterKeys;
|
return _parameterKeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetScopeIndex(){
|
const int GetScopeIndex() const{
|
||||||
return _scopeIndex;
|
return _scopeIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -135,11 +143,11 @@ public:
|
||||||
_valueType = std::move(valueType);
|
_valueType = std::move(valueType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanBeIndexedWith(ScriptType* indexer) final{
|
const bool CanBeIndexedWith(ScriptType* indexer) const final{
|
||||||
return indexer->GetClass() == TypeClass ::Number;
|
return indexer->GetClass() == TypeClass ::Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{
|
||||||
return _valueType;
|
return _valueType;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,11 +21,15 @@ public:
|
||||||
delete _values;
|
delete _values;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanBeIndexedWith(ScriptType* indexer) final{
|
const bool CanBeIndexedWith(ScriptType* indexer) const final{
|
||||||
return indexer->GetClass() == TypeClass ::String;
|
return indexer->GetClass() == TypeClass ::String;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
const bool CanBeIndexedWithIdentifier(uint32_t hash) const final{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{
|
||||||
auto stringKey = (StringScriptType*)indexer;
|
auto stringKey = (StringScriptType*)indexer;
|
||||||
if (stringKey->IsKnownAtBind()){
|
if (stringKey->IsKnownAtBind()){
|
||||||
return _values-> at(stringKey->GetHashValue())->GetType();
|
return _values-> at(stringKey->GetHashValue())->GetType();
|
||||||
|
@ -33,11 +37,15 @@ public:
|
||||||
throw "TODO: indexing with dynamic keys";
|
throw "TODO: indexing with dynamic keys";
|
||||||
}
|
}
|
||||||
|
|
||||||
const unordered_map<uint32_t, BoundVariable*>* GetValues(){
|
const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const final{
|
||||||
|
return _values-> at(hash)->GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
const unordered_map<uint32_t, BoundVariable*>* GetValues() const{
|
||||||
return _values;
|
return _values;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int GetLocalVariableCount(){
|
const int GetLocalVariableCount() const{
|
||||||
return _localVariableCount;
|
return _localVariableCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
_userData = std::move(ud);
|
_userData = std::move(ud);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanBeIndexedWith(ScriptType* indexer) final{
|
const bool CanBeIndexedWith(ScriptType* indexer) const final{
|
||||||
if (indexer->GetClass() != TypeClass ::String){
|
if (indexer->GetClass() != TypeClass ::String){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,25 @@ public:
|
||||||
return _userData->ContainsField(str->GetHashValue());
|
return _userData->ContainsField(str->GetHashValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool CanBeIndexedWithIdentifier(uint32_t hash) const final{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
UserDataField* GetField(uint32_t id){
|
UserDataField* GetField(uint32_t id){
|
||||||
return _userData -> GetField(id);
|
return _userData -> GetField(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
|
const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{
|
||||||
auto stringKey = (StringScriptType*)indexer;
|
auto stringKey = (StringScriptType*)indexer;
|
||||||
if (stringKey->IsKnownAtBind()){
|
if (stringKey->IsKnownAtBind()){
|
||||||
return _userData->GetField(stringKey->GetHashValue())->GetType();
|
return _userData->GetField(stringKey->GetHashValue())->GetType();
|
||||||
}
|
}
|
||||||
throw "TODO: indexing with dynamic keys";
|
throw "TODO: indexing with dynamic keys";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const final{
|
||||||
|
return _userData->GetField(hash)->GetType();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,11 @@ public:
|
||||||
return shared_ptr<EvalValue>(field->Get(_obj));
|
return shared_ptr<EvalValue>(field->Get(_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<EvalValue> IndexValue(uint32_t hash) final{
|
||||||
|
auto field = _userData->GetField(hash);
|
||||||
|
return shared_ptr<EvalValue>(field->Get(_obj));
|
||||||
|
}
|
||||||
|
|
||||||
void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value) final{
|
void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value) final{
|
||||||
auto fieldId = key->GetHashCode();
|
auto fieldId = key->GetHashCode();
|
||||||
auto field = _userData->GetField(fieldId);
|
auto field = _userData->GetField(fieldId);
|
||||||
|
|
|
@ -11,4 +11,18 @@ TEST_CASE( "String indexing", "[integration]" ) {
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Identifier Index", "[integration]" ) {
|
||||||
|
auto script = Script::Create(uR"(
|
||||||
|
foo = {
|
||||||
|
bar = "test"
|
||||||
|
}
|
||||||
|
return foo.bar
|
||||||
|
)");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
auto result = script->Evaluate();
|
||||||
|
REQUIRE(*result->EvaluateString() == u"test");
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue