Skip to content

Commit

Permalink
Gets João compiling and working as an extools module
Browse files Browse the repository at this point in the history
There's still some iffy decisions here, especially that it currently totally crashes when a parser or scanner error takes place, but it does indeed work!

UPDATES THE JOAO SUBMODULE TO THIS COMMIT: Altoids1/Joao@4c2267c
  • Loading branch information
Altoids1 committed Sep 24, 2021
1 parent d709851 commit 97510dc
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 14 deletions.
80 changes: 67 additions & 13 deletions byond-extools/src/joao/joao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,20 @@ const char* enable_joao()
trvh run_script(unsigned int argn, ByondValue* args, ByondValue src)
{
using namespace joao;
if(argn < 2) // If we weren't given a script or signal
if (argn < 2) // If we weren't given a script or signal
return ByondValue::False();

ByondValue& script = args[0];
if(script.type != DataType::STRING) // If what we were given can't be a script
if (script.type != DataType::STRING) // If what we were given can't be a script
{
return ByondValue::False();
}

ByondValue& signal = args[1];
if(signal.type != DataType::DATUM) // If what we were given isn't even a datum (signals are, this comment upholding, /datum/signal/subspace/vocal)
ByondValue& packet = args[1];
if (packet.type != DataType::DATUM)
return ByondValue::False();
ByondValue& signal = args[1].get("signal");
if (signal.type != DataType::DATUM) // If what we were given isn't even a datum (signals are, this comment upholding, /datum/signal/subspace/vocal)
return ByondValue::False();

std::istringstream stream = std::istringstream(std::string(script));
Expand All @@ -86,59 +91,108 @@ trvh run_script(unsigned int argn, ByondValue* args, ByondValue src)
scanner.scan(stream);
Parser pears(scanner);


//Tries to follow the structure of the script_signal var from NTSL
//The default values are not based on the actual incoming signal, since they are used whenever *any* /signal Object is instantiated within Joao.
ObjectType signal_type("signal");
JoaoValue empty_string = JoaoValue(std::string(""));
signal_type.set_typeproperty_raw("content", empty_string);
signal_type.set_typeproperty_raw("freq", 0);
signal_type.set_typeproperty_raw("freq", JoaoValue(0));
signal_type.set_typeproperty_raw("source", empty_string);


pears.IncludeAlienType(&signal_type);
Program parsed = pears.parse();

Interpreter interpreter(parsed, false);

//Constructing the João Object to be passed as the argument
Object* signal_obj = signal_type.makeObject(interpreter, {});

signal_obj->set_property_raw("content", JoaoValue(Core::GetStringFromId(signal.get_by_id(ID::data).get_by_id(ID::message).value)));
signal_obj->set_property_raw("freq", JoaoValue(signal.get_by_id(ID::frequency).valuef)); // I think?
signal_obj->set_property_raw("source", JoaoValue(Core::GetStringFromId(signal.get_by_id(ID::name).value)));
signal_obj->set_property_raw("freq", JoaoValue(JoaoValue::JoaoInt(signal.get_by_id(ID::frequency).valuef))); // I think?
signal_obj->set_property_raw("source", JoaoValue(Core::GetStringFromId(signal.get_by_id(ID::data).get_by_id(ID::name).value)));

JoaoValue jargs = interpreter.makeBaseTable({ JoaoValue(signal_obj) }, {}, nullptr);

//Execute!
JoaoValue ret = interpreter.execute(parsed, jargs);
if (ret.t_vType != JoaoValue::vType::Object || ret.t_value.as_object_ptr->object_type != "/signal") // If the program returned something that isn't a signal object
JoaoValue ret;
try
{
ret = interpreter.execute(parsed, jargs);
}
catch (const JoaoValue& err)
{
ByondValue& error = packet.get("err");
error.set("what", ByondValue(*(err.t_value.as_object_ptr->get_property_raw("what").t_value.as_string_ptr)));
error.set("code", ByondValue(err.t_value.as_object_ptr->get_property_raw("code").t_value.as_int));
return ByondValue::False();
}
catch (std::exception exp)
{
ByondValue& error = packet.get("err");
error.set("what", ByondValue(std::string(exp.what())));
error.set("code", -1);
return ByondValue::False();
}
catch(...) // A real fucking scary thing to put here but I dunno how else to resolve this
{
ByondValue& error = packet.get("err");
error.set("what", "An unknown error occurred!");
error.set("code", -2);
return ByondValue::False();
}
if (ret.t_vType != JoaoValue::vType::Object || ret.t_value.as_object_ptr->object_type != "signal") // If the program returned something that isn't a signal object
{
ByondValue& error = packet.get("err");
error.set("what", "Returned value was not a /signal!");
error.set("code", -3);
return ByondValue::False();
}
Object*& retptr = ret.t_value.as_object_ptr; // $#(@$*@!!!!

//preparing for the agony of setting the elements of a /list
auto datas = signal.get_by_id(ID::data); // "datas" is the plural of "data," which is in turn the plural of "datum."

//Content typecheck & set
JoaoValue& ret_content = retptr->get_property_raw("content");
if (ret_content.t_vType != JoaoValue::vType::String)
{
ByondValue& error = packet.get("err");
error.set("what", "/signal.content was not of type String!");
error.set("code", -4);
return ByondValue::False();
}
signal.get_by_id(ID::data).set_by_id(ID::message, *ret_content.t_value.as_string_ptr);

ManagedValue msg = ManagedValue(*ret_content.t_value.as_string_ptr);
SetAssocElement(datas.type, datas.value, DataType::STRING, ID::message, msg.type, msg.value); // Have to use this raw shit since extools lacks a good API for it

//Frequency typecheck & set
JoaoValue& ret_freq = retptr->get_property_raw("freq");
if (ret_freq.t_vType != JoaoValue::vType::Integer)
{
ByondValue& error = packet.get("err");
error.set("what", "/signal.freq was not of type Integer!");
error.set("code", -4);
return ByondValue::False();
}
signal.get_by_id(ID::data).set_by_id(ID::frequency, ret_freq.t_value.as_int);
//signal.get_by_id(ID::data).set_by_id(ID::frequency, ret_freq.t_value.as_int);

ManagedValue freq = ManagedValue(ret_freq.t_value.as_int);
SetAssocElement(datas.type, datas.value, DataType::STRING, ID::frequency, freq.type, freq.value); // Have to use this raw shit since extools lacks a good API for it

//Source typecheck & set
JoaoValue& ret_source = retptr->get_property_raw("source");
if (ret_source.t_vType != JoaoValue::vType::String)
{
ByondValue& error = packet.get("err");
error.set("what", "/signal.source was not of type String!");
error.set("code", -4);
return ByondValue::False();
}
signal.get_by_id(ID::data).set_by_id(ID::name, *ret_source.t_value.as_string_ptr);
//signal.get_by_id(ID::data).set_by_id(ID::name, *ret_source.t_value.as_string_ptr);

ManagedValue source = ManagedValue(*ret_source.t_value.as_string_ptr);
SetAssocElement(datas.type, datas.value, DataType::STRING, ID::name, source.type, source.value); // Have to use this raw shit since extools lacks a good API for it

return ByondValue::True();
}
Expand Down
2 changes: 1 addition & 1 deletion byond-extools/src/joao/joao_repo
Submodule joao_repo updated 1 files
+5 −1 Interpreter.cpp

0 comments on commit 97510dc

Please sign in to comment.