Skip to content

Commit

Permalink
all: add support for @LOCATION, for more convenient logging/tracing…
Browse files Browse the repository at this point in the history
…, without needing to combine `@FILE`, `@LINE` at runtime (#19488)
  • Loading branch information
spytheman committed Oct 2, 2023
1 parent 6bd4539 commit 8d98a21
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 7 deletions.
24 changes: 19 additions & 5 deletions doc/docs.md
Expand Up @@ -2455,8 +2455,9 @@ user := User.new()
This is an alternative to factory functions like `fn new_user() User {}` and should be used
instead.

Note, that these are not constructors, but simple functions. V doesn't have constructors or
classes.
> **Note**
> Note, that these are not constructors, but simple functions. V doesn't have constructors or
> classes.
### `[noinit]` structs

Expand Down Expand Up @@ -5524,9 +5525,10 @@ 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
- `@LINE` => replaced with the V line number where it appears (as a string).
- `@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
- `@COLUMN` => replaced with the column where it appears (as a string).
- `@LOCATION` => file, line and name of the current type + method; suitable for logging
- `@COLUMN` => replaced with the column where it appears (as a string)
- `@VEXE` => replaced with the path to the V compiler
- `@VEXEROOT` => will be substituted with the *folder*,
where the V executable is (as a string).
Expand All @@ -5538,7 +5540,7 @@ that are substituted at compile time:
That allows you to do the following example, useful while debugging/logging/tracing your code:
```v
eprintln('file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
eprintln(@LOCATION)
```
Another example, is if you want to embed the version/name from v.mod *inside* your executable:
Expand All @@ -5549,6 +5551,18 @@ vm := vmod.decode( @VMOD_FILE ) or { panic(err) }
eprintln('${vm.name} ${vm.version}\n ${vm.description}')
```
A program that prints its own source code (a quine):
```v
print($embed_file(@FILE).to_string())
```
> **Note**
> you can have arbitrary source code in the file, without problems, since the full file
> will be embeded into the executable, produced by compiling it. Also note that printing
> is done with `print` and not `println`, to not add another new line, missing in the
> source code.
### Compile time reflection
`$` is used as a prefix for compile time (also referred to as 'comptime') operations.
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/ast/str.v
Expand Up @@ -430,7 +430,7 @@ pub fn (x Expr) str() string {
return '${x.expr.str()} as ${global_table.type_to_str(x.typ)}'
}
AtExpr {
return '${x.val}'
return '${x.name}'
}
CTempVar {
return x.orig.str()
Expand Down
15 changes: 15 additions & 0 deletions vlib/v/checker/checker.v
Expand Up @@ -3346,6 +3346,21 @@ fn (mut c Checker) at_expr(mut node ast.AtExpr) ast.Type {
.column_nr {
node.val = (node.pos.col + 1).str()
}
.location {
mut mname := 'unknown'
if c.table.cur_fn != unsafe { nil } {
if c.table.cur_fn.is_method {
mname = c.table.type_to_str(c.table.cur_fn.receiver.typ) + '{}.' +
c.table.cur_fn.name.all_after_last('.')
} else {
mname = c.table.cur_fn.name
}
if c.table.cur_fn.is_static_type_method {
mname = mname.replace('__static__', '.') + ' (static)'
}
}
node.val = c.file.path + ':' + (node.pos.line_nr + 1).str() + ', ${mname}'
}
.vhash {
node.val = version.vhash()
}
Expand Down
1 change: 1 addition & 0 deletions vlib/v/parser/comptime.v
Expand Up @@ -350,6 +350,7 @@ fn (mut p Parser) at() ast.AtExpr {
'@FILE' { token.AtKind.file_path }
'@LINE' { token.AtKind.line_nr }
'@FILE_LINE' { token.AtKind.file_path_line_nr }
'@LOCATION' { token.AtKind.location }
'@COLUMN' { token.AtKind.column_nr }
'@VHASH' { token.AtKind.vhash }
'@VMOD_FILE' { token.AtKind.vmod_file }
Expand Down
25 changes: 25 additions & 0 deletions vlib/v/tests/comptime_at_test.v
Expand Up @@ -141,3 +141,28 @@ fn test_line_number_last_token() {
assert line1 == line2
assert line1 == line3
}

fn abc() {
assert @LOCATION.contains('comptime_at_test.v:')
assert @LOCATION.ends_with(', main.abc')
}

struct MyStruct {
}

fn MyStruct.new() MyStruct {
assert @LOCATION.ends_with('main.MyStruct.new (static)')
return MyStruct{}
}

fn (s MyStruct) mymethod() {
assert @LOCATION.contains('comptime_at_test.v:')
assert @LOCATION.ends_with('main.MyStruct{}.mymethod')
}

fn test_at_location() {
abc()
MyStruct.new().mymethod()
assert @LOCATION.contains('comptime_at_test.v:')
assert @LOCATION.ends_with('main.test_at_location')
}
3 changes: 2 additions & 1 deletion vlib/v/token/token.v
Expand Up @@ -178,6 +178,7 @@ pub enum AtKind {
vroot_path // obsolete
vexeroot_path
file_path_line_nr
location
}

pub const (
Expand All @@ -186,7 +187,7 @@ pub const (
.unsigned_right_shift_assign]

valid_at_tokens = ['@VROOT', '@VMODROOT', '@VEXEROOT', '@FN', '@METHOD', '@MOD', '@STRUCT',
'@VEXE', '@FILE', '@LINE', '@COLUMN', '@VHASH', '@VMOD_FILE', '@FILE_LINE']
'@VEXE', '@FILE', '@LINE', '@COLUMN', '@VHASH', '@VMOD_FILE', '@FILE_LINE', '@LOCATION']

token_str = build_token_str()

Expand Down

0 comments on commit 8d98a21

Please sign in to comment.