diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index d43196e8f7..57bdc9d86a 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -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 +} diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 018cda88ba..5da5674852 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -786,6 +786,7 @@ pub: pub enum CompForKind { methods fields + attributes } pub struct CompFor { diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index 0c1ab9d92d..2f0bee7373 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -488,5 +488,6 @@ pub fn (e CompForKind) str() string { match e { .methods { return 'methods' } .fields { return 'fields' } + .attributes { return 'attributes' } } } diff --git a/vlib/v/gen/c/comptime.v b/vlib/v/gen/c/comptime.v index a035948329..9c22647d25 100644 --- a/vlib/v/gen/c/comptime.v +++ b/vlib/v/gen/c/comptime.v @@ -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') diff --git a/vlib/v/parser/comptime.v b/vlib/v/parser/comptime.v index d4a3454f4a..1ba8b27513 100644 --- a/vlib/v/parser/comptime.v +++ b/vlib/v/parser/comptime.v @@ -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{} } diff --git a/vlib/v/tests/comptime_attribute_selector_test.v b/vlib/v/tests/comptime_attribute_selector_test.v new file mode 100644 index 0000000000..3b60d231e0 --- /dev/null +++ b/vlib/v/tests/comptime_attribute_selector_test.v @@ -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' + } + } +}