parser: use Attr.arg field for `[name: arg]` (#6084)

pull/6100/head
Nick Treleaven 2020-08-10 01:00:14 +01:00 committed by GitHub
parent c7fae4dd6f
commit fce106cf83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 32 deletions

View File

@ -2501,7 +2501,7 @@ On Unix-like platforms, the file can be run directly after making it executable
V has several attributes that modify the behavior of functions and structs.
An attribute is specified inside `[]` right before the function/struct declaration and applies only to the following definition.
An attribute is specified inside `[]` right before a function/struct declaration and applies only to the following declaration.
```v
// Calling this function will result in a deprecation warning

View File

@ -1115,18 +1115,7 @@ pub fn (mut f Fmt) or_expr(or_block ast.OrExpr) {
fn (mut f Fmt) attrs(attrs []table.Attr) {
for attr in attrs {
f.write('[')
if attr.is_ctdefine {
f.write('if ')
}
if attr.is_string {
f.write("'")
}
f.write(attr.name)
if attr.is_string {
f.write("'")
}
f.writeln(']')
f.writeln('[$attr]')
}
}
@ -1139,7 +1128,7 @@ fn (mut f Fmt) inline_attrs(attrs []table.Attr) {
if i > 0 {
f.write(';')
}
f.write(attr.name)
f.write('$attr')
}
f.write(']')
}

View File

@ -1,5 +1,7 @@
[inline]
[if debug]
[foo: bar]
[deprecated: 'use bar() instead']
fn keep_attributes() {
println('hi !')
}

View File

@ -88,6 +88,19 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
}
}
fn cgen_attrs(attrs []table.Attr) []string {
mut res := []string{cap: attrs.len}
for attr in attrs {
// we currently don't quote 'arg' (otherwise we could just use `s := attr.str()`)
mut s := attr.name
if attr.arg.len > 0 {
s += ': $attr.arg'
}
res << 'tos_lit("$s")'
}
return res
}
fn (mut g Gen) comp_if(mut it ast.CompIf) {
if it.stmts.len == 0 && it.else_stmts.len == 0 {
return
@ -175,10 +188,7 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
if method.attrs.len == 0 {
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
} else {
mut attrs := []string{}
for attrib in method.attrs {
attrs << 'tos_lit("$attrib.name")'
}
attrs := cgen_attrs(method.attrs)
g.writeln('\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
attrs.join(', ') + '}));')
}
@ -210,10 +220,7 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
if field.attrs.len == 0 {
g.writeln('\t${node.val_var}.attrs = __new_array_with_default(0, 0, sizeof(string), 0);')
} else {
mut attrs := []string{}
for attrib in field.attrs {
attrs << 'tos_lit("$attrib.name")'
}
attrs := cgen_attrs(field.attrs)
g.writeln('\t${node.val_var}.attrs = new_array_from_c_array($attrs.len, $attrs.len, sizeof(string), _MOV((string[$attrs.len]){' +
attrs.join(', ') + '}));')
}

View File

@ -83,8 +83,8 @@ $enc_fn_dec {
}
mut name := field.name
for attr in field.attrs {
if attr.name.starts_with('json:') {
name = attr.name[5..]
if attr.name == 'json' {
name = attr.arg
break
}
}

View File

@ -432,7 +432,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
}
}
.lsbr {
// attrs are stores in `p.attrs()`
// attrs are stored in `p.attrs`
p.attributes()
continue
}
@ -737,7 +737,9 @@ fn (mut p Parser) parse_attr() table.Attr {
is_ctdefine = true
}
mut name := ''
mut arg := ''
is_string := p.tok.kind == .string
mut is_string_arg := false
if is_string {
name = p.tok.lit
p.next()
@ -749,12 +751,13 @@ fn (mut p Parser) parse_attr() table.Attr {
p.error_with_pos('please use `[trusted]` instead', p.tok.position())
}
if p.tok.kind == .colon {
name += ':'
p.next()
// `name: arg`
if p.tok.kind == .name {
name += p.check_name()
} else if p.tok.kind == .string {
name += p.tok.lit
arg = p.check_name()
} else if p.tok.kind == .string { // `name: 'arg'`
arg = p.tok.lit
is_string_arg = true
p.next()
}
}
@ -763,6 +766,8 @@ fn (mut p Parser) parse_attr() table.Attr {
name: name
is_string: is_string
is_ctdefine: is_ctdefine
arg: arg
is_string_arg: is_string_arg
}
}

View File

@ -6,9 +6,38 @@ module table
// e.g. `[unsafe]`
pub struct Attr {
pub:
name string
is_string bool // `['xxx']`
is_ctdefine bool // `[if flag]`
name string // [name]
is_string bool // ['name']
is_ctdefine bool // [if name]
arg string // [name: arg]
is_string_arg bool // [name: 'arg']
}
// no square brackets
pub fn (attr Attr) str() string {
mut s := ''
if attr.is_ctdefine {
s += 'if '
}
if attr.is_string {
s += "'$attr.name'"
}
else {
s += attr.name
if attr.arg.len > 0 {
s += ': '
if attr.is_string_arg {
mut a := attr.arg.replace('\\', '\\\\')
// FIXME: other escapes e.g. \r\n
a = a.replace("'", "\\'")
s += "'$a'"
}
else {
s += attr.arg
}
}
}
return s
}
pub fn (attrs []Attr) contains(str string) bool {