thoughts about compiler

This commit is contained in:
lachrymaL 2023-04-07 16:04:30 -04:00
parent bdf80f37e6
commit 38496209c0
No known key found for this signature in database
GPG key ID: F3640ACFA174B1C1
9 changed files with 78 additions and 47 deletions

View file

@ -249,8 +249,8 @@ namespace ADVect {
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// std::filesystem::current_path("E:\\Archive\\Projects\\NouVeL\\ADVect\\runtime"); std::filesystem::current_path("E:\\Archive\\Projects\\NouVeL\\ADVect\\runtime");
std::filesystem::current_path("/Users/lachrymal/Projects/NouVeL/ADVect/runtime/"); //std::filesystem::current_path("/Users/lachrymal/Projects/NouVeL/ADVect/runtime/");
NVL::Environment::ENVIRONMENT.enter({ NVL::Environment::ENVIRONMENT.enter({
{ {

View file

@ -5,7 +5,7 @@ cmake_minimum_required (VERSION 3.8)
project (NVL) project (NVL)
include_directories("include") include_directories("include")
add_library (NVL STATIC "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h") add_library (NVL STATIC "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" "Compiler.cpp" "Compiler.h")
# add_executable (NVL "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" ) # add_executable (NVL "NouVeL.cpp" "Parser.cpp" "Environment.cpp" "Environment.h" "Common.h" )
# TODO: Add tests and install targets if needed. # TODO: Add tests and install targets if needed.

View file

@ -15,6 +15,7 @@ typedef int64_t i64;
typedef uint64_t u64; typedef uint64_t u64;
#include <string> #include <string>
#include <vector>
#include <locale> #include <locale>
#include <codecvt> #include <codecvt>
@ -24,6 +25,8 @@ namespace NVL {
using Number = f32; using Number = f32;
using Char = char16_t; using Char = char16_t;
using String = std::u16string; using String = std::u16string;
template <typename T>
using Vector = std::vector<T>;
static std::wstring_convert<std::codecvt_utf8_utf16<Char>, Char> str_converter; static std::wstring_convert<std::codecvt_utf8_utf16<Char>, Char> str_converter;

28
NVL/Compiler.cpp Normal file
View file

@ -0,0 +1,28 @@
#include "Compiler.h"
#include "Parser.h"
#include "Environment.h"
namespace NVL::Compiler {
struct _DirectedGraphNode {
Vector<_DirectedGraphNode*> reached_by;
Vector<std::pair<i32, Vector<Environment::Variable>>> sequence;
};
void Compile(Vector<Parse::Scene>& scenes, i32 entry_scene_index) {
_DirectedGraphNode n{};
Vector<Environment::Variable> procs_used{};
for (auto& c : scenes[entry_scene_index].get()) {
Environment::Variable f = Environment::Eval(c[0]);
Vector<Environment::Variable> s{};
u32 i = 1;
while (i < c.size()) {
s.push_back(Environment::Eval(c[i++]));
}
}
}
void Serialize(_DirectedGraphNode root) {
}
}

1
NVL/Compiler.h Normal file
View file

@ -0,0 +1 @@
#include "Common.h"

View file

@ -12,8 +12,8 @@ namespace NVL::Environment {
} }
Variable::Variable(const Number& v) : type(Type::Number), value(v), length(1) {} Variable::Variable(const Number& v) : type(Type::Number), value(v), length(1) {}
Variable::Variable(const String& v) : type(Type::String), value(v), length(1) {} Variable::Variable(const String& v) : type(Type::String), value(v), length(1) {}
Variable::Variable(const std::vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {} Variable::Variable(const Vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
Variable::Variable(const std::function < Variable(std::vector<Variable>)>& v, u32 l) : type(Type::Procedure), value(v), length(l) {} Variable::Variable(const std::function < Variable(Vector<Variable>)>& v, u32 l) : type(Type::Procedure), value(v), length(l) {}
bool Variable::operator==(const Variable& other) const { bool Variable::operator==(const Variable& other) const {
if (other.type != type) if (other.type != type)
@ -62,20 +62,20 @@ namespace NVL::Environment {
return Variable(std::get<String>(obj.value)); return Variable(std::get<String>(obj.value));
case Parse::Type::Array: case Parse::Type::Array:
{ {
std::vector<Variable> v{}; Vector<Variable> v{};
for (const auto& x : std::get<std::vector<Parse::Object>>(obj.value)) for (const auto& x : std::get<Vector<Parse::Object>>(obj.value))
v.push_back(Eval(x)); v.push_back(Eval(x));
return Variable(v); return Variable(v);
} }
case Parse::Type::Subexpression: case Parse::Type::Subexpression:
{ {
return Apply(std::get<std::vector<Parse::Object>>(obj.value)); return Apply(std::get<Vector<Parse::Object>>(obj.value));
} }
} }
} }
Variable Apply(const Parse::Command& c) { Variable Apply(const Parse::Command& c) {
std::vector<Variable> args{}; Vector<Variable> args{};
Variable f = Eval(c[0]); Variable f = Eval(c[0]);
u32 i = 1; u32 i = 1;
@ -83,7 +83,7 @@ namespace NVL::Environment {
args.push_back(Eval(c[i++])); args.push_back(Eval(c[i++]));
} }
if (f.length != -1 && f.length != i - 1) throw std::runtime_error("Function arity mismatch"); if (f.length != -1 && f.length != i - 1) throw std::runtime_error("Function arity mismatch");
return std::get<std::function<Variable(std::vector<Variable>)>>(f.value)(args); return std::get<std::function<Variable(Vector<Variable>)>>(f.value)(args);
} }
void EvalScene(const Parse::Scene& s) { void EvalScene(const Parse::Scene& s) {
@ -92,23 +92,23 @@ namespace NVL::Environment {
} }
// Check MatchMarkup for more information // Check MatchMarkup for more information
MarkupString UnpackMarkupVariable(const std::vector<Variable>& v) { MarkupString UnpackMarkupVariable(const Vector<Variable>& v) {
MarkupString ms{}; MarkupString ms{};
for (const Variable& segment : v) { for (const Variable& segment : v) {
const auto& pair = std::get<std::vector<Variable>>(segment.value); const auto& pair = std::get<Vector<Variable>>(segment.value);
const String s = std::get<String>(pair[0].value); const String s = std::get<String>(pair[0].value);
std::vector<std::pair<String, std::vector<String>>> efs; Vector<std::pair<String, Vector<String>>> efs;
for (const Variable& combination : std::get<std::vector<Variable>>(pair[1].value)) { for (const Variable& combination : std::get<Vector<Variable>>(pair[1].value)) {
if (combination.type == Type::String) { if (combination.type == Type::String) {
const String ef = std::get<String>(combination.value); const String ef = std::get<String>(combination.value);
efs.push_back({ ef, {} }); efs.push_back({ ef, {} });
} }
else if (combination.type == Type::Array) { else if (combination.type == Type::Array) {
const std::vector<Variable>& ef_t = std::get<std::vector<Variable>>(combination.value); const Vector<Variable>& ef_t = std::get<Vector<Variable>>(combination.value);
const String& ef = std::get<String>(ef_t[0].value); const String& ef = std::get<String>(ef_t[0].value);
const std::vector<Variable>& args = std::get<std::vector<Variable>>(ef_t[1].value); const Vector<Variable>& args = std::get<Vector<Variable>>(ef_t[1].value);
std::vector<String> ss{}; Vector<String> ss{};
for (const auto& s : args) { ss.push_back(std::get<String>(s.value)); } for (const auto& s : args) { ss.push_back(std::get<String>(s.value)); }
efs.push_back({ ef, ss }); efs.push_back({ ef, ss });
} }

View file

@ -10,7 +10,7 @@ namespace NVL::Environment {
struct Variable { struct Variable {
Type type; Type type;
std::variant<Number, String, std::vector<Variable>, std::function<Variable(std::vector<Variable>)>> value; std::variant<Number, String, Vector<Variable>, std::function<Variable(Vector<Variable>)>> value;
// Most things will have length 1 (including string); this is mostly for function arity and array length // Most things will have length 1 (including string); this is mostly for function arity and array length
u32 length; u32 length;
bool operator==(const Variable& other) const; bool operator==(const Variable& other) const;
@ -18,8 +18,8 @@ namespace NVL::Environment {
Variable(Type t); // Reserved for Nil Variable(Type t); // Reserved for Nil
Variable(const Number& v); Variable(const Number& v);
Variable(const String& v); Variable(const String& v);
Variable(const std::vector<Variable>& v); Variable(const Vector<Variable>& v);
Variable(const std::function<Variable(std::vector<Variable>)>& v, u32 l); Variable(const std::function<Variable(Vector<Variable>)>& v, u32 l);
}; };
class Environment { class Environment {
@ -41,15 +41,15 @@ namespace NVL::Environment {
struct MarkupSegment { struct MarkupSegment {
String str; String str;
std::vector<std::pair<String, std::vector<String>>> efs; Vector<std::pair<String, Vector<String>>> efs;
}; };
struct MarkupString { struct MarkupString {
private: private:
mutable i32 mem_length = -1; mutable i32 mem_length = -1;
public: public:
std::vector<MarkupSegment> segments{}; Vector<MarkupSegment> segments{};
size_t length() const; size_t length() const;
MarkupString substr(size_t idx) const; MarkupString substr(size_t idx) const;
}; };
MarkupString UnpackMarkupVariable(const std::vector<Variable>& v); MarkupString UnpackMarkupVariable(const Vector<Variable>& v);
} }

View file

@ -125,8 +125,8 @@ namespace {
return to_NVL_string(buffer.str()); return to_NVL_string(buffer.str());
} }
std::vector<String> split_string_by_lines(const String& str) { Vector<String> split_string_by_lines(const String& str) {
std::vector<String> lines; Vector<String> lines;
size_t pos = 0; size_t pos = 0;
size_t prev = 0; size_t prev = 0;
while ((pos = str.find(NEWLINE, prev)) != String::npos) { while ((pos = str.find(NEWLINE, prev)) != String::npos) {
@ -230,7 +230,7 @@ namespace {
Parse::Object ParseArray(const String& f, size_t& pos, u32 layer) { Parse::Object ParseArray(const String& f, size_t& pos, u32 layer) {
SkipComments(f, pos); SkipComments(f, pos);
std::vector<Parse::Object> array{}; Vector<Parse::Object> array{};
array.push_back(ParseExpression(f, pos)); array.push_back(ParseExpression(f, pos));
while (PeekToken(f, pos)[0] != ARRAY_CLOSE) { while (PeekToken(f, pos)[0] != ARRAY_CLOSE) {
@ -246,7 +246,7 @@ namespace {
String ParseString(const String& f, size_t& pos) { String ParseString(const String& f, size_t& pos) {
SkipComments(f, pos); SkipComments(f, pos);
std::vector<size_t> discards{}; Vector<size_t> discards{};
auto start = ++pos; // skip opening quote auto start = ++pos; // skip opening quote
do { do {
if (f[pos] == QUOTE) { if (f[pos] == QUOTE) {
@ -352,7 +352,7 @@ namespace {
bool has_markup = false; bool has_markup = false;
// Match tags // Match tags
std::vector<Parse::Object> segments; Vector<Parse::Object> segments;
String::const_iterator tags_start(s.cbegin()); String::const_iterator tags_start(s.cbegin());
while (srell::regex_search(tags_start, s.cend(), tags_match, typer)) { while (srell::regex_search(tags_start, s.cend(), tags_match, typer)) {
has_markup = true; has_markup = true;
@ -361,13 +361,13 @@ namespace {
if (!before.empty()) if (!before.empty())
segments.push_back({ Parse::Type::Array, { segments.push_back({ Parse::Type::Array, {
{ Parse::Type::String, before }, { Parse::Type::String, before },
{ Parse::Type::Array, std::vector<Parse::Object>{} } { Parse::Type::Array, Vector<Parse::Object>{} }
}}); }});
String inner = tags_match[2].str(); // markupped String inner = tags_match[2].str(); // markupped
// Match markup options // Match markup options
std::vector<Parse::Object> effects{}; Vector<Parse::Object> effects{};
String::const_iterator effects_start(tags_match[1].first); String::const_iterator effects_start(tags_match[1].first);
while (srell::regex_search(effects_start, tags_match[1].second, effects_match, effect)) { while (srell::regex_search(effects_start, tags_match[1].second, effects_match, effect)) {
if (effects_match[3].matched) { // no params if (effects_match[3].matched) { // no params
@ -376,19 +376,19 @@ namespace {
else { // no params else { // no params
// Comma split // Comma split
std::vector<Parse::Object> args; Vector<Parse::Object> args;
String::const_iterator params_start(effects_match[2].first); String::const_iterator params_start(effects_match[2].first);
while (srell::regex_search(params_start, effects_match[2].second, params_match, param)) { while (srell::regex_search(params_start, effects_match[2].second, params_match, param)) {
size_t temp = 0; size_t temp = 0;
args.push_back(ParseExpression(params_match[1].str() + SEPARATOR.accept[0], temp)); // PeekToken will freak out if I don't do this args.push_back(ParseExpression(params_match[1].str() + SEPARATOR.accept[0], temp)); // PeekToken will freak out if I don't do this
params_start = params_match.suffix().first; params_start = params_match.suffix().first;
} }
effects.push_back({ Parse::Type::Array, std::vector<Parse::Object>{ { Parse::Type::String, effects_match[1].str() }, { Parse::Type::Array, args } } }); effects.push_back({ Parse::Type::Array, Vector<Parse::Object>{ { Parse::Type::String, effects_match[1].str() }, { Parse::Type::Array, args } } });
} }
effects_start = effects_match.suffix().first; effects_start = effects_match.suffix().first;
} }
tags_start = tags_match.suffix().first; tags_start = tags_match.suffix().first;
segments.push_back({ Parse::Type::Array, std::vector<Parse::Object>{ { Parse::Type::String, inner }, { Parse::Type::Array, effects } } }); segments.push_back({ Parse::Type::Array, Vector<Parse::Object>{ { Parse::Type::String, inner }, { Parse::Type::Array, effects } } });
} }
if (has_markup) { if (has_markup) {
@ -396,15 +396,15 @@ namespace {
if (!end.empty()) if (!end.empty())
segments.push_back({ Parse::Type::Array, { segments.push_back({ Parse::Type::Array, {
{ Parse::Type::String, end }, { Parse::Type::String, end },
{ Parse::Type::Array, std::vector<Parse::Object>{} } { Parse::Type::Array, Vector<Parse::Object>{} }
}}); }});
return { Parse::Type::Array, segments }; return { Parse::Type::Array, segments };
} }
else { else {
return { Parse::Type::Array, std::vector<Parse::Object>{ return { Parse::Type::Array, Vector<Parse::Object>{
{ Parse::Type::Array, { { Parse::Type::Array, {
{ Parse::Type::String, s} , { Parse::Type::Array, std::vector<Parse::Object>{} } { Parse::Type::String, s} , { Parse::Type::Array, Vector<Parse::Object>{} }
} } } } } }
}; };
} }
@ -489,7 +489,7 @@ namespace NVL::Parse {
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!"); if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
} }
Object::Object(Type t, const std::vector<Object>& v) : type(t), value(v) { Object::Object(Type t, const Vector<Object>& v) : type(t), value(v) {
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!"); if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
} }
@ -500,14 +500,14 @@ namespace NVL::Parse {
if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!"); if (t != Type::String && t != Type::Symbol) throw std::runtime_error("Bad type when constructing object!");
} }
Object::Object(Type t, std::vector<Object>&& v) : type(t), value(std::move(v)) { Object::Object(Type t, Vector<Object>&& v) : type(t), value(std::move(v)) {
if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!"); if (t != Type::Array && t != Type::Subexpression) throw std::runtime_error("Bad type when constructing object!");
} }
std::vector<Scene> ParseFile(const std::string& path) { Vector<Scene> ParseFile(const std::string& path) {
String f = read_file_to_string(path); String f = read_file_to_string(path);
std::vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses Vector<Scene> list {}; // Vector of scenes which each contain a vector of Parses
for (size_t i = 0; i < f.length(); i++) { for (size_t i = 0; i < f.length(); i++) {
list.push_back(ParseScene(f, i)); list.push_back(ParseScene(f, i));
} }

View file

@ -1,5 +1,4 @@
#pragma once #pragma once
#include <vector>
#include <variant> #include <variant>
#include <string> #include <string>
#include <utility> #include <utility>
@ -13,22 +12,22 @@ namespace NVL::Parse {
Object() = delete; Object() = delete;
Object(const Number& v); Object(const Number& v);
Object(Type t, const String& v); Object(Type t, const String& v);
Object(Type t, const std::vector<Object>& v); Object(Type t, const Vector<Object>& v);
Object(Number&& v); Object(Number&& v);
Object(Type t, String&& v); Object(Type t, String&& v);
Object(Type t, std::vector<Object>&& v); Object(Type t, Vector<Object>&& v);
Type type; Type type;
std::variant< std::variant<
Number, Number,
String, String,
std::vector<Object> Vector<Object>
> value; > value;
}; };
using Command = std::vector<Object>; using Command = Vector<Object>;
class Scene { class Scene {
std::vector<Command> commands{}; Vector<Command> commands{};
public: public:
String name; String name;
Scene(const String& name) : name(name) {} Scene(const String& name) : name(name) {}
@ -43,5 +42,5 @@ namespace NVL::Parse {
} }
}; };
std::vector<Scene> ParseFile(const std::string& path); Vector<Scene> ParseFile(const std::string& path);
} }