Implement the is operator for the new static and typedesc type classes
This also makes the first baby steps towards a sound treatment of higher-order kinds (type type int). Adds test cases showcasing the new features. * Also fixes breakage after the rebase
This commit is contained in:
parent
ab9969ed3b
commit
a49b06a52a
10 changed files with 210 additions and 55 deletions
|
|
@ -5,15 +5,16 @@ type
|
|||
x: T
|
||||
y: U
|
||||
|
||||
proc getTypeName(t: typedesc): string = t.name
|
||||
proc getTypeName1(t: typedesc): string = t.name
|
||||
proc getTypeName2(t: type): string = t.name
|
||||
|
||||
proc foo(T: typedesc[float], a: auto): string =
|
||||
proc foo(T: type float, a: auto): string =
|
||||
result = "float " & $(a.len > 5)
|
||||
|
||||
proc foo(T: typedesc[TFoo], a: int): string =
|
||||
result = "TFoo " & $(a)
|
||||
|
||||
proc foo(T: typedesc[int or bool]): string =
|
||||
proc foo(T: type[int or bool]): string =
|
||||
var a: T
|
||||
a = 10
|
||||
result = "int or bool " & ($a)
|
||||
|
|
@ -23,8 +24,8 @@ template foo(T: typedesc[seq]): string = "seq"
|
|||
test "types can be used as proc params":
|
||||
# XXX: `check` needs to know that TFoo[int, float] is a type and
|
||||
# cannot be assigned for a local variable for later inspection
|
||||
check ((string.getTypeName == "string"))
|
||||
check ((getTypeName(int) == "int"))
|
||||
check ((string.getTypeName1 == "string"))
|
||||
check ((getTypeName2(int) == "int"))
|
||||
|
||||
check ((foo(TFoo[int, float], 1000) == "TFoo 1000"))
|
||||
|
||||
|
|
@ -37,6 +38,25 @@ test "types can be used as proc params":
|
|||
check ((foo(seq[int]) == "seq"))
|
||||
check ((foo(seq[TFoo[bool, string]]) == "seq"))
|
||||
|
||||
when false:
|
||||
proc foo(T: typedesc[seq], s: T) = nil
|
||||
template accept(x) =
|
||||
static: assert(compiles(x))
|
||||
|
||||
template reject(x) =
|
||||
static: assert(not compiles(x))
|
||||
|
||||
var
|
||||
si: seq[int]
|
||||
ss: seq[string]
|
||||
|
||||
proc foo(T: typedesc[seq], s: T) =
|
||||
discard
|
||||
|
||||
accept:
|
||||
foo seq[int], si
|
||||
|
||||
reject:
|
||||
foo seq[string], si
|
||||
|
||||
reject:
|
||||
foo seq[int], ss
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ type
|
|||
Base = object of RootObj
|
||||
Child = object of Base
|
||||
|
||||
proc pr(T: typedesc[Base]) = echo "proc " & T.name
|
||||
method me(T: typedesc[Base]) = echo "method " & T.name
|
||||
iterator it(T: typedesc[Base]): auto = yield "yield " & T.name
|
||||
proc pr(T: type[Base]) = echo "proc " & T.name
|
||||
method me(T: type[Base]) = echo "method " & T.name
|
||||
iterator it(T: type[Base]): auto = yield "yield " & T.name
|
||||
|
||||
Base.pr
|
||||
Child.pr
|
||||
|
|
|
|||
|
|
@ -5,16 +5,16 @@ output: "8\n8\n4"
|
|||
import
|
||||
macros, typetraits
|
||||
|
||||
template selectType(x: int): typeDesc =
|
||||
template selectType(x: int): type =
|
||||
when x < 10:
|
||||
int
|
||||
else:
|
||||
string
|
||||
|
||||
template simpleTypeTempl: typeDesc =
|
||||
template simpleTypeTempl: type =
|
||||
string
|
||||
|
||||
macro typeFromMacro: typedesc = string
|
||||
macro typeFromMacro: type = string
|
||||
|
||||
# The tests below check that the result variable of the
|
||||
# selected type matches the literal types in the code:
|
||||
|
|
|
|||
|
|
@ -1,17 +1,42 @@
|
|||
discard """
|
||||
action: run
|
||||
"""
|
||||
|
||||
type
|
||||
R = ref
|
||||
V = var
|
||||
D = distinct
|
||||
P = ptr
|
||||
T = type
|
||||
S = static
|
||||
OBJ = object
|
||||
TPL = tuple
|
||||
SEQ = seq
|
||||
|
||||
var i: int
|
||||
var x: ref int
|
||||
var y: distinct int
|
||||
var z: ptr int
|
||||
const C = @[1, 2, 3]
|
||||
|
||||
static:
|
||||
assert x is ref
|
||||
assert y is distinct
|
||||
assert z is ptr
|
||||
assert C is static
|
||||
assert C[1] is static[int]
|
||||
assert C[0] is static[SomeInteger]
|
||||
assert C isnot static[string]
|
||||
assert C is SEQ|OBJ
|
||||
assert C isnot OBJ|TPL
|
||||
assert int is int
|
||||
assert int is T
|
||||
assert int is SomeInteger
|
||||
assert seq[int] is type
|
||||
assert seq[int] is type[seq]
|
||||
assert seq[int] isnot type[seq[float]]
|
||||
assert i isnot type[int]
|
||||
assert type(i) is type[int]
|
||||
assert x isnot T
|
||||
assert y isnot S
|
||||
assert z isnot enum
|
||||
assert x isnot object
|
||||
assert y isnot tuple
|
||||
assert z isnot seq
|
||||
|
||||
doAssert x is ref
|
||||
doAssert y is distinct
|
||||
doAssert z is ptr
|
||||
|
|
@ -1,25 +1,91 @@
|
|||
discard """
|
||||
nimout: '''
|
||||
staticAlialProc instantiated with 4
|
||||
staticAlialProc instantiated with 6
|
||||
staticAlialProc instantiated with 358
|
||||
staticAlialProc instantiated with 368
|
||||
'''
|
||||
output: '''
|
||||
16
|
||||
16
|
||||
b is 2 times a
|
||||
17
|
||||
'''
|
||||
"""
|
||||
|
||||
import macros
|
||||
|
||||
template ok(x) = assert(x)
|
||||
template no(x) = assert(not x)
|
||||
|
||||
template accept(x) =
|
||||
static: assert(compiles(x))
|
||||
|
||||
template reject(x) =
|
||||
static: assert(not compiles(x))
|
||||
|
||||
proc plus(a, b: int): int = a + b
|
||||
|
||||
template isStatic(x: static): bool = true
|
||||
template isStatic(x: auto): bool = false
|
||||
|
||||
var v = 1
|
||||
|
||||
when true:
|
||||
# test that `isStatic` works as expected
|
||||
const C = 2
|
||||
|
||||
static:
|
||||
ok C.isStatic
|
||||
ok isStatic(plus(1, 2))
|
||||
ok plus(C, 2).isStatic
|
||||
|
||||
no isStatic(v)
|
||||
no plus(1, v).isStatic
|
||||
|
||||
when true:
|
||||
# test that proc instantiation works as expected
|
||||
type
|
||||
StaticTypeAlias = static[int]
|
||||
|
||||
proc staticAliasProc(s: StaticTypeAlias) =
|
||||
static: echo "staticAlialProc instantiated with ", s + 1
|
||||
echo s
|
||||
proc staticAliasProc(a: StaticTypeAlias,
|
||||
b: static[int],
|
||||
c: static int) =
|
||||
static:
|
||||
assert a.isStatic and b.isStatic and c.isStatic
|
||||
assert isStatic(a + plus(b, c))
|
||||
echo "staticAlialProc instantiated with ", a, b, c
|
||||
|
||||
staticAliasProc 1+2
|
||||
staticAliasProc 3
|
||||
staticAliasProc 5
|
||||
when b mod a == 0:
|
||||
echo "b is ", b div a, " times a"
|
||||
|
||||
echo a + b + c
|
||||
|
||||
staticAliasProc 1+2, 5, 8
|
||||
staticAliasProc 3, 2+3, 9-1
|
||||
staticAliasProc 3, 3+3, 4+4
|
||||
|
||||
when true:
|
||||
# test static coercions. normal cases that should work:
|
||||
accept:
|
||||
var s1 = static[int] plus(1, 2)
|
||||
var s2 = static(plus(1,2))
|
||||
var s3 = static plus(1,2)
|
||||
var s4 = static[SomeInteger](1 + 2)
|
||||
|
||||
# the sub-script operator can be used only with types:
|
||||
reject:
|
||||
var just_static3 = static[plus(1,2)]
|
||||
|
||||
# static coercion takes into account the type:
|
||||
reject:
|
||||
var x = static[string](plus(1, 2))
|
||||
reject:
|
||||
var x = static[string] plus(1, 2)
|
||||
reject:
|
||||
var x = static[SomeFloat] plus(3, 4)
|
||||
|
||||
# you cannot coerce a run-time variable
|
||||
reject:
|
||||
var x = static(v)
|
||||
|
||||
when true:
|
||||
type
|
||||
|
|
@ -35,7 +101,7 @@ when true:
|
|||
var aw1: ArrayWrapper1[5]
|
||||
var aw2: ArrayWrapper2[5]
|
||||
var aw3: ArrayWrapper3[(10, "str")]
|
||||
|
||||
|
||||
static:
|
||||
assert aw1.data.high == 5
|
||||
assert aw2.data.high == 6
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ false
|
|||
false
|
||||
true
|
||||
true
|
||||
no'''
|
||||
yes'''
|
||||
"""
|
||||
|
||||
proc IsVoid[T](): string =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue