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;
|
||||
|
||||
public:
|
||||
EvaluationScriptFunctionOption(const shared_ptr<BoundBlockStatement> innerBlock, const shared_ptr<EvaluationScope> scope)
|
||||
: _innerBlock(innerBlock), _scope(scope) {
|
||||
|
||||
EvaluationScriptFunctionOption(shared_ptr<BoundBlockStatement> innerBlock, shared_ptr<EvaluationScope> scope)
|
||||
: _innerBlock(std::move(innerBlock)), _scope(std::move(scope)) {
|
||||
}
|
||||
~EvaluationScriptFunctionOption() final = default;
|
||||
|
||||
const std::shared_ptr<BoundBlockStatement> &GetInnerBlock() const {
|
||||
return _innerBlock;
|
||||
|
@ -36,15 +36,13 @@ namespace Porygon::Evaluation {
|
|||
const std::shared_ptr<EvaluationScope> &GetScope() const {
|
||||
return _scope;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class GenericFunctionEvalValue : public EvalValue{
|
||||
protected:
|
||||
const std::shared_ptr<GenericFunctionScriptType> _type;
|
||||
const std::size_t _hash;
|
||||
std::vector<shared_ptr<GenericFunctionOption>> _options;
|
||||
const shared_ptr<GenericFunctionScriptType> _type;
|
||||
const size_t _hash;
|
||||
vector<shared_ptr<GenericFunctionOption>> _options;
|
||||
public:
|
||||
GenericFunctionEvalValue(shared_ptr<GenericFunctionScriptType> type, size_t hash)
|
||||
: _type(move(type)),
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Porygon {
|
|||
this -> RegisterFunctionOption(option);
|
||||
};
|
||||
|
||||
virtual ~GenericFunctionScriptType() final{
|
||||
~GenericFunctionScriptType() final{
|
||||
for (auto o: _options){
|
||||
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 "../UserData/UserDataFunction.hpp"
|
||||
#include "../UserData/UserDataFunctionType.hpp"
|
||||
#include "../GlobalScriptOptions.hpp"
|
||||
|
||||
namespace Porygon::StandardLibraries{
|
||||
class BasicLibrary{
|
||||
|
@ -22,42 +23,80 @@ namespace Porygon::StandardLibraries{
|
|||
static Evaluation::EvalValue* _assert(void*, Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto assertion = parameters[0]->EvaluateBool();
|
||||
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!");
|
||||
}
|
||||
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:
|
||||
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
|
||||
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
|
||||
// Register error function
|
||||
auto errorFuncTypeOption = new UserData::UserDataFunctionOption(
|
||||
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 errorFuncType = BasicLibrary::GetErrorFuncType();
|
||||
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");
|
||||
auto errorFunc = BasicLibrary::GetFuncEvalValue(_error, errorFuncType, 1);
|
||||
bound->insert({errorLookup, new Binder::BoundVariable(errorFuncType)});
|
||||
values->insert({errorLookup, errorFunc});
|
||||
|
||||
// Register assert function
|
||||
auto assertFuncTypeOption = new UserData::UserDataFunctionOption(
|
||||
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 assertFuncType = BasicLibrary::GetAssertFuncType();
|
||||
auto assertLookup = Utilities::HashedString::CreateLookup(u"assert");
|
||||
auto assertFunc = BasicLibrary::GetFuncEvalValue(_assert, assertFuncType, 2);
|
||||
bound->insert({assertLookup, new Binder::BoundVariable(assertFuncType)});
|
||||
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;
|
||||
}
|
||||
|
||||
~UserDataFunction() final{
|
||||
|
||||
}
|
||||
|
||||
Evaluation::EvalValue* Call(Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
return _call(_obj, parameters, parameterCount);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifdef TESTS_BUILD
|
||||
#include <catch.hpp>
|
||||
#include "../src/Script.hpp"
|
||||
#include "../../src/GlobalScriptOptions.hpp"
|
||||
#include <cstring>
|
||||
|
||||
using namespace Porygon;
|
||||
|
@ -38,6 +39,30 @@ TEST_CASE( "Assert func does not throw if argument is true", "[integration]" ) {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue