Implements setting table values
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2019-06-14 17:12:27 +02:00
parent 996b5be496
commit a9def6c539
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
14 changed files with 141 additions and 15 deletions

View File

@ -29,6 +29,7 @@ BoundStatement* Binder::BindStatement(const ParsedStatement* statement){
case ParsedStatementKind ::Block: return this -> BindBlockStatement(statement);
case ParsedStatementKind ::Expression: return this -> BindExpressionStatement(statement);
case ParsedStatementKind::Assignment: return this -> BindAssignmentStatement(statement);
case ParsedStatementKind::IndexAssignment: return this -> BindIndexAssignmentStatement(statement);
case ParsedStatementKind ::FunctionDeclaration: return this->BindFunctionDeclarationStatement(statement);
case ParsedStatementKind::Return: return this -> BindReturnStatement(statement);
case ParsedStatementKind::Conditional: return this -> BindConditionalStatement(statement);
@ -70,6 +71,17 @@ BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement
}
}
BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) {
auto s = (ParsedIndexAssignmentStatement*) statement;
auto boundIndexExpression = this -> BindIndexExpression((IndexExpression*)s->GetIndexExpression());
auto valueExpression = this -> BindExpression(s->GetValueExpression());
if (boundIndexExpression->GetType()->operator!=(valueExpression->GetType().get())){
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength());
return new BoundBadStatement();
}
return new BoundIndexAssignmentStatement(boundIndexExpression, valueExpression);
}
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s){
switch (s.GetHash()){
case HashedString::ConstHash("number"): return std::make_shared<NumericScriptType>(false, false);
@ -442,3 +454,4 @@ BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expres
return new BoundTableExpression((BoundBlockStatement*)block, tableType, expression->GetStartPosition(), expression->GetLength());
}

View File

@ -20,6 +20,7 @@ class Binder {
BoundStatement *BindBlockStatement(const ParsedStatement *statement);
BoundStatement *BindExpressionStatement(const ParsedStatement *statement);
BoundStatement *BindAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement * statement);
BoundStatement *BindReturnStatement(const ParsedStatement *statement);
BoundStatement *BindConditionalStatement(const ParsedStatement *statement);

View File

@ -18,6 +18,7 @@ enum class BoundStatementKind{
Block,
Expression,
Assignment,
IndexAssignment,
FunctionDeclaration,
Return,
Conditional,
@ -124,6 +125,33 @@ public:
}
};
class BoundIndexAssignmentStatement : public BoundStatement{
const BoundExpression* _indexExpression;
const BoundExpression* _valueExpression;
public:
BoundIndexAssignmentStatement(BoundExpression* index, BoundExpression* value)
: _indexExpression(index), _valueExpression(value)
{
}
~BoundIndexAssignmentStatement() final{
delete _indexExpression;
delete _valueExpression;
}
const BoundStatementKind GetKind() const final{
return BoundStatementKind ::IndexAssignment;
}
const BoundExpression* GetIndexExpression() const {
return _indexExpression;
}
const BoundExpression* GetValueExpression() const {
return _valueExpression;
}
};
class BoundReturnStatement : public BoundStatement{
const BoundExpression* _expression;
public:

View File

@ -22,16 +22,16 @@ public:
virtual shared_ptr<EvalValue> Clone() = 0;
virtual long EvaluateInteger(){
virtual long EvaluateInteger() const{
throw EvaluationException("Can't evaluate this EvalValue as integer.");
}
virtual double EvaluateFloat(){
virtual double EvaluateFloat() const{
throw EvaluationException("Can't evaluate this EvalValue as float.");
}
virtual bool EvaluateBool(){
virtual bool EvaluateBool() const{
throw EvaluationException("Can't evaluate this EvalValue as bool.");
}
virtual std::string* EvaluateString(){
virtual const std::string* EvaluateString() const {
throw EvaluationException("Can't evaluate this EvalValue as string.");
}
@ -40,6 +40,10 @@ public:
virtual shared_ptr<EvalValue> IndexValue(EvalValue* val){
throw EvaluationException("Can't index this EvalValue");
}
virtual void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value){
throw EvaluationException("Can't index this EvalValue");
}
};
class BooleanEvalValue : public EvalValue{
@ -58,7 +62,7 @@ public:
return TypeClass ::Bool;
}
bool EvaluateBool() final{
bool EvaluateBool() const final{
return _value;
}

View File

@ -40,7 +40,7 @@ public:
return false;
}
long EvaluateInteger() final{
long EvaluateInteger() const final{
return _value;
}
@ -65,7 +65,7 @@ public:
return true;
}
double EvaluateFloat() final{
double EvaluateFloat() const final{
return _value;
}

View File

@ -27,7 +27,7 @@ public:
return this->_hash == b->GetHashCode();
};
string* EvaluateString() final{
const string* EvaluateString() const final{
return &_value;
}

View File

@ -45,6 +45,11 @@ public:
auto hash = HashedString::ConstHash(val);
return this -> _table -> at(hash);
}
void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value) final{
auto hash = key->GetHashCode();
this -> _table->at(hash) = value;
}
};

View File

@ -26,6 +26,8 @@ void Evaluator::EvaluateStatement(const BoundStatement *statement) {
case BoundStatementKind ::Block: return this->EvaluateBlockStatement((BoundBlockStatement *) statement);
case BoundStatementKind ::Expression: return this -> EvaluateExpressionStatement((BoundExpressionStatement*)statement);
case BoundStatementKind ::Assignment: return this -> EvaluateAssignmentStatement((BoundAssignmentStatement*)statement);
case BoundStatementKind::IndexAssignment:
return this -> EvaluateIndexAssignmentStatement((BoundIndexAssignmentStatement*)statement);
case BoundStatementKind ::FunctionDeclaration: return this->EvaluateFunctionDeclarationStatement((BoundFunctionDeclarationStatement*)statement);
case BoundStatementKind::Return: return this -> EvaluateReturnStatement((BoundReturnStatement*)statement);
case BoundStatementKind::Conditional: return this -> EvaluateConditionalStatement((BoundConditionalStatement*)statement);
@ -58,6 +60,15 @@ void Evaluator::EvaluateAssignmentStatement(const BoundAssignmentStatement *stat
}
}
void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) {
auto indexExpression = statement -> GetIndexExpression();
auto value = this -> EvaluateExpression(statement -> GetValueExpression());
auto index = ((BoundIndexExpression*)indexExpression);
auto table = this -> EvaluateExpression(index -> GetIndexableExpression());
auto key = this -> EvaluateExpression(index->GetIndexExpression());
table -> SetIndexValue(key.get(), value);
}
void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) {
auto type = statement->GetType();
auto key = statement->GetKey();
@ -300,3 +311,4 @@ shared_ptr<EvalValue> Evaluator::EvaluateUserDataExpression(const BoundExpressio
default: throw;
}
}

View File

@ -26,6 +26,7 @@ class Evaluator {
void EvaluateBlockStatement(const BoundBlockStatement *statement);
void EvaluateExpressionStatement(const BoundExpressionStatement* statement);
void EvaluateAssignmentStatement(const BoundAssignmentStatement* statement);
void EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement* statement);
void EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement);
void EvaluateReturnStatement(const BoundReturnStatement *statement);
void EvaluateConditionalStatement(const BoundConditionalStatement *statement);

View File

@ -19,6 +19,7 @@ enum class ParsedStatementKind{
Block,
Expression,
Assignment,
IndexAssignment,
FunctionDeclaration,
Return,
Conditional
@ -180,6 +181,33 @@ public:
}
};
class ParsedIndexAssignmentStatement : public ParsedStatement{
const ParsedExpression* _indexExpression;
const ParsedExpression* _valueExpression;
public:
ParsedIndexAssignmentStatement(ParsedExpression* indexExpression, ParsedExpression* valueExpression, unsigned int start,
unsigned int length)
: ParsedStatement(start, length),
_indexExpression(indexExpression), _valueExpression(valueExpression){}
~ParsedIndexAssignmentStatement() final{
delete _indexExpression;
delete _valueExpression;
}
const ParsedStatementKind GetKind() const final{
return ParsedStatementKind ::IndexAssignment;
}
const ParsedExpression* GetIndexExpression() const{
return _indexExpression;
}
const ParsedExpression* GetValueExpression() const{
return _valueExpression;
}
};
class ParsedReturnStatement : public ParsedStatement{
const ParsedExpression* _expression;
public:

View File

@ -1,6 +1,4 @@
#include <utility>
#include <algorithm>
#include "Parser.hpp"
#include "ParsedStatements/ParsedStatement.hpp"
@ -38,19 +36,23 @@ const IToken *Parser::Next() {
ParsedStatement* Parser::ParseStatement(const IToken* current){
auto currentKind = current->GetKind();
switch (currentKind){
case TokenKind ::LocalKeyword: return this -> ParseAssignment(current);
case TokenKind ::LocalKeyword: return this->ParseVariableAssignment(current);
case TokenKind ::FunctionKeyword: return this -> ParseFunctionDeclaration(current);
case TokenKind ::ReturnKeyword: return this->ParseReturnStatement(current);
case TokenKind ::IfKeyword: return this -> ParseIfStatement(current);
default: break;
}
if (this->Peek()->GetKind() == TokenKind::AssignmentToken){
return ParseAssignment(current);
return ParseVariableAssignment(current);
}
return new ParsedExpressionStatement(this -> ParseExpression(current));
auto expression = this -> ParseExpression(current);
if (expression->GetKind() == ParsedExpressionKind::Indexer && this -> Peek()->GetKind() == TokenKind::AssignmentToken){
return this -> ParseIndexAssignment(expression);
}
return new ParsedExpressionStatement(expression);
}
ParsedStatement *Parser::ParseAssignment(const IToken *current) {
ParsedStatement *Parser::ParseVariableAssignment(const IToken *current) {
bool isLocal = false;
const IToken* identifier;
if (current -> GetKind() == TokenKind::LocalKeyword){
@ -75,6 +77,14 @@ ParsedStatement *Parser::ParseAssignment(const IToken *current) {
return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> GetValue(), expression, start, expression->GetEndPosition() - start);
}
ParsedStatement *Parser::ParseIndexAssignment(ParsedExpression *indexer) {
this -> Next(); // Consume assignment token
auto valueExpression = this -> ParseExpression(this -> Next());
auto start = indexer->GetStartPosition();
return new ParsedIndexAssignmentStatement(indexer, valueExpression, start, valueExpression->GetEndPosition() - start);
}
ParsedStatement *Parser::ParseBlock(const vector<TokenKind>& endTokens, const vector<const ParsedStatement*>& openStatements) {
auto statements = openStatements;
auto start = this->_position;

View File

@ -27,7 +27,8 @@ class Parser {
const IToken* Next();
ParsedStatement* ParseStatement(const IToken* current);
ParsedStatement* ParseAssignment(const IToken* current);
ParsedStatement* ParseVariableAssignment(const IToken *current);
ParsedStatement* ParseIndexAssignment(ParsedExpression *indexer);
ParsedStatement *ParseBlock(const vector<TokenKind>& endTokens, const vector<const ParsedStatement*>& openStatements = {});
ParsedStatement* ParseFunctionDeclaration(const IToken* current);
ParsedStatement *ParseReturnStatement(const IToken *current);

View File

@ -44,6 +44,12 @@ public:
auto field = _userData->GetField(fieldId);
return shared_ptr<EvalValue>(field->Get(_obj));
}
void SetIndexValue(EvalValue *key, shared_ptr<EvalValue> value) final{
auto fieldId = key->GetHashCode();
auto field = _userData->GetField(fieldId);
field -> Set(_obj, value.get());
}
};

View File

@ -44,5 +44,22 @@ end
delete script;
}
TEST_CASE( "Sets UserData value", "[integration]" ) {
UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData());
Script* script = Script::Create(R"(
function testFunc(testObject obj)
obj["foo"] = 5000
end
)");
REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate();
auto obj = new UserDataTestObject();
auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), obj);
script->CallFunction("testFunc", {parameter});
REQUIRE(obj->foo == 5000);
delete script;
}
#endif