v.parser: eliminate PrefixExpr from `&Type(x).name` and `&Type(x)[idx]` too (fix vinix build)

pull/10848/head
Delyan Angelov 2021-07-17 20:19:29 +03:00
parent fc8a8e3b6f
commit 6edfb2c7fe
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
5 changed files with 89 additions and 16 deletions

View File

@ -1224,12 +1224,13 @@ fn (t Tree) at_expr(node ast.AtExpr) &Node {
fn (t Tree) cast_expr(node ast.CastExpr) &Node {
mut obj := new_object()
obj.add('ast_type', t.string_node('CastExpr'))
obj.add('expr', t.expr(node.expr))
obj.add('arg', t.expr(node.arg))
obj.add('typ', t.type_node(node.typ))
obj.add('ityp', t.number_node(int(node.typ)))
obj.add('typname', t.string_node(node.typname))
obj.add('expr_type', t.type_node(node.expr_type))
obj.add('has_arg', t.bool_node(node.has_arg))
obj.add('arg', t.expr(node.arg))
obj.add('expr_type', t.type_node(node.expr_type))
obj.add('expr', t.expr(node.expr))
obj.add('pos', t.position(node.pos))
return obj
}

View File

@ -1101,9 +1101,9 @@ pub:
pub struct CastExpr {
pub:
arg Expr // `n` in `string(buf, n)`
typ Type // `string` TODO rename to `type_to_cast_to`
pos token.Position
pub mut:
typ Type // `string` TODO rename to `type_to_cast_to`
pos token.Position
expr Expr // `buf` in `string(buf, n)`
typname string // TypeSymbol.name
expr_type Type // `byteptr`

View File

@ -1,4 +1,7 @@
struct Struct {}
struct Struct {
name string
x int
}
fn main() {
unsafe {
@ -27,4 +30,21 @@ fn main() {
dump(voidptr(ppps))
dump(voidptr(pppps))
}
ss := &Struct{
name: 'abc'
x: 123
}
dump(ss)
pss := voidptr(ss)
if &Struct(pss).name == 'abc' {
println('ok')
}
if &Struct(pss).x == 123 {
// &Struct cast and selecting .x
println('ok')
}
if &&Struct(pss) != 0 {
// &&Struct
println('ok')
}
}

View File

@ -578,15 +578,25 @@ fn (mut p Parser) prefix_expr() ast.Expr {
p.next()
mut right := p.expr(int(token.Precedence.prefix))
p.is_amp = false
if mut right is ast.CastExpr && op == .amp {
// Handle &Type(x), as well as &&Type(x) etc:
mut new_cast_type := right.typ.to_ptr()
nct_sym := p.table.get_type_symbol(new_cast_type)
return ast.CastExpr{
...right
typ: new_cast_type
typname: nct_sym.name
pos: pos.extend(right.pos)
if op == .amp {
if mut right is ast.CastExpr {
// Handle &Type(x), as well as &&Type(x) etc:
p.recast_as_pointer(mut right, pos)
return right
}
if mut right is ast.SelectorExpr {
// Handle &Type(x).name :
if mut right.expr is ast.CastExpr {
p.recast_as_pointer(mut right.expr, pos)
return right
}
}
if mut right is ast.IndexExpr {
// Handle &u64(x)[idx] :
if mut right.left is ast.CastExpr {
p.recast_as_pointer(mut right.left, pos)
return right
}
}
}
mut or_stmts := []ast.Stmt{}
@ -627,3 +637,9 @@ fn (mut p Parser) prefix_expr() ast.Expr {
}
}
}
fn (mut p Parser) recast_as_pointer(mut cast_expr ast.CastExpr, pos token.Position) {
cast_expr.typ = cast_expr.typ.to_ptr()
cast_expr.typname = p.table.get_type_symbol(cast_expr.typ).name
cast_expr.pos = pos.extend(cast_expr.pos)
}

View File

@ -1,4 +1,7 @@
struct Struct {}
struct Struct {
name string
x int
}
fn test_byte_pointer_casts() {
unsafe {
@ -38,3 +41,36 @@ fn test_struct_pointer_casts() {
assert voidptr(pppps).str() == 'c'
}
}
fn test_struct_pointer_casts_with_field_selectors() {
ss := &Struct{
name: 'abc'
x: 123
}
dump(ss)
pss := voidptr(ss)
if &Struct(pss).name == 'abc' {
assert true
}
if &Struct(pss).x == 123 {
// &Struct cast and selecting .x
assert true
}
if &&Struct(pss) != 0 {
// &&Struct
assert true
}
}
fn test_pointer_casts_with_indexing() {
mut numbers := [5]u64{}
numbers[0] = 123
numbers[1] = 456
unsafe {
pnumbers := voidptr(&numbers[0])
assert &u64(pnumbers)[0] == 123
assert &u64(pnumbers)[1] == 456
idx := 1
assert &u64(pnumbers)[idx] == 456
}
}