Skip to content

Commit d4ce72a

Browse files
authored
feat(rivetc+rivet): support subimports in import declarations (#58)
This allows submodules to be imported within a single `import` declaration. `import module_path/{ subimports }`
1 parent 13e5f6a commit d4ce72a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+558
-495
lines changed

cmd/src/rivet.ri

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/console;
6-
import std/process;
7-
8-
import rivet;
9-
import rivet/prefs;
10-
import rivet/utils;
5+
import std/{ console, process };
6+
import rivet/{ self, prefs, utils };
117

128
import ./tools;
139

cmd/src/tools/cmd_fmt.ri

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,8 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/flag;
6-
import std/console;
7-
import std/fs.Directory;
8-
9-
import rivet/ast;
10-
import rivet/fmt;
11-
import rivet/prefs;
12-
import rivet/utils;
13-
import rivet/parser;
5+
import std/{ flag, console, fs.Directory };
6+
import rivet/{ ast, fmt, prefs, utils, parser };
147

158
var fmt_desc := "Formats the given Rivet source files or recursively formats all files in the
169
directory, then prints their formatted source to stdout.";

cmd/src/tools/cmd_new.ri

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/flag;
6-
import std/semver;
7-
import std/strings;
8-
import std/console;
9-
import std/process;
10-
import std/fs.{ Path, Directory, self };
11-
12-
import rivet/build;
13-
import rivet/utils;
5+
import std/{
6+
flag, semver, strings, console, process, fs.{self, Path, Directory}
7+
};
8+
import rivet/{ build, utils };
149

1510
import ./templates;
1611

cmd/src/tools/utils.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/console;
6-
import std/console/styles;
5+
import std/{ console, console/styles };
76

87
#[inline]
98
pub func readln(prompt: string) -> ?string {

lib/rivet/src/ast/CHeader.ri

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/traits;
6-
import std/process;
7-
import std/strings;
8-
import std/fs.Path;
5+
import std/{ traits, process, strings, fs.Path };
96

107
import ../token;
118

lib/rivet/src/ast/Decl.ri

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,7 @@ pub enum Decl {
99
Empty(token.Pos),
1010
Comment(Comment),
1111
ComptimeIf(ComptimeIf),
12-
Import {
13-
attributes: Attributes;
14-
is_public: bool;
15-
path: string;
16-
path_pos: token.Pos;
17-
mut alias_name: string;
18-
mut has_custom_alias: bool;
19-
glob: bool;
20-
import_list: []ImportListInfo;
21-
mut info: ImportedMod;
22-
pos: token.Pos;
23-
},
12+
Import(ImportDecl),
2413
Extern {
2514
docs: []Comment;
2615
attributes: Attributes;
@@ -200,10 +189,17 @@ pub struct EnumVariantDecl {
200189
pub pos: token.Pos;
201190
}
202191

203-
pub struct ImportListInfo {
204-
pub name: string;
205-
pub alias_name: string;
192+
pub struct ImportDecl {
193+
pub attributes: Attributes;
194+
pub is_public: bool;
195+
pub path: string;
196+
pub path_pos: token.Pos;
197+
pub mut alias_name: string;
206198
pub mut has_custom_alias: bool;
199+
pub glob: bool;
200+
pub mut subimports: []mut ImportDecl;
201+
pub import_list: []ImportListInfo;
202+
pub mut info: ImportedMod;
207203
pub pos: token.Pos;
208204
}
209205

@@ -216,6 +212,13 @@ pub struct ImportedMod {
216212
pub mut mod: Module;
217213
}
218214

215+
pub struct ImportListInfo {
216+
pub name: string;
217+
pub alias_name: string;
218+
pub mut has_custom_alias: bool;
219+
pub pos: token.Pos;
220+
}
221+
219222
pub func filter_field_decl(decls: []Decl) -> []Decl {
220223
mut fields := []Decl();
221224
for decl in decls {

lib/rivet/src/ast/Env.ri

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/sys;
6-
import std/fs.Path;
5+
import std/{ sys, fs.Path };
76

8-
import ../prefs;
9-
import ../report;
10-
import ../utils;
7+
import ../{ prefs, report, utils };
118

129
#[boxed]
1310
pub struct Env {

lib/rivet/src/ast/Expr.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/traits;
6-
import std/strings;
5+
import std/{ traits, strings };
76

87
import ../token;
98

lib/rivet/src/ast/Sym.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/traits;
6-
import std/strings;
5+
import std/{ traits, strings };
76

87
import ../token;
98

lib/rivet/src/ast/Type.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/traits;
6-
import std/process;
7-
import std/strings.Builder;
5+
import std/{ traits, process, strings.Builder };
86

97
import ../token;
108
import ../utils;

lib/rivet/src/ast/comptime.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
import std/sys;
66

7-
import ../token;
8-
import ../report;
7+
import ../{ token, report };
98

109
pub struct ComptimeIf {
1110
mut branches: []mut ComptimeIfBranch;

lib/rivet/src/builder/mod.ri

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,13 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import std/traits;
6-
import std/console;
7-
import std/process;
8-
import std/fs.{ Path, Directory };
5+
import std/{
6+
traits, console, process, fs.{ Path, Directory }
7+
};
98

10-
import ../ast;
11-
import ../utils;
12-
import ../prefs;
13-
import ../token;
14-
import ../parser;
15-
import ../report;
16-
import ../checker;
17-
import ../codegen;
18-
import ../resolver;
19-
import ../depgraph;
9+
import ../{
10+
ast, utils, prefs, token, parser, report, checker, codegen, resolver, depgraph
11+
};
2012

2113
pub struct Builder {
2214
mut env: ast.Env;
@@ -160,14 +152,7 @@ pub struct Builder {
160152
) -> ! {
161153
for mut decl in decls {
162154
if decl is .Import(mut import_decl) {
163-
if self.env.universe.scope.exists(import_decl.info.full_name) {
164-
continue;
165-
}
166-
import_decl.info = self.load_module(
167-
import_decl.path, import_decl.alias_name, sf.path,
168-
import_decl.path_pos
169-
)!;
170-
import_decl.alias_name = import_decl.info.alias_name;
155+
self.import_module(sf, import_decl)!;
171156
} else if decl is .ComptimeIf(mut comptime_if) {
172157
mut ct_decls := ast.nodes_to_decls(
173158
self.env.evalue_comptime_if(comptime_if)
@@ -177,6 +162,23 @@ pub struct Builder {
177162
}
178163
}
179164

165+
func import_module(mut self, sf: ast.SourceFile, mut import_decl: ast.ImportDecl) -> ! {
166+
if !import_decl.subimports.is_empty() {
167+
for mut subimport in import_decl.subimports {
168+
self.import_module(sf, subimport)!;
169+
}
170+
return;
171+
}
172+
if self.env.universe.scope.exists(import_decl.info.full_name) {
173+
return;
174+
}
175+
import_decl.info = self.load_module(
176+
import_decl.path, import_decl.alias_name, sf.path,
177+
import_decl.path_pos
178+
)!;
179+
import_decl.alias_name = import_decl.info.alias_name;
180+
}
181+
180182
func load_module(
181183
mut self, path: string, alias_name: string, file_path: string, pos: token.Pos
182184
) -> !ast.ImportedMod {
@@ -331,21 +333,33 @@ pub struct Builder {
331333
}
332334
for d in pf.decls {
333335
if d is .Import(import_decl) {
334-
if !import_decl.info.found {
335-
continue; // module not found
336+
if import_decl.subimports.len > 0 {
337+
for subimport in import_decl.subimports {
338+
if dep := import_graph_mod(&subimport, pf) {
339+
deps.push(dep);
340+
}
341+
}
342+
} else if dep := import_graph_mod(&import_decl, pf) {
343+
deps.push(dep);
336344
}
337-
if import_decl.info.full_name == pf.mod.name {
338-
report.error("import cycle detected", import_decl.pos);
339-
continue;
340-
}
341-
deps.push(import_decl.info.full_name);
342345
}
343346
}
344347
g.add(pf.mod.name, deps);
345348
}
346349
return g;
347350
}
348351

352+
func import_graph_mod(import_decl: &ast.ImportDecl, pf: ast.SourceFile) -> ?string {
353+
if !import_decl.info.found {
354+
return none; // module not found
355+
}
356+
if import_decl.info.full_name == pf.mod.name {
357+
report.error("import cycle detected", import_decl.pos);
358+
return none;
359+
}
360+
return import_decl.info.full_name;
361+
}
362+
349363
func vlog(&self, msg: string, args: ...traits.Stringable) {
350364
if self.env.prefs.is_verbose {
351365
console.writeln(utils.bold(utils.green("[rivet-log] ")).concat(msg), args);

lib/rivet/src/checker/builtin_call.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../report;
5+
import ../{ ast, report };
76

87
extend Checker {
98
func check_builtin_call(mut self, mut builtin_call: ast.Expr.BuiltinCall) -> ast.Type {

lib/rivet/src/checker/call_expr.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../report;
7-
import ../utils/maps;
5+
import ../{ ast, report, utils/maps };
86

97
extend Checker {
108
func check_call(mut self, mut call_expr: ast.Expr.Call) -> ast.Type {

lib/rivet/src/checker/decls.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../report;
5+
import ../{ ast, report };
76

87
extend Checker {
98
func check_global_vars(mut self, mut decls: []mut ast.Decl) {

lib/rivet/src/checker/exprs.ri

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../report;
5+
import ../{ ast, report };
76

87
extend Checker {
98
func check_expr(mut self, mut expr: ast.Expr) -> ast.Type {

lib/rivet/src/checker/match_expr.ri

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../utils;
7-
import ../report;
8-
import ../utils/maps;
5+
import ../{ ast, utils, report, utils/maps };
96

107
extend Checker {
118
const MATCH_EXHAUSTIVE_CUTOFF_LIMIT := 12;

lib/rivet/src/checker/mod.ri

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../token;
7-
import ../utils;
8-
import ../report;
5+
import ../{ ast, token, utils, report };
96

107
enum LoopControlLegalityTracker {
118
None,

lib/rivet/src/checker/name_cases.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
import std/traits;
66

7-
import ../token;
8-
import ../utils;
9-
import ../report;
7+
import ../{ token, utils, report };
108

119
extend Checker {
1210
enum NameCase as uint8 < traits.Stringable {

lib/rivet/src/checker/stmts.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../token;
7-
import ../report;
5+
import ../{ ast, token, report };
86

97
extend Checker {
108
func check_stmts(mut self, mut stmts: []mut ast.Stmt) {

lib/rivet/src/checker/check_trait_impl.ri renamed to lib/rivet/src/checker/trait_impl.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// source code is governed by an MIT license that can be found in the LICENSE
33
// file.
44

5-
import ../ast;
6-
import ../token;
7-
import ../report;
5+
import ../{ ast, token, report };
86

97
extend Checker {
108
func check_trait_impl(mut self, impltor: ast.TypeSym, trait_sym: ast.TypeSym, pos: token.Pos) {

0 commit comments

Comments
 (0)