Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions vlib/v/gen/c/cache_program_file_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module c

import os

// cache_program_file_matches must accept a program file under any spelling that
// resolves to it, and resolve each written path at most once per memo.
fn test_cache_program_file_matches_resolves_each_written_path_once() {
root := os.join_path(os.temp_dir(), 'v_cache_program_file_${os.getpid()}')
os.rmdir_all(root) or {}
os.mkdir_all(root)!
defer {
os.rmdir_all(root) or {}
}
program := os.join_path(root, 'main.v')
other := os.join_path(root, 'other.v')
os.write_file(program, 'module main\n')!
os.write_file(other, 'module main\n')!
program_files := {
os.real_path(program): true
}
// This spelling only matches after resolution (join_path would drop the `.`).
dotted := root + os.path_separator + '.' + os.path_separator + 'main.v'
assert !program_files[dotted]
mut memo := map[string]bool{}
assert cache_program_file_matches(program_files, dotted, mut memo)
assert !cache_program_file_matches(program_files, other, mut memo)
assert memo == {
dotted: true
other: false
}
// A memoized answer is used as is; the path is not resolved again.
mut seeded := {
other: true
}
assert cache_program_file_matches(program_files, other, mut seeded)
// Without program files nothing matches, and nothing is resolved or memoized.
mut empty_memo := map[string]bool{}
assert !cache_program_file_matches(map[string]bool{}, other, mut empty_memo)
assert empty_memo.len == 0
}
4 changes: 3 additions & 1 deletion vlib/v/gen/c/cleanc.v
Original file line number Diff line number Diff line change
Expand Up @@ -1926,11 +1926,13 @@ pub fn cache_external_input_snapshot_with_resolved_flags(a &flat.FlatAst, vroot
mut preinclude_context_directives := []string{}
mut conditional_context_mutations := map[string]bool{}
mut conditionals := []CCacheConditional{}
mut program_file_memo := map[string]bool{}
for node_id in c_cache_external_input_node_order(a) {
node := a.nodes[node_id]
if node.kind == .file {
cur_file = node.value
cur_file_is_program = program_files[cur_file] || program_files[os.real_path(cur_file)]
cur_file_is_program = cache_program_file_matches(program_files, cur_file, mut
program_file_memo)
cur_module = ''
conditionals.clear()
continue
Expand Down
10 changes: 8 additions & 2 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,19 @@ fn (mut g FlatGen) gen_fn_items(items []FlatFnGenItem) {
// file_is_cache_program_file reports whether `file`, as written or resolved,
// is one of the cached program files, memoizing the answer per file.
fn (g &FlatGen) file_is_cache_program_file(file string, mut memo map[string]bool) bool {
if g.cache_program_files.len == 0 {
return cache_program_file_matches(g.cache_program_files, file, mut memo)
}

// cache_program_file_matches reports whether `file`, as written or resolved, is
// one of `program_files`. It resolves each written path at most once per memo.
fn cache_program_file_matches(program_files map[string]bool, file string, mut memo map[string]bool) bool {
if program_files.len == 0 {
return false
}
if known := memo[file] {
return known
}
is_program := g.cache_program_files[file] || g.cache_program_files[os.real_path(file)]
is_program := program_files[file] || program_files[os.real_path(file)]
memo[file] = is_program
return is_program
}
Expand Down
Loading