Implements most of the remaining core standard functions
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
7523fb4294
commit
13b382def2
|
@ -122,6 +122,11 @@ namespace Porygon::Evaluation {
|
|||
return _value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::u16string EvaluateString() const final{
|
||||
return Utilities::StringUtils::FloatToString(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline EvalValue* Clone() const final {
|
||||
return new FloatEvalValue(_value);
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace Porygon {
|
|||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < parameters.size(); i++){
|
||||
if (_parameterTypes[i]->GetClass() == TypeClass::All)
|
||||
continue;
|
||||
if (parameters[i]->operator!=(_parameterTypes[i].get())){
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Porygon{
|
|||
Function,
|
||||
UserData,
|
||||
Table,
|
||||
All,
|
||||
};
|
||||
|
||||
class ScriptType{
|
||||
|
@ -33,7 +34,7 @@ namespace Porygon{
|
|||
|
||||
virtual ~ScriptType() = default;
|
||||
|
||||
const TypeClass GetClass() const{
|
||||
[[nodiscard]] const TypeClass GetClass() const{
|
||||
return _class;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,11 @@
|
|||
#include "../UserData/UserDataFunction.hpp"
|
||||
#include "../UserData/UserDataFunctionType.hpp"
|
||||
#include "../ScriptOptions.hpp"
|
||||
#include "../Evaluator/EvalValues/StringEvalValue.hpp"
|
||||
|
||||
namespace Porygon::StandardLibraries{
|
||||
class BasicLibrary{
|
||||
static const Evaluation::EvalValue* _error(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto message = parameters[0]->EvaluateString();
|
||||
auto conv = Utilities::StringUtils::FromUTF8(message);
|
||||
throw Evaluation::EvaluationException(conv);
|
||||
}
|
||||
//region Assert
|
||||
|
||||
static const Evaluation::EvalValue* _assert(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto assertion = parameters[0]->EvaluateBool();
|
||||
|
@ -35,17 +32,103 @@ namespace Porygon::StandardLibraries{
|
|||
return new Evaluation::BooleanEvalValue(true);
|
||||
}
|
||||
|
||||
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)}});
|
||||
}
|
||||
//endregion
|
||||
//region Error
|
||||
|
||||
static const Evaluation::EvalValue* _error(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto message = parameters[0]->EvaluateString();
|
||||
auto conv = Utilities::StringUtils::FromUTF8(message);
|
||||
throw Evaluation::EvaluationException(conv);
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetErrorFuncType(){
|
||||
return GetFuncType(make_shared<ScriptType>(TypeClass::Nil), {{make_shared<StringScriptType>(false, 0)}});
|
||||
}
|
||||
//endregion
|
||||
//region Print
|
||||
|
||||
static const Evaluation::EvalValue* _print(void*, const ScriptOptions* options, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto message = parameters[0]->EvaluateString();
|
||||
options->Print(message.c_str());
|
||||
return new Evaluation::NilEvalValue();
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetPrintFuncType(){
|
||||
return GetFuncType(make_shared<ScriptType>(TypeClass::Nil), {{make_shared<StringScriptType>(false, 0)}});
|
||||
}
|
||||
//endregion
|
||||
//region ToInt
|
||||
|
||||
static const Evaluation::EvalValue* _toInt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto parameter = parameters[0]->EvaluateString();
|
||||
auto parsed = Utilities::StringUtils::ParseInteger(parameter);
|
||||
return new Evaluation::IntegerEvalValue(parsed);
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetToIntFuncType(){
|
||||
return GetFuncType(make_shared<NumericScriptType>(true, false), {{make_shared<StringScriptType>(false, 0)}});
|
||||
}
|
||||
//endregion
|
||||
//region ToFloat
|
||||
|
||||
static const Evaluation::EvalValue* _toFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto parameter = parameters[0]->EvaluateString();
|
||||
auto parsed = Utilities::StringUtils::ParseFloat(parameter);
|
||||
return new Evaluation::FloatEvalValue(parsed);
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetToFloatFuncType(){
|
||||
return GetFuncType(make_shared<NumericScriptType>(true, true),
|
||||
{{make_shared<StringScriptType>(false, 0)}});
|
||||
}
|
||||
//endregion
|
||||
//region ToString
|
||||
|
||||
static const Evaluation::EvalValue* _toString(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto parameter = parameters[0]->EvaluateString();
|
||||
return new Evaluation::StringEvalValue(parameter);
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetToStringFuncType(){
|
||||
return GetFuncType(make_shared<StringScriptType>(false, 0),
|
||||
{{make_shared<ScriptType>(TypeClass::All)}});
|
||||
}
|
||||
//endregion
|
||||
//region Type
|
||||
|
||||
static const Evaluation::EvalValue* _type(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto parameter = parameters[0]->GetTypeClass();
|
||||
switch (parameter){
|
||||
|
||||
case TypeClass::Error: return new Evaluation::StringEvalValue(u"error");
|
||||
case TypeClass::Nil: return new Evaluation::StringEvalValue(u"nil");
|
||||
case TypeClass::Number: return new Evaluation::StringEvalValue(u"number");
|
||||
case TypeClass::Bool: return new Evaluation::StringEvalValue(u"bool");
|
||||
case TypeClass::String: return new Evaluation::StringEvalValue(u"string");
|
||||
case TypeClass::Function: return new Evaluation::StringEvalValue(u"function");
|
||||
case TypeClass::UserData: return new Evaluation::StringEvalValue(u"userdata");
|
||||
case TypeClass::Table: return new Evaluation::StringEvalValue(u"table");
|
||||
case TypeClass::All: return new Evaluation::StringEvalValue(u"all");
|
||||
}
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetTypeFuncType(){
|
||||
return GetFuncType(make_shared<StringScriptType>(false, 0),
|
||||
{{make_shared<ScriptType>(TypeClass::All)}});
|
||||
}
|
||||
//endregion
|
||||
//region IsFloat
|
||||
|
||||
static const Evaluation::EvalValue* _isFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){
|
||||
auto parameter = dynamic_cast<const Evaluation::NumericEvalValue*>(parameters[0]);
|
||||
return new Evaluation::BooleanEvalValue(parameter->IsFloat());
|
||||
}
|
||||
static shared_ptr<GenericFunctionScriptType> GetIsFloatFuncType(){
|
||||
return GetFuncType(make_shared<ScriptType>(TypeClass::Bool),
|
||||
{{make_shared<NumericScriptType>(false, false)}});
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region Generic handling
|
||||
|
||||
static shared_ptr<GenericFunctionScriptType> GetFuncType(const shared_ptr<ScriptType>& result, const vector<vector<shared_ptr<ScriptType>>>& options){
|
||||
auto funcType = make_shared<GenericFunctionScriptType>();
|
||||
|
@ -56,25 +139,6 @@ namespace Porygon::StandardLibraries{
|
|||
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<GenericFunctionScriptType> GetToIntFuncType(){
|
||||
return GetFuncType(make_shared<NumericScriptType>(true, false), {{make_shared<StringScriptType>(false, 0)}});
|
||||
}
|
||||
|
||||
|
||||
static Evaluation::EvalValue* GetFuncEvalValue(
|
||||
const Evaluation::EvalValue* (*func)(void* obj, const ScriptOptions*,
|
||||
const Evaluation::EvalValue* parameters[], int parameterCount),
|
||||
|
@ -86,6 +150,7 @@ namespace Porygon::StandardLibraries{
|
|||
}
|
||||
return f;
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
||||
public:
|
||||
|
@ -118,6 +183,34 @@ namespace Porygon::StandardLibraries{
|
|||
auto toIntFunc = BasicLibrary::GetFuncEvalValue(_toInt, toIntFuncType, 1);
|
||||
bound->insert({toIntLookup, new Binder::BoundVariable(toIntFuncType)});
|
||||
values->insert({toIntLookup, toIntFunc});
|
||||
|
||||
// Register toFloat function
|
||||
auto toFloatFuncType = BasicLibrary::GetToFloatFuncType();
|
||||
auto toFloatLookup = Utilities::HashedString::CreateLookup(u"tofloat");
|
||||
auto toFloatFunc = BasicLibrary::GetFuncEvalValue(_toFloat, toFloatFuncType, 1);
|
||||
bound->insert({toFloatLookup, new Binder::BoundVariable(toFloatFuncType)});
|
||||
values->insert({toFloatLookup, toFloatFunc});
|
||||
|
||||
// Register ToString function
|
||||
auto toStringFuncType = BasicLibrary::GetToStringFuncType();
|
||||
auto toStringLookup = Utilities::HashedString::CreateLookup(u"tostring");
|
||||
auto toStringFunc = BasicLibrary::GetFuncEvalValue(_toString, toStringFuncType, 1);
|
||||
bound->insert({toStringLookup, new Binder::BoundVariable(toStringFuncType)});
|
||||
values->insert({toStringLookup, toStringFunc});
|
||||
|
||||
// Register Type function
|
||||
auto typeFuncType = BasicLibrary::GetTypeFuncType();
|
||||
auto typeLookup = Utilities::HashedString::CreateLookup(u"type");
|
||||
auto typeFunc = BasicLibrary::GetFuncEvalValue(_type, typeFuncType, 1);
|
||||
bound->insert({typeLookup, new Binder::BoundVariable(typeFuncType)});
|
||||
values->insert({typeLookup, typeFunc});
|
||||
|
||||
// Register IsFloat function
|
||||
auto isFloatFuncType = BasicLibrary::GetTypeFuncType();
|
||||
auto isFloatLookup = Utilities::HashedString::CreateLookup(u"isfloat");
|
||||
auto isFloatFunc = BasicLibrary::GetFuncEvalValue(_isFloat, isFloatFuncType, 1);
|
||||
bound->insert({isFloatLookup, new Binder::BoundVariable(isFloatFuncType)});
|
||||
values->insert({isFloatLookup, isFloatFunc});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ namespace Porygon::Utilities{
|
|||
inline static std::u16string IntToString(long const &i) {
|
||||
return to_16.from_bytes(std::to_string(i));
|
||||
}
|
||||
inline static std::u16string FloatToString(double const &i) {
|
||||
return to_16.from_bytes(std::to_string(i));
|
||||
}
|
||||
|
||||
inline static std::u16string ToUTF8(const std::string &s) {
|
||||
return to_16.from_bytes(s);
|
||||
}
|
||||
|
@ -27,6 +31,11 @@ namespace Porygon::Utilities{
|
|||
auto parsed = std::stol(FromUTF8(s));
|
||||
return parsed;
|
||||
}
|
||||
|
||||
inline static double ParseFloat(const std::u16string &s){
|
||||
auto parsed = std::stod(FromUTF8(s));
|
||||
return parsed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,44 @@ TEST_CASE( "toint func works", "[integration]" ) {
|
|||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "tofloat func works", "[integration]" ) {
|
||||
Script* script = Script::Create(u"return tofloat('5.128')");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto result = script->Evaluate();
|
||||
REQUIRE(result->EvaluateFloat() == 5.128);
|
||||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "tostring func works", "[integration]" ) {
|
||||
Script* script = Script::Create(u"return tostring(5.128)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto result = script->Evaluate();
|
||||
REQUIRE(result->EvaluateString() == u"5.128000");
|
||||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "type func works", "[integration]" ) {
|
||||
Script* script = Script::Create(u"return type(5.128)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto result = script->Evaluate();
|
||||
REQUIRE(result->EvaluateString() == u"number");
|
||||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "isfloat returns true for floats", "[integration]" ) {
|
||||
Script* script = Script::Create(u"return isfloat(5.128)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto result = script->Evaluate();
|
||||
REQUIRE(result->EvaluateBool());
|
||||
delete script;
|
||||
}
|
||||
|
||||
TEST_CASE( "isfloat returns false for integers", "[integration]" ) {
|
||||
Script* script = Script::Create(u"return isfloat(5)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
auto result = script->Evaluate();
|
||||
REQUIRE_FALSE(result->EvaluateBool());
|
||||
delete script;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue