summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/semtypes.nim4
-rwxr-xr-xcompiler/semtypinst.nim68
-rwxr-xr-xcompiler/types.nim136
-rw-r--r--tests/accept/compile/tthread_generic.nim35
-rwxr-xr-xweb/nimrod.ini2
5 files changed, 127 insertions, 118 deletions
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5d4515cd9..894dec1cb 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -227,9 +227,9 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
   var isConcrete = true # iterate over arguments:
   for i in countup(1, sonsLen(n)-1): 
     var elem = semTypeNode(c, n.sons[i], nil)
-    if elem.kind == tyGenericParam: isConcrete = false
+    if elem.kind in {tyGenericParam, tyGenericInvokation}: isConcrete = false
     addSon(result, elem)
-  if isConcrete: 
+  if isConcrete:
     if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
     result = instGenericContainer(c, n, result)
 
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index fe45e7517..7cdc81b94 100755
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -14,10 +14,10 @@ import ast, astalgo, msgs, types, semdata
 proc checkConstructedType*(info: TLineInfo, t: PType) = 
   if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: 
     LocalError(info, errInvalidPragmaX, "acyclic")
-  elif computeSize(t) < 0: 
-    LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
   elif t.kind == tyVar and t.sons[0].kind == tyVar: 
     LocalError(info, errVarVarTypeNotAllowed)
+  elif computeSize(t) < 0:
+    LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
   when false:
     if t.kind == tyObject and t.sons[0] != nil:
       if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: 
@@ -91,17 +91,16 @@ proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
   elif result.kind == tyGenericParam: 
     InternalError(cl.info, "substitution with generic parameter")
   
-proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = 
-  result = t
-  if t == nil: return 
-  case t.kind
-  of tyGenericParam: 
-    result = lookupTypeVar(cl, t)
-  of tyGenericInvokation: 
-    var body = t.sons[0]
-    if body.kind != tyGenericBody: InternalError(cl.info, "no generic body")
-    var header: PType = nil
-    for i in countup(1, sonsLen(t) - 1):
+proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = 
+  var body = t.sons[0]
+  if body.kind != tyGenericBody: InternalError(cl.info, "no generic body")
+  var header: PType = nil
+  for i in countup(1, sonsLen(t) - 1):
+    var x = replaceTypeVarsT(cl, t.sons[i])
+    if t.sons[i].kind == tyGenericParam: 
+      if header == nil: header = copyType(t, t.owner, false)
+      header.sons[i] = x
+    when false:
       var x: PType
       if t.sons[i].kind == tyGenericParam: 
         x = lookupTypeVar(cl, t.sons[i])
@@ -109,22 +108,33 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
         header.sons[i] = x
       else: 
         x = t.sons[i]
-      idTablePut(cl.typeMap, body.sons[i-1], x)
-    if header == nil: header = t
-    result = searchInstTypes(gInstTypes, header)
-    if result != nil: return 
-    result = newType(tyGenericInst, t.sons[0].owner)
-    for i in countup(0, sonsLen(t) - 1): 
-      # if one of the params is not concrete, we cannot do anything
-      # but we already raised an error!
-      addSon(result, header.sons[i])
-    idTablePut(gInstTypes, header, result)
-    var newbody = ReplaceTypeVarsT(cl, lastSon(body))
-    newbody.flags = newbody.flags + t.flags + body.flags
-    newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
-    addSon(result, newbody)   
-    #writeln(output, ropeToStr(Typetoyaml(newbody)));
-    checkConstructedType(cl.info, newbody)
+    idTablePut(cl.typeMap, body.sons[i-1], x)
+  if header == nil: header = t
+  result = searchInstTypes(gInstTypes, header)
+  if result != nil: return 
+  result = newType(tyGenericInst, t.sons[0].owner)
+  for i in countup(0, sonsLen(t) - 1): 
+    # if one of the params is not concrete, we cannot do anything
+    # but we already raised an error!
+    addSon(result, header.sons[i])
+  idTablePut(gInstTypes, header, result)
+  var newbody = ReplaceTypeVarsT(cl, lastSon(body))
+  newbody.flags = newbody.flags + t.flags + body.flags
+  newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
+  addSon(result, newbody)   
+  #writeln(output, ropeToStr(Typetoyaml(newbody)));
+  checkConstructedType(cl.info, newbody)
+    
+proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType = 
+  result = t
+  if t == nil: return 
+  case t.kind
+  of tyGenericParam: 
+    result = lookupTypeVar(cl, t)
+    if result.kind == tyGenericInvokation:
+      result = handleGenericInvokation(cl, result)
+  of tyGenericInvokation: 
+    result = handleGenericInvokation(cl, t)
   of tyGenericBody: 
     InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
     result = ReplaceTypeVarsT(cl, lastSon(t))
diff --git a/compiler/types.nim b/compiler/types.nim
index bfa20066f..692b7f61b 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -96,23 +96,22 @@ proc inheritanceDiff(a, b: PType): int =
   # conversion to superclass?
   var x = a
   result = 0
-  while (x != nil): 
+  while x != nil: 
     if x.id == b.id: return 
     x = x.sons[0]
     dec(result)
   var y = b
   result = 0
-  while (y != nil): 
+  while y != nil: 
     if y.id == a.id: return 
     y = y.sons[0]
     inc(result)
   result = high(int)
 
 proc isPureObject(typ: PType): bool = 
-  var t: PType
-  t = typ
+  var t = typ
   while t.sons[0] != nil: t = t.sons[0]
-  result = (t.sym != nil) and (sfPure in t.sym.flags)
+  result = t.sym != nil and sfPure in t.sym.flags
 
 proc getOrdValue(n: PNode): biggestInt = 
   case n.kind
@@ -135,13 +134,13 @@ proc getProcHeader(sym: PSym): string =
   var n = sym.typ.n
   for i in countup(1, sonsLen(n) - 1): 
     var p = n.sons[i]
-    if (p.kind != nkSym): InternalError("getProcHeader")
+    if p.kind != nkSym: InternalError("getProcHeader")
     add(result, p.sym.name.s)
     add(result, ": ")
     add(result, typeToString(p.sym.typ))
-    if i != sonsLen(n) - 1: add(result, ", ")
+    if i != sonsLen(n)-1: add(result, ", ")
   add(result, ')')
-  if n.sons[0].typ != nil: result = result & ": " & typeToString(n.sons[0].typ)
+  if n.sons[0].typ != nil: result.add(": " & typeToString(n.sons[0].typ))
   
 proc elemType(t: PType): PType = 
   assert(t != nil)
@@ -258,7 +257,8 @@ proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
     result = searchTypeForAux(n.sym.typ, p, marker)
   else: internalError(n.info, "searchTypeNodeForAux()")
   
-proc searchTypeForAux(t: PType, predicate: TTypePredicate, marker: var TIntSet): bool = 
+proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
+                      marker: var TIntSet): bool = 
   # iterates over VALUE types!
   result = false
   if t == nil: return 
@@ -293,7 +293,8 @@ proc isObjectWithTypeFieldPredicate(t: PType): bool =
       not ((t.sym != nil) and (sfPure in t.sym.flags)) and
       not (tfFinal in t.flags)
 
-proc analyseObjectWithTypeFieldAux(t: PType, marker: var TIntSet): TTypeFieldResult = 
+proc analyseObjectWithTypeFieldAux(t: PType, 
+                                   marker: var TIntSet): TTypeFieldResult = 
   var res: TTypeFieldResult
   result = frNone
   if t == nil: return 
@@ -430,7 +431,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
   if t == nil: return 
-  if (prefer == preferName) and (t.sym != nil): 
+  if prefer == preferName and t.sym != nil:
     return t.sym.Name.s
   case t.Kind
   of tyGenericBody, tyGenericInst, tyGenericInvokation:
@@ -506,12 +507,9 @@ proc base(t: PType): PType =
 
 proc firstOrd(t: PType): biggestInt = 
   case t.kind
-  of tyBool, tyChar, tySequence, tyOpenArray, tyString: 
-    result = 0
-  of tySet, tyVar: 
-    result = firstOrd(t.sons[0])
-  of tyArray, tyArrayConstr: 
-    result = firstOrd(t.sons[0])
+  of tyBool, tyChar, tySequence, tyOpenArray, tyString: result = 0
+  of tySet, tyVar: result = firstOrd(t.sons[0])
+  of tyArray, tyArrayConstr: result = firstOrd(t.sons[0])
   of tyRange: 
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
@@ -519,14 +517,10 @@ proc firstOrd(t: PType): biggestInt =
   of tyInt: 
     if platform.intSize == 4: result = - (2147483646) - 2
     else: result = 0x8000000000000000'i64
-  of tyInt8: 
-    result = - 128
-  of tyInt16: 
-    result = - 32768
-  of tyInt32: 
-    result = - 2147483646 - 2
-  of tyInt64: 
-    result = 0x8000000000000000'i64
+  of tyInt8: result = - 128
+  of tyInt16: result = - 32768
+  of tyInt32: result = - 2147483646 - 2
+  of tyInt64: result = 0x8000000000000000'i64
   of tyEnum: 
     # if basetype <> nil then return firstOrd of basetype
     if (sonsLen(t) > 0) and (t.sons[0] != nil): 
