diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..b4a50f4
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,213 @@
+Language: Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: BlockIndent
+AlignArrayOfStructures: None
+AlignConsecutiveAssignments:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: true
+AlignConsecutiveBitFields:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignConsecutiveDeclarations:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignConsecutiveMacros:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ PadOperators: false
+AlignEscapedNewlines: Right
+AlignOperands: DontAlign
+AlignTrailingComments: true
+AllowAllArgumentsOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortEnumsOnASingleLine: true
+AllowShortBlocksOnASingleLine: Empty
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortLambdasOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: WithoutElse
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: Yes
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ AfterExternBlock: false
+ BeforeCatch: false
+ BeforeElse: false
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: Always
+BreakBeforeBraces: Attach
+BreakBeforeInheritanceComma: false
+BreakInheritanceList: BeforeColon
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeComma
+BreakAfterJavaFieldAnnotations: false
+BreakArrays: true
+BreakStringLiterals: true
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+QualifierAlignment: Leave
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DeriveLineEnding: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+PackConstructorInitializers: BinPack
+BasedOnStyle: ''
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+AllowAllConstructorInitializersOnNextLine: true
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseLabels: true
+IndentCaseBlocks: false
+IndentGotoLabels: true
+IndentPPDirectives: BeforeHash
+IndentExternBlock: AfterExternBlock
+IndentRequiresClause: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+InsertBraces: false
+InsertTrailingCommas: None
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+LambdaBodyIndentation: Signature
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: All
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PenaltyIndentedWhitespace: 0
+PointerAlignment: Left
+PPIndentWidth: -1
+ReferenceAlignment: Pointer
+ReflowComments: false
+RemoveBracesLLVM: false
+RequiresClausePosition: OwnLine
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SortIncludes: CaseSensitive
+SortJavaStaticImport: Before
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: Never
+SpaceBeforeParensOptions:
+ AfterControlStatements: false
+ AfterForeachMacros: false
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: false
+ AfterOverloadedOperator: false
+ AfterRequiresInClause: false
+ AfterRequiresInExpression: false
+ BeforeNonEmptyParentheses: false
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyBlock: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 0
+SpacesInAngles: Never
+SpacesInConditionalStatement: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpaceBeforeSquareBrackets: false
+BitFieldColonSpacing: Both
+Standard: c++20
+StatementAttributeLikeMacros:
+ - Q_EMIT
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 4
+UseCRLF: false
+UseTab: Never
+WhitespaceSensitiveMacros:
+ - STRINGIZE
+ - PP_STRINGIZE
+ - BOOST_PP_STRINGIZE
+ - NS_SWIFT_NAME
+ - CF_SWIFT_NAME
\ No newline at end of file
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..120a956
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,172 @@
+---
+InheritParentConfig: false
+Checks: '-*,
+bugprone-argument-comment,
+bugprone-assert-side-effect,
+bugprone-bad-signal-to-kill-thread,
+bugprone-branch-clone,
+bugprone-copy-constructor-init,
+bugprone-dangling-handle,
+bugprone-dynamic-static-initializers,
+bugprone-fold-init-type,
+bugprone-forward-declaration-namespace,
+bugprone-forwarding-reference-overload,
+bugprone-inaccurate-erase,
+bugprone-incorrect-roundings,
+bugprone-integer-division,
+bugprone-lambda-function-name,
+bugprone-macro-parentheses,
+bugprone-macro-repeated-side-effects,
+bugprone-misplaced-operator-in-strlen-in-alloc,
+bugprone-misplaced-pointer-arithmetic-in-alloc,
+bugprone-misplaced-widening-cast,
+bugprone-move-forwarding-reference,
+bugprone-multiple-statement-macro,
+bugprone-no-escape,
+bugprone-not-null-terminated-result,
+bugprone-parent-virtual-call,
+bugprone-posix-return,
+bugprone-reserved-identifier,
+bugprone-sizeof-container,
+bugprone-sizeof-expression,
+bugprone-spuriously-wake-up-functions,
+bugprone-string-constructor,
+bugprone-string-integer-assignment,
+bugprone-string-literal-with-embedded-nul,
+bugprone-suspicious-enum-usage,
+bugprone-suspicious-include,
+bugprone-suspicious-memory-comparison,
+bugprone-suspicious-memset-usage,
+bugprone-suspicious-missing-comma,
+bugprone-suspicious-semicolon,
+bugprone-suspicious-string-compare,
+bugprone-swapped-arguments,
+bugprone-terminating-continue,
+bugprone-throw-keyword-missing,
+bugprone-too-small-loop-variable,
+bugprone-undefined-memory-manipulation,
+bugprone-undelegated-constructor,
+bugprone-unhandled-self-assignment,
+bugprone-unused-raii,
+bugprone-unused-return-value,
+bugprone-use-after-move,
+bugprone-virtual-near-miss,
+cert-dcl21-cpp,
+cert-dcl58-cpp,
+cert-err34-c,
+cert-err52-cpp,
+cert-err60-cpp,
+cert-flp30-c,
+cert-msc50-cpp,
+cert-msc51-cpp,
+cert-str34-c,
+cppcoreguidelines-interfaces-global-init,
+cppcoreguidelines-narrowing-conversions,
+cppcoreguidelines-pro-type-member-init,
+cppcoreguidelines-pro-type-static-cast-downcast,
+cppcoreguidelines-slicing,
+google-default-arguments,
+google-explicit-constructor,
+google-runtime-operator,
+hicpp-exception-baseclass,
+hicpp-multiway-paths-covered,
+misc-misplaced-const,
+misc-new-delete-overloads,
+misc-no-recursion,
+misc-non-copyable-objects,
+misc-throw-by-value-catch-by-reference,
+misc-unconventional-assign-operator,
+misc-uniqueptr-reset-release,
+modernize-avoid-bind,
+modernize-concat-nested-namespaces,
+modernize-deprecated-headers,
+modernize-deprecated-ios-base-aliases,
+modernize-loop-convert,
+modernize-make-shared,
+modernize-make-unique,
+modernize-pass-by-value,
+modernize-raw-string-literal,
+modernize-redundant-void-arg,
+modernize-replace-auto-ptr,
+modernize-replace-disallow-copy-and-assign-macro,
+modernize-replace-random-shuffle,
+modernize-return-braced-init-list,
+modernize-shrink-to-fit,
+modernize-unary-static-assert,
+modernize-use-auto,
+modernize-use-bool-literals,
+modernize-use-emplace,
+modernize-use-equals-default,
+modernize-use-equals-delete,
+modernize-use-nodiscard,
+modernize-use-noexcept,
+modernize-use-nullptr,
+modernize-use-override,
+modernize-use-transparent-functors,
+modernize-use-uncaught-exceptions,
+mpi-buffer-deref,
+mpi-type-mismatch,
+openmp-use-default-none,
+performance-faster-string-find,
+performance-for-range-copy,
+performance-implicit-conversion-in-loop,
+performance-inefficient-algorithm,
+performance-inefficient-string-concatenation,
+performance-inefficient-vector-operation,
+performance-move-const-arg,
+performance-move-constructor-init,
+performance-no-automatic-move,
+performance-noexcept-move-constructor,
+performance-trivially-destructible,
+performance-type-promotion-in-math-fn,
+performance-unnecessary-copy-initialization,
+performance-unnecessary-value-param,
+portability-simd-intrinsics,
+readability-avoid-const-params-in-decls,
+readability-const-return-type,
+readability-container-size-empty,
+readability-convert-member-functions-to-static,
+readability-delete-null-pointer,
+readability-deleted-default,
+readability-inconsistent-declaration-parameter-name,
+readability-make-member-function-const,
+readability-misleading-indentation,
+readability-misplaced-array-index,
+readability-non-const-parameter,
+readability-redundant-control-flow,
+readability-redundant-declaration,
+readability-identifier-naming,
+readability-redundant-function-ptr-dereference,
+readability-redundant-smartptr-get,
+readability-redundant-string-cstr,
+readability-redundant-string-init,
+readability-simplify-subscript-expr,
+readability-static-accessed-through-instance,
+readability-static-definition-in-anonymous-namespace,
+readability-string-compare,
+readability-uniqueptr-delete-release,
+readability-use-anyofallof'
+CheckOptions:
+ - {key: readability-identifier-naming.NamespaceCase, value: lower_case }
+ - {key: readability-identifier-naming.AbstractClassCase, value: lower_case }
+ - {key: readability-identifier-naming.ClassCase, value: lower_case }
+ - {key: readability-identifier-naming.ClassMemberCase, value: lower_case }
+ - {key: readability-identifier-naming.ClassMethodCase, value: lower_case }
+ - {key: readability-identifier-naming.ClassConstantCase, value: lower_case }
+ - {key: readability-identifier-naming.ConstantParameterCase, value: lower_case }
+ - {key: readability-identifier-naming.ConstantMemberCase, value: lower_case }
+ - {key: readability-identifier-naming.ConstexprFunctionCase, value: lower_case }
+ - {key: readability-identifier-naming.ConstantPointerParameterCase, value: lower_case }
+ - {key: readability-identifier-naming.TemplateParameterCase, value: CamelCase }
+ - {key: readability-identifier-naming.VirtualMethodCase, value: lower_case }
+ - {key: readability-identifier-naming.TypedefCase, value: lower_case }
+ - {key: readability-identifier-naming.StructCase, value: lower_case }
+ - {key: readability-identifier-naming.FunctionCase, value: lower_case }
+ - {key: readability-identifier-naming.MethodCase, value: lower_case }
+ - {key: readability-identifier-naming.MemberCase, value: lower_case }
+ - {key: readability-identifier-naming.ParameterCase, value: lower_case }
+ - {key: readability-identifier-naming.VariableCase, value: lower_case }
+ - {key: readability-identifier-naming.LocalVariableCase, value: lower_case }
+ - {key: readability-identifier-naming.GlobalConstantCase, value: lower_case }
+ - {key: readability-identifier-naming.ConstexprVariableCase, value: lower_case }
+ - {key: readability-identifier-naming.EnumConstantCase, value: lower_case }
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..fdd45d5
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..0913834
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d0bc7d..fc330bb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,4 +7,11 @@ set(CMAKE_CXX_STANDARD 20)
include_directories(include)
-add_executable(sugar src/main.cpp src/molasses/lexer.cpp src/molasses/generator_primitives_x86_64_linux.cpp include/molasses/lexer.h src/molasses/parser_primitives.cpp include/molasses/parser_primitives.h include/molasses/generator_primitives.h)
+add_executable(sugar
+ src/main.cpp
+ src/molasses/lexer.cpp
+ src/molasses/generator_primitives_x86_64_linux.cpp
+ include/molasses/lexer.h
+ src/molasses/parser_primitives.cpp
+ include/molasses/parser_primitives.h
+ include/molasses/generator_primitives.h)
diff --git a/include/molasses/generator_primitives.h b/include/molasses/generator_primitives.h
index 7a79480..c339749 100644
--- a/include/molasses/generator_primitives.h
+++ b/include/molasses/generator_primitives.h
@@ -6,11 +6,11 @@ namespace molasses {
std::vector generate_return();
- std::vector generate_label(std::string target);
+ std::vector generate_label(const std::string& target);
std::vector generate_push_int32(int32_t target);
- std::vector generate_call(std::string target);
+ std::vector generate_call(const std::string& target);
std::vector generate_enter();
}
\ No newline at end of file
diff --git a/include/molasses/parser_primitives.h b/include/molasses/parser_primitives.h
index c0a508b..e4fb0bf 100644
--- a/include/molasses/parser_primitives.h
+++ b/include/molasses/parser_primitives.h
@@ -11,10 +11,17 @@
enum class architecture_t {
- x86_64
+ x86_64_linux,
+ x86_linux
};
-constexpr architecture_t architecture = architecture_t::x86_64;
+#if defined(__x86_64__) && __linux__
+constexpr architecture_t architecture = architecture_t::x86_64_linux;
+constexpr size_t architecture_ptr_size = 8;
+#elif defined(__i386) || defined(__i386__) || defined(i386) && __linux__
+constexpr architecture_t architecture = architecture_t::x86_linux;
+constexpr size_t architecture_ptr_size = 4;
+#endif
namespace molasses {
struct type {
@@ -113,44 +120,56 @@ namespace molasses {
return lhs.name() <=> rhs.name();
}
- struct TypeInputError : std::runtime_error {
- TypeInputError() : std::runtime_error("Bad type provided") {}
+ struct type_input_error : std::runtime_error {
+ type_input_error() : std::runtime_error("Bad type provided") {}
// TODO: Better error message
};
- struct ValueMissingError : std::runtime_error {
- ValueMissingError() : std::runtime_error("Expected value, none provided") {}
+ struct value_missing_error : std::runtime_error {
+ value_missing_error() : std::runtime_error("Expected value, none provided") {}
// TODO: Better error message
};
- struct ProcedureStackError : std::runtime_error {
- ProcedureStackError() : std::runtime_error("Expected the stack to look like the return stack upon completion") {}
+ struct procedure_stack_error : std::runtime_error {
+ procedure_stack_error() : std::runtime_error("Expected the stack to look like the return stack upon completion") {}
// TODO: Better error message
};
- struct UnexpectedTokenError : std::runtime_error {
- UnexpectedTokenError() : std::runtime_error("An unexpected token has been encountered") {}
+ struct unexpected_token_error : std::runtime_error {
+ unexpected_token_error() : std::runtime_error("An unexpected token has been encountered") {}
// TODO: Better error message
};
- struct ExpectingTokenError : std::runtime_error {
- ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {}
- // TODO: Better error message
- };
- struct UnknownTokenError : std::runtime_error {
- UnknownTokenError() : std::runtime_error("An unknown token has not been encountered") {}
+ struct expecting_token_error : std::runtime_error {
+ expecting_token_error() : std::runtime_error("An expected token has not been encountered before the end of the input") {}
// TODO: Better error message
};
+ struct unknown_token_error : std::runtime_error {
+ unknown_token_error() : std::runtime_error("An unknown token has not been encountered") {}
+ // TODO: Better error message
+ };
+ struct type_expected_with_modifier_error : std::runtime_error {
+ type_expected_with_modifier_error() : std::runtime_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);
- struct parser_context {
- std::vector> types;
- std::vector> operations;
+ struct parser_context {
+ std::vector> types;
+ std::vector> operations;
+ std::vector> procedures;
- [[nodiscard]] std::shared_ptr lookup_type(const std::string&) const;
- [[nodiscard]] std::shared_ptr lookup_operation(const std::string&) const;
- };
+ [[nodiscard]] std::shared_ptr lookup_type(const std::string&) const;
+ [[nodiscard]] std::shared_ptr lookup_operation(const std::string&) const;
+ };
+
+ struct generate_context {
+ lexed_output lexer;
+ parser_context parser;
+ std::vector> procedures;
+ };
- parser_context parse(parser_context, const lexed_output&);
+ generate_context parse(parser_context, const lexed_output&);
+ std::vector generate(generate_context);
parser_context register_integers(parser_context);
parser_context register_i32_operations(parser_context);
diff --git a/prototypes/molasses/basic_file.mol b/prototypes/molasses/basic_file.mol
index ff4ed3d..d69e258 100644
--- a/prototypes/molasses/basic_file.mol
+++ b/prototypes/molasses/basic_file.mol
@@ -1,7 +1,4 @@
-__PROC__ procedure_name
-i16 i8
+__PROC__ main
__--__
-i32
__DO__
-i32 __CAST__ __SWAP__ i32 __CAST__ *
__END__
\ No newline at end of file
diff --git a/prototypes/molasses/first_rountrip.mol b/prototypes/molasses/first_rountrip.mol
index 42fb50e..4f8b7ce 100644
--- a/prototypes/molasses/first_rountrip.mol
+++ b/prototypes/molasses/first_rountrip.mol
@@ -6,12 +6,4 @@ __DO__
__LET__ size, ptr, fd
size ptr __CAST_I64__ fd 1_i64 __SYSCALL4__
__END_LET__
-__END__
-
-proc __DEREF_I64_PTR__
-i64 ptr
---
-i64
-DO
-
-END
\ No newline at end of file
+__END__
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index b3cdd7f..5e5c871 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,55 +1,85 @@
#include "molasses/lexer.h"
#include "molasses/parser_primitives.h"
+#include
+#include
+#include
#include
+#include
+#include
+#include
+#include
-int main() {
- /*
- molasses::lexed_output initial;
-
- initial.dictionary[1] = "+";
- {
- auto v = molasses::lex("hello hello potato 128 hello 128 +");
- auto v2 = molasses::lex("salad hello potato 129 hello 128");
- for (auto symbol: v.symbols) {
- std::cout << "v: " << symbol << " - " << v.dictionary.at(symbol) << "\n";
- }
- std::cout << "\n";
- for (auto symbol: v2.symbols) {
- std::cout << "v2: " << symbol << " - " << v2.dictionary.at(symbol) << "\n";
- }
-
- auto v_merged = molasses::concatenate(initial, molasses::concatenate(v, v2));
-
- std::cout << "\n";
- for (auto symbol: v_merged.symbols) {
- std::cout << "v_merged: " << symbol << " - " << v_merged.dictionary.at(symbol) << "\n";
- }
- }
-
- auto v = molasses::lex("1 2 +");
- molasses::parser_context ctx;
- ctx = molasses::register_integers(ctx);
- ctx.operations.emplace_back(std::make_shared(std::string{"+"}, std::vector({"i32", "i32"}), std::vector({"i32"})));
- if(molasses::type_check(ctx, v, v.symbols, {}, {"i32"})) {
- std::cout << "Checks out\n";
- }*/
- /*
- auto lexed = molasses::lex("__PROC__ sum\n"
- "i32 i32\n"
- "__--__\n"
- "i32\n"
- "__DO__\n"
- "+\n"
- "__END__");*/
-
- auto lexed = molasses::lex("__PROC__ main\n"
- "__--__\n"
- "__DO__\n"
- "__END__");
-
- molasses::parser_context ctx;
- ctx = molasses::register_integers(ctx);
- ctx = molasses::register_i32_operations(ctx);
- molasses::parse(ctx, lexed);
-
+using compile_element = std::variant;
+
+int main(int argc, char** argv) {
+ std::vector arguments;
+ while(argc > 1) {
+ argv++;
+ arguments.emplace_back(*argv, strlen(*argv));
+ argc--;
+ }
+
+ std::stack compile_stack;
+
+ for(auto elem : arguments) {
+ if(elem == "generate") {
+ if(std::holds_alternative(compile_stack.top())) {
+ auto filename = std::get(compile_stack.top());
+ compile_stack.pop();
+ if(std::holds_alternative(compile_stack.top())) {
+ auto generator = std::get(compile_stack.top());
+ compile_stack.pop();
+ auto assembler = molasses::generate(generator);
+ std::ofstream output(filename+".s");
+ for(const auto& line : assembler) {
+ output << line;
+ }
+ compile_stack.emplace(filename);
+ } else throw std::runtime_error("generate expects a parsed output");
+ } else throw std::runtime_error("generate expects a filename");
+ } else if(elem == "parse") {
+ molasses::parser_context ctx;
+ ctx = molasses::register_integers(ctx);
+ ctx = molasses::register_i32_operations(ctx);
+
+ if(std::holds_alternative(compile_stack.top())) {
+ auto lexer = std::get(compile_stack.top());
+ compile_stack.pop();
+ auto generator = molasses::parse(ctx, lexer);
+ compile_stack.emplace(generator);
+ } else throw std::runtime_error("parse expects a lexed output");
+ } else if(elem == "lex") {
+ if(std::holds_alternative(compile_stack.top())) {
+ auto filename = std::get(compile_stack.top());
+ compile_stack.pop();
+ if(not std::filesystem::exists(filename)) throw std::runtime_error("file "+filename+" does not exist");
+ std::ifstream t(filename);
+ std::stringstream buffer;
+ buffer << t.rdbuf();
+ auto lexed = molasses::lex(buffer.str());
+ compile_stack.emplace(lexed);
+ } else throw std::runtime_error("lex expects a filename");
+ } else if(elem == "merge") {
+ if(std::holds_alternative(compile_stack.top())) {
+ auto lexer_1 = std::get(compile_stack.top());
+ compile_stack.pop();
+ if(std::holds_alternative(compile_stack.top())) {
+ auto lexer_2 = std::get(compile_stack.top());
+ compile_stack.pop();
+ compile_stack.emplace(molasses::concatenate(lexer_1, lexer_2));
+ } else throw std::runtime_error("merge expects 2 lexed outputs");
+ } else throw std::runtime_error("merge expects 2 lexed outputs");
+ } else if(elem == "assemble") {
+ if(std::holds_alternative(compile_stack.top())) {
+ auto filename = std::get(compile_stack.top());
+ compile_stack.pop();
+ std::stringstream compile; compile << "clang -c " << filename << ".s -o " << filename << ".o";
+ std::stringstream link; link << "ld -e _start " << filename << ".o -o " << filename;
+ std::cout << compile.str() << std::endl;
+ system(compile.str().c_str());
+ std::cout << link.str() << std::endl;
+ system(link.str().c_str());
+ } else throw std::runtime_error("assemble expects an assembly file");
+ } else compile_stack.emplace(elem);
+ }
}
diff --git a/src/molasses/generator_primitives_x86_64_linux.cpp b/src/molasses/generator_primitives_x86_64_linux.cpp
index 702f3b1..c059a52 100644
--- a/src/molasses/generator_primitives_x86_64_linux.cpp
+++ b/src/molasses/generator_primitives_x86_64_linux.cpp
@@ -2,7 +2,8 @@
#include "molasses/generator_primitives.h"
namespace molasses {
- parser_context register_integers(parser_context ctx) requires (architecture == architecture_t::x86_64) {
+ parser_context register_integers(parser_context ctx)
+ requires (architecture == architecture_t::x86_64_linux) {
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));
@@ -15,7 +16,8 @@ namespace molasses {
return ctx;
}
- parser_context register_i32_operations(parser_context ctx) requires (architecture == architecture_t::x86_64) {
+ parser_context register_i32_operations(parser_context ctx)
+ requires (architecture == architecture_t::x86_64_linux) {
ctx.operations.emplace_back(
std::make_shared(
std::string{"+"},
@@ -168,29 +170,29 @@ namespace molasses {
return ctx;
}
- std::vector generate_call(std::string target)
- requires (architecture == architecture_t::x86_64) {
+ std::vector generate_call(const std::string& target)
+ requires (architecture == architecture_t::x86_64_linux) {
return {
" call "+target+"\n",
};
}
std::vector generate_push_int32(int32_t target)
- requires (architecture == architecture_t::x86_64) {
+ requires (architecture == architecture_t::x86_64_linux) {
return {
" pushq $" +std::to_string(target)+ "\n"
};
}
- std::vector generate_label(std::string target)
- requires (architecture == architecture_t::x86_64) {
+ std::vector generate_label(const std::string& target)
+ requires (architecture == architecture_t::x86_64_linux) {
return {
target+":\n"
};
}
std::vector generate_return()
- requires (architecture == architecture_t::x86_64) {
+ requires (architecture == architecture_t::x86_64_linux) {
return {
" // Return to caller\n",
" addq $-8, %r10\n",
@@ -200,7 +202,7 @@ namespace molasses {
}
std::vector generate_enter()
- requires (architecture == architecture_t::x86_64) {
+ requires (architecture == architecture_t::x86_64_linux) {
return {
" // Prepare the function stack\n",
" popq (%r10)\n"
@@ -209,7 +211,7 @@ namespace molasses {
}
std::vector initialize_stack()
- requires (architecture == architecture_t::x86_64) {
+ requires (architecture == architecture_t::x86_64_linux) {
std::vector operations = {
"code:\n",
" .skip 1000000\n",
@@ -230,11 +232,11 @@ namespace molasses {
" call initialize_callstack\n"
};
- for(auto op : generate_call("main")) {
+ for(const auto& op : generate_call("main")) {
operations.push_back(op);
}
- for(auto op : std::vector{
+ for(const auto& op : std::vector{
" movq $0, %rdi\n",
" movq $60, %rax\n",
" syscall\n"
diff --git a/src/molasses/parser_primitives.cpp b/src/molasses/parser_primitives.cpp
index 9f459a5..d14a01a 100644
--- a/src/molasses/parser_primitives.cpp
+++ b/src/molasses/parser_primitives.cpp
@@ -10,14 +10,14 @@ namespace molasses {
auto args = next_op.argument_types();
while(not (args.empty() or current_stack.empty())) {
if(current_stack.back() != args.back()) {
- throw TypeInputError();
+ throw type_input_error();
} else {
args.pop_back();
current_stack.pop_back();
}
}
if(not args.empty()) {
- throw ValueMissingError();
+ throw value_missing_error();
}
}
{
@@ -78,7 +78,7 @@ namespace molasses {
return type_stack == execution_output;
}
- parser_context parse(parser_context ctx, const lexed_output& lexer_data) {
+ generate_context parse(parser_context ctx, const lexed_output& lexer_data) {
enum op : int {
DO_KW = 1,
SEPARATOR_KW,
@@ -96,14 +96,34 @@ namespace molasses {
std::vector> parsed_procedures;
+ auto register_pointer_type = [&](std::string full_ptr_type_name) -> void {
+ if(auto type = ctx.lookup_type(full_ptr_type_name); !type) {
+ ctx.types.push_back(std::make_shared(std::move(full_ptr_type_name), architecture_ptr_size));
+ }
+ };
+
+ auto compact_type_modifiers = [&](const std::vector& type_info) -> std::vector {
+ std::vector ret_val;
+ for(auto elem : type_info) {
+ if(elem == "ptr") {
+ if(ret_val.empty()) throw type_expected_with_modifier_error();
+ ret_val.back() += " ptr";
+ register_pointer_type(ret_val.back());
+ } else {
+ ret_val.push_back(elem);
+ }
+ }
+ return ret_val;
+ };
+
auto parse_proc = [&](auto it) -> std::pair> {
#define CHECK_FOR_UNEXPECTED_STREAM_END \
if(it == tokens.symbols.end()) { \
- throw ExpectingTokenError(); \
+ throw expecting_token_error(); \
}
if(*it != PROC_KW) {
- throw UnexpectedTokenError();
+ throw unexpected_token_error();
}
++it;
CHECK_FOR_UNEXPECTED_STREAM_END;
@@ -112,10 +132,6 @@ namespace molasses {
++it;
CHECK_FOR_UNEXPECTED_STREAM_END;
- if(it == tokens.symbols.end()) {
- throw ExpectingTokenError();
- }
-
// Process arguments list
std::vector argument_types;
while(*it != SEPARATOR_KW) {
@@ -125,6 +141,7 @@ namespace molasses {
}
++it;
CHECK_FOR_UNEXPECTED_STREAM_END;
+ argument_types = compact_type_modifiers(argument_types);
// Process return types list
std::vector return_types;
@@ -135,6 +152,7 @@ namespace molasses {
}
++it;
CHECK_FOR_UNEXPECTED_STREAM_END;
+ return_types = compact_type_modifiers(return_types);
// Process return types list
std::vector body;
@@ -160,27 +178,15 @@ namespace molasses {
for(auto& proc : parsed_procedures) {
if(not type_check(ctx, tokens, proc->_body, proc->_args, proc->_rets)) {
- throw ProcedureStackError();
+ throw procedure_stack_error();
}
}
- std::vector generated;
-
- for(auto instr : initialize_stack()) {
- generated.push_back(instr);
- }
-
- for(auto proc : parsed_procedures) {
- for(auto instr : proc->generate(ctx, tokens)) {
- generated.push_back(instr);
- }
- }
-
- for(auto line : generated) {
- std::cout << line;
- }
-
- return ctx;
+ return {
+ tokens,
+ ctx,
+ parsed_procedures
+ };
}
std::vector procedure_operation::generate(const parser_context& ctx, const lexed_output& lexer_data) const {
@@ -201,7 +207,7 @@ namespace molasses {
ops.push_back(instruction);
}
} else {
- throw UnknownTokenError();
+ throw unknown_token_error();
}
}
@@ -215,4 +221,19 @@ namespace molasses {
std::vector procedure_operation::emit(const parser_context& ctx) const {
return generate_call(name());
}
+
+ std::vector generate(generate_context ctx) {
+ std::vector generated;
+
+ for(auto instr : initialize_stack()) {
+ generated.push_back(instr);
+ }
+
+ for(auto proc : ctx.procedures) {
+ for(auto instr : proc->generate(ctx.parser, ctx.lexer)) {
+ generated.push_back(instr);
+ }
+ }
+ return generated;
+ }
}