mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: support an unambiguous sizeof[T]() and isreftype[T]() (part 1) (#16684)
This commit is contained in:
parent
e5e73ebbfa
commit
0a11955284
@ -6468,4 +6468,4 @@ Assignment Operators
|
||||
+= -= *= /= %=
|
||||
&= |= ^=
|
||||
>>= <<= >>>=
|
||||
```
|
||||
```
|
@ -1591,19 +1591,21 @@ pub mut:
|
||||
|
||||
pub struct SizeOf {
|
||||
pub:
|
||||
is_type bool
|
||||
pos token.Pos
|
||||
guessed_type bool // a legacy `sizeof( GuessedType )` => a deprecation notice, suggesting `v fmt -w .` => `sizeof[ Type ]()`
|
||||
is_type bool
|
||||
pos token.Pos
|
||||
pub mut:
|
||||
expr Expr // checker uses this to set typ
|
||||
expr Expr // checker uses this to set typ, when !is_type
|
||||
typ Type
|
||||
}
|
||||
|
||||
pub struct IsRefType {
|
||||
pub:
|
||||
is_type bool
|
||||
pos token.Pos
|
||||
guessed_type bool // a legacy `isreftype( GuessedType )` => a deprecation notice, suggesting `v fmt -w .` => `isreftype[ Type ]()`
|
||||
is_type bool
|
||||
pos token.Pos
|
||||
pub mut:
|
||||
expr Expr // checker uses this to set typ
|
||||
expr Expr // checker uses this to set typ, when !is_type
|
||||
typ Type
|
||||
}
|
||||
|
||||
@ -1629,7 +1631,7 @@ pub:
|
||||
is_type bool
|
||||
pos token.Pos
|
||||
pub mut:
|
||||
expr Expr // checker uses this to set typ
|
||||
expr Expr // checker uses this to set typ, when !is_type
|
||||
typ Type
|
||||
}
|
||||
|
||||
|
@ -2520,12 +2520,16 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
|
||||
if !node.is_type {
|
||||
node.typ = c.expr(node.expr)
|
||||
}
|
||||
// c.deprecate_old_isreftype_and_sizeof_of_a_guessed_type(node.guessed_type,
|
||||
// node.typ, node.pos, 'sizeof')
|
||||
return ast.u32_type
|
||||
}
|
||||
ast.IsRefType {
|
||||
if !node.is_type {
|
||||
node.typ = c.expr(node.expr)
|
||||
}
|
||||
// c.deprecate_old_isreftype_and_sizeof_of_a_guessed_type(node.guessed_type,
|
||||
// node.typ, node.pos, 'isreftype')
|
||||
return ast.bool_type
|
||||
}
|
||||
ast.OffsetOf {
|
||||
@ -4395,3 +4399,11 @@ fn semicolonize(main string, details string) string {
|
||||
}
|
||||
return '${main}; ${details}'
|
||||
}
|
||||
|
||||
fn (mut c Checker) deprecate_old_isreftype_and_sizeof_of_a_guessed_type(is_guessed_type bool, typ ast.Type, pos token.Pos, label string) {
|
||||
if is_guessed_type {
|
||||
styp := c.table.type_to_str(typ)
|
||||
c.note('`${label}(${styp})` is deprecated. Use `v fmt -w .` to convert it to `${label}[${styp}]()` instead.',
|
||||
pos)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
vlib/v/checker/tests/unknown_sizeof_type_err_a.vv:14:34: cgen error: unknown type `T`
|
||||
12 | println("size of Abc: ${sizeof(Abc)}")
|
||||
13 | println("size of Xyz: ${sizeof(Xyz)}")
|
||||
14 | println("size of Test: ${sizeof(T)}")
|
||||
| ^
|
||||
12 | println('size of Abc: ${sizeof[Abc]()}')
|
||||
13 | println('size of Xyz: ${sizeof[Xyz]()}')
|
||||
14 | println('size of Test: ${sizeof[T]()}')
|
||||
| ~~
|
||||
15 | }
|
||||
|
@ -9,7 +9,7 @@ struct Xyz {
|
||||
type Test = Abc | Xyz
|
||||
|
||||
fn main() {
|
||||
println("size of Abc: ${sizeof(Abc)}")
|
||||
println("size of Xyz: ${sizeof(Xyz)}")
|
||||
println("size of Test: ${sizeof(T)}")
|
||||
println('size of Abc: ${sizeof[Abc]()}')
|
||||
println('size of Xyz: ${sizeof[Xyz]()}')
|
||||
println('size of Test: ${sizeof[T]()}')
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
vlib/v/checker/tests/unknown_sizeof_type_err_b.vv:14:34: cgen error: unknown type `Zabc`
|
||||
12 | println("size of Abc: ${sizeof(Abc)}")
|
||||
13 | println("size of Xyz: ${sizeof(Xyz)}")
|
||||
14 | println("size of Test: ${sizeof(Zabc)}")
|
||||
| ~~~~
|
||||
12 | println('size of Abc: ${sizeof[Abc]()}')
|
||||
13 | println('size of Xyz: ${sizeof[Xyz]()}')
|
||||
14 | println('size of Test: ${sizeof[Zabc]()}')
|
||||
| ~~~~~
|
||||
15 | }
|
||||
|
@ -9,7 +9,7 @@ struct Xyz {
|
||||
type Test = Abc | Xyz
|
||||
|
||||
fn main() {
|
||||
println("size of Abc: ${sizeof(Abc)}")
|
||||
println("size of Xyz: ${sizeof(Xyz)}")
|
||||
println("size of Test: ${sizeof(Zabc)}")
|
||||
println('size of Abc: ${sizeof[Abc]()}')
|
||||
println('size of Xyz: ${sizeof[Xyz]()}')
|
||||
println('size of Test: ${sizeof[Zabc]()}')
|
||||
}
|
||||
|
@ -2572,23 +2572,43 @@ pub fn (mut f Fmt) selector_expr(node ast.SelectorExpr) {
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) size_of(node ast.SizeOf) {
|
||||
f.write('sizeof(')
|
||||
f.write('sizeof')
|
||||
if node.is_type {
|
||||
// keep the old form for now
|
||||
f.write('(')
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
} else {
|
||||
f.expr(node.expr)
|
||||
f.write(')')
|
||||
return
|
||||
}
|
||||
if node.is_type {
|
||||
f.write('[')
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
f.write(']()')
|
||||
} else {
|
||||
f.write('(')
|
||||
f.expr(node.expr)
|
||||
f.write(')')
|
||||
}
|
||||
f.write(')')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) is_ref_type(node ast.IsRefType) {
|
||||
f.write('isreftype(')
|
||||
f.write('isreftype')
|
||||
if node.is_type {
|
||||
// keep the old form for now
|
||||
f.write('(')
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
} else {
|
||||
f.expr(node.expr)
|
||||
f.write(')')
|
||||
return
|
||||
}
|
||||
if node.is_type {
|
||||
f.write('[')
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
f.write(']()')
|
||||
} else {
|
||||
f.write('(')
|
||||
f.expr(node.expr)
|
||||
f.write(')')
|
||||
}
|
||||
f.write(')')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) {
|
||||
|
@ -236,57 +236,85 @@ pub fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||
.key_sizeof, .key_isreftype {
|
||||
is_reftype := p.tok.kind == .key_isreftype
|
||||
p.next() // sizeof
|
||||
p.check(.lpar)
|
||||
pos := p.tok.pos()
|
||||
mut is_known_var := p.mark_var_as_used(p.tok.lit)
|
||||
|| p.table.global_scope.known_const(p.mod + '.' + p.tok.lit)
|
||||
//|| p.table.known_fn(p.mod + '.' + p.tok.lit)
|
||||
// assume `mod.` prefix leads to a type
|
||||
mut is_type := p.known_import(p.tok.lit) || p.tok.kind.is_start_of_type()
|
||||
|| (p.tok.lit.len > 0 && p.tok.lit[0].is_capital())
|
||||
|
||||
if p.tok.lit in ['c', 'r'] && p.peek_tok.kind == .string {
|
||||
is_known_var = false
|
||||
is_type = false
|
||||
}
|
||||
if is_known_var || !is_type {
|
||||
expr := p.expr(0)
|
||||
if p.tok.kind == .lsbr {
|
||||
// parse sizeof[T]() and isreftype[T]() without guessing:
|
||||
p.check(.lsbr)
|
||||
mut type_pos := p.tok.pos()
|
||||
typ := p.parse_type()
|
||||
type_pos = type_pos.extend(p.tok.pos())
|
||||
p.check(.rsbr)
|
||||
p.check(.lpar)
|
||||
p.check(.rpar)
|
||||
if is_reftype {
|
||||
node = ast.IsRefType{
|
||||
is_type: false
|
||||
expr: expr
|
||||
pos: pos
|
||||
is_type: true
|
||||
typ: typ
|
||||
pos: type_pos
|
||||
}
|
||||
} else {
|
||||
node = ast.SizeOf{
|
||||
is_type: false
|
||||
expr: expr
|
||||
pos: pos
|
||||
is_type: true
|
||||
typ: typ
|
||||
pos: type_pos
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if p.tok.kind == .name {
|
||||
p.register_used_import(p.tok.lit)
|
||||
p.check(.lpar)
|
||||
pos := p.tok.pos()
|
||||
mut is_known_var := p.mark_var_as_used(p.tok.lit)
|
||||
|| p.table.global_scope.known_const(p.mod + '.' + p.tok.lit)
|
||||
//|| p.table.known_fn(p.mod + '.' + p.tok.lit)
|
||||
// assume `mod.` prefix leads to a type
|
||||
mut is_type := p.known_import(p.tok.lit)
|
||||
|| p.tok.kind.is_start_of_type()
|
||||
|| (p.tok.lit.len > 0 && p.tok.lit[0].is_capital())
|
||||
|
||||
if p.tok.lit in ['c', 'r'] && p.peek_tok.kind == .string {
|
||||
is_known_var = false
|
||||
is_type = false
|
||||
}
|
||||
save_expr_mod := p.expr_mod
|
||||
p.expr_mod = ''
|
||||
arg_type := p.parse_type()
|
||||
p.expr_mod = save_expr_mod
|
||||
if is_reftype {
|
||||
node = ast.IsRefType{
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
if is_known_var || !is_type {
|
||||
expr := p.expr(0)
|
||||
if is_reftype {
|
||||
node = ast.IsRefType{
|
||||
is_type: false
|
||||
expr: expr
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
node = ast.SizeOf{
|
||||
is_type: false
|
||||
expr: expr
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
} else {
|
||||
node = ast.SizeOf{
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
if p.tok.kind == .name {
|
||||
p.register_used_import(p.tok.lit)
|
||||
}
|
||||
save_expr_mod := p.expr_mod
|
||||
p.expr_mod = ''
|
||||
arg_type := p.parse_type()
|
||||
p.expr_mod = save_expr_mod
|
||||
if is_reftype {
|
||||
node = ast.IsRefType{
|
||||
guessed_type: true
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
node = ast.SizeOf{
|
||||
guessed_type: true
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
}
|
||||
p.check(.rpar)
|
||||
}
|
||||
p.check(.rpar)
|
||||
}
|
||||
.key_dump {
|
||||
spos := p.tok.pos()
|
||||
|
Loading…
Reference in New Issue
Block a user