Skip to content

Commit aaf1803

Browse files
committed
v3: select imports during fastc discovery
1 parent 0f6f0e4 commit aaf1803

2 files changed

Lines changed: 139 additions & 1 deletion

File tree

vlib/v3/gen/fastc/fastc.v

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,10 @@ fn fastc_resolve_source_files(paths []string, prefs &pref.Preferences) ![]FastcS
734734
source := os.read_file(path)!
735735
mut header := fastc_scan_source_header(source, path, prefs)!
736736
if queued.module_name != '' {
737+
expected_module_name := queued.module_name.all_after_last('.')
738+
if header.module_name != expected_module_name {
739+
return error('fastc imported source `${path}` declares module `${header.module_name}` instead of `${expected_module_name}`')
740+
}
737741
header = FastcSourceHeader{
738742
module_name: queued.module_name
739743
imports: header.imports
@@ -932,11 +936,25 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
932936
tok = scan.scan()
933937
continue
934938
}
939+
if brace_depth == 0 && tok == .dollar {
940+
mut lookahead := scan
941+
if lookahead.scan() == .key_if {
942+
selected := fastc_scan_selected_comptime_branch(mut scan, scan.scan(), path, prefs)!
943+
if selected.source != '' {
944+
selected_header := fastc_scan_source_header(selected.source, path, prefs)!
945+
fastc_merge_source_header_imports(selected_header, path, mut imports, mut
946+
import_order, mut blank_imports)!
947+
has_globals = has_globals || selected_header.has_globals
948+
}
949+
tok = selected.tok
950+
continue
951+
}
952+
}
935953
if brace_depth == 0
936954
&& tok in [.key_fn, .key_struct, .key_enum, .key_interface, .key_type, .key_const, .key_global] {
937955
break
938956
}
939-
if tok != .key_import || brace_depth > 1 {
957+
if tok != .key_import || brace_depth > 0 {
940958
if tok == .lcbr {
941959
brace_depth++
942960
} else if tok == .rcbr && brace_depth > 0 {
@@ -998,6 +1016,27 @@ fn fastc_scan_source_header(source string, path string, prefs &pref.Preferences)
9981016
}
9991017
}
10001018

1019+
fn fastc_merge_source_header_imports(header FastcSourceHeader, path string, mut destination_imports map[string]string, mut destination_import_order []string, mut destination_blank_imports []string) ! {
1020+
for alias, imported_module in header.imports {
1021+
if alias.starts_with('#select#') {
1022+
fastc_register_selective_imports(imported_module, [alias['#select#'.len..]], path, mut
1023+
destination_imports)!
1024+
} else {
1025+
fastc_register_import_alias(imported_module, alias, path, mut destination_imports, mut
1026+
destination_blank_imports)!
1027+
}
1028+
}
1029+
for imported_module in header.blank_imports {
1030+
fastc_register_import_alias(imported_module, '_', path, mut destination_imports, mut
1031+
destination_blank_imports)!
1032+
}
1033+
for imported_module in header.import_order {
1034+
if imported_module !in destination_import_order {
1035+
destination_import_order << imported_module
1036+
}
1037+
}
1038+
}
1039+
10011040
fn fastc_register_import_alias(import_path string, alias string, path string, mut imports map[string]string, mut blank_imports []string) ! {
10021041
if alias == '_' {
10031042
blank_imports << import_path

vlib/v3/gen/fastc/fastc_test.v

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,105 @@ fn test_generate_files_resolves_modules_without_an_ast() {
118118
assert run_result.output.trim_space() == '42'
119119
}
120120

121+
fn test_header_discovers_imports_only_from_selected_comptime_branches() {
122+
root := os.join_path(os.vtmp_dir(), 'v3_fastc_comptime_imports_${os.getpid()}')
123+
os.rmdir_all(root) or {}
124+
os.mkdir_all(os.join_path(root, 'alpha')) or { panic(err) }
125+
os.mkdir_all(os.join_path(root, 'beta')) or { panic(err) }
126+
defer {
127+
os.rmdir_all(root) or {}
128+
}
129+
main_file := os.join_path(root, 'main.v')
130+
os.write_file(main_file, 'module main
131+
132+
\$if linux {
133+
import alpha as dep
134+
} \$else {
135+
import beta as dep
136+
}
137+
138+
fn main() {
139+
dep.ping()
140+
}
141+
') or {
142+
panic(err)
143+
}
144+
os.write_file(os.join_path(root, 'alpha', 'alpha.v'), "module alpha
145+
146+
fn init() {
147+
println('alpha init')
148+
}
149+
150+
fn cleanup() {
151+
println('alpha cleanup')
152+
}
153+
154+
pub fn ping() {}
155+
") or {
156+
panic(err)
157+
}
158+
os.write_file(os.join_path(root, 'beta', 'beta.v'), "module beta
159+
160+
fn init() {
161+
println('beta init')
162+
}
163+
164+
fn cleanup() {
165+
println('beta cleanup')
166+
}
167+
168+
pub fn ping() {}
169+
") or {
170+
panic(err)
171+
}
172+
mut prefs := pref.new_preferences()
173+
prefs.target = pref.target_from('linux', pref.host_arch()) or { panic(err) }
174+
prefs.module_search_paths = [root]
175+
header := fastc_scan_source_header(os.read_file(main_file) or { panic(err) }, main_file, prefs) or {
176+
panic(err)
177+
}
178+
assert header.import_order == ['alpha']
179+
assert header.imports['dep'] == 'alpha'
180+
assert 'beta' !in header.imports.values()
181+
sources := fastc_resolve_source_files([main_file], prefs) or { panic(err) }
182+
mut resolved_modules := []string{}
183+
for source_file in sources {
184+
if source_file.header.module_name !in resolved_modules {
185+
resolved_modules << source_file.header.module_name
186+
}
187+
}
188+
assert resolved_modules == ['main', 'alpha']
189+
prefs.building_v = true
190+
c_source := generate_source_files(sources, prefs) or { panic(err) }
191+
assert c_source.contains('\talpha__init();'), c_source
192+
assert c_source.contains('\talpha__cleanup();'), c_source
193+
assert !c_source.contains('beta__init'), c_source
194+
assert !c_source.contains('beta__cleanup'), c_source
195+
}
196+
197+
fn test_generate_files_rejects_mismatched_imported_module_declarations() {
198+
root := os.join_path(os.vtmp_dir(), 'v3_fastc_module_mismatch_${os.getpid()}')
199+
os.rmdir_all(root) or {}
200+
os.mkdir_all(os.join_path(root, 'foo')) or { panic(err) }
201+
defer {
202+
os.rmdir_all(root) or {}
203+
}
204+
main_file := os.join_path(root, 'main.v')
205+
os.write_file(main_file, 'module main\nimport foo\nfn main() { println(foo.answer()) }\n') or {
206+
panic(err)
207+
}
208+
os.write_file(os.join_path(root, 'foo', 'foo.v'),
209+
'module bar\npub fn answer() int { return 42 }\n') or { panic(err) }
210+
mut prefs := pref.new_preferences()
211+
prefs.module_search_paths = [root]
212+
mut message := ''
213+
_ := generate_files([main_file], prefs) or {
214+
message = err.msg()
215+
''
216+
}
217+
assert message.contains('declares module `bar` instead of `foo`'), message
218+
}
219+
121220
fn test_generate_files_preserves_all_blank_imports() {
122221
root := os.join_path(os.vtmp_dir(), 'v3_fastc_blank_imports_${os.getpid()}')
123222
os.rmdir_all(root) or {}

0 commit comments

Comments
 (0)