From 7d07bef760a8807fe49fbe5c90799a1822f95973 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 8 Oct 2026 19:45:19 +0200 Subject: Make modules re-exportable --- boot/ast.cc | 5 +- boot/dependency.cc | 2 +- boot/parser.yy | 20 ++++++-- boot/symbol.cc | 17 ++++++- include/elna/boot/ast.h | 8 ++- include/elna/boot/dependency.h | 5 +- include/elna/boot/symbol.h | 9 +++- rakelib/gcc.rake | 5 +- source/cctype.elna | 24 --------- source/command_line_interface.elna | 2 +- source/common.elna | 3 +- source/cstdio.elna | 59 ---------------------- source/cstdlib.elna | 24 --------- source/cstring.elna | 30 ----------- source/diagnostic.elna | 2 +- source/lexer.elna | 6 +-- source/main.elna | 2 +- source/name_analysis.elna | 2 +- source/parser.elna | 4 +- source/qbe.elna | 2 +- source/symbol.elna | 2 +- source/sys/posix/cctype.elna | 24 +++++++++ source/sys/posix/cstdio.elna | 59 ++++++++++++++++++++++ source/sys/posix/cstdlib.elna | 24 +++++++++ source/sys/posix/cstring.elna | 30 +++++++++++ source/tac.elna | 2 +- .../fail_compilation/transitive_import/helper.elna | 6 +++ .../fail_compilation/transitive_import/middle.elna | 5 ++ .../fail_compilation/transitive_import/sut.elna | 8 +++ testsuite/runnable/reexport/helper.elna | 6 +++ testsuite/runnable/reexport/left.elna | 5 ++ testsuite/runnable/reexport/middle.elna | 5 ++ testsuite/runnable/reexport/right.elna | 5 ++ testsuite/runnable/reexport/sut.elna | 6 +++ tools/tree-sitter/grammar.js | 9 ++-- 35 files changed, 256 insertions(+), 171 deletions(-) delete mode 100644 source/cctype.elna delete mode 100644 source/cstdio.elna delete mode 100644 source/cstdlib.elna delete mode 100644 source/cstring.elna create mode 100644 source/sys/posix/cctype.elna create mode 100644 source/sys/posix/cstdio.elna create mode 100644 source/sys/posix/cstdlib.elna create mode 100644 source/sys/posix/cstring.elna create mode 100644 testsuite/fail_compilation/transitive_import/helper.elna create mode 100644 testsuite/fail_compilation/transitive_import/middle.elna create mode 100644 testsuite/fail_compilation/transitive_import/sut.elna create mode 100644 testsuite/runnable/reexport/helper.elna create mode 100644 testsuite/runnable/reexport/left.elna create mode 100644 testsuite/runnable/reexport/middle.elna create mode 100644 testsuite/runnable/reexport/right.elna create mode 100644 testsuite/runnable/reexport/sut.elna diff --git a/boot/ast.cc b/boot/ast.cc index 69b15d3..456797a 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -1681,8 +1681,9 @@ namespace elna::boot delete this->alternative; } - import_declaration::import_declaration(const source_position position, std::vector&& segments) - : node(position), segments(std::move(segments)) + import_declaration::import_declaration(const source_position position, std::vector&& segments, + const bool exported) + : node(position), segments(std::move(segments)), exported(exported) { } diff --git a/boot/dependency.cc b/boot/dependency.cc index 5053a36..31eccc9 100644 --- a/boot/dependency.cc +++ b/boot/dependency.cc @@ -90,7 +90,7 @@ namespace elna::boot } for (const auto& import : imports) { - const std::vector collisions = result.value.add_import(import.symbols); + const std::vector collisions = result.value.add_import(import.symbols, import.reexport); for (const import_collision& collision : collisions) { diff --git a/boot/parser.yy b/boot/parser.yy index cfa63d5..65d3dba 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -160,7 +160,8 @@ along with GCC; see the file COPYING3. If not see %type > identifier_definitions; %type > attribute; %type > attributes; -%type > import_declaration; +%type , bool>> import_declaration; +%type > import_path; %type > required_identifiers optional_identifiers generic_parameters; %type > enumeration_member; %type > enumeration_members; @@ -736,22 +737,31 @@ variable_declarations: $$ = $2; $$.insert(std::cbegin($$), $1); } -import_declaration: - IDENTIFIER "." import_declaration +import_path: + IDENTIFIER "." import_path { $$ = $3; $$.emplace($$.cbegin(), $1); } | IDENTIFIER { $$.emplace_back($1); } +import_declaration: + import_path "*" { $$ = { $1, true }; } + | import_path { $$ = { $1, false }; } import_declarations: import_declaration "," import_declarations { + auto [segments, exported] = $1; + $$ = $3; - $$.emplace($$.cbegin(), new boot::import_declaration(boot::make_position(@$), $1)); + $$.emplace($$.cbegin(), + new boot::import_declaration(boot::make_position(@$), std::move(segments), exported)); } | import_declaration { - $$.emplace_back(new boot::import_declaration(boot::make_position(@$), $1)); + auto [segments, exported] = $1; + + $$.emplace_back( + new boot::import_declaration(boot::make_position(@$), std::move(segments), exported)); } type_declaration: identifier_definition generic_parameters "=" type_expression diff --git a/boot/symbol.cc b/boot/symbol.cc index 375cbfd..2805839 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -522,7 +522,8 @@ namespace elna::boot return this->unresolved.insert({ symbol_name, std::move(forward_declaration) }).second; } - std::vector symbol_bag::add_import(const std::shared_ptr& symbols) + std::vector symbol_bag::add_import(const std::shared_ptr& symbols, + const bool reexport) { std::vector collisions; @@ -538,7 +539,10 @@ namespace elna::boot } } this->imports.push_back(symbols); - + if (reexport) + { + this->reexports.push_back(symbols); + } return collisions; } @@ -553,6 +557,15 @@ namespace elna::boot if (!m_exported) { m_exported = std::make_shared(symbols->scope()); + // The same symbol can reach a module along several re-export + // paths; it is the same info then, so entering it twice is a no-op. + for (const auto& reexported : this->reexports) + { + for (const auto& [name, info] : *reexported) + { + m_exported->enter(name, info); + } + } for (const auto& [name, info] : *symbols) { if (info->exported) diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 6edeb25..06e5d41 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -1027,13 +1027,19 @@ namespace elna::boot /** * Import statement. + * + * An asterisk after the module path marks a re-export: the symbols the + * imported module exports become visible to the modules importing this + * one as well. */ class import_declaration : public node { public: const std::vector segments; + const bool exported; - import_declaration(const source_position position, std::vector&& segments); + import_declaration(const source_position position, std::vector&& segments, + const bool exported = false); void accept(parser_visitor *visitor) override; }; diff --git a/include/elna/boot/dependency.h b/include/elna/boot/dependency.h index 7bd3de9..f52bfb1 100644 --- a/include/elna/boot/dependency.h +++ b/include/elna/boot/dependency.h @@ -156,6 +156,8 @@ namespace elna::boot { source_position position; std::shared_ptr symbols; + /// Whether the importing module re-exports the symbols. + bool reexport = false; }; /** @@ -302,7 +304,8 @@ namespace elna::boot } imports.push_back({ .position = sub_tree->position(), - .symbols = this->cache.find(module_path)->second.exported_symbols() + .symbols = this->cache.find(module_path)->second.exported_symbols(), + .reexport = sub_tree->exported }); } result.append(key, std::move(circular)); diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 07bcf80..bdac269 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -558,6 +558,8 @@ namespace elna::boot { std::shared_ptr symbols; std::vector> imports; + // The subset of imports that is re-exported by this module. + std::vector> reexports; forward_table unresolved; std::shared_ptr lookup_import(const std::string& name) const; @@ -643,11 +645,14 @@ namespace elna::boot * earlier import keeps its names. * * \param symbols Exported symbol table of another module. + * \param reexport Whether the imported symbols are exported by this + * module as well, so they are visible to its importers. * * \return Names an earlier import already brought into the scope, * sorted by name. */ - std::vector add_import(const std::shared_ptr& symbols); + std::vector add_import(const std::shared_ptr& symbols, + const bool reexport = false); /** * Tells whether the current scope is the module global scope. @@ -661,7 +666,7 @@ namespace elna::boot /** * The symbol table containing the exported declarations of the - * module, computed lazily. Must be called while the current scope is + * module and the symbols of the modules it re-exports, computed lazily. Must be called while the current scope is * still the module scope. * * \return Exported symbols of the module. diff --git a/rakelib/gcc.rake b/rakelib/gcc.rake index 6dce877..aeffd06 100644 --- a/rakelib/gcc.rake +++ b/rakelib/gcc.rake @@ -130,8 +130,9 @@ end def multi_module_extra_sources(test_target) sources = test_target.glob('**/*.elna') - .map { |extra| %("#{extra.relative_path_from(test_target)}") } - "(* { dg-additional-sources #{sources * ' '} } *)" + .map { |extra| extra.relative_path_from(test_target) } + .sort + "(* { dg-additional-sources \"#{sources * ' '}\" } *)" end def convert_multi_module_test(test_path, test_target, category) diff --git a/source/cctype.elna b/source/cctype.elna deleted file mode 100644 index 19c3491..0000000 --- a/source/cctype.elna +++ /dev/null @@ -1,24 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -module - -proc isdigit*(c: Int ) -> Int -extern - -proc isalnum*(c: Int) -> Int -extern - -proc isalpha*(c: Int) -> Int -extern - -proc isspace*(c: Int) -> Int -extern - -proc tolower*(c: Int) -> Int -extern - -proc toupper*(c: Int) -> Int -extern - -end. diff --git a/source/command_line_interface.elna b/source/command_line_interface.elna index 1318e67..4c3c1a6 100644 --- a/source/command_line_interface.elna +++ b/source/command_line_interface.elna @@ -5,7 +5,7 @@ Command line handling. *) module -import cstdlib, cstring, common +import sys.posix.cstdlib, sys.posix.cstring, common type CommandLine* = record diff --git a/source/common.elna b/source/common.elna index 65b0a65..93b4363 100644 --- a/source/common.elna +++ b/source/common.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import cstring, cstdio, cstdlib +import sys.posix.cstring, sys.posix.cstdio, sys.posix.cstdlib type ElnaLocation* = record @@ -86,4 +86,3 @@ begin return nil end. - diff --git a/source/cstdio.elna b/source/cstdio.elna deleted file mode 100644 index 928c7e1..0000000 --- a/source/cstdio.elna +++ /dev/null @@ -1,59 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -module - -type - FILE* = extern - -var - stdin*: ^FILE := extern - stdout*: ^FILE := extern - stderr*: ^FILE := extern - -proc fopen*(pathname, mode: ^const Word8) -> ^FILE -extern - -proc fclose*(stream: ^FILE) -> Int -extern - -proc fseek*(stream: ^FILE; off: Int; whence: Int) -> Int -extern - -proc rewind*(stream: ^FILE) -extern - -proc ftell*(stream: ^FILE) -> Int -extern - -proc fflush*(stream: ^FILE) -> Int -extern - -proc fread*#[T](ptr: ^T; size: Word; nmemb: Word; stream: ^FILE) -> Word -extern - -proc fwrite*#[T](ptr: ^const T; size: Word; nitems: Word; stream: ^FILE) -> Word -extern - -proc fputc*(c: Int; stream: ^FILE) -> Word -extern - -proc perror*(s: ^const Word8) -extern - -proc puts*(s: ^const Word8) -> Int -extern - -proc putchar*(c: Int) -> Int -extern - -proc sprintf*(str: ^Word8; format: ^const Word8) #{varargs} -> Int -extern - -proc fprintf*(stream: ^FILE; format: ^const Word8) #{varargs} -> Int -extern - -proc fdopen*(fildes: Int; mode: ^const Word8) -> ^FILE -extern - -end. diff --git a/source/cstdlib.elna b/source/cstdlib.elna deleted file mode 100644 index 10a4d80..0000000 --- a/source/cstdlib.elna +++ /dev/null @@ -1,24 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -module - -proc malloc*#[T](size: Word) -> ^T -extern - -proc free*#[T](ptr: ^T) -extern - -proc calloc*#[T](nmemb: Word; size: Word) -> ^T -extern - -proc realloc*#[T](ptr: ^T; size: Word) -> ^T -extern - -proc atoi*(str: ^Word8) -> Int -extern - -proc exit*(code: Int) #{noreturn} -extern - -end. diff --git a/source/cstring.elna b/source/cstring.elna deleted file mode 100644 index 3973573..0000000 --- a/source/cstring.elna +++ /dev/null @@ -1,30 +0,0 @@ -(* This Source Code Form is subject to the terms of the Mozilla Public License, - v. 2.0. If a copy of the MPL was not distributed with this file, You can - obtain one at https://mozilla.org/MPL/2.0/. *) -module - -proc memset*#[T](ptr: ^T; c: Int; n: Word) -> ^Word8 -extern - -proc memcpy*#[T](dst: ^T; src: ^const T; n: Word) -extern - -proc memcmp*#[T](s1, s2: ^const T; n: Word) -> Int -extern - -proc strcmp*(s1: ^const Word8; s2: ^const Word8) -> Int -extern - -proc strncmp*(s1: ^const Word8; s2: ^const Word8; n: Word) -> Int -extern - -proc strncpy*(dst: ^Word8; src: ^const Word8; dsize: Word) -> ^Word8 -extern - -proc strcpy*(dst: ^Word8; src: ^const Word8) -> ^Word8 -extern - -proc strlen*(ptr: ^const Word8) -> Word -extern - -end. diff --git a/source/diagnostic.elna b/source/diagnostic.elna index 771ce38..2356544 100644 --- a/source/diagnostic.elna +++ b/source/diagnostic.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import common, cstdio, cstdlib, lexer, ast +import common, sys.posix.cstdio, sys.posix.cstdlib, lexer, ast type ElnaErrorKind* = ( diff --git a/source/lexer.elna b/source/lexer.elna index 9ba593f..71e76a7 100644 --- a/source/lexer.elna +++ b/source/lexer.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import cstdio, common, cstdlib +import sys.posix.cstdio, common, sys.posix.cstdlib type ElnaLexerState* = ( @@ -762,8 +762,8 @@ begin cursor^.start := code_pointer; cursor^.finish := code_pointer; cursor^.token := nil; - cursor^.position.start_location := ElnaLocation{ line: 1u, column: 1u }; - cursor^.position.end_location := ElnaLocation{ line: 1u, column: 1u } + cursor^.position.start_location := { ElnaLocation; line: 1u, column: 1u }; + cursor^.position.end_location := { ElnaLocation; line: 1u, column: 1u } return (** diff --git a/source/main.elna b/source/main.elna index 6049362..3b78651 100644 --- a/source/main.elna +++ b/source/main.elna @@ -4,7 +4,7 @@ program(parameters) import - cstdio, cstdlib, cstring, common, command_line_interface, + sys.posix.cstdio, sys.posix.cstdlib, sys.posix.cstring, common, command_line_interface, lexer, ast, diagnostic, symbol, parser, name_analysis, type_check, tac, qbe proc read_file_to_buffer(filename: ^Word8) -> []const Word8 diff --git a/source/name_analysis.elna b/source/name_analysis.elna index 75d6dbd..cbb27c0 100644 --- a/source/name_analysis.elna +++ b/source/name_analysis.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import common, cstdlib, lexer, ast, symbol, diagnostic +import common, sys.posix.cstdlib, lexer, ast, symbol, diagnostic proc elna_name_type_expression*(parser_node: ^ElnaTreeTypeExpression; error_list: ^ElnaList) -> ^ElnaType var diff --git a/source/parser.elna b/source/parser.elna index 30f79f8..3912b65 100644 --- a/source/parser.elna +++ b/source/parser.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import common, cstdlib, lexer, ast, diagnostic +import common, sys.posix.cstdlib, lexer, ast, diagnostic proc elna_parser_expect*(cursor: ^ElnaLexerCursor; expected: ElnaLexerKind; error_list: ^ElnaList) -> ^ElnaLexerToken var @@ -1129,7 +1129,7 @@ var begin result := malloc#[ElnaTreeModuleDeclaration](#size(ElnaTreeModuleDeclaration)); result^.kind := ElnaTreeKind.module_declaration; - result^.position.start_location := ElnaLocation{ line: 1u, column: 1u }; + result^.position.start_location := { ElnaLocation; line: 1u, column: 1u }; result^.position.end_location := result^.position.start_location; result^.types := elna_parser_type_part(cursor, error_list); diff --git a/source/qbe.elna b/source/qbe.elna index 0a5a45b..47eac88 100644 --- a/source/qbe.elna +++ b/source/qbe.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import common, cstdlib, cstdio, cstring, lexer, ast, symbol, tac +import common, sys.posix.cstdlib, sys.posix.cstdio, sys.posix.cstring, lexer, ast, symbol, tac var qbe_unique_id: Word := 0u diff --git a/source/symbol.elna b/source/symbol.elna index 531f58c..a07a9f3 100644 --- a/source/symbol.elna +++ b/source/symbol.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import cstdlib, common, ast +import sys.posix.cstdlib, common, ast type ElnaSymbolInfoKind* = (type_info, temporary_info, procedure_info) diff --git a/source/sys/posix/cctype.elna b/source/sys/posix/cctype.elna new file mode 100644 index 0000000..19c3491 --- /dev/null +++ b/source/sys/posix/cctype.elna @@ -0,0 +1,24 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module + +proc isdigit*(c: Int ) -> Int +extern + +proc isalnum*(c: Int) -> Int +extern + +proc isalpha*(c: Int) -> Int +extern + +proc isspace*(c: Int) -> Int +extern + +proc tolower*(c: Int) -> Int +extern + +proc toupper*(c: Int) -> Int +extern + +end. diff --git a/source/sys/posix/cstdio.elna b/source/sys/posix/cstdio.elna new file mode 100644 index 0000000..928c7e1 --- /dev/null +++ b/source/sys/posix/cstdio.elna @@ -0,0 +1,59 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module + +type + FILE* = extern + +var + stdin*: ^FILE := extern + stdout*: ^FILE := extern + stderr*: ^FILE := extern + +proc fopen*(pathname, mode: ^const Word8) -> ^FILE +extern + +proc fclose*(stream: ^FILE) -> Int +extern + +proc fseek*(stream: ^FILE; off: Int; whence: Int) -> Int +extern + +proc rewind*(stream: ^FILE) +extern + +proc ftell*(stream: ^FILE) -> Int +extern + +proc fflush*(stream: ^FILE) -> Int +extern + +proc fread*#[T](ptr: ^T; size: Word; nmemb: Word; stream: ^FILE) -> Word +extern + +proc fwrite*#[T](ptr: ^const T; size: Word; nitems: Word; stream: ^FILE) -> Word +extern + +proc fputc*(c: Int; stream: ^FILE) -> Word +extern + +proc perror*(s: ^const Word8) +extern + +proc puts*(s: ^const Word8) -> Int +extern + +proc putchar*(c: Int) -> Int +extern + +proc sprintf*(str: ^Word8; format: ^const Word8) #{varargs} -> Int +extern + +proc fprintf*(stream: ^FILE; format: ^const Word8) #{varargs} -> Int +extern + +proc fdopen*(fildes: Int; mode: ^const Word8) -> ^FILE +extern + +end. diff --git a/source/sys/posix/cstdlib.elna b/source/sys/posix/cstdlib.elna new file mode 100644 index 0000000..10a4d80 --- /dev/null +++ b/source/sys/posix/cstdlib.elna @@ -0,0 +1,24 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module + +proc malloc*#[T](size: Word) -> ^T +extern + +proc free*#[T](ptr: ^T) +extern + +proc calloc*#[T](nmemb: Word; size: Word) -> ^T +extern + +proc realloc*#[T](ptr: ^T; size: Word) -> ^T +extern + +proc atoi*(str: ^Word8) -> Int +extern + +proc exit*(code: Int) #{noreturn} +extern + +end. diff --git a/source/sys/posix/cstring.elna b/source/sys/posix/cstring.elna new file mode 100644 index 0000000..3973573 --- /dev/null +++ b/source/sys/posix/cstring.elna @@ -0,0 +1,30 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + v. 2.0. If a copy of the MPL was not distributed with this file, You can + obtain one at https://mozilla.org/MPL/2.0/. *) +module + +proc memset*#[T](ptr: ^T; c: Int; n: Word) -> ^Word8 +extern + +proc memcpy*#[T](dst: ^T; src: ^const T; n: Word) +extern + +proc memcmp*#[T](s1, s2: ^const T; n: Word) -> Int +extern + +proc strcmp*(s1: ^const Word8; s2: ^const Word8) -> Int +extern + +proc strncmp*(s1: ^const Word8; s2: ^const Word8; n: Word) -> Int +extern + +proc strncpy*(dst: ^Word8; src: ^const Word8; dsize: Word) -> ^Word8 +extern + +proc strcpy*(dst: ^Word8; src: ^const Word8) -> ^Word8 +extern + +proc strlen*(ptr: ^const Word8) -> Word +extern + +end. diff --git a/source/tac.elna b/source/tac.elna index 7b05ab2..3d65e42 100644 --- a/source/tac.elna +++ b/source/tac.elna @@ -2,7 +2,7 @@ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. *) module -import common, cstdlib, cstdio, cstring, lexer, ast, symbol, diagnostic +import common, sys.posix.cstdlib, sys.posix.cstdio, sys.posix.cstring, lexer, ast, symbol, diagnostic type ElnaTacOperator* = ( diff --git a/testsuite/fail_compilation/transitive_import/helper.elna b/testsuite/fail_compilation/transitive_import/helper.elna new file mode 100644 index 0000000..c3c0bfd --- /dev/null +++ b/testsuite/fail_compilation/transitive_import/helper.elna @@ -0,0 +1,6 @@ +module + +proc multiply*(x, y: Int) -> Int +return x * y + +end. diff --git a/testsuite/fail_compilation/transitive_import/middle.elna b/testsuite/fail_compilation/transitive_import/middle.elna new file mode 100644 index 0000000..0aab392 --- /dev/null +++ b/testsuite/fail_compilation/transitive_import/middle.elna @@ -0,0 +1,5 @@ +module + +import helper + +end. diff --git a/testsuite/fail_compilation/transitive_import/sut.elna b/testsuite/fail_compilation/transitive_import/sut.elna new file mode 100644 index 0000000..5423dbd --- /dev/null +++ b/testsuite/fail_compilation/transitive_import/sut.elna @@ -0,0 +1,8 @@ +module + +import middle + +proc call() -> Int +return multiply(3, 4) (* @Error Symbol 'multiply' not declared *) + +end. diff --git a/testsuite/runnable/reexport/helper.elna b/testsuite/runnable/reexport/helper.elna new file mode 100644 index 0000000..c3c0bfd --- /dev/null +++ b/testsuite/runnable/reexport/helper.elna @@ -0,0 +1,6 @@ +module + +proc multiply*(x, y: Int) -> Int +return x * y + +end. diff --git a/testsuite/runnable/reexport/left.elna b/testsuite/runnable/reexport/left.elna new file mode 100644 index 0000000..f149065 --- /dev/null +++ b/testsuite/runnable/reexport/left.elna @@ -0,0 +1,5 @@ +module + +import helper* + +end. diff --git a/testsuite/runnable/reexport/middle.elna b/testsuite/runnable/reexport/middle.elna new file mode 100644 index 0000000..0e593db --- /dev/null +++ b/testsuite/runnable/reexport/middle.elna @@ -0,0 +1,5 @@ +module + +import left*, right* + +end. diff --git a/testsuite/runnable/reexport/right.elna b/testsuite/runnable/reexport/right.elna new file mode 100644 index 0000000..f149065 --- /dev/null +++ b/testsuite/runnable/reexport/right.elna @@ -0,0 +1,5 @@ +module + +import helper* + +end. diff --git a/testsuite/runnable/reexport/sut.elna b/testsuite/runnable/reexport/sut.elna new file mode 100644 index 0000000..8ddb567 --- /dev/null +++ b/testsuite/runnable/reexport/sut.elna @@ -0,0 +1,6 @@ +program() +import middle + +begin + assert(multiply(3, 4) = 12) +end. diff --git a/tools/tree-sitter/grammar.js b/tools/tree-sitter/grammar.js index bfb4c26..b854e82 100644 --- a/tools/tree-sitter/grammar.js +++ b/tools/tree-sitter/grammar.js @@ -92,6 +92,7 @@ module.exports = grammar({ import_path: $ => seq( $.identifier, repeat(seq('.', $.identifier)), + optional(field('exported', '*')), ), type_section: $ => seq( @@ -485,12 +486,12 @@ module.exports = grammar({ ')', ), - record_constructor: $ => prec(PREC.CALL, seq( - field('type', choice($.identifier, $.generic_type)), + record_constructor: $ => seq( '{', - optional(commaSep1($.field_initializer)), + field('type', $._type_expression), + optional(seq(';', commaSep1($.field_initializer))), '}', - )), + ), field_initializer: $ => seq( field('name', $.identifier), -- cgit v1.2.3