v.gen.c: support `T.typ` - an int for the type index of the generic type `T` (#11175)
parent
fb3671107e
commit
900c37aa65
|
@ -1325,6 +1325,7 @@ fn (t Tree) selector_expr(node ast.SelectorExpr) &Node {
|
||||||
obj.add('field_name', t.string_node(node.field_name))
|
obj.add('field_name', t.string_node(node.field_name))
|
||||||
obj.add('typ', t.type_node(node.typ))
|
obj.add('typ', t.type_node(node.typ))
|
||||||
obj.add('name_type', t.type_node(node.name_type))
|
obj.add('name_type', t.type_node(node.name_type))
|
||||||
|
obj.add('gkind_field', t.enum_node(node.gkind_field))
|
||||||
obj.add('from_embed_type', t.type_node(node.from_embed_type))
|
obj.add('from_embed_type', t.type_node(node.from_embed_type))
|
||||||
obj.add('next_token', t.token_node(node.next_token))
|
obj.add('next_token', t.token_node(node.next_token))
|
||||||
obj.add('pos', t.position(node.pos))
|
obj.add('pos', t.position(node.pos))
|
||||||
|
|
|
@ -146,3 +146,43 @@ pub fn radians(degrees f64) f64 {
|
||||||
pub fn signbit(x f64) bool {
|
pub fn signbit(x f64) bool {
|
||||||
return f64_bits(x) & sign_mask != 0
|
return f64_bits(x) & sign_mask != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tolerance(a f64, b f64, tol f64) bool {
|
||||||
|
mut ee := tol
|
||||||
|
// Multiplying by ee here can underflow denormal values to zero.
|
||||||
|
// Check a==b so that at least if a and b are small and identical
|
||||||
|
// we say they match.
|
||||||
|
if a == b {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
mut d := a - b
|
||||||
|
if d < 0 {
|
||||||
|
d = -d
|
||||||
|
}
|
||||||
|
// note: b is correct (expected) value, a is actual value.
|
||||||
|
// make error tolerance a fraction of b, not a.
|
||||||
|
if b != 0 {
|
||||||
|
ee = ee * b
|
||||||
|
if ee < 0 {
|
||||||
|
ee = -ee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d < ee
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(a f64, b f64) bool {
|
||||||
|
return tolerance(a, b, 1e-14)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn veryclose(a f64, b f64) bool {
|
||||||
|
return tolerance(a, b, 4e-16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alike(a f64, b f64) bool {
|
||||||
|
if is_nan(a) && is_nan(b) {
|
||||||
|
return true
|
||||||
|
} else if a == b {
|
||||||
|
return signbit(a) == signbit(b)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -186,50 +186,10 @@ const (
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn tolerance(a f64, b f64, tol f64) bool {
|
|
||||||
mut ee := tol
|
|
||||||
// Multiplying by ee here can underflow denormal values to zero.
|
|
||||||
// Check a==b so that at least if a and b are small and identical
|
|
||||||
// we say they match.
|
|
||||||
if a == b {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
mut d := a - b
|
|
||||||
if d < 0 {
|
|
||||||
d = -d
|
|
||||||
}
|
|
||||||
// note: b is correct (expected) value, a is actual value.
|
|
||||||
// make error tolerance a fraction of b, not a.
|
|
||||||
if b != 0 {
|
|
||||||
ee = ee * b
|
|
||||||
if ee < 0 {
|
|
||||||
ee = -ee
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return d < ee
|
|
||||||
}
|
|
||||||
|
|
||||||
fn close(a f64, b f64) bool {
|
|
||||||
return tolerance(a, b, 1e-14)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn veryclose(a f64, b f64) bool {
|
|
||||||
return tolerance(a, b, 4e-16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn soclose(a f64, b f64, e f64) bool {
|
fn soclose(a f64, b f64, e f64) bool {
|
||||||
return tolerance(a, b, e)
|
return tolerance(a, b, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alike(a f64, b f64) bool {
|
|
||||||
if is_nan(a) && is_nan(b) {
|
|
||||||
return true
|
|
||||||
} else if a == b {
|
|
||||||
return signbit(a) == signbit(b)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn test_nan() {
|
fn test_nan() {
|
||||||
nan_f64 := nan()
|
nan_f64 := nan()
|
||||||
assert nan_f64 != nan_f64
|
assert nan_f64 != nan_f64
|
||||||
|
|
|
@ -129,6 +129,12 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum GenericKindField {
|
||||||
|
unknown
|
||||||
|
name
|
||||||
|
typ
|
||||||
|
}
|
||||||
|
|
||||||
// `foo.bar`
|
// `foo.bar`
|
||||||
pub struct SelectorExpr {
|
pub struct SelectorExpr {
|
||||||
pub:
|
pub:
|
||||||
|
@ -142,6 +148,7 @@ pub mut:
|
||||||
expr_type Type // type of `Foo` in `Foo.bar`
|
expr_type Type // type of `Foo` in `Foo.bar`
|
||||||
typ Type // type of the entire thing (`Foo.bar`)
|
typ Type // type of the entire thing (`Foo.bar`)
|
||||||
name_type Type // T in `T.name` or typeof in `typeof(expr).name`
|
name_type Type // T in `T.name` or typeof in `typeof(expr).name`
|
||||||
|
gkind_field GenericKindField // `T.name` => ast.GenericKindField.name, `T.typ` => ast.GenericKindField.typ, or .unknown
|
||||||
scope &Scope
|
scope &Scope
|
||||||
from_embed_type Type // holds the type of the embed that the method is called from
|
from_embed_type Type // holds the type of the embed that the method is called from
|
||||||
}
|
}
|
||||||
|
|
|
@ -3365,12 +3365,23 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
if name_type > 0 {
|
if name_type > 0 {
|
||||||
if node.field_name != 'name' {
|
|
||||||
c.error('invalid field `.$node.field_name` for type `$node.expr`', node.pos)
|
|
||||||
}
|
|
||||||
node.name_type = name_type
|
node.name_type = name_type
|
||||||
|
match node.gkind_field {
|
||||||
|
.name {
|
||||||
return ast.string_type
|
return ast.string_type
|
||||||
}
|
}
|
||||||
|
.typ {
|
||||||
|
return ast.int_type
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if node.field_name != 'name' {
|
||||||
|
c.error('invalid field `.$node.field_name` for type `$node.expr`',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
return ast.string_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
old_selector_expr := c.inside_selector_expr
|
old_selector_expr := c.inside_selector_expr
|
||||||
c.inside_selector_expr = true
|
c.inside_selector_expr = true
|
||||||
|
|
|
@ -3649,9 +3649,25 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
prevent_sum_type_unwrapping_once := g.prevent_sum_type_unwrapping_once
|
prevent_sum_type_unwrapping_once := g.prevent_sum_type_unwrapping_once
|
||||||
g.prevent_sum_type_unwrapping_once = false
|
g.prevent_sum_type_unwrapping_once = false
|
||||||
if node.name_type > 0 {
|
if node.name_type > 0 {
|
||||||
|
match node.gkind_field {
|
||||||
|
.name {
|
||||||
g.type_name(node.name_type)
|
g.type_name(node.name_type)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
.typ {
|
||||||
|
g.write(int(g.unwrap_generic(node.name_type)).str())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
.unknown {
|
||||||
|
if node.field_name == 'name' {
|
||||||
|
// typeof(expr).name
|
||||||
|
g.type_name(node.name_type)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.error('unknown generic field', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if node.expr_type == 0 {
|
if node.expr_type == 0 {
|
||||||
g.checker_bug('unexpected SelectorExpr.expr_type = 0', node.pos)
|
g.checker_bug('unexpected SelectorExpr.expr_type = 0', node.pos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2158,6 +2158,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
|
fkind := match field {
|
||||||
|
'name' { ast.GenericKindField.name }
|
||||||
|
'typ' { ast.GenericKindField.typ }
|
||||||
|
else { ast.GenericKindField.unknown }
|
||||||
|
}
|
||||||
pos.extend(p.tok.position())
|
pos.extend(p.tok.position())
|
||||||
return ast.SelectorExpr{
|
return ast.SelectorExpr{
|
||||||
expr: ast.Ident{
|
expr: ast.Ident{
|
||||||
|
@ -2165,6 +2170,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
}
|
}
|
||||||
field_name: field
|
field_name: field
|
||||||
|
gkind_field: fkind
|
||||||
pos: pos
|
pos: pos
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import math
|
||||||
|
|
||||||
|
struct Any {
|
||||||
|
mut:
|
||||||
|
data voidptr
|
||||||
|
typ int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_any<T>(obj T) Any {
|
||||||
|
tsize := int(sizeof(T))
|
||||||
|
mut a := Any{
|
||||||
|
typ: T.typ
|
||||||
|
data: unsafe { malloc(tsize) }
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
vmemcpy(a.data, &obj, tsize)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cast<T>(obj Any) ?T {
|
||||||
|
if T.typ == obj.typ {
|
||||||
|
return *&T(obj.data)
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_any_values() {
|
||||||
|
arr := [make_any(true), make_any(false), make_any(7), make_any('cat'),
|
||||||
|
make_any([3.1415926535]),
|
||||||
|
]
|
||||||
|
for elm in arr {
|
||||||
|
if b := cast<bool>(elm) {
|
||||||
|
println(!b)
|
||||||
|
} else if i := cast<int>(elm) {
|
||||||
|
println(i + 1)
|
||||||
|
} else if s := cast<string>(elm) {
|
||||||
|
println(s + '!')
|
||||||
|
} else if f := cast<[]f64>(elm) {
|
||||||
|
println(f[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b := cast<bool>(arr[0]) {
|
||||||
|
assert b == true
|
||||||
|
}
|
||||||
|
if b := cast<bool>(arr[1]) {
|
||||||
|
assert b == false
|
||||||
|
}
|
||||||
|
if s := cast<string>(arr[3]) {
|
||||||
|
assert s == 'cat'
|
||||||
|
}
|
||||||
|
if f := cast<[]f64>(arr[4]) {
|
||||||
|
assert math.veryclose(f[0], 3.1415926535)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue