From f1a96d849ba55741bbf2a6aedb38e680212ae836 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Thu, 26 Jan 2023 20:51:37 +0100 Subject: [PATCH] Compiles and build completely --- .clang-format | 213 ++++++++++++++++++ .clang-tidy | 172 ++++++++++++++ .idea/codeStyles/Project.xml | 48 ++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/inspectionProfiles/Project_Default.xml | 7 + CMakeLists.txt | 9 +- include/molasses/generator_primitives.h | 4 +- include/molasses/parser_primitives.h | 65 ++++-- prototypes/molasses/basic_file.mol | 5 +- prototypes/molasses/first_rountrip.mol | 10 +- src/main.cpp | 130 +++++++---- .../generator_primitives_x86_64_linux.cpp | 26 ++- src/molasses/parser_primitives.cpp | 77 ++++--- 13 files changed, 642 insertions(+), 129 deletions(-) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml 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; + } }