Skip to content

Commit af8ef12

Browse files
authored
ast: use AttrKind (#9845)
1 parent 1b46f9a commit af8ef12

13 files changed

+89
-88
lines changed

vlib/v/ast/attr.v

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,55 +5,49 @@ module ast
55

66
import v.token
77

8+
pub enum AttrKind {
9+
plain // [name]
10+
string // ['name']
11+
number // [123]
12+
comptime_define // [if name]
13+
}
14+
815
// e.g. `[unsafe]`
916
pub struct Attr {
1017
pub:
11-
name string // [name]
12-
is_string bool // ['name']
13-
is_comptime_define bool // [if name]
14-
arg string // [name: arg]
15-
is_string_arg bool // [name: 'arg']
16-
is_number_arg bool // [name: 123]
17-
pos token.Position
18+
name string // [name]
19+
has_arg bool
20+
arg string // [name: arg]
21+
kind AttrKind
22+
pos token.Position
1823
}
1924

20-
// no square brackets
21-
pub fn (attr Attr) str() string {
25+
// str returns the string representation without square brackets
26+
pub fn (a Attr) str() string {
2227
mut s := ''
23-
if attr.is_comptime_define {
24-
s += 'if '
25-
}
26-
if attr.is_string {
27-
s += "'$attr.name'"
28+
mut arg := if a.has_arg {
29+
s += '$a.name: '
30+
a.arg
2831
} else {
29-
s += attr.name
30-
if attr.arg.len > 0 {
31-
s += ': '
32-
if attr.is_string_arg {
33-
a := attr.arg.replace("'", "\\'")
34-
s += "'$a'"
35-
} else {
36-
s += attr.arg
37-
}
38-
}
32+
a.name
33+
}
34+
s += match a.kind {
35+
.plain, .number { arg }
36+
.string { "'$arg'" }
37+
.comptime_define { 'if $arg' }
3938
}
4039
return s
4140
}
4241

4342
pub fn (attrs []Attr) contains(str string) bool {
44-
for a in attrs {
45-
if a.name == str {
46-
return true
47-
}
48-
}
49-
return false
43+
return attrs.any(it.name == str)
5044
}
5145

52-
pub fn (attrs []Attr) has_comptime_define() (bool, string) {
46+
pub fn (attrs []Attr) find_comptime_define() ?string {
5347
for a in attrs {
54-
if a.is_comptime_define {
55-
return true, a.name
48+
if a.kind == .comptime_define {
49+
return a.name
5650
}
5751
}
58-
return false, ''
52+
return none
5953
}

vlib/v/checker/checker.v

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6481,12 +6481,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
64816481
c.main_fn_decl_node = node
64826482
}
64836483
if node.return_type != ast.void_type {
6484-
for attr in node.attrs {
6485-
if attr.is_comptime_define {
6486-
c.error('only functions that do NOT return values can have `[if $attr.name]` tags',
6487-
node.pos)
6488-
break
6489-
}
6484+
if ct_name := node.attrs.find_comptime_define() {
6485+
c.error('only functions that do NOT return values can have `[if $ct_name]` tags',
6486+
node.pos)
64906487
}
64916488
}
64926489
if node.is_method {

vlib/v/gen/c/sql.v

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ fn (mut g Gen) parse_db_from_type_string(name string) SqlType {
10751075
fn (mut g Gen) get_sql_field_type(field ast.StructField) ast.Type {
10761076
mut typ := field.typ
10771077
for attr in field.attrs {
1078-
if attr.name == 'sql' && !attr.is_string_arg && attr.arg != '' {
1078+
if attr.kind == .plain && attr.name == 'sql' && attr.arg != '' {
10791079
if attr.arg.to_lower() == 'serial' {
10801080
typ = ast.Type(-1)
10811081
break
@@ -1090,7 +1090,7 @@ fn (mut g Gen) get_table_name(table_expr ast.TypeNode) string {
10901090
info := g.table.get_type_symbol(table_expr.typ).struct_info()
10911091
mut tablename := util.strip_mod_name(g.table.get_type_symbol(table_expr.typ).name)
10921092
for attr in info.attrs {
1093-
if attr.name == 'table' && attr.is_string_arg && attr.arg != '' {
1093+
if attr.kind == .string && attr.name == 'table' && attr.arg != '' {
10941094
tablename = attr.arg
10951095
break
10961096
}
@@ -1112,7 +1112,7 @@ fn (mut g Gen) get_struct_field(name string) ast.StructField {
11121112
fn (mut g Gen) get_field_name(field ast.StructField) string {
11131113
mut name := field.name
11141114
for attr in field.attrs {
1115-
if attr.name == 'sql' && attr.is_string_arg && attr.arg != '' {
1115+
if attr.kind == .string && attr.name == 'sql' && attr.arg != '' {
11161116
name = attr.arg
11171117
break
11181118
}

vlib/v/parser/fn.v

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
177177
is_manualfree := p.is_manualfree || p.attrs.contains('manualfree')
178178
is_deprecated := p.attrs.contains('deprecated')
179179
is_direct_arr := p.attrs.contains('direct_array_access')
180-
is_conditional, conditional_ctdefine := p.attrs.has_comptime_define()
180+
conditional_ctdefine := p.attrs.find_comptime_define() or { '' }
181181
mut is_unsafe := p.attrs.contains('unsafe')
182182
is_keep_alive := p.attrs.contains('keep_args_alive')
183183
is_pub := p.tok.kind == .key_pub
@@ -349,7 +349,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
349349
is_unsafe: is_unsafe
350350
is_main: is_main
351351
is_test: is_test
352-
is_conditional: is_conditional
352+
is_conditional: conditional_ctdefine != ''
353353
is_keep_alive: is_keep_alive
354354
ctdefine: conditional_ctdefine
355355
no_body: no_body
@@ -378,7 +378,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
378378
is_unsafe: is_unsafe
379379
is_main: is_main
380380
is_test: is_test
381-
is_conditional: is_conditional
381+
is_conditional: conditional_ctdefine != ''
382382
is_keep_alive: is_keep_alive
383383
ctdefine: conditional_ctdefine
384384
no_body: no_body
@@ -421,7 +421,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
421421
is_variadic: is_variadic
422422
is_main: is_main
423423
is_test: is_test
424-
is_conditional: is_conditional
424+
is_conditional: conditional_ctdefine != ''
425425
is_keep_alive: is_keep_alive
426426
receiver: ast.StructField{
427427
name: rec.name

vlib/v/parser/parser.v

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -439,30 +439,14 @@ pub fn (mut p Parser) parse_block_no_scope(is_top_level bool) []ast.Stmt {
439439
return stmts
440440
}
441441

442-
/*
443-
fn (mut p Parser) next_with_comment() {
444-
p.tok = p.peek_tok
445-
p.peek_tok = p.scanner.scan()
446-
}
447-
*/
448442
fn (mut p Parser) next() {
449443
p.prev_tok = p.tok
450444
p.tok = p.peek_tok
451445
p.peek_tok = p.scanner.scan()
452-
/*
453-
if p.tok.kind==.comment {
454-
p.comments << ast.Comment{text:p.tok.lit, line_nr:p.tok.line_nr}
455-
p.next()
456-
}
457-
*/
458446
}
459447

460448
fn (mut p Parser) check(expected token.Kind) {
461449
p.name_error = false
462-
// for p.tok.kind in [.line_comment, .mline_comment] {
463-
// p.next()
464-
// }
465-
466450
if _likely_(p.tok.kind == expected) {
467451
p.next()
468452
} else {
@@ -1469,7 +1453,7 @@ fn (mut p Parser) attributes() {
14691453
p.error_with_pos('duplicate attribute `$attr.name`', start_pos.extend(p.prev_tok.position()))
14701454
return
14711455
}
1472-
if attr.is_comptime_define {
1456+
if attr.kind == .comptime_define {
14731457
if has_ctdefine {
14741458
p.error_with_pos('only one `[if flag]` may be applied at a time `$attr.name`',
14751459
start_pos.extend(p.prev_tok.position()))
@@ -1496,61 +1480,55 @@ fn (mut p Parser) attributes() {
14961480
}
14971481

14981482
fn (mut p Parser) parse_attr() ast.Attr {
1483+
mut kind := ast.AttrKind.plain
14991484
apos := p.prev_tok.position()
15001485
if p.tok.kind == .key_unsafe {
15011486
p.next()
15021487
return ast.Attr{
15031488
name: 'unsafe'
1489+
kind: kind
15041490
pos: apos.extend(p.tok.position())
15051491
}
15061492
}
1507-
is_comptime_define := p.tok.kind == .key_if
1508-
if is_comptime_define {
1509-
p.next()
1510-
}
15111493
mut name := ''
1494+
mut has_arg := false
15121495
mut arg := ''
1513-
is_string := p.tok.kind == .string
1514-
mut is_string_arg := false
1515-
mut is_number_arg := false
1516-
if is_string {
1496+
if p.tok.kind == .key_if {
1497+
kind = .comptime_define
1498+
p.next()
1499+
p.check(.name)
1500+
name = p.prev_tok.lit
1501+
} else if p.tok.kind == .string {
15171502
name = p.tok.lit
1503+
kind = .string
15181504
p.next()
15191505
} else {
15201506
name = p.check_name()
1521-
if name == 'unsafe_fn' {
1522-
p.error_with_pos('[unsafe_fn] is obsolete, use `[unsafe]` instead', apos.extend(p.tok.position()))
1523-
return ast.Attr{}
1524-
} else if name == 'trusted_fn' {
1525-
p.error_with_pos('[trusted_fn] is obsolete, use `[trusted]` instead', apos.extend(p.tok.position()))
1526-
return ast.Attr{}
1527-
} else if name == 'ref_only' {
1528-
p.warn_with_pos('[ref_only] is deprecated, use [heap] instead', apos.extend(p.tok.position()))
1529-
name = 'heap'
1530-
}
15311507
if p.tok.kind == .colon {
1508+
has_arg = true
15321509
p.next()
15331510
// `name: arg`
15341511
if p.tok.kind == .name {
1512+
kind = .plain
15351513
arg = p.check_name()
15361514
} else if p.tok.kind == .number {
1515+
kind = .number
15371516
arg = p.tok.lit
1538-
is_number_arg = true
15391517
p.next()
15401518
} else if p.tok.kind == .string { // `name: 'arg'`
1519+
kind = .string
15411520
arg = p.tok.lit
1542-
is_string_arg = true
15431521
p.next()
1522+
} else {
1523+
p.error('unexpected $p.tok, an argument is expected after `:`')
15441524
}
15451525
}
15461526
}
15471527
return ast.Attr{
15481528
name: name
1549-
is_string: is_string
1550-
is_comptime_define: is_comptime_define
1529+
has_arg: has_arg
15511530
arg: arg
1552-
is_string_arg: is_string_arg
1553-
is_number_arg: is_number_arg
1531+
kind: kind
15541532
pos: apos.extend(p.tok.position())
15551533
}
15561534
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
vlib/v/parser/tests/invalid_attribute_a.vv:1:9: error: unexpected token `]`, an argument is expected after `:`
2+
1 | [foobar:]
3+
| ^
4+
2 | fn my_fn_with_invalid_attr() {
5+
3 | }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[foobar:]
2+
fn my_fn_with_invalid_attr() {
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
vlib/v/parser/tests/invalid_attribute_b.vv:1:6: error: unexpected token `:`, an argument is expected after `:`
2+
1 | [foo::]
3+
| ^
4+
2 | fn my_fn_with_invalid_attr() {
5+
3 | }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[foo::]
2+
fn my_fn_with_invalid_attr() {
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
vlib/v/parser/tests/invalid_attribute_c.vv:1:6: error: unexpected token `[`, an argument is expected after `:`
2+
1 | [bar:[]
3+
| ^
4+
2 | fn my_fn_with_invalid_attr() {
5+
3 | }

0 commit comments

Comments
 (0)