Work to add C style entry points to library that allow most functionality
This commit is contained in:
parent
6206fef4c5
commit
43dede9ae2
|
@ -7,21 +7,9 @@ include_directories(extern)
|
||||||
file(GLOB_RECURSE SRC_FILES "src/*.cpp" "src/*.hpp")
|
file(GLOB_RECURSE SRC_FILES "src/*.cpp" "src/*.hpp")
|
||||||
file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp")
|
file(GLOB_RECURSE TEST_FILES "tests/*.cpp" "tests/*.hpp")
|
||||||
|
|
||||||
add_library(PorygonLang ${SRC_FILES})
|
add_library(PorygonLang SHARED ${SRC_FILES})
|
||||||
add_executable(PorygonLangTests
|
add_executable(PorygonLangTests
|
||||||
${SRC_FILES}
|
${SRC_FILES}
|
||||||
${TEST_FILES})
|
${TEST_FILES})
|
||||||
|
|
||||||
target_compile_definitions(PorygonLangTests PRIVATE TESTS_BUILD)
|
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)
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "Diagnostics.hpp"
|
||||||
|
|
||||||
|
vector<Diagnostic> 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);
|
||||||
|
}
|
||||||
|
|
|
@ -21,31 +21,18 @@ public:
|
||||||
_diagnostics.clear();
|
_diagnostics.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length){
|
void Log(DiagnosticSeverity severity, DiagnosticCode code, unsigned int start, unsigned int length);
|
||||||
_diagnostics.emplace_back(severity, code, start, length);
|
void LogError(DiagnosticCode code, unsigned int start, unsigned int length);
|
||||||
if (severity >= DiagnosticSeverity::Error){
|
void LogWarning(DiagnosticCode code, unsigned int start, unsigned int length);
|
||||||
_hasErrors = true;
|
void LogInfo(DiagnosticCode code, unsigned int start, unsigned int length);
|
||||||
}
|
|
||||||
}
|
|
||||||
void LogError(DiagnosticCode code, unsigned int start, unsigned int length){
|
|
||||||
Log(DiagnosticSeverity::Error, code, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogWarning(DiagnosticCode code, unsigned int start, unsigned int length){
|
bool HasErrors();
|
||||||
Log(DiagnosticSeverity::Warning, code, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogInfo(DiagnosticCode code, unsigned int start, unsigned int length){
|
vector<Diagnostic> GetDiagnostics();
|
||||||
Log(DiagnosticSeverity::Info, code, start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasErrors(){
|
int DiagnosticsCount();
|
||||||
return _hasErrors;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<Diagnostic> GetDiagnostics(){
|
Diagnostic* GetDiagnosticAt(int position);
|
||||||
return _diagnostics;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ shared_ptr<StringEvalValue> Evaluator::EvaluateStringBinary(BoundBinaryExpressio
|
||||||
throw;
|
throw;
|
||||||
std::ostringstream strs;
|
std::ostringstream strs;
|
||||||
auto left = this -> EvaluateStringExpression(expression->GetLeft());
|
auto left = this -> EvaluateStringExpression(expression->GetLeft());
|
||||||
strs << left->EvaluateString();
|
strs << *left->EvaluateString();
|
||||||
auto right = this -> EvaluateExpression(expression->GetRight());
|
auto right = this -> EvaluateExpression(expression->GetRight());
|
||||||
strs << right->EvaluateString();
|
strs << *right->EvaluateString();
|
||||||
return make_shared<StringEvalValue>(strs.str());
|
return make_shared<StringEvalValue>(strs.str());
|
||||||
}
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#import "EvalValue.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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 <catch.hpp>
|
||||||
|
#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
|
|
@ -31,7 +31,7 @@ public:
|
||||||
virtual bool EvaluateBool(){
|
virtual bool EvaluateBool(){
|
||||||
throw EvaluationException("Can't evaluate this EvalValue as bool.");
|
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.");
|
throw EvaluationException("Can't evaluate this EvalValue as string.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -62,12 +62,6 @@ public:
|
||||||
return false;
|
return false;
|
||||||
return this->EvaluateBool() == b->EvaluateBool();
|
return this->EvaluateBool() == b->EvaluateBool();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string EvaluateString() final{
|
|
||||||
std::ostringstream strs;
|
|
||||||
strs << _value;
|
|
||||||
return strs.str();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //PORYGONLANG_EVALVALUE_HPP
|
#endif //PORYGONLANG_EVALVALUE_HPP
|
||||||
|
|
|
@ -42,12 +42,6 @@ public:
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EvaluateString() final{
|
|
||||||
std::ostringstream strs;
|
|
||||||
strs << _value;
|
|
||||||
return strs.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<EvalValue> Clone() final{
|
shared_ptr<EvalValue> Clone() final{
|
||||||
return make_shared<IntegerEvalValue>(_value);
|
return make_shared<IntegerEvalValue>(_value);
|
||||||
}
|
}
|
||||||
|
@ -70,12 +64,6 @@ public:
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EvaluateString() final{
|
|
||||||
std::ostringstream strs;
|
|
||||||
strs << _value;
|
|
||||||
return strs.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_ptr<EvalValue> Clone() final{
|
shared_ptr<EvalValue> Clone() final{
|
||||||
return make_shared<FloatEvalValue>(_value);
|
return make_shared<FloatEvalValue>(_value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@ public:
|
||||||
bool operator ==(EvalValue* b) final{
|
bool operator ==(EvalValue* b) final{
|
||||||
if (b->GetType()->GetClass() != TypeClass::String)
|
if (b->GetType()->GetClass() != TypeClass::String)
|
||||||
return false;
|
return false;
|
||||||
return this->_value == b->EvaluateString();
|
return this->_value == *b->EvaluateString();
|
||||||
};
|
};
|
||||||
|
|
||||||
string EvaluateString() final{
|
string* EvaluateString() final{
|
||||||
return _value;
|
return &_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<EvalValue> Clone() final{
|
shared_ptr<EvalValue> Clone() final{
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Evaluator.hpp"
|
#include "Evaluator.hpp"
|
||||||
|
@ -36,7 +40,7 @@ void Evaluator::EvaluateBlockStatement(BoundBlockStatement* statement) {
|
||||||
|
|
||||||
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
|
void Evaluator::EvaluateExpressionStatement(BoundExpressionStatement *statement) {
|
||||||
// Save new value
|
// Save new value
|
||||||
this->_scriptData->_lastValue = this -> EvaluateExpression(statement->GetExpression());
|
this->_lastValue = this -> EvaluateExpression(statement->GetExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement) {
|
void Evaluator::EvaluateAssignmentStatement(BoundAssignmentStatement *statement) {
|
||||||
|
@ -169,4 +173,5 @@ shared_ptr<EvalValue> Evaluator::EvaluateFunctionCallExpression(BoundExpression*
|
||||||
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
this->EvaluateBlockStatement(function->GetInnerBlock().get());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ using namespace std;
|
||||||
|
|
||||||
class Evaluator {
|
class Evaluator {
|
||||||
shared_ptr<EvalValue> _result;
|
shared_ptr<EvalValue> _result;
|
||||||
|
shared_ptr<EvalValue> _lastValue;
|
||||||
|
|
||||||
Script* _scriptData;
|
Script* _scriptData;
|
||||||
EvaluationScope* _evaluationScope;
|
EvaluationScope* _evaluationScope;
|
||||||
|
@ -57,7 +58,9 @@ public:
|
||||||
return _evaluationScope;
|
return _evaluationScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EvalValue* GetLastValue(){
|
||||||
|
return _lastValue.get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,17 @@ Script* Script::Create(string script) {
|
||||||
Script::Script() {
|
Script::Script() {
|
||||||
Diagnostics = new class Diagnostics();
|
Diagnostics = new class Diagnostics();
|
||||||
_evaluator = new Evaluator(this);
|
_evaluator = new Evaluator(this);
|
||||||
_lastValue = nullptr;
|
_boundScript = nullptr;
|
||||||
BoundScript = nullptr;
|
|
||||||
_scriptVariables = new unordered_map<int, shared_ptr<EvalValue>>(0);
|
_scriptVariables = new unordered_map<int, shared_ptr<EvalValue>>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::Evaluate() {
|
void Script::Evaluate() {
|
||||||
_evaluator->Evaluate(BoundScript);
|
_evaluator->Evaluate(_boundScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
Script::~Script() {
|
Script::~Script() {
|
||||||
delete this -> Diagnostics;
|
delete this -> Diagnostics;
|
||||||
delete this -> BoundScript;
|
delete this -> _boundScript;
|
||||||
delete this -> _evaluator;
|
delete this -> _evaluator;
|
||||||
this->_scriptVariables->clear();
|
this->_scriptVariables->clear();
|
||||||
delete this->_scriptVariables;
|
delete this->_scriptVariables;
|
||||||
|
@ -43,7 +42,7 @@ void Script::Parse(string script) {
|
||||||
if (!Diagnostics->HasErrors()){
|
if (!Diagnostics->HasErrors()){
|
||||||
unordered_map<int, BoundVariable*> scriptScope;
|
unordered_map<int, BoundVariable*> scriptScope;
|
||||||
auto bindScope = new BoundScope(&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){
|
for (const auto& v : scriptScope){
|
||||||
this->_scriptVariables -> insert({v.first, nullptr});
|
this->_scriptVariables -> insert({v.first, nullptr});
|
||||||
delete v.second;
|
delete v.second;
|
||||||
|
@ -62,3 +61,30 @@ bool Script::HasVariable(const string &key) {
|
||||||
return f != _scriptVariables->end();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_SCRIPT_HPP
|
#ifndef PORYGONLANG_SCRIPT_HPP
|
||||||
#define PORYGONLANG_SCRIPT_HPP
|
#define PORYGONLANG_SCRIPT_HPP
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "Diagnostics/Diagnostics.hpp"
|
#include "Diagnostics/Diagnostics.hpp"
|
||||||
|
@ -19,14 +17,12 @@ using namespace std;
|
||||||
class Script {
|
class Script {
|
||||||
friend class Evaluator;
|
friend class Evaluator;
|
||||||
|
|
||||||
shared_ptr<EvalValue> _lastValue;
|
|
||||||
Evaluator* _evaluator;
|
Evaluator* _evaluator;
|
||||||
unordered_map<int, shared_ptr<EvalValue>>* _scriptVariables;
|
unordered_map<int, shared_ptr<EvalValue>>* _scriptVariables;
|
||||||
|
BoundScriptStatement* _boundScript;
|
||||||
|
|
||||||
explicit Script();
|
explicit Script();
|
||||||
|
|
||||||
void Parse(string script);
|
void Parse(string script);
|
||||||
BoundScriptStatement* BoundScript;
|
|
||||||
public:
|
public:
|
||||||
static Script* Create(string script);
|
static Script* Create(string script);
|
||||||
Diagnostics* Diagnostics;
|
Diagnostics* Diagnostics;
|
||||||
|
@ -35,12 +31,12 @@ public:
|
||||||
|
|
||||||
void Evaluate();
|
void Evaluate();
|
||||||
|
|
||||||
EvalValue* GetLastValue(){
|
EvalValue* GetLastValue();
|
||||||
return _lastValue.get();
|
|
||||||
};
|
|
||||||
|
|
||||||
EvalValue* GetVariable(const string& key);
|
EvalValue* GetVariable(const string& key);
|
||||||
bool HasVariable(const string& key);
|
bool HasVariable(const string& key);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,25 @@ TEST_CASE( "Simple String", "[integration]" ) {
|
||||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
script->Evaluate();
|
script->Evaluate();
|
||||||
auto lastValue = script->GetLastValue();
|
auto lastValue = script->GetLastValue();
|
||||||
REQUIRE(lastValue->EvaluateString() == "foo bar");
|
REQUIRE(*lastValue->EvaluateString() == "foo bar");
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE( "String Concat", "[integration]" ) {
|
TEST_CASE( "String Concat", "[integration]" ) {
|
||||||
auto script = Script::Create("\"foo\" + \"bar\"");
|
auto script = Script::Create(R"("foo" + "bar")");
|
||||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
script->Evaluate();
|
script->Evaluate();
|
||||||
auto lastValue = script->GetLastValue();
|
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;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue