NouVeL/NVL/Compiler.cpp

177 lines
4.5 KiB
C++

#include "Compiler.h"
namespace {
template <typename T>
void SerializeDirect(std::ostringstream& s, const T& v) {
s.write(reinterpret_cast<const char*>(&v), sizeof v);
}
void SerializeString(std::ostringstream& s, const NVL::String& st) {
u16 v = st.size() * sizeof NVL::Char;
s.write(reinterpret_cast<const char*>(&v), sizeof v);
s.write(reinterpret_cast<const char*>(st.c_str()), v);
}
void SerializeVariable(std::ostringstream& s, const NVL::Environment::Variable& v) {
using NVL::Environment::Type;
SerializeDirect(s, v.type);
switch (v.type) {
case Type::Array:
{
const auto& e = std::get<NVL::Vector<NVL::Environment::Variable>>(v.value);
SerializeDirect(s, static_cast<u16>(e.size()));
for (const auto& x : e) {
SerializeVariable(s, x);
}
return;
}
case Type::Nil:
return;
case Type::Number:
case Type::StaticReference:
SerializeDirect(s, std::get<NVL::Number>(v.value));
return;
case Type::String:
SerializeString(s, std::get<NVL::String>(v.value));
return;
}
}
template <typename T>
void DeserializeDirect(std::istringstream& s, T& v) {
s.read(reinterpret_cast<char*>(&v), sizeof v);
}
NVL::String DeserializeString(std::istringstream& s) {
u16 size{};
DeserializeDirect(s, size);
u8* str = new u8[size + sizeof NVL::Char];
s.read(reinterpret_cast<char*>(str), size);
reinterpret_cast<NVL::Char*>(str)[size / sizeof NVL::Char] = u'\0';
NVL::String st = NVL::String(reinterpret_cast<NVL::Char*>(str));
delete[] str;
return st;
}
NVL::Environment::Variable DeserializeVariable(std::istringstream& s) {
using NVL::Environment::Type;
NVL::Environment::Type t{};
DeserializeDirect(s, t);
switch (t) {
case Type::Array:
{
u16 size{};
NVL::Vector<NVL::Environment::Variable> vs{};
DeserializeDirect(s, size);
for (u16 i = 0; i < size; i++) {
vs.push_back(DeserializeVariable(s));
}
return vs;
}
case Type::Nil:
return {Type::Nil};
case Type::Number:
case Type::StaticReference:
{
NVL::Number n{};
DeserializeDirect(s, n);
return { n, t == Type::StaticReference };
}
case Type::String:
return DeserializeString(s);
}
}
}
namespace NVL::Compiler {
Environment::Variable StaticEval(Vector<String>& refs, const Parse::Object& obj) {
Environment::Variable actual = Environment::Eval(obj);
if (actual.type == Environment::Type::Procedure) {
u32 proc_index = -1; // lol
const String& proc = std::get<String>(obj.value);
for (u32 i = 0; i < refs.size(); i++) {
if (refs[i] == proc) {
proc_index = i;
break;
}
}
if (proc_index == -1) {
proc_index = refs.size();
refs.push_back(proc);
}
return Environment::Variable(proc_index, true);
}
return actual;
}
NVLGraph Compile(const Vector<Parse::Scene>& scenes, i32 entry_scene_index) {
std::vector<_DirectedGraphNode> nodes{};
Vector<String> procedure_names;
_DirectedGraphNode n{};
for (auto& c : scenes[entry_scene_index].get()) {
Vector<Environment::Variable> s{};
for (auto& v : c) {
s.push_back(StaticEval(procedure_names, v));
}
// TODO route nodes when JUMP
n.sequence.push_back(s);
n.description = scenes[entry_scene_index].name;
}
nodes.push_back(n);
return NVLGraph{ nodes, procedure_names };
}
std::ostringstream Serialize(const NVLGraph& g) {
std::ostringstream s;
SerializeDirect(s, static_cast<u16>(g.static_refs.size()));
for (const String& r : g.static_refs) {
SerializeString(s, r);
}
SerializeDirect(s, static_cast<u16>(g.nodes.size()));
for (const _DirectedGraphNode& n : g.nodes) {
SerializeString(s, n.description);
SerializeDirect(s, static_cast<u16>(n.sequence.size()));
for (const Vector<Environment::Variable>& c : n.sequence) {
SerializeDirect(s, static_cast<u16>(c.size()));
for (const Environment::Variable& v : c) {
SerializeVariable(s, v);
}
}
}
return s;
}
NVLGraph Deserialize(std::istringstream& buf) {
NVLGraph g{};
u16 size{};
DeserializeDirect(buf, size);
for (u16 i = 0; i < size; i++) {
g.static_refs.push_back(DeserializeString(buf));
}
DeserializeDirect(buf, size);
for (u16 i = 0; i < size; i++) {
_DirectedGraphNode n{};
n.description = DeserializeString(buf);
u16 size2{};
DeserializeDirect(buf, size2);
for (u16 j = 0; j < size2; j++) {
Vector<Environment::Variable> cmd{};
u16 size3{};
DeserializeDirect(buf, size3);
for (u16 k = 0; k < size3; k++) {
cmd.push_back(DeserializeVariable(buf));
}
n.sequence.push_back(cmd);
}
g.nodes.push_back(n);
}
return g;
}
}