@@ -534,22 +528,17 @@ proc firstOrd(t: PType): biggestInt =
     else: 
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
-  of tyGenericInst, tyDistinct: 
-    result = firstOrd(lastSon(t))
+  of tyGenericInst, tyDistinct: result = firstOrd(lastSon(t))
   else: 
     InternalError("invalid kind for first(" & $t.kind & ')')
     result = 0
 
 proc lastOrd(t: PType): biggestInt = 
   case t.kind
-  of tyBool: 
-    result = 1
-  of tyChar: 
-    result = 255
-  of tySet, tyVar: 
-    result = lastOrd(t.sons[0])
-  of tyArray, tyArrayConstr: 
-    result = lastOrd(t.sons[0])
+  of tyBool: result = 1
+  of tyChar: result = 255
+  of tySet, tyVar: result = lastOrd(t.sons[0])
+  of tyArray, tyArrayConstr: result = lastOrd(t.sons[0])
   of tyRange: 
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
@@ -557,19 +546,14 @@ proc lastOrd(t: PType): biggestInt =
   of tyInt: 
     if platform.intSize == 4: result = 0x7FFFFFFF
     else: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyInt8: 
-    result = 0x0000007F
-  of tyInt16: 
-    result = 0x00007FFF
-  of tyInt32: 
-    result = 0x7FFFFFFF
-  of tyInt64: 
-    result = 0x7FFFFFFFFFFFFFFF'i64
+  of tyInt8: result = 0x0000007F
+  of tyInt16: result = 0x00007FFF
+  of tyInt32: result = 0x7FFFFFFF
+  of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
   of tyEnum: 
     assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
     result = t.n.sons[sonsLen(t.n) - 1].sym.position
-  of tyGenericInst, tyDistinct: 
-    result = firstOrd(lastSon(t))
+  of tyGenericInst, tyDistinct: result = lastOrd(lastSon(t))
   else: 
     InternalError("invalid kind for last(" & $t.kind & ')')
     result = 0
@@ -666,8 +650,7 @@ proc sameTuple(a, b: PType, DistinctOf: bool): bool =
     result = false
   
 proc SameType(x, y: PType): bool = 
-  if x == y: 
-    return true
+  if x == y: return true
   var a = skipTypes(x, {tyGenericInst})
   var b = skipTypes(y, {tyGenericInst})
   assert(a != nil)
@@ -678,12 +661,9 @@ proc SameType(x, y: PType): bool =
   of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
      tyInt..tyFloat128, tyExpr, tyStmt, tyTypeDesc: 
     result = true
-  of tyEnum, tyForward, tyObject, tyDistinct: 
-    result = (a.id == b.id)
-  of tyTuple: 
-    result = sameTuple(a, b, false)
-  of tyGenericInst: 
-    result = sameType(lastSon(a), lastSon(b))
+  of tyEnum, tyForward, tyObject, tyDistinct: result = (a.id == b.id)
+  of tyTuple: result = sameTuple(a, b, false)
+  of tyGenericInst: result = sameType(lastSon(a), lastSon(b))
   of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, tyOrdinal, 
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc: 
     if sonsLen(a) == sonsLen(b): 
@@ -699,14 +679,11 @@ proc SameType(x, y: PType): bool =
     result = SameTypeOrNil(a.sons[0], b.sons[0]) and
         SameValue(a.n.sons[0], b.n.sons[0]) and
         SameValue(a.n.sons[1], b.n.sons[1])
-  of tyNone: 
-    result = false
+  of tyNone: result = false
   
 proc equalOrDistinctOf(x, y: PType): bool = 
-  if x == y: 
-    return true
-  if (x == nil) or (y == nil): 
-    return false
+  if x == y: return true
+  if x == nil or y == nil: return false
   var a = skipTypes(x, {tyGenericInst})
   var b = skipTypes(y, {tyGenericInst})
   assert(a != nil)
@@ -719,12 +696,9 @@ proc equalOrDistinctOf(x, y: PType): bool =
   of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
      tyInt..tyFloat128, tyExpr, tyStmt, tyTypeDesc: 
     result = true
-  of tyEnum, tyForward, tyObject, tyDistinct: 
-    result = (a.id == b.id)
-  of tyTuple: 
-    result = sameTuple(a, b, true)
-  of tyGenericInst: 
-    result = equalOrDistinctOf(lastSon(a), lastSon(b))
+  of tyEnum, tyForward, tyObject, tyDistinct: result = (a.id == b.id)
+  of tyTuple: result = sameTuple(a, b, true)
+  of tyGenericInst: result = equalOrDistinctOf(lastSon(a), lastSon(b))
   of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, tyOrdinal, 
      tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyArray, tyProc: 
     if sonsLen(a) == sonsLen(b): 
