diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index 8d0db8d9bf..602b4753a0 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -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)) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index e1a6e9ebe6..6d49a84d66 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -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})" diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9e6e31e500..7129a46d4c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -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() diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index db69498033..a1b529cefe 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -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', diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 5c44998a2b..792763162a 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -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) } diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index f6215a7c5d..883fa31da9 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -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 { diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 205330d45e..649cfd4d34 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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()) } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 2c9018dd49..4ff3cda1f2 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -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 { diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index f8d0e4d7af..6d03f12bd9 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -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',), 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') diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index ca334f4e0d..998583a677 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -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 diff --git a/vlib/v/gen/golang/golang.v b/vlib/v/gen/golang/golang.v index 52c6891a0f..2573b04ece 100644 --- a/vlib/v/gen/golang/golang.v +++ b/vlib/v/gen/golang/golang.v @@ -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 != '' { diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index c55556012b..e9ce833eec 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -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++ } } diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index 336c6bf615..f259e4d168 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -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: '' diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index e17634d9c3..cc9544464f 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -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) }