parser,ast,checker,cgen: use enum comparisons instead of string ones on ast.ComptimeCall.method_name (#25003)

This commit is contained in:
Delyan Angelov 2025-07-30 13:59:36 +03:00 committed by GitHub
parent cd94cff219
commit b876644e82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 88 additions and 69 deletions

View File

@ -1072,13 +1072,13 @@ fn (t Tree) comptime_call(node ast.ComptimeCall) &Node {
mut obj := create_object()
obj.add_terse('ast_type', t.string_node('ComptimeCall'))
obj.add_terse('method_name', t.string_node(node.method_name))
obj.add_terse('kind', t.enum_node(node.kind))
obj.add_terse('left', t.expr(node.left))
obj.add_terse('is_vweb', t.bool_node(node.is_vweb))
obj.add_terse('is_veb', t.bool_node(node.is_veb))
obj.add_terse('veb_tmpl', t.string_node(node.veb_tmpl.path))
obj.add_terse('args_var', t.string_node(node.args_var))
obj.add_terse('has_parens', t.bool_node(node.has_parens))
obj.add_terse('is_embed', t.bool_node(node.is_embed))
obj.add_terse('embed_file', t.embed_file(node.embed_file))
obj.add('method_pos', t.pos(node.method_pos))
obj.add_terse('left_type', t.type_node(node.left_type))

View File

@ -2050,21 +2050,32 @@ pub mut:
typ_key string // `f.typ` cached key for type resolver
}
pub enum ComptimeCallKind {
unknown
d
env
res
html
tmpl
method
pkgconfig
embed_file
compile_warn
compile_error
}
@[minify]
pub struct ComptimeCall {
pub:
pos token.Pos
has_parens bool // if $() is used, for vfmt
method_name string
method_pos token.Pos
scope &Scope = unsafe { nil }
is_vweb bool
is_veb bool
is_embed bool // $embed_file(...)
is_env bool // $env(...) // TODO: deprecate after $d() is stable
is_compile_value bool // $d(...)
env_pos token.Pos
is_pkgconfig bool
pos token.Pos
has_parens bool // if $() is used, for vfmt
method_name string
kind ComptimeCallKind
method_pos token.Pos
scope &Scope = unsafe { nil }
is_vweb bool
is_veb bool
env_pos token.Pos
mut:
is_d_resolved bool
pub mut:
@ -2087,7 +2098,7 @@ pub fn (mut cc ComptimeCall) resolve_compile_value(compile_values map[string]str
if cc.is_d_resolved {
return
}
if !cc.is_compile_value {
if cc.kind != .d {
return error('ComptimeCall is not \$d()')
}
arg := cc.args[0] or {
@ -2109,7 +2120,7 @@ pub fn (mut cc ComptimeCall) resolve_compile_value(compile_values map[string]str
// `ast.Expr`'s `str()' method (used by e.g. vfmt).
pub fn (cc ComptimeCall) expr_str() string {
mut str := 'ast.ComptimeCall'
if cc.is_compile_value {
if cc.kind == .d {
arg := cc.args[0] or { return str }
if arg.expr.is_pure_literal() {
str = "\$${cc.method_name}('${cc.args_var}', ${arg})"

View File

@ -4669,7 +4669,7 @@ fn (mut c Checker) find_obj_definition(obj ast.ScopeObject) !ast.Expr {
if mut expr is ast.Ident {
return c.find_definition(expr)
}
if mut expr is ast.ComptimeCall && expr.is_compile_value {
if mut expr is ast.ComptimeCall && expr.kind == .d {
if expr.result_type == ast.bool_type {
return ast.BoolLiteral{
val: expr.compile_value.bool()

View File

@ -15,14 +15,14 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
if node.left !is ast.EmptyExpr {
node.left_type = c.expr(mut node.left)
}
if node.method_name == 'compile_error' {
if node.kind == .compile_error {
c.error(c.comptime_call_msg(node), node.pos)
return ast.void_type
} else if node.method_name == 'compile_warn' {
} else if node.kind == .compile_warn {
c.warn(c.comptime_call_msg(node), node.pos)
return ast.void_type
}
if node.is_env {
if node.kind == .env {
env_value := util.resolve_env_value("\$env('${node.args_var}')", false) or {
c.error(err.msg(), node.env_pos)
return ast.string_type
@ -30,14 +30,14 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
node.env_value = env_value
return ast.string_type
}
if node.is_compile_value {
if node.kind == .d {
node.resolve_compile_value(c.pref.compile_values) or {
c.error(err.msg(), node.pos)
return ast.void_type
}
return node.result_type
}
if node.is_embed {
if node.kind == .embed_file {
if node.args.len == 1 {
embed_arg := node.args[0]
mut raw_path := ''
@ -111,7 +111,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
c.table.cur_fn = save_cur_fn
}
if node.method_name == 'html' {
if node.kind == .html {
ret_sym := c.table.sym(c.table.cur_fn.return_type)
if ret_sym.cname !in ['veb__Result', 'vweb__Result', 'x__vweb__Result'] {
ct_call := if node.is_veb { 'veb' } else { 'vweb' }
@ -138,7 +138,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
return c.type_resolver.get_type(node)
}
if node.method_name == 'res' {
if node.kind == .res {
if !c.inside_defer {
c.error('`res` can only be used in defer blocks', node.pos)
return ast.void_type
@ -1096,7 +1096,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
}
}
ast.ComptimeCall {
if cond.is_pkgconfig {
if cond.kind == .pkgconfig {
mut m := pkgconfig.main([cond.args_var]) or {
c.error(err.msg(), cond.pos)
return .skip
@ -1104,7 +1104,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
m.run() or { return .skip }
return .eval
}
if cond.is_compile_value {
if cond.kind == .d {
t := c.expr(mut cond)
if t != ast.bool_type {
c.error('inside \$if, only \$d() expressions that return bool are allowed',

View File

@ -357,7 +357,7 @@ fn (mut c Checker) eval_array_fixed_sizes(mut size_expr ast.Expr, size int, elem
fixed_size = size_expr.val.int()
}
ast.ComptimeCall {
if size_expr.is_compile_value {
if size_expr.kind == .d {
size_expr.resolve_compile_value(c.pref.compile_values) or {
c.error(err.msg(), size_expr.pos)
}

View File

@ -208,7 +208,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
c.error('cannot use `${c.table.type_to_str(got_type)}` as ${c.error_type_name(exp_type)} in return argument',
exprv.pos())
}
if exprv is ast.ComptimeCall && exprv.method_name == 'tmpl'
if exprv is ast.ComptimeCall && exprv.kind == .tmpl
&& c.table.final_sym(exp_type).kind != .string {
c.error('cannot use `string` as type `${c.table.type_to_str(exp_type)}` in return argument',
exprv.pos)
@ -351,7 +351,7 @@ fn has_top_return(stmts []ast.Stmt) bool {
return true
}
} else if stmt.expr is ast.ComptimeCall {
if stmt.expr.method_name == 'compile_error' {
if stmt.expr.kind == .compile_error {
return true
}
} else if stmt.expr is ast.LockExpr {

View File

@ -244,7 +244,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
if sym.info is ast.ArrayFixed && field.typ == field.default_expr_typ {
if sym.info.size_expr is ast.ComptimeCall {
// field [$d('x' ,2)]int = [1 ,2]!
if sym.info.size_expr.method_name == 'd' {
if sym.info.size_expr.kind == .d {
c.error('cannot initialize a fixed size array field that uses `\$d()` as size quantifier since the size may change via -d',
field.default_expr.pos())
}

View File

@ -2247,7 +2247,7 @@ pub fn (mut f Fmt) chan_init(mut node ast.ChanInit) {
pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
if node.is_vweb {
if node.method_name == 'html' {
if node.kind == .html {
if node.args.len == 1 && node.args[0].expr is ast.StringLiteral {
if node.is_veb {
f.write('\$veb.html(')
@ -2270,7 +2270,7 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
}
} else {
match true {
node.is_embed {
node.kind == .embed_file {
f.write('\$embed_file(')
f.expr(node.args[0].expr)
if node.embed_file.compression_type != 'none' {
@ -2278,13 +2278,13 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
}
f.write(')')
}
node.is_env {
node.kind == .env {
f.write("\$env('${node.args_var}')")
}
node.is_pkgconfig {
node.kind == .pkgconfig {
f.write("\$pkgconfig('${node.args_var}')")
}
node.method_name in ['compile_error', 'compile_warn'] {
node.kind in [.compile_error, .compile_warn] {
if node.args.len == 0 {
if node.args_var.contains("'") {
f.write('\$${node.method_name}("${node.args_var}")')
@ -2297,12 +2297,12 @@ pub fn (mut f Fmt) comptime_call(node ast.ComptimeCall) {
f.write(')')
}
}
node.method_name == 'd' {
node.kind == .d {
f.write("\$d('${node.args_var}', ")
f.expr(node.args[0].expr)
f.write(')')
}
node.method_name == 'res' {
node.kind == .res {
if node.args_var != '' {
f.write('\$res(${node.args_var})')
} else {

View File

@ -45,19 +45,19 @@ fn (mut g Gen) gen_comptime_selector(expr ast.ComptimeSelector) string {
}
fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
if node.is_embed {
if node.kind == .embed_file {
// $embed_file('/path/to/file')
g.gen_embed_file_init(mut node)
return
}
if node.method_name == 'env' {
if node.kind == .env {
// $env('ENV_VAR_NAME')
// TODO: deprecate after support for $d() is stable
val := util.cescaped_path(os.getenv(node.args_var))
g.write('_S("${val}")')
return
}
if node.method_name == 'd' {
if node.kind == .d {
// $d('some_string',<default value>), affected by `-d some_string=actual_value`
val := util.cescaped_path(node.compile_value)
if node.result_type == ast.string_type {
@ -69,7 +69,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
}
return
}
if node.method_name == 'res' {
if node.kind == .res {
if node.args_var != '' {
g.write('${g.defer_return_tmp_var}.arg${node.args_var}')
return
@ -79,7 +79,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
return
}
if node.is_vweb {
is_html := node.method_name == 'html'
is_html := node.kind == .html
mut cur_line := ''
if !is_html {
@ -799,11 +799,11 @@ fn (mut g Gen) comptime_if_cond(cond ast.Expr, pkg_exist bool) (bool, bool) {
return true, false
}
ast.ComptimeCall {
if cond.method_name == 'pkgconfig' {
if cond.kind == .pkgconfig {
g.write('${pkg_exist}')
return true, false
}
if cond.method_name == 'd' {
if cond.kind == .d {
if cond.result_type == ast.bool_type {
if cond.compile_value == 'true' {
g.write('1')

View File

@ -1335,7 +1335,7 @@ fn (mut g Gen) gen_to_str_method_call(node ast.CallExpr) bool {
g.gen_expr_to_string(left_node, rec_type)
return true
} else if left_node is ast.ComptimeCall {
if left_node.method_name == 'method' {
if left_node.kind == .method {
sym := g.table.sym(g.unwrap_generic(left_node.left_type))
if m := sym.find_method(g.comptime.comptime_for_method.name) {
rec_type = m.return_type
@ -2069,7 +2069,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
typ = g.type_resolver.get_ct_type_or_default(expr.typ_key, typ)
}
} else if expr is ast.ComptimeCall {
if expr.method_name == 'method' {
if expr.kind == .method {
sym := g.table.sym(g.unwrap_generic(expr.left_type))
if m := sym.find_method(g.comptime.comptime_for_method.name) {
typ = m.return_type

View File

@ -1542,21 +1542,21 @@ pub fn (mut f Gen) chan_init(mut node ast.ChanInit) {
pub fn (mut f Gen) comptime_call(node ast.ComptimeCall) {
if node.is_vweb {
if node.method_name == 'html' {
if node.kind == .html {
f.write('\$vweb.html()')
} else {
f.write("\$tmpl('${node.args_var}')")
}
} else {
if node.is_embed {
if node.kind == .embed_file {
if node.embed_file.compression_type == 'none' {
f.write("\$embed_file('${node.embed_file.rpath}')")
} else {
f.write("\$embed_file('${node.embed_file.rpath}', .${node.embed_file.compression_type})")
}
} else if node.is_env {
} else if node.kind == .env {
f.write("\$env('${node.args_var}')")
} else if node.is_pkgconfig {
} else if node.kind == .pkgconfig {
f.write("\$pkgconfig('${node.args_var}')")
} else {
inner_args := if node.args_var != '' {

View File

@ -476,7 +476,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
if node.is_vweb {
w.stmts(node.veb_tmpl.stmts)
}
if node.is_embed {
if node.kind == .embed_file {
w.features.used_maps++
}
}

View File

@ -123,6 +123,7 @@ const error_msg = 'only `\$tmpl()`, `\$env()`, `\$embed_file()`, `\$pkgconfig()`
fn (mut p Parser) comptime_call() ast.ComptimeCall {
err_node := ast.ComptimeCall{
scope: unsafe { nil }
kind: .unknown
}
start_pos := p.tok.pos()
p.check(.dollar)
@ -163,14 +164,14 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
s := p.tok.lit
p.check(.string)
p.check(.rpar)
is_env := method_name == 'env'
return ast.ComptimeCall{
scope: unsafe { nil }
method_name: method_name
args_var: s
is_env: method_name == 'env'
is_pkgconfig: method_name == 'pkgconfig'
env_pos: start_pos
pos: start_pos.extend(p.prev_tok.pos())
scope: unsafe { nil }
method_name: method_name
kind: if is_env { .env } else { .pkgconfig }
args_var: s
env_pos: start_pos
pos: start_pos.extend(p.prev_tok.pos())
}
} else if method_name in ['compile_error', 'compile_warn'] {
mut s := ''
@ -189,6 +190,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
return ast.ComptimeCall{
scope: unsafe { nil }
method_name: method_name
kind: if method_name == 'compile_error' { .compile_error } else { .compile_warn }
args_var: s
env_pos: start_pos
pos: start_pos.extend(p.prev_tok.pos())
@ -207,6 +209,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
return ast.ComptimeCall{
scope: unsafe { nil }
method_name: method_name
kind: .res
args_var: type_index
pos: start_pos.extend(p.prev_tok.pos())
}
@ -214,6 +217,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
return ast.ComptimeCall{
scope: unsafe { nil }
method_name: method_name
kind: .res
pos: start_pos.extend(p.prev_tok.pos())
}
} else if method_name == 'd' {
@ -230,12 +234,12 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
]
p.check(.rpar)
return ast.ComptimeCall{
scope: unsafe { nil }
is_compile_value: true
method_name: method_name
args_var: const_string
args: args
pos: start_pos.extend(p.prev_tok.pos())
scope: unsafe { nil }
method_name: method_name
kind: .d
args_var: const_string
args: args
pos: start_pos.extend(p.prev_tok.pos())
}
}
has_string_arg := p.tok.kind == .string
@ -280,13 +284,14 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
p.register_auto_import('v.preludes.embed_file.zlib')
}
return ast.ComptimeCall{
scope: unsafe { nil }
is_embed: true
embed_file: ast.EmbeddedFile{
scope: unsafe { nil }
method_name: method_name
kind: .embed_file
embed_file: ast.EmbeddedFile{
compression_type: embed_compression_type
}
args: [arg]
pos: start_pos.extend(p.prev_tok.pos())
args: [arg]
pos: start_pos.extend(p.prev_tok.pos())
}
}
// Compile vweb html template to V code, parse that V code and embed the resulting V function
@ -324,6 +329,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
is_vweb: true
is_veb: is_veb
method_name: method_name
kind: if is_html { .html } else { .tmpl }
args_var: literal_string_param
args: [arg]
pos: start_pos.extend(p.prev_tok.pos())
@ -371,6 +377,7 @@ fn (mut p Parser) comptime_call() ast.ComptimeCall {
is_veb: is_veb
veb_tmpl: file
method_name: method_name
kind: if is_html { .html } else { .tmpl }
args_var: literal_string_param
args: [arg]
pos: start_pos.extend(p.prev_tok.pos())
@ -537,6 +544,7 @@ fn (mut p Parser) comptime_selector(left ast.Expr) ast.Expr {
return ast.ComptimeCall{
left: left
method_name: method_name
kind: .method
method_pos: method_pos
scope: p.scope
args_var: ''

View File

@ -27,7 +27,7 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ
size_unresolved = false
}
ast.ComptimeCall {
if size_expr.is_compile_value {
if size_expr.kind == .d {
size_expr.resolve_compile_value(p.pref.compile_values) or {
p.error_with_pos(err.msg(), size_expr.pos)
}