Cleans up basic library handling, implements print function
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
db2d731b06
commit
5e02b6b389
|
@ -24,10 +24,10 @@ namespace Porygon::Evaluation {
|
||||||
const std::shared_ptr<EvaluationScope> _scope;
|
const std::shared_ptr<EvaluationScope> _scope;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EvaluationScriptFunctionOption(const shared_ptr<BoundBlockStatement> innerBlock, const shared_ptr<EvaluationScope> scope)
|
EvaluationScriptFunctionOption(shared_ptr<BoundBlockStatement> innerBlock, shared_ptr<EvaluationScope> scope)
|
||||||
: _innerBlock(innerBlock), _scope(scope) {
|
: _innerBlock(std::move(innerBlock)), _scope(std::move(scope)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
~EvaluationScriptFunctionOption() final = default;
|
||||||
|
|
||||||
const std::shared_ptr<BoundBlockStatement> &GetInnerBlock() const {
|
const std::shared_ptr<BoundBlockStatement> &GetInnerBlock() const {
|
||||||
return _innerBlock;
|
return _innerBlock;
|
||||||
|
@ -36,15 +36,13 @@ namespace Porygon::Evaluation {
|
||||||
const std::shared_ptr<EvaluationScope> &GetScope() const {
|
const std::shared_ptr<EvaluationScope> &GetScope() const {
|
||||||
return _scope;
|
return _scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenericFunctionEvalValue : public EvalValue{
|
class GenericFunctionEvalValue : public EvalValue{
|
||||||
protected:
|
protected:
|
||||||
const std::shared_ptr<GenericFunctionScriptType> _type;
|
const shared_ptr<GenericFunctionScriptType> _type;
|
||||||
const std::size_t _hash;
|
const size_t _hash;
|
||||||
std::vector<shared_ptr<GenericFunctionOption>> _options;
|
vector<shared_ptr<GenericFunctionOption>> _options;
|
||||||
public:
|
public:
|
||||||
GenericFunctionEvalValue(shared_ptr<GenericFunctionScriptType> type, size_t hash)
|
GenericFunctionEvalValue(shared_ptr<GenericFunctionScriptType> type, size_t hash)
|
||||||
: _type(move(type)),
|
: _type(move(type)),
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Porygon {
|
||||||
this -> RegisterFunctionOption(option);
|
this -> RegisterFunctionOption(option);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~GenericFunctionScriptType() final{
|
~GenericFunctionScriptType() final{
|
||||||
for (auto o: _options){
|
for (auto o: _options){
|
||||||
delete o;
|
delete o;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "GlobalScriptOptions.hpp"
|
||||||
|
#include "Utilities/StringUtils.hpp"
|
||||||
|
|
||||||
|
std::streambuf* Porygon::GlobalScriptOptions::_printBuffer = std::cout.rdbuf();
|
||||||
|
std::ostream* Porygon::GlobalScriptOptions::_printStream = new std::ostream(Porygon::GlobalScriptOptions::_printBuffer);
|
||||||
|
|
||||||
|
static void DefaultPrint(const std::u16string& s){
|
||||||
|
Porygon::GlobalScriptOptions::GetPrintStream() << Porygon::Utilities::StringUtils::FromUTF8(s) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*Porygon::GlobalScriptOptions::_print)(const std::u16string &) = DefaultPrint;
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP
|
||||||
|
#define PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Porygon{
|
||||||
|
class GlobalScriptOptions{
|
||||||
|
static void (*_print)(const std::u16string& s);
|
||||||
|
static std::streambuf* _printBuffer;
|
||||||
|
static std::ostream* _printStream;
|
||||||
|
public:
|
||||||
|
static void Print(const std::u16string& s){
|
||||||
|
GlobalScriptOptions::_print(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetPrintFunc(void (*print)(const std::u16string&)){
|
||||||
|
GlobalScriptOptions::_print = print;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::ostream& GetPrintStream(){
|
||||||
|
return *GlobalScriptOptions::_printStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetPrintStream(std::ostream* stream){
|
||||||
|
delete GlobalScriptOptions::_printStream;
|
||||||
|
GlobalScriptOptions::_printStream = stream;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //PORYGONLANG_GLOBALSCRIPTOPTIONS_HPP
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../Binder/BoundVariables/BoundVariable.hpp"
|
#include "../Binder/BoundVariables/BoundVariable.hpp"
|
||||||
#include "../UserData/UserDataFunction.hpp"
|
#include "../UserData/UserDataFunction.hpp"
|
||||||
#include "../UserData/UserDataFunctionType.hpp"
|
#include "../UserData/UserDataFunctionType.hpp"
|
||||||
|
#include "../GlobalScriptOptions.hpp"
|
||||||
|
|
||||||
namespace Porygon::StandardLibraries{
|
namespace Porygon::StandardLibraries{
|
||||||
class BasicLibrary{
|
class BasicLibrary{
|
||||||
|
@ -22,42 +23,80 @@ namespace Porygon::StandardLibraries{
|
||||||
static Evaluation::EvalValue* _assert(void*, Evaluation::EvalValue* parameters[], int parameterCount){
|
static Evaluation::EvalValue* _assert(void*, Evaluation::EvalValue* parameters[], int parameterCount){
|
||||||
auto assertion = parameters[0]->EvaluateBool();
|
auto assertion = parameters[0]->EvaluateBool();
|
||||||
if (!assertion){
|
if (!assertion){
|
||||||
|
if (parameterCount >= 2){
|
||||||
|
auto error = parameters[1]->EvaluateString();
|
||||||
|
auto conv = Utilities::StringUtils::FromUTF8(error);
|
||||||
|
throw Evaluation::EvaluationException(conv);
|
||||||
|
}
|
||||||
throw Evaluation::EvaluationException("assertion failed!");
|
throw Evaluation::EvaluationException("assertion failed!");
|
||||||
}
|
}
|
||||||
return new Evaluation::BooleanEvalValue(true);
|
return new Evaluation::BooleanEvalValue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Evaluation::EvalValue* _print(void*, Evaluation::EvalValue* parameters[], int parameterCount){
|
||||||
|
auto message = parameters[0]->EvaluateString();
|
||||||
|
GlobalScriptOptions::Print(message);
|
||||||
|
return new Evaluation::NilEvalValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<GenericFunctionScriptType> GetFuncType(const shared_ptr<ScriptType>& result, const vector<vector<shared_ptr<ScriptType>>>& options){
|
||||||
|
auto funcType = make_shared<GenericFunctionScriptType>();
|
||||||
|
for (const auto& o: options){
|
||||||
|
auto option = new UserData::UserDataFunctionOption(result, o);
|
||||||
|
funcType->RegisterFunctionOption(option);
|
||||||
|
}
|
||||||
|
return funcType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<GenericFunctionScriptType> GetErrorFuncType(){
|
||||||
|
return GetFuncType(make_shared<ScriptType>(TypeClass::Nil), {{make_shared<StringScriptType>(false, 0)}});
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<GenericFunctionScriptType> GetAssertFuncType(){
|
||||||
|
return GetFuncType(make_shared<ScriptType>(TypeClass::Bool),
|
||||||
|
{{make_shared<ScriptType>(TypeClass::Bool)},
|
||||||
|
{make_shared<ScriptType>(TypeClass::Bool), make_shared<StringScriptType>(false, 0)}});
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<GenericFunctionScriptType> GetPrintFuncType(){
|
||||||
|
return GetFuncType(make_shared<ScriptType>(TypeClass::Nil), {{make_shared<StringScriptType>(false, 0)}});
|
||||||
|
}
|
||||||
|
|
||||||
|
static shared_ptr<Evaluation::EvalValue> GetFuncEvalValue(
|
||||||
|
Evaluation::EvalValue* (*func)(void* obj, Evaluation::EvalValue* parameters[], int parameterCount),
|
||||||
|
shared_ptr<GenericFunctionScriptType> type, size_t optionLength){
|
||||||
|
auto f = make_shared<Evaluation::GenericFunctionEvalValue>(type, rand());
|
||||||
|
for (int i = 0; i < optionLength; i++){
|
||||||
|
auto funcOption = new UserData::UserDataFunction(func, nullptr);
|
||||||
|
f->RegisterOption(funcOption);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
|
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
|
||||||
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
|
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
|
||||||
// Register error function
|
// Register error function
|
||||||
auto errorFuncTypeOption = new UserData::UserDataFunctionOption(
|
auto errorFuncType = BasicLibrary::GetErrorFuncType();
|
||||||
make_shared<ScriptType>(TypeClass::Nil),
|
|
||||||
vector<shared_ptr<ScriptType>>{make_shared<StringScriptType>(false, 0)});
|
|
||||||
auto errorFuncType = make_shared<GenericFunctionScriptType>();
|
|
||||||
errorFuncType->RegisterFunctionOption(errorFuncTypeOption);
|
|
||||||
auto errorFuncOption = new UserData::UserDataFunction(_error, nullptr);
|
|
||||||
auto errorFunc = make_shared<Evaluation::GenericFunctionEvalValue>(errorFuncType, rand());
|
|
||||||
errorFunc->RegisterOption(errorFuncOption);
|
|
||||||
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");
|
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");
|
||||||
|
auto errorFunc = BasicLibrary::GetFuncEvalValue(_error, errorFuncType, 1);
|
||||||
bound->insert({errorLookup, new Binder::BoundVariable(errorFuncType)});
|
bound->insert({errorLookup, new Binder::BoundVariable(errorFuncType)});
|
||||||
values->insert({errorLookup, errorFunc});
|
values->insert({errorLookup, errorFunc});
|
||||||
|
|
||||||
// Register assert function
|
// Register assert function
|
||||||
auto assertFuncTypeOption = new UserData::UserDataFunctionOption(
|
auto assertFuncType = BasicLibrary::GetAssertFuncType();
|
||||||
make_shared<ScriptType>(TypeClass::Bool),
|
|
||||||
vector<shared_ptr<ScriptType>>{make_shared<ScriptType>(TypeClass::Bool)});
|
|
||||||
auto assertFuncType = make_shared<GenericFunctionScriptType>();
|
|
||||||
assertFuncType->RegisterFunctionOption(assertFuncTypeOption);
|
|
||||||
auto assertFuncOption = new UserData::UserDataFunction(_assert, nullptr);
|
|
||||||
auto assertFunc = make_shared<Evaluation::GenericFunctionEvalValue>(assertFuncType, rand());
|
|
||||||
assertFunc->RegisterOption(assertFuncOption);
|
|
||||||
|
|
||||||
auto assertLookup = Utilities::HashedString::CreateLookup(u"assert");
|
auto assertLookup = Utilities::HashedString::CreateLookup(u"assert");
|
||||||
|
auto assertFunc = BasicLibrary::GetFuncEvalValue(_assert, assertFuncType, 2);
|
||||||
bound->insert({assertLookup, new Binder::BoundVariable(assertFuncType)});
|
bound->insert({assertLookup, new Binder::BoundVariable(assertFuncType)});
|
||||||
values->insert({assertLookup, assertFunc});
|
values->insert({assertLookup, assertFunc});
|
||||||
|
|
||||||
|
// Register print function
|
||||||
|
auto printFuncType = BasicLibrary::GetPrintFuncType();
|
||||||
|
auto printLookup = Utilities::HashedString::CreateLookup(u"print");
|
||||||
|
auto printFunc = BasicLibrary::GetFuncEvalValue(_print, printFuncType, 1);
|
||||||
|
bound->insert({printLookup, new Binder::BoundVariable(printFuncType)});
|
||||||
|
values->insert({printLookup, printFunc});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@ namespace Porygon::UserData{
|
||||||
_obj = obj;
|
_obj = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~UserDataFunction() final{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Evaluation::EvalValue* Call(Evaluation::EvalValue* parameters[], int parameterCount){
|
Evaluation::EvalValue* Call(Evaluation::EvalValue* parameters[], int parameterCount){
|
||||||
return _call(_obj, parameters, parameterCount);
|
return _call(_obj, parameters, parameterCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifdef TESTS_BUILD
|
#ifdef TESTS_BUILD
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "../src/Script.hpp"
|
#include "../src/Script.hpp"
|
||||||
|
#include "../../src/GlobalScriptOptions.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace Porygon;
|
using namespace Porygon;
|
||||||
|
@ -38,6 +39,30 @@ TEST_CASE( "Assert func does not throw if argument is true", "[integration]" ) {
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Assert func works with second argument", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(u"assert(false, 'foobar')");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
try{
|
||||||
|
script -> Evaluate();
|
||||||
|
throw;
|
||||||
|
} catch (const EvaluationException& e){
|
||||||
|
auto err = e.what();
|
||||||
|
REQUIRE(std::strcmp(err, "An evaluation exception occurred: foobar") == 0);
|
||||||
|
}
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Print func works", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(u"print('foobar')");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
auto stream = new std::stringstream();
|
||||||
|
GlobalScriptOptions::SetPrintStream(stream);
|
||||||
|
script->Evaluate();
|
||||||
|
auto printVal = stream->str();
|
||||||
|
REQUIRE(printVal == "foobar\n");
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue