parser,checker: support `$compile_error('message')` and `$compile_warn('message')` (#14320)
parent
4400f9891e
commit
d24dce8eb3
|
@ -2,6 +2,7 @@
|
|||
-*Not yet released, changelog is not full*
|
||||
- Introduce `isize` and `usize` types, deprecate `size_t` in favor of `usize`.
|
||||
- Add `datatypes` and `datatypes.fsm` modules.
|
||||
- Add `compile_error` and `compile_warn` comptime functions.
|
||||
|
||||
-## V 0.2.4
|
||||
-*Not yet released, changelog is not full*
|
||||
|
|
31
doc/docs.md
31
doc/docs.md
|
@ -5433,9 +5433,6 @@ numbers: [1, 2, 3]
|
|||
3
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
#### `$env`
|
||||
|
||||
```v
|
||||
|
@ -5451,6 +5448,34 @@ V can bring in values at compile time from environment variables.
|
|||
`$env('ENV_VAR')` can also be used in top-level `#flag` and `#include` statements:
|
||||
`#flag linux -I $env('JAVA_HOME')/include`.
|
||||
|
||||
#### `$compile_error` and `$compile_warn`
|
||||
|
||||
These two comptime functions are very useful for displaying custom errors/warnings during
|
||||
compile time.
|
||||
|
||||
Both receive as their only argument a string literal that contains the message to display:
|
||||
|
||||
```v failcompile nofmt
|
||||
// x.v
|
||||
module main
|
||||
|
||||
$if linux {
|
||||
$compile_error('Linux is not supported')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
$ v run x.v
|
||||
x.v:4:5: error: Linux is not supported
|
||||
2 |
|
||||
3 | $if linux {
|
||||
4 | $compile_error('Linux is not supported')
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
5 | }
|
||||
6 |
|
||||
```
|
||||
|
||||
### Environment specific files
|
||||
|
||||
If a file has an environment-specific suffix, it will only be compiled for that environment.
|
||||
|
|
|
@ -10,6 +10,13 @@ import v.pkgconfig
|
|||
|
||||
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
||||
node.left_type = c.expr(node.left)
|
||||
if node.method_name == 'compile_error' {
|
||||
c.error(node.args_var, node.pos)
|
||||
return ast.void_type
|
||||
} else if node.method_name == 'compile_warn' {
|
||||
c.warn(node.args_var, node.pos)
|
||||
return ast.void_type
|
||||
}
|
||||
if node.is_env {
|
||||
env_value := util.resolve_env_value("\$env('$node.args_var')", false) or {
|
||||
c.error(err.msg(), node.env_pos)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
vlib/v/checker/tests/compile_error.vv:4:5: error: Only Serenity is supported
|
||||
2 |
|
||||
3 | $if !serenity {
|
||||
4 | $compile_error('Only Serenity is supported')
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
5 | }
|
||||
6 |
|
||||
vlib/v/checker/tests/compile_error.vv:8:5: error: On non Vinix this warning should be shown
|
||||
6 |
|
||||
7 | $if !vinix {
|
||||
8 | $compile_warn('On non Vinix this warning should be shown')
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
9 | }
|
||||
10 |
|
|
@ -0,0 +1,15 @@
|
|||
module main
|
||||
|
||||
$if !serenity {
|
||||
$compile_error('Only Serenity is supported')
|
||||
}
|
||||
|
||||
$if !vinix {
|
||||
$compile_warn('On non Vinix this warning should be shown')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('Hello from Serenity')
|
||||
}
|
||||
|
||||
|
|
@ -9,7 +9,8 @@ import v.pref
|
|||
import v.token
|
||||
|
||||
const (
|
||||
supported_comptime_calls = ['html', 'tmpl', 'env', 'embed_file', 'pkgconfig']
|
||||
supported_comptime_calls = ['html', 'tmpl', 'env', 'embed_file', 'pkgconfig', 'compile_error',
|
||||
'compile_warn']
|
||||
comptime_types = ['Map', 'Array', 'Int', 'Float', 'Struct', 'Interface', 'Enum',
|
||||
'Sumtype']
|
||||
)
|
||||
|
@ -85,9 +86,9 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
err_node := ast.ComptimeCall{
|
||||
scope: 0
|
||||
}
|
||||
start_pos := p.tok.pos()
|
||||
p.check(.dollar)
|
||||
start_pos := p.prev_tok.pos()
|
||||
error_msg := 'only `\$tmpl()`, `\$env()`, `\$embed_file()`, `\$pkgconfig()` and `\$vweb.html()` comptime functions are supported right now'
|
||||
error_msg := 'only `\$tmpl()`, `\$env()`, `\$embed_file()`, `\$pkgconfig()`, `\$vweb.html()`, `\$compile_error()` and `\$compile_warn()` comptime functions are supported right now'
|
||||
if p.peek_tok.kind == .dot {
|
||||
name := p.check_name() // skip `vweb.html()` TODO
|
||||
if name != 'vweb' {
|
||||
|
@ -96,7 +97,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
}
|
||||
p.check(.dot)
|
||||
}
|
||||
method_name := p.check_name() // (.name)
|
||||
method_name := p.check_name()
|
||||
if method_name !in parser.supported_comptime_calls {
|
||||
p.error(error_msg)
|
||||
return err_node
|
||||
|
@ -105,8 +106,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
is_html := method_name == 'html'
|
||||
// $env('ENV_VAR_NAME')
|
||||
p.check(.lpar)
|
||||
spos := p.tok.pos()
|
||||
if method_name == 'env' {
|
||||
if method_name in ['env', 'pkgconfig', 'compile_error', 'compile_warn'] {
|
||||
s := p.tok.lit
|
||||
p.check(.string)
|
||||
p.check(.rpar)
|
||||
|
@ -114,22 +114,10 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
scope: 0
|
||||
method_name: method_name
|
||||
args_var: s
|
||||
is_env: true
|
||||
env_pos: spos
|
||||
pos: spos.extend(p.prev_tok.pos())
|
||||
}
|
||||
}
|
||||
if method_name == 'pkgconfig' {
|
||||
s := p.tok.lit
|
||||
p.check(.string)
|
||||
p.check(.rpar)
|
||||
return ast.ComptimeCall{
|
||||
scope: 0
|
||||
method_name: method_name
|
||||
args_var: s
|
||||
is_pkgconfig: true
|
||||
env_pos: spos
|
||||
pos: spos.extend(p.prev_tok.pos())
|
||||
is_env: method_name == 'env'
|
||||
is_pkgconfig: method_name == 'pkgconfig'
|
||||
env_pos: start_pos
|
||||
pos: start_pos.extend(p.prev_tok.pos())
|
||||
}
|
||||
}
|
||||
literal_string_param := if is_html { '' } else { p.tok.lit }
|
||||
|
@ -152,7 +140,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
// Validate that the epath exists, and that it is actually a file.
|
||||
if epath == '' {
|
||||
p.error_with_pos('supply a valid relative or absolute file path to the file to embed',
|
||||
spos)
|
||||
start_pos)
|
||||
return err_node
|
||||
}
|
||||
if !p.pref.is_fmt {
|
||||
|
@ -163,12 +151,12 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||
epath = os.real_path(os.join_path_single(os.dir(p.file_name), epath))
|
||||
if !os.exists(epath) {
|
||||
p.error_with_pos('"$epath" does not exist so it cannot be embedded',
|
||||
spos)
|
||||
start_pos)
|
||||
return err_node
|
||||
}
|
||||
if !os.is_file(epath) {
|
||||
p.error_with_pos('"$epath" is not a file so it cannot be embedded',
|
||||
spos)
|
||||
start_pos)
|
||||
return err_node
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue