Implements assignment binding
This commit is contained in:
parent
dbd7dfdd73
commit
5d1c3ac9ba
|
@ -1,9 +1,11 @@
|
|||
|
||||
#include "Binder.hpp"
|
||||
|
||||
BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s) {
|
||||
BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s, BoundScope* scriptScope) {
|
||||
auto binder = Binder();
|
||||
binder.ScriptData = script;
|
||||
binder._scriptData = script;
|
||||
|
||||
binder._scope = scriptScope;
|
||||
auto statements = s->GetStatements();
|
||||
vector<BoundStatement*> boundStatements (statements.size());
|
||||
for (int i = 0; i < statements.size(); i++){
|
||||
|
@ -12,11 +14,18 @@ BoundScriptStatement *Binder::Bind(Script* script, ParsedScriptStatement *s) {
|
|||
return new BoundScriptStatement(boundStatements);
|
||||
}
|
||||
|
||||
Binder::~Binder() {
|
||||
delete _scope;
|
||||
}
|
||||
|
||||
BoundStatement* Binder::BindStatement(ParsedStatement* statement){
|
||||
switch (statement -> GetKind()) {
|
||||
case ParsedStatementKind ::Script: throw; // This shouldn't happen.
|
||||
case ParsedStatementKind ::Block: return this -> BindBlockStatement(statement);
|
||||
case ParsedStatementKind ::Expression: return this -> BindExpressionStatement(statement);
|
||||
case ParsedStatementKind::Assignment: return this -> BindAssignmentStatement(statement);
|
||||
|
||||
case ParsedStatementKind::Bad: return new BoundBadStatement();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +43,20 @@ BoundStatement *Binder::BindExpressionStatement(ParsedStatement *statement) {
|
|||
return new BoundExpressionStatement(this -> BindExpression(exp));
|
||||
}
|
||||
|
||||
BoundStatement* Binder::BindAssignmentStatement(ParsedStatement *statement){
|
||||
auto s = (ParsedAssignmentStatement*) statement;
|
||||
auto boundExpression = this->BindExpression(s->GetExpression());
|
||||
auto assignment = this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType());
|
||||
if (assignment.GetResult() == VariableAssignmentResult::Ok){
|
||||
auto key = assignment.GetKey();
|
||||
return new BoundAssignmentStatement(key, boundExpression);
|
||||
}
|
||||
else{
|
||||
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
}
|
||||
|
||||
BoundExpression* Binder::BindExpression(ParsedExpression* expression){
|
||||
switch (expression -> GetKind()){
|
||||
case ParsedExpressionKind ::LiteralInteger:
|
||||
|
@ -149,7 +172,7 @@ BoundExpression* Binder::BindBinaryOperator(BinaryExpression* expression){
|
|||
expression->GetStartPosition(), expression->GetLength());
|
||||
break;
|
||||
}
|
||||
this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength());
|
||||
this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(), expression->GetLength());
|
||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||
}
|
||||
|
||||
|
@ -179,7 +202,8 @@ BoundExpression* Binder::BindUnaryOperator(UnaryExpression* expression){
|
|||
default:
|
||||
break;
|
||||
}
|
||||
this -> ScriptData -> Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), expression->GetLength());
|
||||
this -> _scriptData -> Diagnostics->LogError(DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(), expression->GetLength());
|
||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,20 +4,25 @@
|
|||
#include "../Parser/ParsedStatements/ParsedStatement.hpp"
|
||||
#include "BoundStatements/BoundStatement.hpp"
|
||||
#include "../Script.hpp"
|
||||
#include "BoundVariables/BoundScope.hpp"
|
||||
|
||||
|
||||
class Binder {
|
||||
Script* ScriptData;
|
||||
Script* _scriptData;
|
||||
BoundScope* _scope;
|
||||
|
||||
~Binder();
|
||||
|
||||
BoundStatement *BindStatement(ParsedStatement *statement);
|
||||
BoundStatement *BindBlockStatement(ParsedStatement *statement);
|
||||
BoundStatement *BindExpressionStatement(ParsedStatement *statement);
|
||||
BoundStatement *BindAssignmentStatement(ParsedStatement *statement);
|
||||
|
||||
BoundExpression *BindExpression(ParsedExpression *expression);
|
||||
BoundExpression *BindBinaryOperator(BinaryExpression *expression);
|
||||
BoundExpression *BindUnaryOperator(UnaryExpression *expression);
|
||||
public:
|
||||
static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s);
|
||||
static BoundScriptStatement* Bind(Script* script, ParsedScriptStatement* s, BoundScope* scriptScope);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
|
||||
#include <vector>
|
||||
#include "../BoundExpressions/BoundExpression.hpp"
|
||||
#include "../BoundVariables/BoundVariableKey.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum class BoundStatementKind{
|
||||
Bad,
|
||||
Script,
|
||||
Block,
|
||||
Expression,
|
||||
Assignment,
|
||||
};
|
||||
|
||||
class BoundStatement{
|
||||
|
@ -21,6 +24,13 @@ public:
|
|||
virtual ~BoundStatement() = default;
|
||||
};
|
||||
|
||||
class BoundBadStatement : public BoundStatement{
|
||||
public:
|
||||
BoundStatementKind GetKind() final{
|
||||
return BoundStatementKind ::Bad;
|
||||
}
|
||||
};
|
||||
|
||||
class BoundBlockStatement : public BoundStatement{
|
||||
vector<BoundStatement*> _statements;
|
||||
public:
|
||||
|
@ -72,4 +82,22 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class BoundAssignmentStatement : public BoundStatement{
|
||||
BoundVariableKey* _key;
|
||||
BoundExpression* _expression;
|
||||
public:
|
||||
BoundAssignmentStatement(BoundVariableKey* key, BoundExpression* expression){
|
||||
_key = key;
|
||||
_expression = expression;
|
||||
}
|
||||
~BoundAssignmentStatement() final{
|
||||
delete _key;
|
||||
delete _expression;
|
||||
}
|
||||
|
||||
BoundStatementKind GetKind() final{
|
||||
return BoundStatementKind ::Assignment;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_BOUNDSTATEMENT_HPP
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "BoundScope.hpp"
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
#ifndef PORYGONLANG_BOUNDSCOPE_HPP
|
||||
#define PORYGONLANG_BOUNDSCOPE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "BoundVariable.hpp"
|
||||
#include "BoundVariableKey.hpp"
|
||||
#include "VariableAssigmentResult.hpp"
|
||||
#include "../../Utilities/HashedString.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BoundScope {
|
||||
unordered_map<int, BoundVariable*>* _scriptScope;
|
||||
vector<unordered_map<int, BoundVariable*>> _localScope;
|
||||
int _currentScope;
|
||||
public:
|
||||
explicit BoundScope(unordered_map<int, BoundVariable*> *scriptScope){
|
||||
_scriptScope = scriptScope;
|
||||
_currentScope = 1;
|
||||
_localScope = vector<unordered_map<int, BoundVariable*>>(1);
|
||||
}
|
||||
~BoundScope(){
|
||||
_localScope.clear();
|
||||
}
|
||||
|
||||
int Exists(int key){
|
||||
auto found = this -> _scriptScope -> find(key);
|
||||
if (found != _scriptScope -> end()){
|
||||
return 0;
|
||||
}
|
||||
for (int i = _currentScope - 1; i >= 0; i--){
|
||||
auto scope = _localScope.at(i);
|
||||
found = scope.find(key);
|
||||
if (found != scope.end()){
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BoundVariable* GetVariable(int scope, int identifier){
|
||||
if (scope == 0){
|
||||
auto find = this -> _scriptScope->find(identifier);
|
||||
if (find != _scriptScope->end()){
|
||||
return find -> second;
|
||||
}
|
||||
return nullptr;
|
||||
} else{
|
||||
auto s = this->_localScope.at(scope);
|
||||
auto find = s.find(identifier);
|
||||
if (find != s.end()){
|
||||
return find -> second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VariableAssignment CreateExplicitLocal(HashedString& identifier, ScriptType* type){
|
||||
auto scope = this->_localScope.at(this->_currentScope);
|
||||
if (scope.find(identifier.GetHash()) != scope.end()){
|
||||
return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr);
|
||||
}
|
||||
scope.insert({identifier.GetHash(), new BoundVariable(type)});
|
||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier.GetHash(), this->_currentScope, true));
|
||||
}
|
||||
|
||||
VariableAssignment AssignVariable(int identifier, ScriptType* type){
|
||||
int exists = this->Exists(identifier);
|
||||
if (exists == -1){
|
||||
// Creation
|
||||
_scriptScope->insert({identifier, new BoundVariable(type)});
|
||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, 0, true));
|
||||
} else{
|
||||
// Assigning
|
||||
auto var = this->GetVariable(exists, identifier);
|
||||
if (var->GetType() != type){
|
||||
return VariableAssignment(VariableAssignmentResult::VariableDefinedWithDifferentType, nullptr);
|
||||
}
|
||||
return VariableAssignment(VariableAssignmentResult::Ok, new BoundVariableKey(identifier, exists, false));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //PORYGONLANG_BOUNDSCOPE_HPP
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
#ifndef PORYGONLANG_BOUNDVARIABLE_HPP
|
||||
#define PORYGONLANG_BOUNDVARIABLE_HPP
|
||||
|
||||
#include "../../ScriptType.hpp"
|
||||
|
||||
class BoundVariable{
|
||||
ScriptType* _type;
|
||||
public:
|
||||
explicit BoundVariable(ScriptType* type){
|
||||
_type = type;
|
||||
}
|
||||
~BoundVariable(){
|
||||
delete _type;
|
||||
}
|
||||
|
||||
ScriptType* GetType(){
|
||||
return _type;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_BOUNDVARIABLE_HPP
|
|
@ -0,0 +1,33 @@
|
|||
#include <utility>
|
||||
|
||||
|
||||
#ifndef PORYGONLANG_BOUNDVARIABLEKEY_HPP
|
||||
#define PORYGONLANG_BOUNDVARIABLEKEY_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
class BoundVariableKey{
|
||||
int _identifier;
|
||||
unsigned int _scopeId;
|
||||
bool _isCreation;
|
||||
public:
|
||||
BoundVariableKey(int id, unsigned int scope, bool creation){
|
||||
_identifier = std::move(id);
|
||||
_scopeId = scope;
|
||||
_isCreation = creation;
|
||||
}
|
||||
|
||||
int GetIdentifier(){
|
||||
return _identifier;
|
||||
}
|
||||
|
||||
unsigned int GetScopeId(){
|
||||
return _scopeId;
|
||||
}
|
||||
|
||||
bool IsCreation(){
|
||||
return _isCreation;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_BOUNDVARIABLEKEY_HPP
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
#ifndef PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP
|
||||
#define PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP
|
||||
|
||||
#include "BoundVariableKey.hpp"
|
||||
|
||||
enum class VariableAssignmentResult{
|
||||
Ok,
|
||||
ExplicitLocalVariableExists,
|
||||
VariableDefinedWithDifferentType
|
||||
};
|
||||
|
||||
class VariableAssignment{
|
||||
VariableAssignmentResult _result;
|
||||
BoundVariableKey* _key;
|
||||
public:
|
||||
VariableAssignment(VariableAssignmentResult result, BoundVariableKey *key) {
|
||||
_result = result;
|
||||
_key = key;
|
||||
}
|
||||
|
||||
VariableAssignmentResult GetResult(){
|
||||
return _result;
|
||||
}
|
||||
|
||||
BoundVariableKey* GetKey(){
|
||||
return _key;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_VARIABLEASSIGMENTRESULT_HPP
|
|
@ -13,6 +13,7 @@ enum class DiagnosticCode{
|
|||
// Bind diagnostics
|
||||
NoBinaryOperationFound,
|
||||
NoUnaryOperationFound,
|
||||
CantAssignVariable,
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
|
||||
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
|
@ -8,6 +12,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "../ParsedExpressions/ParsedExpression.hpp"
|
||||
#include "../../Utilities/HashedString.hpp"
|
||||
|
||||
enum class ParsedStatementKind{
|
||||
Bad,
|
||||
|
@ -32,6 +37,10 @@ public:
|
|||
return _start;
|
||||
}
|
||||
|
||||
unsigned int GetLength(){
|
||||
return _length;
|
||||
}
|
||||
|
||||
unsigned int GetEndPosition(){
|
||||
return _start + _length - 1;
|
||||
}
|
||||
|
@ -98,13 +107,13 @@ public:
|
|||
|
||||
class ParsedAssignmentStatement : public ParsedStatement{
|
||||
bool _local;
|
||||
std::string _identifier;
|
||||
HashedString _identifier;
|
||||
ParsedExpression* _expression;
|
||||
public:
|
||||
ParsedAssignmentStatement(bool local, std::string identifier, ParsedExpression* expression, unsigned int start, unsigned int length)
|
||||
: ParsedStatement(start, length){
|
||||
: ParsedStatement(start, length), _identifier(HashedString(std::move(identifier)))
|
||||
{
|
||||
_local = local;
|
||||
_identifier = std::move(identifier);
|
||||
_expression = expression;
|
||||
}
|
||||
~ParsedAssignmentStatement() final{
|
||||
|
@ -119,7 +128,7 @@ public:
|
|||
return _local;
|
||||
}
|
||||
|
||||
std::string GetIdentifier(){
|
||||
HashedString GetIdentifier(){
|
||||
return _identifier;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#include <utility>
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
#include "Script.hpp"
|
||||
#include "Parser/Lexer.hpp"
|
||||
#include "Parser/Parser.hpp"
|
||||
#include "Binder/Binder.hpp"
|
||||
|
||||
Script Script::Create(string script) {
|
||||
auto s = Script();
|
||||
s.Parse(std::move(script));
|
||||
Script* Script::Create(string script) {
|
||||
auto s = new Script();
|
||||
s -> Parse(std::move(script));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -40,7 +39,14 @@ void Script::Parse(string script) {
|
|||
}
|
||||
lexResult.clear();
|
||||
if (!Diagnostics->HasErrors()){
|
||||
this->BoundScript = Binder::Bind(this, parseResult);
|
||||
unordered_map<int, BoundVariable*> scriptScope;
|
||||
auto bindScope = new BoundScope(&scriptScope);
|
||||
this->BoundScript = Binder::Bind(this, parseResult, bindScope);
|
||||
for (const auto& v : scriptScope){
|
||||
this->_scopeVariables.insert({v.first, nullptr});
|
||||
delete v.second;
|
||||
}
|
||||
scriptScope.clear();
|
||||
}
|
||||
delete parseResult;
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
#define PORYGONLANG_SCRIPT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <boost/any.hpp>
|
||||
#include <unordered_map>
|
||||
#include "Diagnostics/Diagnostics.hpp"
|
||||
#include "Binder/BoundStatements/BoundStatement.hpp"
|
||||
class Script;
|
||||
class Evaluator;
|
||||
#include "Evaluator/Evaluator.hpp"
|
||||
#include "Evaluator/EvalValues/EvalValue.hpp"
|
||||
#include "Utilities/HashedString.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -19,15 +20,15 @@ class Script {
|
|||
friend class Evaluator;
|
||||
|
||||
EvalValue* _lastValue;
|
||||
|
||||
Evaluator* _evaluator;
|
||||
unordered_map<int, EvalValue*> _scopeVariables;
|
||||
|
||||
explicit Script();
|
||||
|
||||
void Parse(string script);
|
||||
BoundScriptStatement* BoundScript;
|
||||
public:
|
||||
static Script Create(string script);
|
||||
static Script* Create(string script);
|
||||
Diagnostics* Diagnostics;
|
||||
|
||||
~Script();
|
||||
|
@ -37,6 +38,10 @@ public:
|
|||
EvalValue* GetLastValue(){
|
||||
return _lastValue;
|
||||
};
|
||||
|
||||
EvalValue* GetVariable(const string& key){
|
||||
return _scopeVariables.at(HashedString(key).GetHash());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
#ifndef PORYGONLANG_HASHEDSTRING_HPP
|
||||
#define PORYGONLANG_HASHEDSTRING_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
class HashedString{
|
||||
int _hash;
|
||||
static unsigned constexpr const_hash(char const *input) {
|
||||
return *input ?
|
||||
static_cast<unsigned int>(*input) + 33 * const_hash(input + 1) :
|
||||
5381;
|
||||
}
|
||||
public:
|
||||
explicit HashedString(std::string s){
|
||||
_hash = const_hash(s.c_str());
|
||||
}
|
||||
|
||||
const int GetHash(){
|
||||
return _hash;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PORYGONLANG_HASHEDSTRING_HPP
|
|
@ -4,9 +4,9 @@
|
|||
#include "../src/Script.hpp"
|
||||
|
||||
TEST_CASE( "Diagnostic invalid character", "[integration]" ) {
|
||||
Script script = Script::Create("1 + 1 @");
|
||||
REQUIRE(script.Diagnostics -> HasErrors());
|
||||
auto diags = script.Diagnostics -> GetDiagnostics();
|
||||
auto script = Script::Create("1 + 1 @");
|
||||
REQUIRE(script->Diagnostics -> HasErrors());
|
||||
auto diags = script->Diagnostics -> GetDiagnostics();
|
||||
REQUIRE(diags.size() == 1);
|
||||
CHECK(diags[0].GetCode() == DiagnosticCode::UnexpectedCharacter);
|
||||
CHECK(diags[0].GetStartPosition() == 6);
|
||||
|
@ -14,9 +14,9 @@ TEST_CASE( "Diagnostic invalid character", "[integration]" ) {
|
|||
}
|
||||
|
||||
TEST_CASE( "Diagnostic invalid token", "[integration]" ) {
|
||||
Script script = Script::Create("1 +/ 1");
|
||||
REQUIRE(script.Diagnostics -> HasErrors());
|
||||
auto diags = script.Diagnostics -> GetDiagnostics();
|
||||
auto script = Script::Create("1 +/ 1");
|
||||
REQUIRE(script->Diagnostics -> HasErrors());
|
||||
auto diags = script->Diagnostics -> GetDiagnostics();
|
||||
REQUIRE(diags.size() == 1);
|
||||
CHECK(diags[0].GetCode() == DiagnosticCode::UnexpectedToken);
|
||||
CHECK(diags[0].GetStartPosition() == 3);
|
||||
|
|
|
@ -4,55 +4,55 @@
|
|||
#include "../src/Script.hpp"
|
||||
|
||||
TEST_CASE( "True Equals True", "[integration]" ) {
|
||||
Script script = Script::Create("true == true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true == true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "True Not Equals True", "[integration]" ) {
|
||||
Script script = Script::Create("true == false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true == false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "True Nequals False", "[integration]" ) {
|
||||
Script script = Script::Create("true ~= false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true ~= false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "True Not Nequals True", "[integration]" ) {
|
||||
Script script = Script::Create("true ~= true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true ~= true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE( "False Equals False", "[integration]" ) {
|
||||
Script script = Script::Create("false == false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false == false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "10 Equals 10", "[integration]" ) {
|
||||
Script script = Script::Create("10 == 10");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("10 == 10");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "10 Not Equals 5", "[integration]" ) {
|
||||
Script script = Script::Create("10 == 5");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("10 == 5");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,92 +3,92 @@
|
|||
#include "../src/Script.hpp"
|
||||
|
||||
TEST_CASE( "Basic True", "[integration]" ) {
|
||||
Script script = Script::Create("true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "Basic False", "[integration]" ) {
|
||||
Script script = Script::Create("false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "True and True", "[integration]" ) {
|
||||
Script script = Script::Create("true and true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true and true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "True and False", "[integration]" ) {
|
||||
Script script = Script::Create("true and false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true and false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "False and True", "[integration]" ) {
|
||||
Script script = Script::Create("false and true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false and true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "False and False", "[integration]" ) {
|
||||
Script script = Script::Create("false and false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false and false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "True or True", "[integration]" ) {
|
||||
Script script = Script::Create("true or true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true or true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "True or False", "[integration]" ) {
|
||||
Script script = Script::Create("true or false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("true or false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "False or True", "[integration]" ) {
|
||||
Script script = Script::Create("false or true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false or true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
TEST_CASE( "False or False", "[integration]" ) {
|
||||
Script script = Script::Create("false or false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("false or false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "Not True", "[integration]" ) {
|
||||
Script script = Script::Create("not true");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("not true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(!lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
TEST_CASE( "Not False", "[integration]" ) {
|
||||
Script script = Script::Create("not false");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("not false");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateBool());
|
||||
}
|
||||
|
||||
|
|
|
@ -3,75 +3,75 @@
|
|||
#include "../src/Script.hpp"
|
||||
|
||||
TEST_CASE( "Integer Negation", "[integration]" ) {
|
||||
Script script = Script::Create("-60");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("-60");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateInteger() == -60);
|
||||
}
|
||||
TEST_CASE( "Float Negation", "[integration]" ) {
|
||||
Script script = Script::Create("-5.65");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("-5.65");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateFloat() == Approx(-5.65));
|
||||
}
|
||||
|
||||
TEST_CASE( "Integer Addition", "[integration]" ) {
|
||||
Script script = Script::Create("1 + 5");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("1 + 5");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateInteger() == 6);
|
||||
}
|
||||
TEST_CASE( "Integer Subtraction", "[integration]" ) {
|
||||
Script script = Script::Create("1 - 5");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("1 - 5");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateInteger() == -4);
|
||||
}
|
||||
TEST_CASE( "Integer Multiplication", "[integration]" ) {
|
||||
Script script = Script::Create("5 * 8");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("5 * 8");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateInteger() == 40);
|
||||
}
|
||||
TEST_CASE( "Integer Division", "[integration]" ) {
|
||||
Script script = Script::Create("40 / 8");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("40 / 8");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateInteger() == 5);
|
||||
}
|
||||
|
||||
TEST_CASE( "Float Addition", "[integration]" ) {
|
||||
Script script = Script::Create("1.2 + 5.34");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("1.2 + 5.34");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateFloat() == 6.54);
|
||||
}
|
||||
TEST_CASE( "Float Subtraction", "[integration]" ) {
|
||||
Script script = Script::Create("1.8 - 5.14");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("1.8 - 5.14");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateFloat() == -3.34);
|
||||
}
|
||||
TEST_CASE( "Float Multiplication", "[integration]" ) {
|
||||
Script script = Script::Create("5.2 * 8.9");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("5.2 * 8.9");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateFloat() == 46.28);
|
||||
}
|
||||
TEST_CASE( "Float Division", "[integration]" ) {
|
||||
Script script = Script::Create("95.18 / 8.87");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("95.18 / 8.87");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateFloat() == Approx(10.7305524239));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
|
||||
|
||||
TEST_CASE( "Simple String", "[integration]" ) {
|
||||
Script script = Script::Create("\"foo bar\"");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("\"foo bar\"");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateString() == "foo bar");
|
||||
}
|
||||
|
||||
TEST_CASE( "String Concat", "[integration]" ) {
|
||||
Script script = Script::Create("\"foo\" + \"bar\"");
|
||||
REQUIRE(!script.Diagnostics -> HasErrors());
|
||||
script.Evaluate();
|
||||
auto lastValue = script.GetLastValue();
|
||||
auto script = Script::Create("\"foo\" + \"bar\"");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
auto lastValue = script->GetLastValue();
|
||||
REQUIRE(lastValue->EvaluateString() == "foobar");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#ifdef TESTS_BUILD
|
||||
#include <catch.hpp>
|
||||
#include "../src/Script.hpp"
|
||||
|
||||
TEST_CASE( "Create script variable", "[integration]" ) {
|
||||
Script* script = Script::Create("foo = true");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto variable = script->GetVariable("foo");
|
||||
REQUIRE(variable == nullptr);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -168,7 +168,7 @@ TEST_CASE( "Parse Global Assignment", "[parser]" ) {
|
|||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment);
|
||||
auto assignment = (ParsedAssignmentStatement*)firstStatement;
|
||||
REQUIRE(!assignment -> IsLocal());
|
||||
REQUIRE(assignment->GetIdentifier() == "foo");
|
||||
REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash());
|
||||
REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue());
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) {
|
|||
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment);
|
||||
auto assignment = (ParsedAssignmentStatement*)firstStatement;
|
||||
REQUIRE(assignment -> IsLocal());
|
||||
REQUIRE(assignment->GetIdentifier() == "foo");
|
||||
REQUIRE(assignment->GetIdentifier().GetHash() == HashedString("foo").GetHash());
|
||||
REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue