diff --git a/doc/docs.md b/doc/docs.md index 8abb4ad2b4..fa9a6bbf15 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -6052,6 +6052,7 @@ that are substituted at compile time: - `@MOD` => replaced with the name of the current V module. - `@STRUCT` => replaced with the name of the current V struct. - `@FILE` => replaced with the absolute path of the V source file. +- `@DIR` => replaced with the absolute path of the *folder*, where the V source file is. - `@LINE` => replaced with the V line number where it appears (as a string). - `@FILE_LINE` => like `@FILE:@LINE`, but the file part is a relative path. - `@LOCATION` => file, line and name of the current type + method; suitable for logging. diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 31b7380128..ab6a374aec 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2636,6 +2636,13 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) { 'include', 'insert', 'preinclude', 'postinclude' { original_flag := node.main mut flag := node.main + if flag.contains('@DIR') { + vdir := c.dir_path() + val := flag.replace('@DIR', vdir) + node.val = '${node.kind} ${val}' + node.main = val + flag = val + } if flag.contains('@VROOT') { // c.note(checker.vroot_is_deprecated_message, node.pos) vroot := util.resolve_vmodroot(flag.replace('@VROOT', '@VMODROOT'), c.file.path) or { @@ -2742,6 +2749,10 @@ fn (mut c Checker) hash_stmt(mut node ast.HashStmt) { return } } + if flag.contains('@DIR') { + // expand `@DIR` to its absolute path + flag = flag.replace('@DIR', c.dir_path()) + } if flag.contains('@VEXEROOT') { // expand `@VEXEROOT` to its absolute path flag = flag.replace('@VEXEROOT', c.pref.vroot) @@ -3914,6 +3925,9 @@ fn (mut c Checker) at_expr(mut node ast.AtExpr) ast.Type { .file_path { node.val = os.real_path(c.file.path) } + .file_dir { + node.val = os.real_path(os.dir(c.file.path)) + } .line_nr { node.val = (node.pos.line_nr + 1).str() } @@ -5733,3 +5747,7 @@ pub fn (mut c Checker) update_unresolved_fixed_sizes() { } } } + +fn (mut c Checker) dir_path() string { + return os.real_path(os.dir(c.file.path)) +} diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 6024700be1..1e642bc68c 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -466,6 +466,7 @@ fn (mut p Parser) at() ast.AtExpr { '@MOD' { token.AtKind.mod_name } '@STRUCT' { token.AtKind.struct_name } '@FILE' { token.AtKind.file_path } + '@DIR' { token.AtKind.file_dir } '@LINE' { token.AtKind.line_nr } '@FILE_LINE' { token.AtKind.file_path_line_nr } '@LOCATION' { token.AtKind.location } diff --git a/vlib/v/scanner/tests/unknown_comptime_var_err.out b/vlib/v/scanner/tests/unknown_comptime_var_err.out index 88c5ae4267..3c2f9df3da 100644 --- a/vlib/v/scanner/tests/unknown_comptime_var_err.out +++ b/vlib/v/scanner/tests/unknown_comptime_var_err.out @@ -4,5 +4,5 @@ vlib/v/scanner/tests/unknown_comptime_var_err.vv:2:9: error: @ must be used befo | ^ 3 | } Details: available compile time variables: @VROOT, @VMODROOT, @VEXEROOT, @FN, @METHOD, @MOD, -@STRUCT, @VEXE, @FILE, @LINE, @COLUMN, @VHASH, @VCURRENTHASH, @VMOD_FILE, @VMODHASH, +@STRUCT, @VEXE, @FILE, @DIR, @LINE, @COLUMN, @VHASH, @VCURRENTHASH, @VMOD_FILE, @VMODHASH, @FILE_LINE, @LOCATION, @BUILD_DATE, @BUILD_TIME, @BUILD_TIMESTAMP diff --git a/vlib/v/tests/comptime/comptime_at_test.v b/vlib/v/tests/comptime/comptime_at_test.v index 51a52e4911..a6a761bc39 100644 --- a/vlib/v/tests/comptime/comptime_at_test.v +++ b/vlib/v/tests/comptime/comptime_at_test.v @@ -83,6 +83,16 @@ fn test_at_file() { assert f == 'comptime_at_test.v' } +fn test_at_dir() { + // Test @DIR + f := os.file_name(@DIR) + assert f == 'comptime' + assert os.dir(@FILE) == @DIR + d := @DIR + assert d.len > 0 + assert !d.ends_with('.v') +} + fn test_at_file_len() { // Test @FILE_LINE line1, line2 := '${@LINE}', '${@FILE_LINE}' diff --git a/vlib/v/tests/project_with_c_code/main.v b/vlib/v/tests/project_with_c_code/main.v index 87266710b3..e006b4da91 100644 --- a/vlib/v/tests/project_with_c_code/main.v +++ b/vlib/v/tests/project_with_c_code/main.v @@ -2,8 +2,15 @@ module main import v.tests.project_with_c_code.mod1 +#include "@DIR/relative.h" + +fn C.abc() int + fn main() { res := mod1.vadd(1, 2) println(res) assert res == 1003 + res2 := C.abc() + assert res2 == 142 + dump(res2) } diff --git a/vlib/v/tests/project_with_c_code/main1_test.v b/vlib/v/tests/project_with_c_code/main1_test.v index a136b4d2e9..68780a8e9b 100644 --- a/vlib/v/tests/project_with_c_code/main1_test.v +++ b/vlib/v/tests/project_with_c_code/main1_test.v @@ -2,6 +2,11 @@ // vtest retry: 3 import v.tests.project_with_c_code.mod1 +#include "@DIR/relative.h" + +fn C.abc() int + fn test_using_c_code_in_the_same_module_works() { assert 1003 == mod1.vadd(1, 2) + assert 142 == C.abc() } diff --git a/vlib/v/tests/project_with_c_code/relative.h b/vlib/v/tests/project_with_c_code/relative.h new file mode 100644 index 0000000000..71deb4a537 --- /dev/null +++ b/vlib/v/tests/project_with_c_code/relative.h @@ -0,0 +1,5 @@ +int abc() { + return 142; +} + + diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index 81ae70201e..41576b1627 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -174,6 +174,7 @@ pub enum AtKind { struct_name vexe_path file_path + file_dir line_nr column_nr vhash @@ -195,8 +196,8 @@ pub const assign_tokens = [Kind.assign, .decl_assign, .plus_assign, .minus_assig .left_shift_assign, .unsigned_right_shift_assign, .boolean_and_assign, .boolean_or_assign] pub const valid_at_tokens = ['@VROOT', '@VMODROOT', '@VEXEROOT', '@FN', '@METHOD', '@MOD', '@STRUCT', - '@VEXE', '@FILE', '@LINE', '@COLUMN', '@VHASH', '@VCURRENTHASH', '@VMOD_FILE', '@VMODHASH', - '@FILE_LINE', '@LOCATION', '@BUILD_DATE', '@BUILD_TIME', '@BUILD_TIMESTAMP'] + '@VEXE', '@FILE', '@DIR', '@LINE', '@COLUMN', '@VHASH', '@VCURRENTHASH', '@VMOD_FILE', + '@VMODHASH', '@FILE_LINE', '@LOCATION', '@BUILD_DATE', '@BUILD_TIME', '@BUILD_TIMESTAMP'] pub const token_str = build_token_str()