Skip to content

Commit 16259e6

Browse files
committed
Language: MetaCircularVirtualMachine
1 parent 6c53467 commit 16259e6

12 files changed

Lines changed: 273 additions & 272 deletions

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,8 @@
5555
- [`CSV Mapping`](modules/Language/CSV/Mapping.mpp) - Type-safe CSV to struct mapping with support for custom conversion functions
5656
- [`CLikeCompiler`](modules/Language/CLikeCompiler.mpp) - Compiler for C-inspired language
5757
- [`GrammarParser`](modules/Language/GrammarParser.mpp) - A parser for defining and interpreting custom grammars, used for building language parsers
58-
- [`MetaCircularEvaluator`](modules/Language/MetaCircularEvaluator.mpp) - Homoiconic meta-circular evaluator with extensible reflexivity
59-
- [`MetaCircularArithmetic`](modules/Language/MetaCircularArithmetic.mpp) - Extension of `MetaCircularEvaluator` providing basic arithmetic operations (+, -, *, /, %)
60-
- [`MetaCircularParser`](modules/Language/MetaCircularParser.mpp) - Extension of `MetaCircularArithmetic` for building parsers with input stream reading capabilities
58+
- [`MetaCircularVirtualMachine`](modules/Language/MetaCircularVirtualMachine.mpp) - Homoiconic meta-circular virtual machine with extensible reflexivity
59+
- [`MetaCircularParser`](modules/Language/MetaCircularParser.mpp) - Extension of `MetaCircularVirtualMachine` for building parsers with input stream reading capabilities
6160
- [`ASTParser`](modules/Language/ASTParser.mpp) - AST parser (work in progress <img src="resources/loading.gif" width="12" height="12"/>)
6261
- [`VirtualMachine`](modules/Language/VirtualMachine.mpp) - Generic virtual machine
6362

modules/Language/ASTParser.mpp

Lines changed: 47 additions & 47 deletions
Large diffs are not rendered by default.

modules/Language/Language.mpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ export import CppUtils.Language.AST;
44
export import CppUtils.Language.ASTParser;
55
export import CppUtils.Language.GrammarParser;
66
export import CppUtils.Language.VirtualMachine;
7-
export import CppUtils.Language.MetaCircularArithmetic;
8-
export import CppUtils.Language.MetaCircularEvaluator;
7+
export import CppUtils.Language.MetaCircularVirtualMachine;
98
export import CppUtils.Language.MetaCircularParser;
109
export import CppUtils.Language.CSV.Mapping;
1110
export import CppUtils.Language.CSV.Parsing;

modules/Language/MetaCircularArithmetic.mpp

Lines changed: 0 additions & 45 deletions
This file was deleted.

modules/Language/MetaCircularParser.mpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
export module CppUtils.Language.MetaCircularParser;
22

33
import std;
4-
import CppUtils.Language.MetaCircularArithmetic;
4+
import CppUtils.Language.MetaCircularVirtualMachine;
55
import CppUtils.String;
66
import CppUtils.Type;
77

88
export namespace CppUtils::Language
99
{
1010
template<String::StringView Source>
11-
struct MetaCircularParser: public MetaCircularArithmetic
11+
struct MetaCircularParser: public MetaCircularVirtualMachine
1212
{
1313
Source source;
1414

modules/Language/MetaCircularEvaluator.mpp renamed to modules/Language/MetaCircularVirtualMachine.mpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export module CppUtils.Language.MetaCircularEvaluator;
1+
export module CppUtils.Language.MetaCircularVirtualMachine;
22

33
import std;
44
import CppUtils.Container.MeshNetwork;
@@ -12,7 +12,7 @@ export namespace CppUtils::Language
1212
{
1313
namespace v1
1414
{
15-
struct MetaCircularEvaluator
15+
struct MetaCircularVirtualMachine
1616
{
1717
using Cursor = String::Cursor<std::string_view>;
1818

@@ -70,7 +70,7 @@ export namespace CppUtils::Language
7070
return scopes.back().get();
7171
}
7272

73-
std::unordered_map<Type::Token, std::function<std::expected<void, std::string_view>(Cursor&, const ASTNode&, MetaCircularEvaluator&)>> functions;
73+
std::unordered_map<Type::Token, std::function<std::expected<void, std::string_view>(Cursor&, const ASTNode&, MetaCircularVirtualMachine&)>> functions;
7474
ASTNode rootAst = {0uz, {ASTNode{Type::hash("main")}}};
7575
std::vector<std::reference_wrapper<ASTNode>> scopes = {std::ref(rootAst)};
7676
bool exit = false;
@@ -79,36 +79,65 @@ export namespace CppUtils::Language
7979

8080
inline namespace v2
8181
{
82-
struct MetaCircularEvaluator
82+
struct MetaCircularVirtualMachine
8383
{
8484
using MeshNodePtr = Container::MeshNodePtr<Type::Token, Type::Token>;
8585

8686
MeshNodePtr context = MeshNodePtr::makeRoot(0uz);
87-
std::unordered_map<Type::Token, std::function<std::expected<void, std::string_view>(MetaCircularEvaluator&, MeshNodePtr)>> functions;
87+
std::unordered_map<Type::Token, std::function<std::expected<void, std::string_view>(MetaCircularVirtualMachine&, MeshNodePtr)>> functions;
8888
Thread::ThreadPool threadPool;
8989
std::size_t instructionPosition = 0;
9090

91-
template<class T = MetaCircularEvaluator>
91+
template<class T = MetaCircularVirtualMachine>
9292
inline auto addFunction(Type::Token token, auto&& function) -> void
9393
{
9494
using namespace String::Literals;
9595

9696
if (not functions.contains(token))
9797
{
98-
functions[token] = [function = std::forward<decltype(function)>(function)](MetaCircularEvaluator& interpreter, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
98+
functions[token] = [function = std::forward<decltype(function)>(function)](MetaCircularVirtualMachine& interpreter, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
9999
return function(static_cast<T&>(interpreter), instruction);
100100
};
101101
if (not context.contains(token))
102102
context[token] >> MeshNodePtr::make(token);
103103
}
104104
}
105105

106-
inline MetaCircularEvaluator()
106+
template<String::FixedString Name>
107+
static auto arithmeticOperation(auto&& operation)
108+
{
109+
return [operation = std::forward<decltype(operation)>(operation)](MetaCircularVirtualMachine&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
110+
using namespace String::Literals;
111+
112+
static constexpr auto lhsError = Name + ": Missing lhs";
113+
static constexpr auto rhsError = Name + ": Missing rhs";
114+
static constexpr auto resultError = Name + ": Missing result";
115+
116+
auto lhs = instruction.at("lhs"_token).and_then([](auto branch) { return branch.front(); });
117+
if (not lhs)
118+
return std::unexpected{static_cast<std::string_view>(lhsError)};
119+
120+
auto rhs = instruction.at("rhs"_token).and_then([](auto branch) { return branch.front(); });
121+
if (not rhs)
122+
return std::unexpected{static_cast<std::string_view>(rhsError)};
123+
124+
auto result = instruction.at("result"_token).and_then([](auto branch) { return branch.front(); });
125+
if (not result)
126+
return std::unexpected{static_cast<std::string_view>(resultError)};
127+
128+
const auto lhsValue = lhs->getValue().value();
129+
const auto rhsValue = rhs->getValue().value();
130+
result->setValue(operation(lhsValue, rhsValue));
131+
return {};
132+
};
133+
}
134+
135+
inline MetaCircularVirtualMachine()
107136
{
108137
using namespace std::literals;
109138
using namespace String::Literals;
110139

111-
addFunction("define"_token, [](MetaCircularEvaluator&, MeshNodePtr instruction) {
140+
addFunction("define"_token, [](MetaCircularVirtualMachine&, MeshNodePtr instruction) {
112141
return instruction.at("value"_token)
113142
.and_then([](auto valueBranch) { return valueBranch.back(); })
114143
.and_then([&instruction](auto valueNode) {
@@ -121,7 +150,7 @@ export namespace CppUtils::Language
121150
});
122151
});
123152

124-
addFunction("jump"_token, [](MetaCircularEvaluator& interpreter, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
153+
addFunction("jump"_token, [](MetaCircularVirtualMachine& interpreter, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
125154
auto conditionNode = instruction.at("condition"_token).and_then([](auto branch) { return branch.front(); });
126155
if (conditionNode and conditionNode->getValue().value() == 0)
127156
return {};
@@ -134,12 +163,12 @@ export namespace CppUtils::Language
134163
return {};
135164
});
136165

137-
addFunction("return"_token, [](MetaCircularEvaluator& interpreter, MeshNodePtr) -> std::expected<void, std::string_view> {
166+
addFunction("return"_token, [](MetaCircularVirtualMachine& interpreter, MeshNodePtr) -> std::expected<void, std::string_view> {
138167
interpreter.instructionPosition = std::numeric_limits<std::size_t>::max() - 1;
139168
return {};
140169
});
141170

142-
addFunction("link"_token, [](MetaCircularEvaluator&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
171+
addFunction("link"_token, [](MetaCircularVirtualMachine&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
143172
return instruction.at("source"_token).and_then([&](auto sources) {
144173
return instruction.at("branch"_token).and_then([&](auto branches) -> std::expected<void, std::string_view> {
145174
for (auto branch : branches)
@@ -156,7 +185,7 @@ export namespace CppUtils::Language
156185
});
157186
});
158187

159-
addFunction("unlink"_token, [](MetaCircularEvaluator&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
188+
addFunction("unlink"_token, [](MetaCircularVirtualMachine&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
160189
auto sourcesBranch = instruction.at("source"_token);
161190
if (not sourcesBranch)
162191
return std::unexpected{"unlink: Missing source"sv};
@@ -178,7 +207,7 @@ export namespace CppUtils::Language
178207
return {};
179208
});
180209

181-
addFunction("=="_token, [](MetaCircularEvaluator&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
210+
addFunction("=="_token, [](MetaCircularVirtualMachine&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
182211
auto lhs = instruction.at("lhs"_token).and_then([](auto branch) { return branch.front(); });
183212
if (not lhs)
184213
return std::unexpected{"==: Missing lhs"sv};
@@ -197,7 +226,7 @@ export namespace CppUtils::Language
197226
return {};
198227
});
199228

200-
addFunction("not"_token, [](MetaCircularEvaluator&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
229+
addFunction("not"_token, [](MetaCircularVirtualMachine&, MeshNodePtr instruction) -> std::expected<void, std::string_view> {
201230
auto value = instruction.at("value"_token).and_then([](auto branch) { return branch.front(); });
202231
if (not value)
203232
return std::unexpected{"not: Missing value"sv};
@@ -206,9 +235,16 @@ export namespace CppUtils::Language
206235
value->setValue(result);
207236
return {};
208237
});
238+
239+
addFunction("+"_token, arithmeticOperation<"+">(std::plus<>{}));
240+
addFunction("-"_token, arithmeticOperation<"-">(std::minus<>{}));
241+
addFunction("*"_token, arithmeticOperation<"*">(std::multiplies<>{}));
242+
addFunction("/"_token, arithmeticOperation<"/">(std::divides<>{}));
243+
addFunction("%"_token, arithmeticOperation<"%">(std::modulus<>{}));
244+
addFunction("<"_token, arithmeticOperation<"<">(std::less<>{}));
209245
}
210246

211-
virtual ~MetaCircularEvaluator() = default;
247+
virtual ~MetaCircularVirtualMachine() = default;
212248

213249
[[nodiscard]] inline auto get(Type::Token token) -> std::expected<MeshNodePtr, std::string_view>
214250
{

modules/String/Utility.mpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,37 @@ export namespace CppUtils::String
192192
return string | std::ranges::views::split(separator) | std::ranges::to<std::vector<std::string>>();
193193
}
194194

195+
template<std::size_t Size>
196+
struct FixedString final
197+
{
198+
char data[Size]{};
199+
200+
constexpr FixedString(const char (&string)[Size]) noexcept
201+
{
202+
std::copy_n(string, Size, data);
203+
}
204+
205+
template<std::size_t OtherSize>
206+
[[nodiscard]] constexpr auto operator+(const char (&other)[OtherSize]) const noexcept -> FixedString<Size + OtherSize - 1>
207+
{
208+
char result[Size + OtherSize - 1]{};
209+
std::copy_n(data, Size - 1, result);
210+
std::copy_n(other, OtherSize, result + Size - 1);
211+
return result;
212+
}
213+
214+
[[nodiscard]] constexpr operator std::string_view() const noexcept
215+
{
216+
return {data, Size - 1};
217+
}
218+
};
219+
220+
template<std::size_t Size>
221+
FixedString(const char (&)[Size]) -> FixedString<Size>;
222+
223+
static_assert(std::string_view{FixedString{"foo"}} == "foo");
224+
static_assert(std::string_view{FixedString{"foo"} + "bar"} == "foobar");
225+
195226
[[nodiscard]] inline constexpr auto excelColumnToPosition(std::string_view excelColumn) noexcept -> std::size_t
196227
{
197228
auto base = 26uz;

tests/Language/ASTParser.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace CppUtils::UnitTest::Language::ASTParser
77
{
88
auto _ = TestSuite{
99
"Language/ASTParser",
10-
{"Logger", "Container/Tree", "Language/MetaCircularEvaluator"},
10+
{"Logger", "Container/Tree", "Language/MetaCircularVirtualMachine"},
1111
[](TestSuite& suite) {
1212
using namespace std::literals;
1313
using namespace CppUtils::String::Literals;

0 commit comments

Comments
 (0)