scanner: add support for @VMOD_FILE
parent
bb48851092
commit
3cfdd2a4cd
26
doc/docs.md
26
doc/docs.md
|
@ -1622,6 +1622,32 @@ $if debug {
|
||||||
If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign. Right now it can only be used to detect
|
If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign. Right now it can only be used to detect
|
||||||
an OS or a `-debug` compilation option.
|
an OS or a `-debug` compilation option.
|
||||||
|
|
||||||
|
## Compile time pseudo variables
|
||||||
|
|
||||||
|
V also gives your code access to a set of pseudo string variables, that are substituted at compile time:
|
||||||
|
|
||||||
|
- `@FN` => replaced with the name of the current V function
|
||||||
|
- `@MOD` => replaced with the name of the current V module
|
||||||
|
- `@STRUCT` => replaced with the name of the current V struct
|
||||||
|
- `@FILE` => replaced with the path of the V source file
|
||||||
|
- `@LINE` => replaced with the V line number where it appears (as a string).
|
||||||
|
- `@COLUMN` => replaced with the column where it appears (as a string).
|
||||||
|
- `@VEXE` => replaced with the path to the V compiler
|
||||||
|
- `@VHASH` => replaced with the shortened commit hash of the V compiler (as a string).
|
||||||
|
- `@VMOD_FILE` => replaced with the contents of the nearest v.mod file (as a string).
|
||||||
|
|
||||||
|
That allows you to do the following example, useful while debugging/logging/tracing your code:
|
||||||
|
```v
|
||||||
|
eprintln( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
|
||||||
|
```
|
||||||
|
|
||||||
|
Another example, is if you want to embed the version/name from v.mod *inside* your executable:
|
||||||
|
```v
|
||||||
|
import v.vmod
|
||||||
|
vm := vmod.decode( @VMOD_FILE ) or { panic(err) }
|
||||||
|
eprintln('$vm.name $vm.version\n $vm.description')
|
||||||
|
```
|
||||||
|
|
||||||
## Reflection via codegen
|
## Reflection via codegen
|
||||||
|
|
||||||
Having built-in JSON support is nice, but V also allows you to create efficient
|
Having built-in JSON support is nice, but V also allows you to create efficient
|
||||||
|
|
|
@ -7,6 +7,7 @@ import os
|
||||||
import v.token
|
import v.token
|
||||||
import v.pref
|
import v.pref
|
||||||
import v.util
|
import v.util
|
||||||
|
import v.vmod
|
||||||
|
|
||||||
const (
|
const (
|
||||||
single_quote = `\'`
|
single_quote = `\'`
|
||||||
|
@ -32,6 +33,7 @@ pub mut:
|
||||||
fn_name string // needed for @FN
|
fn_name string // needed for @FN
|
||||||
mod_name string // needed for @MOD
|
mod_name string // needed for @MOD
|
||||||
struct_name string // needed for @STRUCT
|
struct_name string // needed for @STRUCT
|
||||||
|
vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path*
|
||||||
is_print_line_on_error bool
|
is_print_line_on_error bool
|
||||||
is_print_colored_error bool
|
is_print_colored_error bool
|
||||||
is_print_rel_paths_on_error bool
|
is_print_rel_paths_on_error bool
|
||||||
|
@ -745,6 +747,7 @@ pub fn (mut s Scanner) scan() token.Token {
|
||||||
// @LINE => will be substituted with the V line number where it appears (as a string).
|
// @LINE => will be substituted with the V line number where it appears (as a string).
|
||||||
// @COLUMN => will be substituted with the column where it appears (as a string).
|
// @COLUMN => will be substituted with the column where it appears (as a string).
|
||||||
// @VHASH => will be substituted with the shortened commit hash of the V compiler (as a string).
|
// @VHASH => will be substituted with the shortened commit hash of the V compiler (as a string).
|
||||||
|
// @VMOD_FILE => will be substituted with the contents of the nearest v.mod file (as a string).
|
||||||
// This allows things like this:
|
// This allows things like this:
|
||||||
// println( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
|
// println( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
|
||||||
// ... which is useful while debugging/tracing
|
// ... which is useful while debugging/tracing
|
||||||
|
@ -773,6 +776,17 @@ pub fn (mut s Scanner) scan() token.Token {
|
||||||
if name == 'VHASH' {
|
if name == 'VHASH' {
|
||||||
return s.new_token(.string, util.vhash(), 6)
|
return s.new_token(.string, util.vhash(), 6)
|
||||||
}
|
}
|
||||||
|
if name == 'VMOD_FILE' {
|
||||||
|
if s.vmod_file_content.len == 0 {
|
||||||
|
vmod_file_location := vmod.mod_file_cacher.get( os.dir( os.real_path(s.file_path) ) )
|
||||||
|
if vmod_file_location.vmod_file.len == 0 {
|
||||||
|
s.error('@VMOD_FILE can be used only in projects, that have v.mod file')
|
||||||
|
}
|
||||||
|
vmod_content := os.read_file(vmod_file_location.vmod_file) or {''}
|
||||||
|
s.vmod_file_content = vmod_content
|
||||||
|
}
|
||||||
|
return s.new_token(.string, s.vmod_file_content, 10)
|
||||||
|
}
|
||||||
if !token.is_key(name) {
|
if !token.is_key(name) {
|
||||||
s.error('@ must be used before keywords (e.g. `@type string`)')
|
s.error('@ must be used before keywords (e.g. `@type string`)')
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,3 +82,12 @@ fn test_scan() {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_vmod_file() {
|
||||||
|
content := @VMOD_FILE
|
||||||
|
assert content.len > 0
|
||||||
|
assert content.contains('Module {')
|
||||||
|
assert content.contains('name:')
|
||||||
|
assert content.contains('version:')
|
||||||
|
assert content.contains('description:')
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue