v2 / vlib / v / ast / attr.v
98 lines · 87 sloc · 2.39 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module ast
5
6import v.token
7
8pub enum AttrKind {
9 plain // [name]
10 string // ['name']
11 number // [123]
12 bool // [true] || [false]
13 comptime_define // [if name]
14}
15
16// e.g. `@[unsafe]`
17@[minify]
18pub struct Attr {
19pub:
20 name string // [name]
21 has_arg bool
22 arg string // [name: arg]
23 kind AttrKind
24 quote u8 = `'` // quote for .string attrs: `"` or `'`
25 ct_opt bool // true for [if user_defined_name?]
26 pos token.Pos
27 has_at bool // new syntax `@[attr]`
28 // original call-style metadata for `@[foo(...)]`, used by vfmt
29 call_name string
30 call_arg_name string
31 call_arg_idx int = -1
32pub mut:
33 ct_expr Expr // .kind == comptime_define, for [if !name]
34 ct_evaled bool // whether ct_skip has been evaluated already
35 ct_skip bool // is the comptime expr *false*, filled by checker
36}
37
38pub fn (a &Attr) debug() string {
39 return 'Attr{ name: "${a.name}", has_arg: ${a.has_arg}, arg: "${a.arg}", kind: ${a.kind}, ct_expr: ${a.ct_expr}, ct_opt: ${a.ct_opt}, ct_skip: ${a.ct_skip}, call_name: "${a.call_name}", call_arg_name: "${a.call_arg_name}", call_arg_idx: ${a.call_arg_idx} }'
40}
41
42// str returns the string representation without square brackets
43pub fn (a &Attr) str() string {
44 mut s := ''
45 quote := if a.quote == `"` { '"' } else { "'" }
46 mut arg := if a.has_arg {
47 s += '${a.name}: '
48 a.arg
49 } else {
50 a.name
51 }
52 s += match a.kind {
53 .plain, .number, .bool { arg }
54 .string { '${quote}${arg}${quote}' }
55 .comptime_define { 'if ${arg}' }
56 }
57
58 return s
59}
60
61pub fn (attrs []Attr) contains(str string) bool {
62 return attrs.any(it.name == str)
63}
64
65pub fn (attrs []Attr) contains_arg(str string, arg string) bool {
66 return attrs.any(it.has_arg && it.name == str && it.arg == arg)
67}
68
69@[direct_array_access]
70pub fn (attrs []Attr) find_first(aname string) ?Attr {
71 for a in attrs {
72 if a.name == aname {
73 return a
74 }
75 }
76 return none
77}
78
79@[direct_array_access]
80pub fn (attrs []Attr) find_last(aname string) ?Attr {
81 for idx := attrs.len - 1; idx > -1; idx-- {
82 a := attrs[idx]
83 if a.name == aname {
84 return a
85 }
86 }
87 return none
88}
89
90@[direct_array_access]
91pub fn (attrs []Attr) find_comptime_define() ?int {
92 for idx in 0 .. attrs.len {
93 if attrs[idx].kind == .comptime_define {
94 return idx
95 }
96 }
97 return none
98}
99