mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
v,breaking: add ability to read enum, fn, interface and sumtype attributes in compile-time, change builtin StructAttribute
to VAttribute
(#21149)
This commit is contained in:
parent
dbc4896aa1
commit
24af002249
13 changed files with 139 additions and 30 deletions
|
@ -151,7 +151,7 @@ pub enum AttributeKind {
|
||||||
comptime_define // [if name]
|
comptime_define // [if name]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructAttribute {
|
pub struct VAttribute {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
has_arg bool
|
has_arg bool
|
||||||
|
|
|
@ -51,10 +51,10 @@ fn test_mysql_orm() {
|
||||||
name: 'id'
|
name: 'id'
|
||||||
typ: typeof[int]().idx
|
typ: typeof[int]().idx
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
kind: .plain
|
kind: .plain
|
||||||
|
|
|
@ -55,13 +55,13 @@ fn test_pg_orm() {
|
||||||
default_val: ''
|
default_val: ''
|
||||||
is_arr: false
|
is_arr: false
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
has_arg: false
|
has_arg: false
|
||||||
arg: ''
|
arg: ''
|
||||||
kind: .plain
|
kind: .plain
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'serial'
|
arg: 'serial'
|
||||||
|
|
|
@ -36,10 +36,10 @@ fn test_sqlite_orm() {
|
||||||
name: 'id'
|
name: 'id'
|
||||||
typ: typeof[int]().idx
|
typ: typeof[int]().idx
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
kind: .plain
|
kind: .plain
|
||||||
|
|
|
@ -152,7 +152,7 @@ pub:
|
||||||
typ int
|
typ int
|
||||||
nullable bool
|
nullable bool
|
||||||
default_val string
|
default_val string
|
||||||
attrs []StructAttribute
|
attrs []VAttribute
|
||||||
is_arr bool
|
is_arr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,10 +156,10 @@ fn test_orm_table_gen() {
|
||||||
default_val: '10'
|
default_val: '10'
|
||||||
nullable: true
|
nullable: true
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'serial'
|
arg: 'serial'
|
||||||
|
@ -188,10 +188,10 @@ fn test_orm_table_gen() {
|
||||||
nullable: true
|
nullable: true
|
||||||
default_val: '10'
|
default_val: '10'
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'serial'
|
arg: 'serial'
|
||||||
|
@ -220,10 +220,10 @@ fn test_orm_table_gen() {
|
||||||
nullable: true
|
nullable: true
|
||||||
default_val: '10'
|
default_val: '10'
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'serial'
|
arg: 'serial'
|
||||||
|
@ -235,7 +235,7 @@ fn test_orm_table_gen() {
|
||||||
name: 'test'
|
name: 'test'
|
||||||
typ: typeof[string]().idx
|
typ: typeof[string]().idx
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'unique'
|
name: 'unique'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -255,10 +255,10 @@ fn test_orm_table_gen() {
|
||||||
nullable: true
|
nullable: true
|
||||||
default_val: '10'
|
default_val: '10'
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'primary'
|
name: 'primary'
|
||||||
},
|
},
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'serial'
|
arg: 'serial'
|
||||||
|
@ -271,7 +271,7 @@ fn test_orm_table_gen() {
|
||||||
typ: typeof[string]().idx
|
typ: typeof[string]().idx
|
||||||
nullable: true
|
nullable: true
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'unique'
|
name: 'unique'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'test'
|
arg: 'test'
|
||||||
|
@ -285,7 +285,7 @@ fn test_orm_table_gen() {
|
||||||
nullable: true
|
nullable: true
|
||||||
default_val: '6754'
|
default_val: '6754'
|
||||||
attrs: [
|
attrs: [
|
||||||
StructAttribute{
|
VAttribute{
|
||||||
name: 'unique'
|
name: 'unique'
|
||||||
has_arg: true
|
has_arg: true
|
||||||
arg: 'test'
|
arg: 'test'
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub mut:
|
||||||
redefined_fns []string
|
redefined_fns []string
|
||||||
fn_generic_types map[string][][]Type // for generic functions
|
fn_generic_types map[string][][]Type // for generic functions
|
||||||
interfaces map[int]InterfaceDecl
|
interfaces map[int]InterfaceDecl
|
||||||
|
sumtypes map[int]SumTypeDecl
|
||||||
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
|
||||||
is_fmt bool
|
is_fmt bool
|
||||||
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
|
||||||
|
@ -222,6 +223,10 @@ pub fn (mut t Table) register_interface(idecl InterfaceDecl) {
|
||||||
t.interfaces[idecl.typ] = idecl
|
t.interfaces[idecl.typ] = idecl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut t Table) register_sumtype(sumtyp SumTypeDecl) {
|
||||||
|
t.sumtypes[sumtyp.typ] = sumtyp
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut t TypeSymbol) register_method(new_fn Fn) int {
|
pub fn (mut t TypeSymbol) register_method(new_fn Fn) int {
|
||||||
// returns a method index, stored in the ast.FnDecl
|
// returns a method index, stored in the ast.FnDecl
|
||||||
// for faster lookup in the checker's fn_decl method
|
// for faster lookup in the checker's fn_decl method
|
||||||
|
@ -2519,3 +2524,27 @@ pub fn (t &Table) get_trace_fn_name(cur_fn FnDecl, node CallExpr) (string, strin
|
||||||
}
|
}
|
||||||
return hash_fn, fn_name
|
return hash_fn, fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_attrs retrieve the attribrutes from the type symbol
|
||||||
|
pub fn (t &Table) get_attrs(sym TypeSymbol) []Attr {
|
||||||
|
match sym.info {
|
||||||
|
Enum {
|
||||||
|
return t.enum_decls[sym.name].attrs
|
||||||
|
}
|
||||||
|
Struct {
|
||||||
|
return sym.info.attrs
|
||||||
|
}
|
||||||
|
FnType {
|
||||||
|
return sym.info.func.attrs
|
||||||
|
}
|
||||||
|
Interface {
|
||||||
|
return unsafe { t.interfaces[sym.idx].attrs }
|
||||||
|
}
|
||||||
|
SumType {
|
||||||
|
return unsafe { t.sumtypes[sym.idx].attrs }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -932,11 +932,11 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if node.kind == .attributes {
|
} else if node.kind == .attributes {
|
||||||
if sym.info is ast.Struct {
|
attrs := g.table.get_attrs(sym)
|
||||||
if sym.info.attrs.len > 0 {
|
if attrs.len > 0 {
|
||||||
g.writeln('\tStructAttribute ${node.val_var} = {0};')
|
g.writeln('\tVAttribute ${node.val_var} = {0};')
|
||||||
}
|
|
||||||
for attr in sym.info.attrs {
|
for attr in attrs {
|
||||||
g.writeln('/* attribute ${i} */ {')
|
g.writeln('/* attribute ${i} */ {')
|
||||||
g.writeln('\t${node.val_var}.name = _SLIT("${attr.name}");')
|
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}.has_arg = ${attr.has_arg};')
|
||||||
|
|
|
@ -170,14 +170,14 @@ fn (mut g Gen) write_orm_create_table(node ast.SqlStmtLine, table_name string, c
|
||||||
g.writeln('.is_arr = ${sym.kind == .array}, ')
|
g.writeln('.is_arr = ${sym.kind == .array}, ')
|
||||||
g.writeln('.nullable = ${field.typ.has_flag(.option)},')
|
g.writeln('.nullable = ${field.typ.has_flag(.option)},')
|
||||||
g.writeln('.default_val = (string){ .str = (byteptr) "${field.default_val}", .is_lit = 1 },')
|
g.writeln('.default_val = (string){ .str = (byteptr) "${field.default_val}", .is_lit = 1 },')
|
||||||
g.writeln('.attrs = new_array_from_c_array(${field.attrs.len}, ${field.attrs.len}, sizeof(StructAttribute),')
|
g.writeln('.attrs = new_array_from_c_array(${field.attrs.len}, ${field.attrs.len}, sizeof(VAttribute),')
|
||||||
g.indent++
|
g.indent++
|
||||||
|
|
||||||
if field.attrs.len > 0 {
|
if field.attrs.len > 0 {
|
||||||
g.write('_MOV((StructAttribute[${field.attrs.len}]){')
|
g.write('_MOV((VAttribute[${field.attrs.len}]){')
|
||||||
g.indent++
|
g.indent++
|
||||||
for attr in field.attrs {
|
for attr in field.attrs {
|
||||||
g.write('(StructAttribute){')
|
g.write('(VAttribute){')
|
||||||
g.indent++
|
g.indent++
|
||||||
g.write(' .name = _SLIT("${attr.name}"),')
|
g.write(' .name = _SLIT("${attr.name}"),')
|
||||||
g.write(' .has_arg = ${attr.has_arg},')
|
g.write(' .has_arg = ${attr.has_arg},')
|
||||||
|
|
|
@ -360,7 +360,7 @@ fn (mut p Parser) comptime_for() ast.ComptimeFor {
|
||||||
'attributes' {
|
'attributes' {
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
name: val_var
|
name: val_var
|
||||||
typ: p.table.find_type_idx('StructAttribute')
|
typ: p.table.find_type_idx('VAttribute')
|
||||||
pos: var_pos
|
pos: var_pos
|
||||||
})
|
})
|
||||||
kind = .attributes
|
kind = .attributes
|
||||||
|
|
|
@ -4409,7 +4409,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
name_pos)
|
name_pos)
|
||||||
return ast.SumTypeDecl{}
|
return ast.SumTypeDecl{}
|
||||||
}
|
}
|
||||||
return ast.SumTypeDecl{
|
node := ast.SumTypeDecl{
|
||||||
name: name
|
name: name
|
||||||
typ: typ
|
typ: typ
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
|
@ -4419,6 +4419,8 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
pos: decl_pos
|
pos: decl_pos
|
||||||
name_pos: name_pos
|
name_pos: name_pos
|
||||||
}
|
}
|
||||||
|
p.table.register_sumtype(node)
|
||||||
|
return node
|
||||||
}
|
}
|
||||||
// type MyType = int
|
// type MyType = int
|
||||||
if generic_types.len > 0 {
|
if generic_types.len > 0 {
|
||||||
|
|
78
vlib/v/tests/comptime_attr_test.v
Normal file
78
vlib/v/tests/comptime_attr_test.v
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
@[bar; foo]
|
||||||
|
fn abc() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@[foo]
|
||||||
|
struct Foo {
|
||||||
|
}
|
||||||
|
|
||||||
|
@[bar]
|
||||||
|
fn Foo.bar() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@[baz]
|
||||||
|
enum EnumFoo {
|
||||||
|
a
|
||||||
|
b
|
||||||
|
}
|
||||||
|
|
||||||
|
@[iface]
|
||||||
|
interface IFoo {
|
||||||
|
}
|
||||||
|
|
||||||
|
@[custom]
|
||||||
|
type CustomType = EnumFoo | Foo
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
mut c := 0
|
||||||
|
$for f in abc.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name in ['foo', 'bar']
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 2
|
||||||
|
|
||||||
|
$for f in Foo.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name == 'foo'
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 3
|
||||||
|
|
||||||
|
a := Foo.bar
|
||||||
|
$for f in a.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name == 'bar'
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 4
|
||||||
|
|
||||||
|
b := abc
|
||||||
|
$for f in b.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name in ['foo', 'bar']
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 6
|
||||||
|
|
||||||
|
$for f in EnumFoo.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name == 'baz'
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 7
|
||||||
|
|
||||||
|
$for f in IFoo.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name == 'iface'
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 8
|
||||||
|
|
||||||
|
$for f in CustomType.attributes {
|
||||||
|
dump(f)
|
||||||
|
assert f.name == 'custom'
|
||||||
|
c++
|
||||||
|
}
|
||||||
|
assert c == 9
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ fn test_main() {
|
||||||
dump(f)
|
dump(f)
|
||||||
dump(f.name)
|
dump(f.name)
|
||||||
c += 1
|
c += 1
|
||||||
assert typeof(f).name == 'StructAttribute'
|
assert typeof(f).name == 'VAttribute'
|
||||||
}
|
}
|
||||||
assert c == 8
|
assert c == 8
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue