mirror of
https://github.com/vlang/v.git
synced 2025-09-07 22:30:57 -04:00
comptime: support type interpolation in the msg argument of $compile_warn(msg)
and $compile_error(msg)
(#24992)
This commit is contained in:
parent
56b51b69d8
commit
cd94cff219
@ -9,16 +9,17 @@ import v.token
|
|||||||
import v.util
|
import v.util
|
||||||
import v.pkgconfig
|
import v.pkgconfig
|
||||||
import v.type_resolver
|
import v.type_resolver
|
||||||
|
import strings
|
||||||
|
|
||||||
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
||||||
if node.left !is ast.EmptyExpr {
|
if node.left !is ast.EmptyExpr {
|
||||||
node.left_type = c.expr(mut node.left)
|
node.left_type = c.expr(mut node.left)
|
||||||
}
|
}
|
||||||
if node.method_name == 'compile_error' {
|
if node.method_name == 'compile_error' {
|
||||||
c.error(node.args_var, node.pos)
|
c.error(c.comptime_call_msg(node), node.pos)
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
} else if node.method_name == 'compile_warn' {
|
} else if node.method_name == 'compile_warn' {
|
||||||
c.warn(node.args_var, node.pos)
|
c.warn(c.comptime_call_msg(node), node.pos)
|
||||||
return ast.void_type
|
return ast.void_type
|
||||||
}
|
}
|
||||||
if node.is_env {
|
if node.is_env {
|
||||||
@ -203,6 +204,16 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
|||||||
return f.return_type
|
return f.return_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut c Checker) comptime_call_msg(node ast.ComptimeCall) string {
|
||||||
|
return if node.args_var.len > 0 {
|
||||||
|
node.args_var
|
||||||
|
} else if value := c.eval_comptime_const_expr(node.args[0].expr, -1) {
|
||||||
|
value.string() or { '' }
|
||||||
|
} else {
|
||||||
|
''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut c Checker) comptime_selector(mut node ast.ComptimeSelector) ast.Type {
|
fn (mut c Checker) comptime_selector(mut node ast.ComptimeSelector) ast.Type {
|
||||||
node.left_type = c.expr(mut node.left)
|
node.left_type = c.expr(mut node.left)
|
||||||
mut expr_type := c.unwrap_generic(c.expr(mut node.field_expr))
|
mut expr_type := c.unwrap_generic(c.expr(mut node.field_expr))
|
||||||
@ -415,6 +426,22 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp
|
|||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
return util.smart_quote(expr.val, expr.is_raw)
|
return util.smart_quote(expr.val, expr.is_raw)
|
||||||
}
|
}
|
||||||
|
ast.StringInterLiteral {
|
||||||
|
if nlevel < 0 {
|
||||||
|
mut sb := strings.new_builder(20)
|
||||||
|
for i, val in expr.vals {
|
||||||
|
sb.write_string(val)
|
||||||
|
if e := expr.exprs[i] {
|
||||||
|
if value := c.eval_comptime_const_expr(e, nlevel + 1) {
|
||||||
|
sb.write_string(value.string() or { '' })
|
||||||
|
} else {
|
||||||
|
c.error('unsupport expr `${e.str()}`', e.pos())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.str()
|
||||||
|
}
|
||||||
|
}
|
||||||
ast.CharLiteral {
|
ast.CharLiteral {
|
||||||
runes := expr.val.runes()
|
runes := expr.val.runes()
|
||||||
if runes.len > 0 {
|
if runes.len > 0 {
|
||||||
@ -427,6 +454,28 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp
|
|||||||
// an existing constant?
|
// an existing constant?
|
||||||
return c.eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
return c.eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
||||||
}
|
}
|
||||||
|
idx := c.table.cur_fn.generic_names.index(expr.name)
|
||||||
|
if typ := c.table.cur_concrete_types[idx] {
|
||||||
|
sym := c.table.sym(typ)
|
||||||
|
return sym.str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
if expr.expr is ast.Ident {
|
||||||
|
idx := c.table.cur_fn.generic_names.index(expr.expr.name)
|
||||||
|
if typ := c.table.cur_concrete_types[idx] {
|
||||||
|
sym := c.table.sym(typ)
|
||||||
|
match expr.field_name {
|
||||||
|
'name' {
|
||||||
|
return sym.name
|
||||||
|
}
|
||||||
|
'idx' {
|
||||||
|
return i32(sym.idx)
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
cast_expr_value := c.eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
cast_expr_value := c.eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
||||||
|
@ -2285,10 +2285,16 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
|
|||||||
f.write("\$pkgconfig('${node.args_var}')")
|
f.write("\$pkgconfig('${node.args_var}')")
|
||||||
}
|
}
|
||||||
node.method_name in ['compile_error', 'compile_warn'] {
|
node.method_name in ['compile_error', 'compile_warn'] {
|
||||||
if node.args_var.contains("'") {
|
if node.args.len == 0 {
|
||||||
f.write('\$${node.method_name}("${node.args_var}")')
|
if node.args_var.contains("'") {
|
||||||
|
f.write('\$${node.method_name}("${node.args_var}")')
|
||||||
|
} else {
|
||||||
|
f.write("\$${node.method_name}('${node.args_var}')")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
f.write("\$${node.method_name}('${node.args_var}')")
|
f.write('\$${node.method_name}(')
|
||||||
|
f.expr(node.args[0].expr)
|
||||||
|
f.write(')')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.method_name == 'd' {
|
node.method_name == 'd' {
|
||||||
|
@ -159,7 +159,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||||||
is_html := method_name == 'html'
|
is_html := method_name == 'html'
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
arg_pos := p.tok.pos()
|
arg_pos := p.tok.pos()
|
||||||
if method_name in ['env', 'pkgconfig', 'compile_error', 'compile_warn'] {
|
if method_name in ['env', 'pkgconfig'] {
|
||||||
s := p.tok.lit
|
s := p.tok.lit
|
||||||
p.check(.string)
|
p.check(.string)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
@ -172,6 +172,28 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
|
|||||||
env_pos: start_pos
|
env_pos: start_pos
|
||||||
pos: start_pos.extend(p.prev_tok.pos())
|
pos: start_pos.extend(p.prev_tok.pos())
|
||||||
}
|
}
|
||||||
|
} else if method_name in ['compile_error', 'compile_warn'] {
|
||||||
|
mut s := ''
|
||||||
|
mut args := []ast.CallArg{}
|
||||||
|
if p.tok.kind == .string && p.peek_tok.kind == .rpar {
|
||||||
|
s = p.tok.lit
|
||||||
|
p.check(.string)
|
||||||
|
} else {
|
||||||
|
args << ast.CallArg{
|
||||||
|
expr: p.string_expr()
|
||||||
|
typ: ast.string_type
|
||||||
|
ct_expr: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.check(.rpar)
|
||||||
|
return ast.ComptimeCall{
|
||||||
|
scope: unsafe { nil }
|
||||||
|
method_name: method_name
|
||||||
|
args_var: s
|
||||||
|
env_pos: start_pos
|
||||||
|
pos: start_pos.extend(p.prev_tok.pos())
|
||||||
|
args: args
|
||||||
|
}
|
||||||
} else if method_name == 'res' {
|
} else if method_name == 'res' {
|
||||||
mut has_args := false
|
mut has_args := false
|
||||||
mut type_index := ''
|
mut type_index := ''
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
const msg = 'invalid type'
|
||||||
|
|
||||||
|
fn t[T]() int {
|
||||||
|
$if T is i8 {
|
||||||
|
assert typeof[T]().name == typeof[i8]().name
|
||||||
|
$compile_warn('invalid type ${T.name} ${T.idx}')
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn t2[T, R]() int {
|
||||||
|
$if T is i8 && R is i16 {
|
||||||
|
assert typeof[T]().name == typeof[i8]().name
|
||||||
|
assert typeof[R]().name == typeof[i16]().name
|
||||||
|
$compile_warn('invalid type ${T.name} ${T.idx}, ${R.name} ${R.idx}')
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn t3[T, R, E]() int {
|
||||||
|
$if T is i8 && R is i16 && E is i32 {
|
||||||
|
assert typeof[T]().name == typeof[i8]().name
|
||||||
|
assert typeof[R]().name == typeof[i16]().name
|
||||||
|
assert typeof[E]().name == typeof[i32]().name
|
||||||
|
$compile_warn('invalid type ${T.name} ${T.idx}, ${R.name} ${R.idx}, ${E.name} ${E.idx}')
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
assert t[i8]() == 1
|
||||||
|
assert t2[i8, i16]() == 1
|
||||||
|
assert t3[i8, i16, i32]() == 1
|
||||||
|
assert t[i16]() == 0
|
||||||
|
assert t2[i16, i16]() == 0
|
||||||
|
assert t3[i16, i16, i16]() == 0
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user