Static[T] fixes (#7333)

* fix the usage of unresolved static[T] parameters in proc signatures
* fix tsametype and tmacrogenerics
* Allow creating composite type classes with concepts and using them in type signatures
* Allow integers to be used in ident concatenations
* Support using imported C++ generic types in proc signatures
* fixes #7230
* closes #7379
* re-enable some metatype tests
This commit is contained in:
zah 2018-03-24 16:28:09 +02:00 • committed by Andreas Rumpf
commit 121b9e26fb
18 changed files with 265 additions and 26 deletions

View file

@ -0,0 +1,19 @@
discard """
output: "1\n2\n3"
"""
type
MyConcept = concept x
someProc(x)
SomeSeq = seq[MyConcept]
proc someProc(x:int) = echo x
proc work (s: SomeSeq) =
for item in s:
someProc item
var s = @[1, 2, 3]
work s

View file

@ -300,7 +300,7 @@ reject wantsVarPointer2(pcat)
# covariance may be allowed for certain extern types
{.emit: """
{.emit: """/*TYPESECTION*/
template <class T> struct FN { typedef void (*type)(T); };
template <class T> struct ARR { typedef T DataType[2]; DataType data; };
""".}

View file

@ -2,7 +2,7 @@ discard """
targets: "cpp"
"""
{.emit: """
{.emit: """/*TYPESECTION*/
template <class T>
struct Vector {

View file

@ -14,7 +14,6 @@ AST b
20Test
20
'''
disabled: true
"""
import macros
@ -26,7 +25,7 @@ type
const data: Tconfig = (@["aa", "bb"], @[11, 22])
macro mymacro(data: static[TConfig]) =
macro mymacro(data: static[TConfig]): untyped =
echo "letters"
for s in items(data.letters):
echo s
@ -44,10 +43,10 @@ const
a : Ta = @[(11, 22), (33, 44)]
b : Tb = (@[55,66], @[77, 88])
macro mA(data: static[Ta]) =
macro mA(data: static[Ta]): untyped =
echo "AST a \n", repr(data)
macro mB(data: static[Tb]) =
macro mB(data: static[Tb]): untyped =
echo "AST b \n", repr(data)
echo data.e[0]
@ -57,13 +56,15 @@ mB(b)
type
Foo[N: static[int], Z: static[string]] = object
macro staticIntMacro(f: static[int]) = echo f
macro staticIntMacro(f: static[int]): untyped =
echo f
staticIntMacro 10
var
x: Foo[20, "Test"]
macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12) =
macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): untyped =
echo N, Z
genericMacro x

View file

@ -1,4 +1,9 @@
import macros
discard """
output: "8\n8\n4"
"""
import
macros, typetraits
template selectType(x: int): typeDesc =
when x < 10:
@ -11,6 +16,9 @@ template simpleTypeTempl: typeDesc =
macro typeFromMacro: typedesc = string
# The tests below check that the result variable of the
# selected type matches the literal types in the code:
proc t1*(x: int): simpleTypeTempl() =
result = "test"
@ -37,3 +45,57 @@ proc t6*(x: type(t3(0))): type(t1(0)) =
proc t7*(x: int): type($x) =
result = "test"
# This is a more compicated example involving a type
# selection through a macro:
# https://github.com/nim-lang/Nim/issues/7230
macro getBase*(bits: static[int]): untyped =
if bits >= 128:
result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint64"))
else:
result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint32"))
type
BaseUint* = SomeUnsignedInt or MpUintBase
MpUintBase*[T] = object
lo*, hi*: T
## This gets type mismatch
MpUint*[bits: static[int]] = getBase(bits)
var m1: MpUint[128]
var m2: MpUint[64]
var m3: getBase(32)
static:
# assert m1.type.name == "MpUintBase[uint64]"
assert m1.lo.type.name == "uint64"
assert m2.lo.type.name == "uint32"
assert m3.type.name == "MpUintBase[system.uint32]"
# https://github.com/nim-lang/Nim/issues/7379
import macros, typetraits
macro works(): untyped =
result = getType(int64)
macro fails(bits: static[int]): untyped =
if bits > 64:
result = getType(int64)
else:
result = getType(int32)
type
Foo*[bits: static[int]] = works()
Bar*[bits: static[int]] = fails(bits)
var a: Foo[16]
var b: Bar[256]
var c: Bar[32]
echo sizeof(a)
echo sizeof(b)
echo sizeof(c)

View file

@ -1,7 +1,6 @@
discard """
errormsg: "type mismatch: got <string> but expected 'ptr'"
line: 20
disabled: true
"""
import typetraits
@ -12,7 +11,7 @@ type
var x = Vec([1, 2, 3])
static:
assert x.type.name == "Vec[static[int](3), int]"
assert x.type.name == "Vec[3, system.int]"
var str1: string = "hello, world!"
var ptr1: ptr = addr(str1)

View file

@ -0,0 +1,32 @@
type
Hash*[bits: static[int]] = object
data*: array[bits div 8, uint8]
{.emit: """
void sha_256(void* input, int input_len, void* output, int output_len) {}
void sha_512(void* input, int input_len, void* output, int output_len) {}
void keccak_256(void* input, int input_len, void* output, int output_len) {}
void keccak_512(void* input, int input_len, void* output, int output_len) {}
""".}
template defineKeccak(bits: untyped) =
proc `extKeccak bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "keccak_" & astToStr(bits).}
template defineSha(bits: static[int]) =
proc `extSha bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "sha_" & astToStr(bits).}
template defineHashProcs(bits) =
defineSha(bits)
defineKeccak(bits)
defineHashProcs(256)
defineHashProcs(512)
extSha256(nil, 0, nil, 0)
extSha512(nil, 0, nil, 0)
extKeccak256(nil, 0, nil, 0)
extKeccak512(nil, 0, nil, 0)

View file

@ -0,0 +1,44 @@
discard """
output: "Digest[128]\nDigest[256]"
"""
import typetraits
type
Digest[bits: static[int]] = object
data: array[bits div 8, byte]
ContextKind = enum
A, B, C
HashingContext[bits: static[int], kind: static[ContextKind]] = object
ctx: array[bits div 8, byte]
Hash128 = HashingContext[128, A]
Hash256 = HashingContext[256, B]
HMAC[HashType] = object
h: HashType
proc init(c: var HashingContext) = discard
proc update(c: var HashingContext, data: ptr byte, dataLen: uint) = discard
proc finish(c: var HashingContext): Digest[c.bits] = discard
proc digest(T: typedesc, data: ptr byte, dataLen: uint): Digest[T.bits] =
mixin init, update, finish
var ctx: T
ctx.init()
ctx.update(data, dataLen)
result = ctx.finish()
var h = Hash128.digest(nil, 0)
echo h.type.name
proc finish(hmac: var HMAC): Digest[HMAC.HashType.bits] =
discard
var hm: HMAC[Hash256]
var d = hm.finish
echo d.type.name

View file

@ -1,9 +1,9 @@
discard """
targets: "cpp"
output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest"
output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest\n[0, 0, 20, 0]"
"""
{.emit: """
{.emit: """/*TYPESECTION*/
template <int N, class T>
struct GenericIntType {
@ -51,3 +51,9 @@ echo c.field
echo d.field
echo e.field
proc plus(a, b: GenInt4): GenInt4 =
for i in 0 ..< result.data.len:
result.data[i] = a.data[i] + b.data[i]
echo plus(a, a).data