#include "Compiler.h" namespace { template void SerializeDirect(std::ostringstream& s, const T& v) { s.write(reinterpret_cast(&v), sizeof v); } void SerializeString(std::ostringstream& s, const NVL::String& st) { u16 v = st.size() * sizeof NVL::Char; s.write(reinterpret_cast(&v), sizeof v); s.write(reinterpret_cast(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>(v.value); SerializeDirect(s, static_cast(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(v.value)); return; case Type::String: SerializeString(s, std::get(v.value)); return; } } template void DeserializeDirect(std::istringstream& s, T& v) { s.read(reinterpret_cast(&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(str), size); reinterpret_cast(str)[size / sizeof NVL::Char] = u'\0'; NVL::String st = NVL::String(reinterpret_cast(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 vs{}; DeserializeDirect(s, size); for (u16 i = 0; i < size; i++) { vs.push_back(DeserializeVariable(s)); } return vs; } case Type::Nil: return {}; 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& 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(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& scenes, i32 entry_scene_index) { std::vector<_DirectedGraphNode> nodes{}; Vector procedure_names; _DirectedGraphNode n{}; for (auto& c : scenes[entry_scene_index].get()) { Vector s{}; for (auto& v : c) { s.push_back(StaticEval(procedure_names, v)); } // TODO route nodes when JUMP n.sequence.push_back(s); } nodes.push_back(n); return NVLGraph{ nodes, procedure_names }; } std::ostringstream Serialize(const NVLGraph& g) { std::ostringstream s; SerializeDirect(s, static_cast(g.static_refs.size())); for (const String& r : g.static_refs) { SerializeString(s, r); } SerializeDirect(s, static_cast(g.nodes.size())); for (const _DirectedGraphNode& n : g.nodes) { SerializeDirect(s, static_cast(n.sequence.size())); for (const Vector& c : n.sequence) { SerializeDirect(s, static_cast(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{}; u16 size2{}; DeserializeDirect(buf, size2); for (u16 j = 0; j < size2; j++) { Vector 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; } }