v: support `$for attr in Test.attributes` (#9836)

pull/9876/head
Louis Schmieder 2021-04-25 17:29:26 +02:00 committed by GitHub
parent 515e83dcbc
commit fc3b628440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 1 deletions

View File

@ -121,3 +121,18 @@ pub:
is_mut bool
typ int
}
pub enum AttributeKind {
plain // [name]
string // ['name']
number // [123]
comptime_define // [if name]
}
pub struct StructAttribute {
pub:
name string
has_arg bool
arg string
kind AttributeKind
}

View File

@ -786,6 +786,7 @@ pub:
pub enum CompForKind {
methods
fields
attributes
}
pub struct CompFor {

View File

@ -488,5 +488,6 @@ pub fn (e CompForKind) str() string {
match e {
.methods { return 'methods' }
.fields { return 'fields' }
.attributes { return 'attributes' }
}
}

View File

@ -468,6 +468,22 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
}
g.comptime_var_type_map.delete(node.val_var)
}
} else if node.kind == .attributes {
if sym.info is ast.Struct {
if sym.info.attrs.len > 0 {
g.writeln('\tStructAttribute $node.val_var = {0};')
}
for attr in sym.info.attrs {
g.writeln('/* attribute $i */ {')
g.writeln('\t${node.val_var}.name = _SLIT("$attr.name");')
g.writeln('\t${node.val_var}.has_arg = $attr.has_arg;')
g.writeln('\t${node.val_var}.arg = _SLIT("$attr.arg");')
g.writeln('\t${node.val_var}.kind = AttributeKind_$attr.kind;')
g.writeln('}')
}
}
}
g.indent--
g.writeln('}// \$for')

View File

@ -253,8 +253,15 @@ fn (mut p Parser) comp_for() ast.CompFor {
pos: var_pos
})
kind = .fields
} else if for_val == 'attributes' {
p.scope.register(ast.Var{
name: val_var
typ: p.table.find_type_idx('StructAttribute')
pos: var_pos
})
kind = .attributes
} else {
p.error_with_pos('unknown kind `$for_val`, available are: `methods` or `fields`',
p.error_with_pos('unknown kind `$for_val`, available are: `methods`, `fields` or `attributes`',
p.prev_tok.position())
return ast.CompFor{}
}

View File

@ -0,0 +1,14 @@
[test: 'hello']
[abc]
struct Test {}
fn test_attributes() {
$for attr in Test.attributes {
if attr.has_arg {
assert attr.name == 'test'
assert attr.arg == 'hello'
} else {
assert attr.name == 'abc'
}
}
}