v: support @DIR (as a comptime equivalent to os.dir(@FILE)) at runtime) (#24742)

This commit is contained in:
Delyan Angelov 2025-06-17 21:25:41 +03:00 committed by GitHub
parent e14853d6e0
commit 080684dda1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 51 additions and 3 deletions

View File

@ -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.

View File

@ -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))
}

View File

@ -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 }

View File

@ -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

View File

@ -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}'

View File

@ -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)
}

View File

@ -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()
}

View File

@ -0,0 +1,5 @@
int abc() {
return 142;
}

View File

@ -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()