From 43dede9ae2f5e3d333d8a1057a3ed6305f4d4e9f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Wed, 5 Jun 2019 17:46:46 +0200 Subject: [PATCH] Work to add C style entry points to library that allow most functionality --- CMakeLists.txt | 16 +------ src/Diagnostics/Diagnostics.cpp | 45 ++++++++++++++++++ src/Diagnostics/Diagnostics.hpp | 29 ++++-------- src/Evaluator/BinaryEvaluation.cpp | 4 +- src/Evaluator/EvalValues/EvalValue.cpp | 46 +++++++++++++++++++ src/Evaluator/EvalValues/EvalValue.hpp | 8 +--- src/Evaluator/EvalValues/NumericEvalValue.hpp | 12 ----- src/Evaluator/EvalValues/StringEvalValue.hpp | 6 +-- src/Evaluator/Evaluator.cpp | 9 +++- src/Evaluator/Evaluator.hpp | 5 +- src/Script.cpp | 36 +++++++++++++-- src/Script.hpp | 14 ++---- tests/integration/ExternFunctionsTests.cpp | 3 ++ tests/integration/StringOperationsTests.cpp | 15 ++++-- 14 files changed, 169 insertions(+), 79 deletions(-) create mode 100644 src/Diagnostics/Diagnostics.cpp create mode 100644 src/Evaluator/EvalValues/EvalValue.cpp create mode 100644 tests/integration/ExternFunctionsTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a8932f6..15f86f6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,21 +7,9 @@ include_directories(extern) file(GLOB_RECURSE SRC_FILES "src/*.cpp" "src/*.hpp") file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp") -add_library(PorygonLang ${SRC_FILES}) +add_library(PorygonLang SHARED ${SRC_FILES}) add_executable(PorygonLangTests ${SRC_FILES} ${TEST_FILES}) -target_compile_definitions(PorygonLangTests PRIVATE TESTS_BUILD) - - -find_package( Boost ) - -include_directories( - ${BOOST_INCLUDE_DIRS} -) - -target_link_libraries(PorygonLang ${Boost_LIBRARIES} ) -target_link_libraries(PorygonLangTests ${Boost_LIBRARIES} ) - -include(CTest) +target_compile_definitions(PorygonLangTests PRIVATE TESTS_BUILD) \ No newline at end of file diff --git a/src/Diagnostics/Diagnostics.cpp b/src/Diagnostics/Diagnostics.cpp new file mode 100644 index 0000000..9bf35f5 --- /dev/null +++ b/src/Diagnostics/Diagnostics.cpp @@ -0,0 +1,45 @@ +#include "Diagnostics.hpp" + +vector Diagnostics::GetDiagnostics() { + return _diagnostics; +} + +void Diagnostics::Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length) { + _diagnostics.emplace_back(severity, code, start, length); + if (severity >= DiagnosticSeverity::Error){ + _hasErrors = true; + } +} + +void Diagnostics::LogError(DiagnosticCode code, unsigned int start, unsigned int length) { + Log(DiagnosticSeverity::Error, code, start, length); +} + +void Diagnostics::LogWarning(DiagnosticCode code, unsigned int start, unsigned int length) { + Log(DiagnosticSeverity::Warning, code, start, length); +} + +void Diagnostics::LogInfo(DiagnosticCode code, unsigned int start, unsigned int length) { + Log(DiagnosticSeverity::Info, code, start, length); +} + +bool Diagnostics::HasErrors() { + return _hasErrors; +} + +int Diagnostics::DiagnosticsCount() { + return _diagnostics.size(); +} + +Diagnostic *Diagnostics::GetDiagnosticAt(int position) { + return &_diagnostics[position]; +} + +extern "C" int GetDiagnosticsCount (Diagnostics* diagnostics){ + return diagnostics->DiagnosticsCount(); +} + +extern "C" Diagnostic* GetDiagnosticAt(Diagnostics* diagnostics, int position){ + return diagnostics->GetDiagnosticAt(position); +} + diff --git a/src/Diagnostics/Diagnostics.hpp b/src/Diagnostics/Diagnostics.hpp index d1285db..e305434 100644 --- a/src/Diagnostics/Diagnostics.hpp +++ b/src/Diagnostics/Diagnostics.hpp @@ -21,31 +21,18 @@ public: _diagnostics.clear(); } - void Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length){ - _diagnostics.emplace_back(severity, code, start, length); - if (severity >= DiagnosticSeverity::Error){ - _hasErrors = true; - } - } - void LogError(DiagnosticCode code, unsigned int start, unsigned int length){ - Log(DiagnosticSeverity::Error, code, start, length); - } + void Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length); + void LogError(DiagnosticCode code, unsigned int start, unsigned int length); + void LogWarning(DiagnosticCode code, unsigned int start, unsigned int length); + void LogInfo(DiagnosticCode code, unsigned int start, unsigned int length); - void LogWarning(DiagnosticCode code, unsigned int start, unsigned int length){ - Log(DiagnosticSeverity::Warning, code, start, length); - } + bool HasErrors(); - void LogInfo(DiagnosticCode code, unsigned int start, unsigned int length){ - Log(DiagnosticSeverity::Info, code, start, length); - } + vector GetDiagnostics(); - bool HasErrors(){ - return _hasErrors; - } + int DiagnosticsCount(); - vector GetDiagnostics(){ - return _diagnostics; - } + Diagnostic* GetDiagnosticAt(int position); }; diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index 93389f2..f374407 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -69,8 +69,8 @@ shared_ptr Evaluator::EvaluateStringBinary(BoundBinaryExpressio throw; std::ostringstream strs; auto left = this -> EvaluateStringExpression(expression->GetLeft()); - strs << left->EvaluateString(); + strs << *left->EvaluateString(); auto right = this -> EvaluateExpression(expression->GetRight()); - strs << right->EvaluateString(); + strs << *right->EvaluateString(); return make_shared(strs.str()); } \ No newline at end of file diff --git a/src/Evaluator/EvalValues/EvalValue.cpp b/src/Evaluator/EvalValues/EvalValue.cpp new file mode 100644 index 0000000..3b30793 --- /dev/null +++ b/src/Evaluator/EvalValues/EvalValue.cpp @@ -0,0 +1,46 @@ +#import "EvalValue.hpp" +#include + +extern "C" { + TypeClass GetEvalValueTypeClass(EvalValue* v){ + return v->GetType().get()->GetClass(); + } + + ScriptType* GetEvalValueType(EvalValue* v){ + return v->GetType().get(); + } + + int64_t EvaluateEvalValueInteger(EvalValue* v){ + return v->EvaluateInteger(); + } + + double EvaluateEvalValueFloat(EvalValue* v){ + return v->EvaluateFloat(); + } + + bool EvaluateEvalValueBool(EvalValue* v){ + return v->EvaluateBool(); + } + + const char* EvaluateEvalValueString(EvalValue* v){ + return v->EvaluateString() -> c_str(); + } + +} + +#ifdef TESTS_BUILD +#include +#include "../src/Script.hpp" + + +TEST_CASE( "Evaluate String", "[integration]" ) { + auto script = Script::Create("\"foo bar\""); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto lastValue = script->GetLastValue(); + REQUIRE(std::strcmp(EvaluateEvalValueString(lastValue), "foo bar") == 0); + delete script; +} + + +#endif diff --git a/src/Evaluator/EvalValues/EvalValue.hpp b/src/Evaluator/EvalValues/EvalValue.hpp index 3d892c7..202d6b9 100644 --- a/src/Evaluator/EvalValues/EvalValue.hpp +++ b/src/Evaluator/EvalValues/EvalValue.hpp @@ -31,7 +31,7 @@ public: virtual bool EvaluateBool(){ throw EvaluationException("Can't evaluate this EvalValue as bool."); } - virtual std::string EvaluateString(){ + virtual std::string* EvaluateString(){ throw EvaluationException("Can't evaluate this EvalValue as string."); } }; @@ -62,12 +62,6 @@ public: return false; return this->EvaluateBool() == b->EvaluateBool(); }; - - std::string EvaluateString() final{ - std::ostringstream strs; - strs << _value; - return strs.str(); - } }; #endif //PORYGONLANG_EVALVALUE_HPP diff --git a/src/Evaluator/EvalValues/NumericEvalValue.hpp b/src/Evaluator/EvalValues/NumericEvalValue.hpp index b408618..fcafa63 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.hpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.hpp @@ -42,12 +42,6 @@ public: return _value; } - std::string EvaluateString() final{ - std::ostringstream strs; - strs << _value; - return strs.str(); - } - shared_ptr Clone() final{ return make_shared(_value); } @@ -70,12 +64,6 @@ public: return _value; } - std::string EvaluateString() final{ - std::ostringstream strs; - strs << _value; - return strs.str(); - } - shared_ptr Clone() final{ return make_shared(_value); } diff --git a/src/Evaluator/EvalValues/StringEvalValue.hpp b/src/Evaluator/EvalValues/StringEvalValue.hpp index 686fd2f..d366c2e 100644 --- a/src/Evaluator/EvalValues/StringEvalValue.hpp +++ b/src/Evaluator/EvalValues/StringEvalValue.hpp @@ -22,11 +22,11 @@ public: bool operator ==(EvalValue* b) final{ if (b->GetType()->GetClass() != TypeClass::String) return false; - return this->_value == b->EvaluateString(); + return this->_value == *b->EvaluateString(); }; - string EvaluateString() final{ - return _value; + string* EvaluateString() final{ + return &_value; } shared_ptr Clone() final{ diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 21a4ef1..5525382 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -1,3 +1,7 @@ +#include + +#include + #include #include "Evaluator.hpp" @@ -36,7 +40,7 @@ void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement) { void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) { // Save new value - this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression()); + this->_lastValue = this -> EvaluateExpression(statement->GetExpression()); } void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement) { @@ -169,4 +173,5 @@ shared_ptr Evaluator::EvaluateFunctionCallExpression(BoundExpression* this->EvaluateBlockStatement(function->GetInnerBlock().get()); return nullptr; -} \ No newline at end of file +} + diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index 7367309..e23b06f 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -15,6 +15,7 @@ using namespace std; class Evaluator { shared_ptr _result; + shared_ptr _lastValue; Script* _scriptData; EvaluationScope* _evaluationScope; @@ -57,7 +58,9 @@ public: return _evaluationScope; } - + EvalValue* GetLastValue(){ + return _lastValue.get(); + } }; diff --git a/src/Script.cpp b/src/Script.cpp index 55d4fc1..979fc38 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -14,18 +14,17 @@ Script* Script::Create(string script) { Script::Script() { Diagnostics = new class Diagnostics(); _evaluator = new Evaluator(this); - _lastValue = nullptr; - BoundScript = nullptr; + _boundScript = nullptr; _scriptVariables = new unordered_map>(0); } void Script::Evaluate() { - _evaluator->Evaluate(BoundScript); + _evaluator->Evaluate(_boundScript); } Script::~Script() { delete this -> Diagnostics; - delete this -> BoundScript; + delete this -> _boundScript; delete this -> _evaluator; this->_scriptVariables->clear(); delete this->_scriptVariables; @@ -43,7 +42,7 @@ void Script::Parse(string script) { if (!Diagnostics->HasErrors()){ unordered_map scriptScope; auto bindScope = new BoundScope(&scriptScope); - this->BoundScript = Binder::Bind(this, parseResult, bindScope); + this->_boundScript = Binder::Bind(this, parseResult, bindScope); for (const auto& v : scriptScope){ this->_scriptVariables -> insert({v.first, nullptr}); delete v.second; @@ -62,3 +61,30 @@ bool Script::HasVariable(const string &key) { return f != _scriptVariables->end(); } +EvalValue *Script::GetLastValue() { + return _evaluator->GetLastValue(); +} + +extern "C" { + Script* CreateScript(char * s){ + return Script::Create(s); + } + + void EvaluateScript(Script* script){ + script->Evaluate(); + } + + EvalValue* GetLastValue(Script* script){ + return script->GetLastValue(); + } + + bool HasVariable(Script* script, const char* key){ + return script->HasVariable(key); + } + + EvalValue* GetVariable(Script* script, const char* key){ + return script->GetVariable(key); + } +} + + diff --git a/src/Script.hpp b/src/Script.hpp index aa9e9d5..5179ff3 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -1,9 +1,7 @@ -#include - - #ifndef PORYGONLANG_SCRIPT_HPP #define PORYGONLANG_SCRIPT_HPP +#include #include #include #include "Diagnostics/Diagnostics.hpp" @@ -19,14 +17,12 @@ using namespace std; class Script { friend class Evaluator; - shared_ptr _lastValue; Evaluator* _evaluator; unordered_map>* _scriptVariables; + BoundScriptStatement* _boundScript; explicit Script(); - void Parse(string script); - BoundScriptStatement* BoundScript; public: static Script* Create(string script); Diagnostics* Diagnostics; @@ -35,12 +31,12 @@ public: void Evaluate(); - EvalValue* GetLastValue(){ - return _lastValue.get(); - }; + EvalValue* GetLastValue(); EvalValue* GetVariable(const string& key); bool HasVariable(const string& key); + + }; diff --git a/tests/integration/ExternFunctionsTests.cpp b/tests/integration/ExternFunctionsTests.cpp new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/tests/integration/ExternFunctionsTests.cpp @@ -0,0 +1,3 @@ + + + diff --git a/tests/integration/StringOperationsTests.cpp b/tests/integration/StringOperationsTests.cpp index e65f739..41428f2 100644 --- a/tests/integration/StringOperationsTests.cpp +++ b/tests/integration/StringOperationsTests.cpp @@ -9,16 +9,25 @@ TEST_CASE( "Simple String", "[integration]" ) { REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(lastValue->EvaluateString() == "foo bar"); + REQUIRE(*lastValue->EvaluateString() == "foo bar"); delete script; } TEST_CASE( "String Concat", "[integration]" ) { - auto script = Script::Create("\"foo\" + \"bar\""); + auto script = Script::Create(R"("foo" + "bar")"); REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(lastValue->EvaluateString() == "foobar"); + REQUIRE(*lastValue->EvaluateString() == "foobar"); + delete script; +} + +TEST_CASE( "String Concat 2", "[integration]" ) { + auto script = Script::Create("'foo' + 'bar'"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto lastValue = script->GetLastValue(); + REQUIRE(*lastValue->EvaluateString() == "foobar"); delete script; }