diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 6a2e36a..dd4f849 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,57 +1,57 @@ - - - + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 79ee123..307554b 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 79b3c94..f1c67df 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 427b63b..dc122c9 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + \ No newline at end of file diff --git a/.idea/sugar.iml b/.idea/sugar.iml index f08604b..6d70257 100644 --- a/.idea/sugar.iml +++ b/.idea/sugar.iml @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..9661ac7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3697459..6f8a3cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,11 @@ add_executable(sugar include/molasses/lexer.h src/molasses/parser_primitives.cpp include/molasses/parser_primitives.h - include/molasses/generator_primitives.h src/molasses/interpreter.cpp) + include/molasses/generator_primitives.h + src/molasses/interpreter.cpp + include/molasses/errors.h + include/molasses/parser_types.h + src/molasses/generator_primitives.cpp) function(add_expect_test [testname filename]) add_test( diff --git a/include/molasses/errors.h b/include/molasses/errors.h new file mode 100644 index 0000000..4c2d440 --- /dev/null +++ b/include/molasses/errors.h @@ -0,0 +1,85 @@ +#pragma once +#include "lexer.h" +#include +#include + + +namespace molasses { + namespace details { + template + std::string concatenate_builder_impl(std::stringstream& stream) + requires(sizeof...(RestT) == 0) + { + return stream.str(); + } + template + std::string concatenate_builder_impl(std::stringstream& stream, FirstT first, RestT... rest) { + stream << first; + return concatenate_builder_impl(stream, rest...); + } + template + std::string concatenate_builder(RestT... rest) { + std::stringstream stream{}; + return concatenate_builder_impl(stream, rest...); + } + } + + struct build_system_error : std::runtime_error { + explicit build_system_error(const std::string& message) + : std::runtime_error(message) {} + }; + + struct interpreter_error : std::runtime_error { + explicit interpreter_error(const std::string& message) + : std::runtime_error(message) {} + }; + + struct parser_error : public std::runtime_error { + explicit parser_error(const std::string& str) + : std::runtime_error(str) {} + }; + + struct type_input_error : public parser_error { + type_input_error() + : parser_error("Bad type provided") {} + // TODO: Better error message + }; + struct value_missing_error : public parser_error { + value_missing_error() + : parser_error("Expected value, none provided") {} + // TODO: Better error message + }; + struct procedure_stack_error : public parser_error { + procedure_stack_error() + : parser_error("Expected the stack to look like the return stack upon completion\n") {} + // TODO: Better error message + }; + struct unexpected_token_error : public parser_error { + unexpected_token_error(const symbol& sym, const std::string& found, const std::string& expected) + : parser_error(details::concatenate_builder( + "Unexpected token encountered\n", "\tAt ", sym.file_name, ":", sym.line, ":", sym.column, "\n", + "\tExpected ", expected, "\n", "\tFound ", found, "\n" + )) {} + }; + struct expecting_token_error : public parser_error { + expecting_token_error(const std::string& expected, const std::string& context) + : parser_error(details::concatenate_builder( + "An expected token has not been encountered before the end of the input\n", "\tExpected ", expected, + "\n", "\t", context, "\n" + )) {} + // TODO: Better error message + }; + struct unknown_token_error : public parser_error { + explicit unknown_token_error(const symbol& sym) + : parser_error(details::concatenate_builder( + "An unknown token has been encountered\n", "\tAt ", sym.file_name, ":", sym.line, ":", sym.column, + "\n" + )) {} + // TODO: Better error message + }; + struct type_expected_with_modifier_error : public parser_error { + type_expected_with_modifier_error() + : parser_error("A type is expected before a modifier") {} + // TODO: Better error message + }; +} \ No newline at end of file diff --git a/include/molasses/parser_primitives.h b/include/molasses/parser_primitives.h index 1d31abc..84a5c6f 100644 --- a/include/molasses/parser_primitives.h +++ b/include/molasses/parser_primitives.h @@ -13,6 +13,7 @@ #include #include "molasses/lexer.h" +#include "parser_types.h" enum class architecture_t { @@ -29,193 +30,11 @@ constexpr size_t architecture_ptr_size = 4; #endif namespace molasses { - namespace details { - template - std::string concatenate_builder_impl(std::stringstream& stream) - requires (sizeof...(RestT) == 0) - { - return stream.str(); - } - template - std::string concatenate_builder_impl(std::stringstream& stream, FirstT first, RestT... rest) { - stream << first; - return concatenate_builder_impl(stream, rest...); - } - template - std::string concatenate_builder(RestT... rest) { - std::stringstream stream{}; - return concatenate_builder_impl(stream, rest...); - } - } - - struct type { - [[nodiscard]] virtual std::string name() const = 0; - [[nodiscard]] virtual size_t byte_size() const = 0; - }; - - inline auto operator<=>(const type& lhs, const type& rhs) { - return lhs.name() <=> rhs.name(); - } - - struct primitive_type : public type { - std::string _name; - size_t _byte_size; - - primitive_type(std::string name, size_t byte_size) - : _name(std::forward(name)) - , _byte_size(byte_size) - {} - - [[nodiscard]] std::string name() const final { - return _name; - } - [[nodiscard]] size_t byte_size() const final { - return _byte_size; - }; - }; - - struct parser_context; - - struct ptr_type{ - void* ptr; - std::shared_ptr pointed; - }; - - using stack_element = std::variant; - - using interpreter_stack = std::stack; - - struct generate_context; - - struct operation { - [[nodiscard]] virtual std::string name() const = 0; - [[nodiscard]] virtual std::vector argument_types() const = 0; - [[nodiscard]] virtual std::vector return_types() const = 0; - [[nodiscard]] virtual std::vector generate(const parser_context&, const lexed_output& lexer_data) const = 0; - [[nodiscard]] virtual std::vector emit(const parser_context&) const = 0; - virtual void execute(const generate_context&, interpreter_stack&) const = 0; - }; - - struct primitive_operation : public operation { - std::string _name; - std::vector _args; - std::vector _rets; - std::vector _instructions; - std::function _executable; - - primitive_operation(std::string name, std::vector args, std::vector rets, std::vector body, std::function executable) - : _name(std::forward(name)) - , _args(std::forward>(args)) - , _rets(std::forward>(rets)) - , _instructions(std::forward>(body)) - , _executable(std::move(executable)) - {} - - [[nodiscard]] std::string name() const final { - return _name; - } - [[nodiscard]] std::vector argument_types() const final { - return _args; - } - [[nodiscard]] std::vector return_types() const final { - return _rets; - } - [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final { - return {}; - } - [[nodiscard]] std::vector emit(const parser_context&) const final { - return _instructions; - } - - void execute(const generate_context& ctx, interpreter_stack& stack) const override { - _executable(ctx, stack); - }; - }; - - struct procedure_operation : public operation { - std::string _name; - std::vector _args; - std::vector _rets; - std::vector _body; - - procedure_operation(std::string name, std::vector args, std::vector rets, std::vector body) - : _name(std::forward(name)) - , _args(std::forward>(args)) - , _rets(std::forward>(rets)) - , _body(std::forward>(body)) - {} - - [[nodiscard]] std::string name() const final { - return _name; - } - [[nodiscard]] std::vector argument_types() const final { - return _args; - } - [[nodiscard]] std::vector return_types() const final { - return _rets; - } - [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final; - [[nodiscard]] std::vector emit(const parser_context&) const final; - void execute(const generate_context&, interpreter_stack&) const final; - }; - - inline auto operator<=>(const operation& lhs, const operation& rhs) { - return lhs.name() <=> rhs.name(); - } - - struct parser_error : public std::runtime_error { - explicit parser_error(const std::string& str) : std::runtime_error(str) {} - }; - - struct type_input_error : public parser_error { - type_input_error() : parser_error("Bad type provided") {} - // TODO: Better error message - }; - struct value_missing_error : public parser_error { - value_missing_error() : parser_error("Expected value, none provided") {} - // TODO: Better error message - }; - struct procedure_stack_error : public parser_error { - procedure_stack_error() : parser_error("Expected the stack to look like the return stack upon completion\n") {} - // TODO: Better error message - }; - struct unexpected_token_error : public parser_error { - unexpected_token_error(const symbol& sym, const std::string& found, const std::string& expected) - : parser_error ( - details::concatenate_builder( - "Unexpected token encountered\n", - "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n", - "\tExpected ", expected, "\n", - "\tFound ", found, "\n" - ) - ) {} - }; - struct expecting_token_error : public parser_error { - expecting_token_error(const std::string& expected, const std::string& context) - : parser_error( - details::concatenate_builder( - "An expected token has not been encountered before the end of the input\n", - "\tExpected ", expected,"\n", - "\t", context,"\n" - ) - ) - {} - // TODO: Better error message - }; - struct unknown_token_error : public parser_error { - explicit unknown_token_error(const symbol& sym) : parser_error(details::concatenate_builder("An unknown token has been encountered\n", "\tAt ", sym.file_name,":",sym.line,":",sym.column,"\n")) {} - // TODO: Better error message - }; - struct type_expected_with_modifier_error : public parser_error { - type_expected_with_modifier_error() : parser_error("A type is expected before a modifier") {} - // TODO: Better error message - }; - std::vector operator>>(std::vector current_stack, const operation& next_op); - + std::optional try_parse_int32(const std::string& str); std::optional try_parse_int64(const std::string& str); - + struct parser_context { std::vector> types; std::vector> operations; @@ -235,6 +54,7 @@ namespace molasses { std::tuple>> interpret(interpreter_stack, generate_context, std::string ); + std::optional try_parse_int32(const std::string& str); generate_context parse(parser_context, const lexed_output&); std::vector generate(const generate_context&); diff --git a/include/molasses/parser_types.h b/include/molasses/parser_types.h new file mode 100644 index 0000000..7fce53f --- /dev/null +++ b/include/molasses/parser_types.h @@ -0,0 +1,126 @@ +#pragma once + +#include "lexer.h" +#include +#include +#include +#include +#include +#include +namespace molasses { + + struct type { + [[nodiscard]] virtual std::string name() const = 0; + [[nodiscard]] virtual size_t byte_size() const = 0; + }; + + inline auto operator<=>(const type& lhs, const type& rhs) { + return lhs.name() <=> rhs.name(); + } + + struct primitive_type : public type { + std::string _name; + size_t _byte_size; + + primitive_type(std::string name, size_t byte_size) + : _name(std::forward(name)) + , _byte_size(byte_size) + {} + + [[nodiscard]] std::string name() const final { + return _name; + } + [[nodiscard]] size_t byte_size() const final { + return _byte_size; + }; + }; + + struct parser_context; + + struct ptr_type{ + void* ptr; + std::shared_ptr pointed; + }; + + using stack_element = std::variant; + + using interpreter_stack = std::stack; + + struct generate_context; + + struct operation { + [[nodiscard]] virtual std::string name() const = 0; + [[nodiscard]] virtual std::vector argument_types() const = 0; + [[nodiscard]] virtual std::vector return_types() const = 0; + [[nodiscard]] virtual std::vector generate(const parser_context&, const lexed_output& lexer_data) const = 0; + [[nodiscard]] virtual std::vector emit(const parser_context&) const = 0; + virtual void execute(const generate_context&, interpreter_stack&) const = 0; + }; + + struct primitive_operation : public operation { + std::string _name; + std::vector _args; + std::vector _rets; + std::vector _instructions; + std::function _executable; + + primitive_operation(std::string name, std::vector args, std::vector rets, std::vector body, std::function executable) + : _name(std::forward(name)) + , _args(std::forward>(args)) + , _rets(std::forward>(rets)) + , _instructions(std::forward>(body)) + , _executable(std::move(executable)) + {} + + [[nodiscard]] std::string name() const final { + return _name; + } + [[nodiscard]] std::vector argument_types() const final { + return _args; + } + [[nodiscard]] std::vector return_types() const final { + return _rets; + } + [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final { + return {}; + } + [[nodiscard]] std::vector emit(const parser_context&) const final { + return _instructions; + } + + void execute(const generate_context& ctx, interpreter_stack& stack) const override { + _executable(ctx, stack); + }; + }; + + struct procedure_operation : public operation { + std::string _name; + std::vector _args; + std::vector _rets; + std::vector _body; + + procedure_operation(std::string name, std::vector args, std::vector rets, std::vector body) + : _name(std::forward(name)) + , _args(std::forward>(args)) + , _rets(std::forward>(rets)) + , _body(std::forward>(body)) + {} + + [[nodiscard]] std::string name() const final { + return _name; + } + [[nodiscard]] std::vector argument_types() const final { + return _args; + } + [[nodiscard]] std::vector return_types() const final { + return _rets; + } + [[nodiscard]] std::vector generate(const parser_context&, const lexed_output& lexer_data) const final; + [[nodiscard]] std::vector emit(const parser_context&) const final; + void execute(const generate_context&, interpreter_stack&) const final; + }; + + inline auto operator<=>(const operation& lhs, const operation& rhs) { + return lhs.name() <=> rhs.name(); + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 6c2a56d..b547f95 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include "molasses/lexer.h" #include "molasses/parser_primitives.h" +#include "molasses/errors.h" #include #include #include @@ -10,12 +11,6 @@ using compile_element = std::variant; -struct build_system_error : std::runtime_error { - explicit build_system_error(const std::string& message) - : std::runtime_error(message) - {} -}; - int main(int argc, char** argv) { std::vector arguments; while(argc > 1) { @@ -43,9 +38,9 @@ int main(int argc, char** argv) { } compile_stack.emplace(filename); } else - throw build_system_error("generate expects a parsed output\n"); + throw molasses::build_system_error("generate expects a parsed output\n"); } else - throw build_system_error("generate expects a filename\n"); + throw molasses::build_system_error("generate expects a filename\n"); } else if(elem == "parse") { molasses::parser_context ctx; ctx = molasses::register_integers(ctx); @@ -57,27 +52,27 @@ int main(int argc, char** argv) { auto generator = molasses::parse(ctx, lexer); compile_stack.emplace(generator); } else - throw build_system_error("parse expects a lexed output\n"); + throw molasses::build_system_error("parse expects a lexed output\n"); } else if(elem == "lex") { if(not compile_stack.empty() and std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); compile_stack.pop(); if(not std::filesystem::exists(filename)) - throw build_system_error("file " + filename + " does not exist\n"); + throw molasses::build_system_error("file " + filename + " does not exist\n"); std::ifstream t(filename); std::stringstream buffer; buffer << t.rdbuf(); auto lexed = molasses::lex(filename, buffer.str()); compile_stack.emplace(lexed); } else - throw build_system_error("lex expects a filename\n"); + throw molasses::build_system_error("lex expects a filename\n"); } else if(elem == "lex-all") { std::vector lexed_list; while(not compile_stack.empty() and std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); compile_stack.pop(); if(not std::filesystem::exists(filename)) - throw build_system_error("file " + filename + " does not exist\n"); + throw molasses::build_system_error("file " + filename + " does not exist\n"); std::ifstream t(filename); std::stringstream buffer; buffer << t.rdbuf(); @@ -96,9 +91,9 @@ int main(int argc, char** argv) { compile_stack.pop(); compile_stack.emplace(molasses::concatenate(lexer_1, lexer_2)); } else - throw build_system_error("merge expects 2 lexed outputs\n"); + throw molasses::build_system_error("merge expects 2 lexed outputs\n"); } else - throw build_system_error("merge expects 2 lexed outputs\n"); + throw molasses::build_system_error("merge expects 2 lexed outputs\n"); } else if(elem == "merge-all") { if(not compile_stack.empty() and std::holds_alternative(compile_stack.top())) { auto lexer_1 = std::get(compile_stack.top()); @@ -110,7 +105,7 @@ int main(int argc, char** argv) { } compile_stack.emplace(lexer_1); } else - throw build_system_error("merge-all expects at least 1 lexed outputs\n"); + throw molasses::build_system_error("merge-all expects at least 1 lexed outputs\n"); } else if(elem == "interpret") { if(not compile_stack.empty() and std::holds_alternative(compile_stack.top())) { auto context = std::get(compile_stack.top()); @@ -123,7 +118,7 @@ int main(int argc, char** argv) { molasses::interpret(stack, context, contents); } } else - throw build_system_error("merge-all expects at least 1 lexed outputs\n"); + throw molasses::build_system_error("interpreter expects 1 generated context\n"); } else if(elem == "assemble") { if(not compile_stack.empty() and std::holds_alternative(compile_stack.top())) { auto filename = std::get(compile_stack.top()); @@ -137,7 +132,7 @@ int main(int argc, char** argv) { std::cout << link.str() << std::endl; system(link.str().c_str()); } else - throw build_system_error("assemble expects an assembly file\n"); + throw molasses::build_system_error("assemble expects an assembly file\n"); } else if(elem == "help" or elem == "--help") { std::cout << "# Sugar\n\n"; std::cout << "## Commands\n\n"; @@ -202,7 +197,7 @@ int main(int argc, char** argv) { } catch (molasses::parser_error& error) { std::cerr << "COMPILER ERROR:\n" << error.what(); return 1; - } catch (build_system_error& error) { + } catch (molasses::build_system_error& error) { std::cerr << "BUILD SYSTEM ERROR:\n" << error.what(); return 1; } diff --git a/src/molasses/generator_primitives.cpp b/src/molasses/generator_primitives.cpp new file mode 100644 index 0000000..eecb4f2 --- /dev/null +++ b/src/molasses/generator_primitives.cpp @@ -0,0 +1,16 @@ + +#include "molasses/parser_primitives.h" +namespace molasses { + parser_context register_integers(parser_context ctx) { + ctx.types.push_back(std::make_shared("i8", 1)); + ctx.types.push_back(std::make_shared("i16", 2)); + ctx.types.push_back(std::make_shared("i32", 4)); + ctx.types.push_back(std::make_shared("i64", 8)); + ctx.types.push_back(std::make_shared("u8", 1)); + ctx.types.push_back(std::make_shared("u16", 2)); + ctx.types.push_back(std::make_shared("u32", 4)); + ctx.types.push_back(std::make_shared("u64", 8)); + + return ctx; + } +} \ No newline at end of file diff --git a/src/molasses/generator_primitives_x86_64_linux.cpp b/src/molasses/generator_primitives_x86_64_linux.cpp index 7a14128..6b2cca8 100644 --- a/src/molasses/generator_primitives_x86_64_linux.cpp +++ b/src/molasses/generator_primitives_x86_64_linux.cpp @@ -1,5 +1,6 @@ #include "molasses/parser_primitives.h" #include "molasses/generator_primitives.h" +#include "molasses/errors.h" namespace molasses { @@ -117,21 +118,6 @@ namespace molasses { return builder.str(); } - // TODO: move to a platform independent file - parser_context register_integers(parser_context ctx) - { - ctx.types.push_back(std::make_shared("i8", 1)); - ctx.types.push_back(std::make_shared("i16", 2)); - ctx.types.push_back(std::make_shared("i32", 4)); - ctx.types.push_back(std::make_shared("i64", 8)); - ctx.types.push_back(std::make_shared("u8", 1)); - ctx.types.push_back(std::make_shared("u16", 2)); - ctx.types.push_back(std::make_shared("u32", 4)); - ctx.types.push_back(std::make_shared("u64", 8)); - - return ctx; - } - template<> parser_context register_i32_operations(parser_context ctx) { ctx.operations.emplace_back( @@ -150,7 +136,7 @@ namespace molasses { auto value_a = current_stack.top();current_stack.pop(); auto value_b = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value_a) or not std::holds_alternative(value_b)) { - // TODO: handle errors + throw interpreter_error("+ expects i32 i32 as input"); } current_stack.emplace(get(value_a) + get(value_b)); } @@ -171,7 +157,7 @@ namespace molasses { auto value_a = current_stack.top();current_stack.pop(); auto value_b = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value_a) or not std::holds_alternative(value_b)) { - // TODO: handle errors + throw interpreter_error("+_i64 expects i64 i64 as input"); } current_stack.emplace(get(value_a) + get(value_b)); } @@ -194,7 +180,9 @@ namespace molasses { auto value_a = current_stack.top();current_stack.pop(); auto value_b = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value_a) or not std::holds_alternative(value_b)) { - // TODO: handle errors + throw interpreter_error("/%_i64 expects i64 i64 as input"); + } else if(get(value_b) == 0) { + throw interpreter_error("/%_i64 division by zero"); } current_stack.emplace(get(value_a) / get(value_b)); current_stack.emplace(get(value_a) % get(value_b)); @@ -211,7 +199,7 @@ namespace molasses { [](const generate_context&, interpreter_stack& current_stack){ auto value = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value) && not (get(value).pointed->name() == "u8 ptr")) { - // TODO: handle errors + throw interpreter_error("u8-ptr_to_i64 expects u8 ptr as input"); } current_stack.emplace(intptr_t(get(value).ptr)); } @@ -233,7 +221,7 @@ namespace molasses { auto value_a = current_stack.top();current_stack.pop(); auto value_b = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value_a) or not std::holds_alternative(value_b)) { - // TODO: handle errors + throw interpreter_error("* expects i32 i32 as input"); } current_stack.emplace(get(value_a) * get(value_b)); } @@ -255,7 +243,7 @@ namespace molasses { auto value_a = current_stack.top();current_stack.pop(); auto value_b = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value_a) or not std::holds_alternative(value_b)) { - // TODO: handle errors + throw interpreter_error("- expects i32 i32 as input"); } current_stack.emplace(get(value_a) - get(value_b)); } @@ -274,7 +262,7 @@ namespace molasses { [](const generate_context&, interpreter_stack& current_stack){ auto value = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value)) { - // TODO: handle errors + throw interpreter_error("i32-to-i64 expects i32 as input"); } current_stack.emplace(int64_t(get(value))); } @@ -292,7 +280,7 @@ namespace molasses { [](const generate_context&, interpreter_stack& current_stack){ auto value = current_stack.top();current_stack.pop(); if(not std::holds_alternative(value)) { - // TODO: handle errors + throw interpreter_error("i32-to-i64 expects i32 as input"); } } ) @@ -316,7 +304,7 @@ namespace molasses { not std::holds_alternative(value_0) or not std::holds_alternative(value_1) ) { - // TODO: handle errors + throw interpreter_error("syscall1 expects i64 i64 as input"); } #ifdef linux unix_system::syscall1{}(get(value_0), get(value_1)); @@ -345,7 +333,7 @@ namespace molasses { not std::holds_alternative(value_1) or not std::holds_alternative(value_2) ) { - // TODO: handle errors + throw interpreter_error("syscall2 expects i64 i64 i64 as input"); } #ifdef linux unix_system::syscall2{}(get(value_0), get(value_1), get(value_2)); @@ -377,7 +365,7 @@ namespace molasses { not std::holds_alternative(value_2) or not std::holds_alternative(value_3) ) { - // TODO: handle errors + throw interpreter_error("syscall3 expects i64 i64 i64 i64 as input"); } #ifdef linux unix_system::syscall3{}(get(value_0), get(value_1), get(value_2), get(value_3)); @@ -412,7 +400,7 @@ namespace molasses { not std::holds_alternative(value_3) or not std::holds_alternative(value_4) ) { - // TODO: handle errors + throw interpreter_error("syscall4 expects i64 i64 i64 i64 i64 as input"); } #ifdef linux unix_system::syscall4{}(get(value_0), get(value_1), get(value_2), get(value_3), get(value_4)); @@ -450,7 +438,7 @@ namespace molasses { not std::holds_alternative(value_4) or not std::holds_alternative(value_5) ) { - // TODO: handle errors + throw interpreter_error("syscall5 expects i64 i64 i64 i64 i64 i64 as input"); } #ifdef linux unix_system::syscall5{}(get(value_0), get(value_1), get(value_2), get(value_3), get(value_4), get(value_5)); @@ -491,7 +479,7 @@ namespace molasses { not std::holds_alternative(value_5) or not std::holds_alternative(value_6) ) { - // TODO: handle errors + throw interpreter_error("syscall6 expects i64 i64 i64 i64 i64 i64 i64 as input"); } #ifdef linux unix_system::syscall6{}( diff --git a/src/molasses/parser_primitives.cpp b/src/molasses/parser_primitives.cpp index 43daa23..cf3da20 100644 --- a/src/molasses/parser_primitives.cpp +++ b/src/molasses/parser_primitives.cpp @@ -2,6 +2,7 @@ #include #include "molasses/parser_primitives.h" #include "molasses/generator_primitives.h" +#include "molasses/errors.h" namespace molasses { std::vector operator>>(std::vector current_stack, const operation& next_op) { @@ -299,7 +300,17 @@ namespace molasses { } void procedure_operation::execute(const generate_context& ctx, interpreter_stack& stack) const { + for(const auto& elem : _body) { + if(auto n = ctx.parser.lookup_operation(ctx.lexer.dictionary.at(elem)); n) + n->execute(ctx, stack); + else if(auto maybe_i64 = try_parse_int64(ctx.lexer.dictionary.at(elem)); maybe_i64) + stack.emplace(int64_t(maybe_i64.value())); + else if(auto maybe_i32 = try_parse_int32(ctx.lexer.dictionary.at(elem)); maybe_i32) + stack.emplace(int32_t(maybe_i32.value())); + else + std::cerr << "OPERATION NOT FOUND: " << elem <<"\n"; + } } }