diff --git a/libs/ast/include/pslang/ast/control.hpp b/libs/ast/include/pslang/ast/control.hpp index 50228ae..b460880 100644 --- a/libs/ast/include/pslang/ast/control.hpp +++ b/libs/ast/include/pslang/ast/control.hpp @@ -7,9 +7,6 @@ namespace pslang::ast { - // N.B.: if_block, else_block, and else_if_block are temporary parsing elements - // and are not present in the final AST - struct if_block { expression_ptr condition; diff --git a/libs/ast/include/pslang/ast/statement.hpp b/libs/ast/include/pslang/ast/statement.hpp index 3c75cc9..6b7b8b3 100644 --- a/libs/ast/include/pslang/ast/statement.hpp +++ b/libs/ast/include/pslang/ast/statement.hpp @@ -30,14 +30,13 @@ namespace pslang::ast ast::location location; }; - using statement_impl = std::variant< + using pre_statement_impl = std::variant< expression_ptr, assignment, variable_declaration, if_block, else_block, else_if_block, - if_chain, while_block, function_definition, foreign_function_declaration, @@ -46,12 +45,31 @@ namespace pslang::ast struct_definition >; + struct pre_statement + : pre_statement_impl + { + using pre_statement_impl::pre_statement_impl; + }; + + using statement_impl = std::variant< + expression_ptr, + assignment, + variable_declaration, + if_chain, + while_block, + function_definition, + foreign_function_declaration, + return_statement, + struct_definition + >; + struct statement : statement_impl { using statement_impl::statement_impl; }; + location get_location(pre_statement const & statement); location get_location(statement const & statement); } diff --git a/libs/ast/include/pslang/ast/statement_fwd.hpp b/libs/ast/include/pslang/ast/statement_fwd.hpp index 134aaa9..c877e9f 100644 --- a/libs/ast/include/pslang/ast/statement_fwd.hpp +++ b/libs/ast/include/pslang/ast/statement_fwd.hpp @@ -6,15 +6,23 @@ namespace pslang::ast { + struct pre_statement; struct statement; + using pre_statement_ptr = std::shared_ptr; using statement_ptr = std::shared_ptr; + struct pre_statement_list + { + std::vector statements; + }; + struct statement_list { std::vector statements; }; + using pre_statement_list_ptr = std::shared_ptr; using statement_list_ptr = std::shared_ptr; } diff --git a/libs/ast/source/print.cpp b/libs/ast/source/print.cpp index 5a7fbbc..bae351d 100644 --- a/libs/ast/source/print.cpp +++ b/libs/ast/source/print.cpp @@ -386,26 +386,6 @@ namespace pslang::ast child(node.initializer); } - void apply(if_block const & node) - { - put_indent(out, options); - out << "if\n"; - child(node.condition); - } - - void apply(else_block const & node) - { - put_indent(out, options); - out << "else\n"; - } - - void apply(else_if_block const & node) - { - put_indent(out, options); - out << "else if\n"; - child(node.condition); - } - void apply(if_chain const & node) { put_indent(out, options); @@ -483,20 +463,17 @@ namespace pslang::ast child(node.value); } - void apply(field_definition const & node) - { - put_indent(out, options); - out << "field { name = \"" << node.name << "\", type = "; - print(out, *node.type); - out << ", offset = " << node.layout.offset << " }\n"; - } - void apply(struct_definition const & node) { put_indent(out, options); out << "struct { name = \"" << node.name << "\", size = " << node.layout.size << ", align = " << node.layout.alignment << " }\n"; for (auto const & field : node.fields) - child(field); + { + put_indent(out, as_child(options)); + out << "field { name = \"" << node.name << "\", type = "; + print(out, *field.type); + out << ", offset = " << field.layout.offset << " }\n"; + } } }; diff --git a/libs/ast/source/resolve_identifiers.cpp b/libs/ast/source/resolve_identifiers.cpp index 42fe176..e370993 100644 --- a/libs/ast/source/resolve_identifiers.cpp +++ b/libs/ast/source/resolve_identifiers.cpp @@ -71,15 +71,6 @@ namespace pslang::ast void apply(variable_declaration const &) {} - void apply(if_block const &) - {} - - void apply(else_if_block const &) - {} - - void apply(else_block const &) - {} - void apply(if_chain const &) {} @@ -105,9 +96,6 @@ namespace pslang::ast void apply(return_statement const &) {} - void apply(field_definition const &) - {} - void apply(struct_definition const & struct_definition) { if (scopes.back().contains(struct_definition.name)) @@ -270,21 +258,6 @@ namespace pslang::ast scopes.back().variables.insert(variable_declaration.name); } - void apply(if_block const & if_block) - { - throw invalid_ast_error("if blocks cannot be present in the final AST", if_block.location); - } - - void apply(else_if_block const & else_if_block) - { - throw invalid_ast_error("else if blocks cannot be present in the final AST", else_if_block.location); - } - - void apply(else_block const & else_block) - { - throw invalid_ast_error("else blocks cannot be present in the final AST", else_block.location); - } - void apply(if_chain const & if_chain) { for (auto const & block : if_chain.blocks) @@ -351,17 +324,12 @@ namespace pslang::ast apply(*return_statement.value); } - void apply(field_definition const & field_definition) - { - apply(*field_definition.type); - } - void apply(struct_definition const & struct_definition) { // Already added to scope by populate_globals_visitor for (auto const & field : struct_definition.fields) - apply(field); + apply(*field.type); scopes.back().structs.insert(struct_definition.name); } diff --git a/libs/ast/source/statement.cpp b/libs/ast/source/statement.cpp index 2a85fc9..0a732e2 100644 --- a/libs/ast/source/statement.cpp +++ b/libs/ast/source/statement.cpp @@ -1,5 +1,4 @@ #include -#include namespace pslang::ast { @@ -8,71 +7,14 @@ namespace pslang::ast { struct get_location_visitor - : const_statement_visitor { - using const_statement_visitor::apply; - - location apply(expression_ptr const & node) + location operator()(expression_ptr const & node) { return get_location(*node); } - location apply(assignment const & node) - { - return node.location; - } - - location apply(variable_declaration const & node) - { - return node.location; - } - - location apply(if_block const & node) - { - return node.location; - } - - location apply(else_block const & node) - { - return node.location; - } - - location apply(else_if_block const & node) - { - return node.location; - } - - location apply(if_chain const & node) - { - return node.location; - } - - location apply(while_block const & node) - { - return node.location; - } - - location apply(function_definition const & node) - { - return node.location; - } - - location apply(foreign_function_declaration const & node) - { - return node.location; - } - - location apply(return_statement const & node) - { - return node.location; - } - - location apply(field_definition const & node) - { - return node.location; - } - - location apply(struct_definition const & node) + template + location operator()(Node const & node) { return node.location; } @@ -80,9 +22,14 @@ namespace pslang::ast } + location get_location(pre_statement const & statement) + { + return std::visit(get_location_visitor{}, statement); + } + location get_location(statement const & statement) { - return get_location_visitor{}.apply(statement); + return std::visit(get_location_visitor{}, statement); } } diff --git a/libs/ast/source/type_check.cpp b/libs/ast/source/type_check.cpp index e8c370d..8885e8b 100644 --- a/libs/ast/source/type_check.cpp +++ b/libs/ast/source/type_check.cpp @@ -197,15 +197,6 @@ namespace pslang::ast void apply(variable_declaration const &) {} - void apply(if_block const &) - {} - - void apply(else_if_block const &) - {} - - void apply(else_block const &) - {} - void apply(if_chain const &) {} @@ -253,16 +244,13 @@ namespace pslang::ast void apply(return_statement const &) {} - void apply(field_definition & node) - { - resolve_types(scopes, *node.type); - node.inferred_type = get_type(*node.type); - } - void apply(struct_definition & node) { for (auto & field : node.fields) - apply(field); + { + resolve_types(scopes, *field.type); + field.inferred_type = get_type(*field.type); + } scopes.back().structs[node.name].node = &node; } @@ -751,21 +739,6 @@ namespace pslang::ast }; } - void apply(if_block const & node) - { - throw invalid_ast_error("if blocks cannot be present in the final AST", node.location); - } - - void apply(else_if_block const & node) - { - throw invalid_ast_error("else if blocks cannot be present in the final AST", node.location); - } - - void apply(else_block const & node) - { - throw invalid_ast_error("else blocks cannot be present in the final AST", node.location); - } - void apply(if_chain const & node) { for (auto const & block : node.blocks) @@ -856,9 +829,6 @@ namespace pslang::ast } } - void apply(field_definition const &) - {} - void apply(struct_definition const & node) { // Already added to scope by populate_globals_visitor diff --git a/libs/ast/source/validate.cpp b/libs/ast/source/validate.cpp index 7798359..56e183a 100644 --- a/libs/ast/source/validate.cpp +++ b/libs/ast/source/validate.cpp @@ -13,19 +13,13 @@ namespace pslang::ast : const_statement_visitor { using const_statement_visitor::apply; - + void apply(expression_ptr const &) {} void apply(assignment const &) {} void apply(variable_declaration const &) {} - void apply(if_block const &) {} - - void apply(else_block const &) {} - - void apply(else_if_block const &) {} - void apply(if_chain const & node) { for (auto const & block : node.blocks) @@ -53,8 +47,6 @@ namespace pslang::ast void apply(return_statement const &) {} - void apply(field_definition const &) {} - void apply(struct_definition const &) {} }; @@ -65,4 +57,4 @@ namespace pslang::ast validate_visitor{}.apply(*statements); } -} \ No newline at end of file +} diff --git a/libs/interpreter/source/exec.cpp b/libs/interpreter/source/exec.cpp index 561dae7..c35088a 100644 --- a/libs/interpreter/source/exec.cpp +++ b/libs/interpreter/source/exec.cpp @@ -81,21 +81,6 @@ namespace pslang::interpreter context.frame_stack.back().variables[variable_declaration.name] = {.category = variable_declaration.category, .value = value}; } - void exec_impl(context & context, ast::if_block const & if_block) - { - throw internal_error("if blocks cannot be present in the final AST", if_block.location); - } - - void exec_impl(context & context, ast::else_block const & else_block) - { - throw internal_error("else blocks cannot be present in the final AST", else_block.location); - } - - void exec_impl(context & context, ast::else_if_block const & else_if_block) - { - throw internal_error("else if blocks cannot be present in the final AST", else_if_block.location); - } - void exec_impl(context & context, ast::if_chain const & if_chain) { for (auto const & block : if_chain.blocks) @@ -225,11 +210,6 @@ namespace pslang::interpreter throw internal_error("Cannot return outside of function scope", return_statement.location); } - void exec_impl(context & context, ast::field_definition const & field_definition) - { - throw internal_error("Field definitions cannot be present in the final AST outside of struct definitions", field_definition.location); - } - void exec_impl(context & context, ast::struct_definition const & struct_definition) { auto & frame = context.frame_stack.back(); diff --git a/libs/ir/source/compiler.cpp b/libs/ir/source/compiler.cpp index 04f92cc..1e71eb2 100644 --- a/libs/ir/source/compiler.cpp +++ b/libs/ir/source/compiler.cpp @@ -58,12 +58,6 @@ namespace pslang::ir void apply(ast::variable_declaration const &) {} - void apply(ast::if_block const &) {} - - void apply(ast::else_block const &) {} - - void apply(ast::else_if_block const &) {} - void apply(ast::if_chain const &) {} void apply(ast::while_block const &) {} @@ -80,8 +74,6 @@ namespace pslang::ir void apply(ast::return_statement const &) {} - void apply(ast::field_definition const &) {} - void apply(ast::struct_definition const & node) { lcontext.scopes.back().structs[node.name] = &node; @@ -277,7 +269,7 @@ namespace pslang::ir if (jump_to_next) std::get((*jump_to_next)->instruction).target = last(); } - + auto end = last(); for (auto const & jump_to_end : jumps_to_end) std::get(jump_to_end->instruction).target = end; @@ -324,7 +316,7 @@ namespace pslang::ir return last(); } - // TODO: struct_definition, field_definition + // TODO: struct_definition // Statement list @@ -379,12 +371,6 @@ namespace pslang::ir void apply(ast::variable_declaration const &) {} - void apply(ast::if_block const &) {} - - void apply(ast::else_block const &) {} - - void apply(ast::else_if_block const &) {} - void apply(ast::if_chain const & node) { for (auto const & block : node.blocks) @@ -420,8 +406,6 @@ namespace pslang::ir void apply(ast::return_statement const &) {} - void apply(ast::field_definition const &) {} - void apply(ast::struct_definition const &) {} void apply(ast::statement_list const & list) @@ -447,7 +431,7 @@ namespace pslang::ir statements, {}, }); - + mcontext.nodes.emplace_back(nop{}); auto extra_nop = std::prev(mcontext.nodes.end()); local_context lcontext; @@ -467,4 +451,4 @@ namespace pslang::ir mcontext.entry_point = lcontext.functions.at(std::get_if(root.get())); } -} \ No newline at end of file +} diff --git a/libs/jit/source/arch/aarch64/compiler.cpp b/libs/jit/source/arch/aarch64/compiler.cpp index da5be1a..292a865 100644 --- a/libs/jit/source/arch/aarch64/compiler.cpp +++ b/libs/jit/source/arch/aarch64/compiler.cpp @@ -235,15 +235,6 @@ namespace pslang::jit::aarch64 apply(*node.initializer); } - void apply(ast::if_block const &) - {} - - void apply(ast::else_block const &) - {} - - void apply(ast::else_if_block const &) - {} - void apply(ast::if_chain const & node) { for (auto const & block : node.blocks) @@ -280,9 +271,6 @@ namespace pslang::jit::aarch64 apply(*node.value); } - void apply(ast::field_definition const &) - {} - void apply(ast::struct_definition const &) {} @@ -357,12 +345,6 @@ namespace pslang::jit::aarch64 void apply(ast::variable_declaration const &) {} - void apply(ast::if_block const &) {} - - void apply(ast::else_block const &) {} - - void apply(ast::else_if_block const &) {} - void apply(ast::if_chain const &) {} void apply(ast::while_block const &) {} @@ -379,8 +361,6 @@ namespace pslang::jit::aarch64 void apply(ast::return_statement const &) {} - void apply(ast::field_definition const &) {} - void apply(ast::struct_definition const & node) { lcontext.scopes.back().structs[node.name] = &node; @@ -1364,12 +1344,6 @@ namespace pslang::jit::aarch64 void apply(ast::variable_declaration const &) {} - void apply(ast::if_block const &) {} - - void apply(ast::else_block const &) {} - - void apply(ast::else_if_block const &) {} - void apply(ast::if_chain const & node) { for (auto const & block : node.blocks) @@ -1392,8 +1366,6 @@ namespace pslang::jit::aarch64 void apply(ast::return_statement const &) {} - void apply(ast::field_definition const &) {} - void apply(ast::struct_definition const &) {} void apply(ast::statement_list const & node) diff --git a/libs/parser/include/pslang/parser/indented_statement.hpp b/libs/parser/include/pslang/parser/indented_statement.hpp index 7edbc15..cb94132 100644 --- a/libs/parser/include/pslang/parser/indented_statement.hpp +++ b/libs/parser/include/pslang/parser/indented_statement.hpp @@ -10,7 +10,7 @@ namespace pslang::parser struct indented_statement { std::size_t indentation; - ast::statement_ptr statement; + ast::pre_statement_ptr statement; }; struct indented_statement_list diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index 83fb75e..4b0c629 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -165,7 +165,7 @@ template %type indented_statement_list %type statement_line %type indentation -%type statement +%type statement %type > function_declaration_argument_list %type > nonempty_function_declaration_argument_list %type function_declaration_single_argument @@ -192,12 +192,12 @@ module indented_statement_list : statement_line { indented_statement_list tmp; tmp.statements.push_back(std::move($1)); $$ = std::move(tmp); } | empty_line { $$ = {}; } -| indented_statement_list newline statement_line { auto tmp = $1; tmp.statements.push_back(std::move($3)); $$ = std::move(tmp); } +| indented_statement_list newline statement_line { auto tmp = $1; tmp.statements.push_back(std::move($3)); $$ = std::move(tmp); } | indented_statement_list newline empty_line { $$ = $1; } ; statement_line -: indentation statement optional_comment { $$ = indented_statement{$1, std::make_unique($2)}; } +: indentation statement optional_comment { $$ = indented_statement{$1, std::make_unique($2)}; } ; empty_line diff --git a/libs/parser/source/finalize.cpp b/libs/parser/source/finalize.cpp index c91c17c..af1f442 100644 --- a/libs/parser/source/finalize.cpp +++ b/libs/parser/source/finalize.cpp @@ -18,7 +18,7 @@ namespace pslang::parser ast::location apply(ast::expression_ptr const & node) { - return ast::get_location(node); + return ast::get_location(*node); } ast::location apply(ast::assignment const & node) @@ -31,21 +31,6 @@ namespace pslang::parser return node.location; } - ast::location apply(ast::if_block const & node) - { - return node.location; - } - - ast::location apply(ast::else_block const & node) - { - return node.location; - } - - ast::location apply(ast::else_if_block const & node) - { - return node.location; - } - ast::location apply(ast::if_chain & node) { bool first = true; @@ -81,16 +66,11 @@ namespace pslang::parser return node.location; } - ast::location apply(ast::field_definition const & node) - { - return node.location; - } - ast::location apply(ast::struct_definition & node) { node.location = node.prelude_location; for (auto const & field : node.fields) - node.location = ast::merge(node.location, apply(field)); + node.location = ast::merge(node.location, field.location); return node.location; } @@ -200,13 +180,13 @@ namespace pslang::parser { while_block->statements = std::make_unique(); list = while_block->statements.get(); - current_statement_list(location)->statements.push_back(std::move(statement.statement)); + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*while_block))); } else if (auto function_definition = std::get_if(statement.statement.get())) { function_definition->statements = std::make_unique(); list = function_definition->statements.get(); - current_statement_list(location)->statements.push_back(std::move(statement.statement)); + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*function_definition))); is_function_definition = true; } else if (auto field_definition = std::get_if(statement.statement.get())) @@ -217,9 +197,9 @@ namespace pslang::parser throw parse_error("Duplicate field definition: \"" + field.name + "\"", field.location); current->fields.push_back(*field_definition); } - else if (std::get_if(statement.statement.get())) + else if (auto struct_definition = std::get_if(statement.statement.get())) { - current_statement_list(location)->statements.push_back(std::move(statement.statement)); + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*struct_definition))); stack.push_back(std::get_if(current_statement_list(location)->statements.back().get())); ++current_indent; if (in_function_scope > 0) @@ -230,11 +210,27 @@ namespace pslang::parser if (in_function_scope == 0) throw parse_error("Return statement outside of function scope", return_statement->location); return_statement->level = stack.size() - in_function_scope; - current_statement_list(location)->statements.push_back(std::move(statement.statement)); + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*return_statement))); + } + else if (auto expression_ptr = std::get_if(statement.statement.get())) + { + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*expression_ptr))); + } + else if (auto assignment = std::get_if(statement.statement.get())) + { + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*assignment))); + } + else if (auto variable_declaration = std::get_if(statement.statement.get())) + { + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*variable_declaration))); + } + else if (auto foreign_function_declaration = std::get_if(statement.statement.get())) + { + current_statement_list(location)->statements.push_back(std::make_unique(std::move(*foreign_function_declaration))); } else { - current_statement_list(location)->statements.push_back(std::move(statement.statement)); + throw ast::invalid_ast_error(std::format("Unknown pre-statement \"{}\"", std::visit([](auto const & statement){ return typeid(statement).name(); }, *statement.statement)), location); } if (list) diff --git a/plans.txt b/plans.txt index 49f3cbf..45698af 100644 --- a/plans.txt +++ b/plans.txt @@ -43,4 +43,3 @@ General backlog: * Replace std::runtime_error with appropriate custom exception types * Replace std::ostringstream with std::format (need support for std::format in type/ast printing) * TEST COVERAGE!!! -* Separate actual AST from pre-AST (the one before indentation & scoping is resolved)