@@ -739,8 +713,7 @@ proc equalOrDistinctOf(x, y: PType): bool =
     result = equalOrDistinctOf(a.sons[0], b.sons[0]) and
         SameValue(a.n.sons[0], b.n.sons[0]) and
         SameValue(a.n.sons[1], b.n.sons[1])
-  of tyNone: 
-    result = false
+  of tyNone: result = false
   
 proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool
 proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool = 
@@ -835,8 +808,7 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var biggestInt): biggestInt =
       case n.sons[i].kind
       of nkOfBranch, nkElse: 
         res = computeRecSizeAux(lastSon(n.sons[i]), b, currOffset)
-        if res < 0: 
-          return res
+        if res < 0: return res
         maxSize = max(maxSize, res)
         maxAlign = max(maxAlign, b)
       else: internalError("computeRecSizeAux(record case branch)")
@@ -848,8 +820,7 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var biggestInt): biggestInt =
     maxAlign = 1
     for i in countup(0, sonsLen(n) - 1): 
       res = computeRecSizeAux(n.sons[i], b, currOffset)
-      if res < 0: 
-        return res
+      if res < 0: return res
       currOffset = align(currOffset, b) + res
       result = align(result, b) + res
       if b > maxAlign: maxAlign = b
@@ -914,18 +885,12 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
     a = result
   of tySet: 
     length = lengthOrd(typ.sons[0])
-    if length <= 8: 
-      result = 1
-    elif length <= 16: 
-      result = 2
-    elif length <= 32: 
-      result = 4
-    elif length <= 64: 
-      result = 8
-    elif align(length, 8) mod 8 == 0: 
-      result = align(length, 8) div 8
-    else: 
-      result = align(length, 8) div 8 + 1 # BUGFIX!
+    if length <= 8: result = 1
+    elif length <= 16: result = 2
+    elif length <= 32: result = 4
+    elif length <= 64: result = 8
+    elif align(length, 8) mod 8 == 0: result = align(length, 8) div 8
+    else: result = align(length, 8) div 8 + 1
     a = result
   of tyRange: 
     result = computeSizeAux(typ.sons[0], a)
@@ -934,8 +899,7 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
     maxAlign = 1
     for i in countup(0, sonsLen(typ) - 1): 
       res = computeSizeAux(typ.sons[i], a)
-      if res < 0: 
-        return res
+      if res < 0: return res
       maxAlign = max(maxAlign, a)
       result = align(result, a) + res
     result = align(result, maxAlign)
@@ -959,7 +923,7 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt =
   of tyGenericInst, tyDistinct, tyGenericBody: 
     result = computeSizeAux(lastSon(typ), a)
   else: 
-    #internalError('computeSizeAux()');
+    #internalError("computeSizeAux()")
     result = - 1
   typ.size = result
   typ.align = int(a)
diff --git a/tests/accept/compile/tthread_generic.nim b/tests/accept/compile/tthread_generic.nim
new file mode 100644
index 000000000..4ef939408
--- /dev/null
+++ b/tests/accept/compile/tthread_generic.nim
@@ -0,0 +1,35 @@
+type
+  TThreadFuncArgs[T] = object of TObject
+    a: proc(): T {.thread.}
+    b: proc(val: T) {.thread.}
+
+proc handleThreadFunc(arg: TThreadFuncArgs[int]){.thread.} =
+  var func = arg.a
+  var callback = arg.b
+  var output = func()
+  callback(output)
+
+proc `@||->`*[T](func: proc(): T {.thread.}, 
+                 callback: proc(val: T){.thread.}): TThread[TThreadFuncArgs[T]] =
+  var thr: TThread[TThreadFuncArgs[T]]
+  var args: TThreadFuncArgs[T]
+  args.a = func
+  args.b = callback
+  createThread(thr, handleThreadFunc, args)
+  return thr
+
+proc `||->`*[T](func: proc(): T{.thread.}, callback: proc(val: T){.thread.}) =
+  discard func @||-> callback
+
+when isMainModule:
+  import os
+  proc testFunc(): int {.thread.} =
+    return 1
+  proc callbackFunc(val: int) {.thread.} =
+    echo($(val))
+   
+  var thr = (testFunc @||-> callbackFunc)
+  echo("test")
+  joinThread(thr)
+  os.sleep(3000)
+
diff --git a/web/nimrod.ini b/web/nimrod.ini
index b0c6d0139..156bc5221 100755
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -41,7 +41,7 @@ srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
 srcdoc: "impure/rdstdin;wrappers/zmq;wrappers/sphinx"
 srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
 srcdoc: "pure/collections/intsets;pure/collections/queues;pure/encodings"
-srcdoc: "pure/lib/events;pure/collections/sequtils"
+srcdoc: "pure/events;pure/collections/sequtils"
 
 webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
 webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"