all: new function `isreftype(T)` to know if `T` contains pointers (#10438)
parent
4a59316600
commit
2ac39d9112
|
@ -979,6 +979,9 @@ fn (t Tree) expr(expr ast.Expr) &Node {
|
|||
ast.SizeOf {
|
||||
return t.size_of(expr)
|
||||
}
|
||||
ast.IsRefType {
|
||||
return t.is_ref_type(expr)
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
return t.prefix_expr(expr)
|
||||
}
|
||||
|
@ -1225,6 +1228,16 @@ fn (t Tree) size_of(node ast.SizeOf) &Node {
|
|||
return obj
|
||||
}
|
||||
|
||||
fn (t Tree) is_ref_type(node ast.IsRefType) &Node {
|
||||
mut obj := new_object()
|
||||
obj.add('ast_type', t.string_node('IsRefType'))
|
||||
obj.add('is_type', t.bool_node(node.is_type))
|
||||
obj.add('typ', t.type_node(node.typ))
|
||||
obj.add('expr', t.expr(node.expr))
|
||||
obj.add('pos', t.position(node.pos))
|
||||
return obj
|
||||
}
|
||||
|
||||
fn (t Tree) prefix_expr(node ast.PrefixExpr) &Node {
|
||||
mut obj := new_object()
|
||||
obj.add('ast_type', t.string_node('PrefixExpr'))
|
||||
|
|
|
@ -12,10 +12,10 @@ pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
|||
pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
|
||||
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
||||
ComptimeSelector | ConcatExpr | DumpExpr | EmptyExpr | EnumVal | FloatLiteral | GoExpr |
|
||||
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||
MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr |
|
||||
PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
|
||||
StringLiteral | StructInit | TypeNode | TypeOf | UnsafeExpr
|
||||
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | IsRefType |
|
||||
Likely | LockExpr | MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr |
|
||||
PostfixExpr | PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr |
|
||||
StringInterLiteral | StringLiteral | StructInit | TypeNode | TypeOf | UnsafeExpr
|
||||
|
||||
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
||||
DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
|
||||
|
@ -1338,6 +1338,15 @@ pub mut:
|
|||
typ Type
|
||||
}
|
||||
|
||||
pub struct IsRefType {
|
||||
pub:
|
||||
is_type bool
|
||||
expr Expr // checker uses this to set typ
|
||||
pos token.Position
|
||||
pub mut:
|
||||
typ Type
|
||||
}
|
||||
|
||||
pub struct OffsetOf {
|
||||
pub:
|
||||
struct_type Type
|
||||
|
@ -1516,10 +1525,10 @@ pub fn (expr Expr) position() token.Position {
|
|||
}
|
||||
NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr,
|
||||
CastExpr, ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector,
|
||||
EnumVal, DumpExpr, FloatLiteral, GoExpr, Ident, IfExpr, IntegerLiteral, Likely, LockExpr,
|
||||
MapInit, MatchExpr, None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr,
|
||||
SelectExpr, SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit,
|
||||
TypeNode, TypeOf, UnsafeExpr {
|
||||
EnumVal, DumpExpr, FloatLiteral, GoExpr, Ident, IfExpr, IntegerLiteral, IsRefType, Likely,
|
||||
LockExpr, MapInit, MatchExpr, None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr,
|
||||
RangeExpr, SelectExpr, SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral,
|
||||
StructInit, TypeNode, TypeOf, UnsafeExpr {
|
||||
return expr.pos
|
||||
}
|
||||
IndexExpr {
|
||||
|
|
|
@ -4833,6 +4833,12 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
|||
}
|
||||
return ast.u32_type
|
||||
}
|
||||
ast.IsRefType {
|
||||
if !node.is_type {
|
||||
node.typ = c.expr(node.expr)
|
||||
}
|
||||
return ast.bool_type
|
||||
}
|
||||
ast.OffsetOf {
|
||||
return c.offset_of(node)
|
||||
}
|
||||
|
|
|
@ -601,6 +601,9 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
|||
ast.SizeOf {
|
||||
f.size_of(node)
|
||||
}
|
||||
ast.IsRefType {
|
||||
f.is_ref_type(node)
|
||||
}
|
||||
ast.SqlExpr {
|
||||
f.sql_expr(node)
|
||||
}
|
||||
|
@ -2321,6 +2324,16 @@ pub fn (mut f Fmt) size_of(node ast.SizeOf) {
|
|||
f.write(')')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) is_ref_type(node ast.IsRefType) {
|
||||
f.write('isreftype(')
|
||||
if node.is_type {
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
} else {
|
||||
f.expr(node.expr)
|
||||
}
|
||||
f.write(')')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) sql_expr(node ast.SqlExpr) {
|
||||
// sql app.db { select from Contributor where repo == id && user == 0 }
|
||||
f.write('sql ')
|
||||
|
|
|
@ -3303,6 +3303,15 @@ fn (mut g Gen) expr(node ast.Expr) {
|
|||
styp := g.typ(node_typ)
|
||||
g.write('/*SizeOf*/ sizeof(${util.no_dots(styp)})')
|
||||
}
|
||||
ast.IsRefType {
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
sym := g.table.get_type_symbol(node_typ)
|
||||
if sym.language == .v && sym.kind in [.placeholder, .any] {
|
||||
g.error('unknown type `$sym.name`', node.pos)
|
||||
}
|
||||
is_ref_type := g.contains_ptr(node_typ)
|
||||
g.write('/*IsRefType*/ $is_ref_type')
|
||||
}
|
||||
ast.OffsetOf {
|
||||
styp := g.typ(node.struct_type)
|
||||
g.write('/*OffsetOf*/ (u32)(__offsetof(${util.no_dots(styp)}, $node.field))')
|
||||
|
|
|
@ -637,7 +637,7 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
|||
ast.SelectorExpr {
|
||||
g.gen_selector_expr(node)
|
||||
}
|
||||
ast.SizeOf {
|
||||
ast.SizeOf, ast.IsRefType {
|
||||
// TODO
|
||||
}
|
||||
ast.OffsetOf {
|
||||
|
|
|
@ -298,7 +298,7 @@ fn (mut w Walker) expr(node ast.Expr) {
|
|||
w.expr(node.high)
|
||||
}
|
||||
}
|
||||
ast.SizeOf {
|
||||
ast.SizeOf, ast.IsRefType {
|
||||
w.expr(node.expr)
|
||||
}
|
||||
ast.StringInterLiteral {
|
||||
|
|
|
@ -190,7 +190,8 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr {
|
|||
pos: pos
|
||||
}
|
||||
}
|
||||
.key_sizeof {
|
||||
.key_sizeof, .key_isreftype {
|
||||
is_reftype := p.tok.kind == .key_isreftype
|
||||
p.next() // sizeof
|
||||
p.check(.lpar)
|
||||
pos := p.tok.position()
|
||||
|
@ -198,10 +199,18 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr {
|
|||
// assume mod. prefix leads to a type
|
||||
if is_known_var || !(p.known_import(p.tok.lit) || p.tok.kind.is_start_of_type()) {
|
||||
expr := p.expr(0)
|
||||
node = ast.SizeOf{
|
||||
is_type: false
|
||||
expr: expr
|
||||
pos: pos
|
||||
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 {
|
||||
if p.tok.kind == .name {
|
||||
|
@ -209,12 +218,20 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr {
|
|||
}
|
||||
save_expr_mod := p.expr_mod
|
||||
p.expr_mod = ''
|
||||
sizeof_type := p.parse_type()
|
||||
arg_type := p.parse_type()
|
||||
p.expr_mod = save_expr_mod
|
||||
node = ast.SizeOf{
|
||||
is_type: true
|
||||
typ: sizeof_type
|
||||
pos: pos
|
||||
if is_reftype {
|
||||
node = ast.IsRefType{
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
node = ast.SizeOf{
|
||||
is_type: true
|
||||
typ: arg_type
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
}
|
||||
p.check(.rpar)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
struct S1 {
|
||||
p voidptr
|
||||
}
|
||||
|
||||
struct S2 {
|
||||
i int
|
||||
}
|
||||
|
||||
struct S3 {
|
||||
x &S2
|
||||
y int
|
||||
}
|
||||
|
||||
struct S4 {
|
||||
x S2
|
||||
mut:
|
||||
y f64
|
||||
}
|
||||
|
||||
struct S5 {
|
||||
S3
|
||||
a f32
|
||||
}
|
||||
|
||||
fn test_isreftype() {
|
||||
assert isreftype(S1) == true
|
||||
assert isreftype(S2) == false
|
||||
assert isreftype(S3) == true
|
||||
assert isreftype(S4) == false
|
||||
assert isreftype(S5) == true
|
||||
assert isreftype(f64) == false
|
||||
assert isreftype([]f64) == true
|
||||
assert isreftype([3]int) == false
|
||||
}
|
||||
|
||||
fn check_ref<T>() string {
|
||||
if isreftype(T) {
|
||||
return 'ref'
|
||||
} else {
|
||||
return 'no ref'
|
||||
}
|
||||
}
|
||||
|
||||
fn test_generic_ref() {
|
||||
assert check_ref<f64>() == 'no ref'
|
||||
assert check_ref<S3>() == 'ref'
|
||||
}
|
||||
|
||||
fn test_expression_ref() {
|
||||
mut a := S3{
|
||||
x: &S2{}
|
||||
}
|
||||
b := S4{}
|
||||
c := 32.5 * 6
|
||||
assert isreftype(a) == true
|
||||
assert isreftype(b) == false
|
||||
assert isreftype(c) == false
|
||||
}
|
|
@ -111,6 +111,7 @@ pub enum Kind {
|
|||
key_return
|
||||
key_select
|
||||
key_sizeof
|
||||
key_isreftype
|
||||
key_likely
|
||||
key_unlikely
|
||||
key_offsetof
|
||||
|
@ -267,6 +268,7 @@ fn build_token_str() []string {
|
|||
s[Kind.key_return] = 'return'
|
||||
s[Kind.key_module] = 'module'
|
||||
s[Kind.key_sizeof] = 'sizeof'
|
||||
s[Kind.key_isreftype] = 'isreftype'
|
||||
s[Kind.key_likely] = '_likely_'
|
||||
s[Kind.key_unlikely] = '_unlikely_'
|
||||
s[Kind.key_go] = 'go'
|
||||
|
|
Loading…
Reference in New Issue