summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/pragmas.nim5
-rw-r--r--compiler/semexprs.nim6
-rw-r--r--compiler/semtempl.nim34
-rw-r--r--compiler/vmgen.nim14
-rw-r--r--lib/pure/events.nim4
-rw-r--r--lib/wrappers/zip/zlib.nim126
-rw-r--r--tests/array/tarrayplus.nim2
-rw-r--r--tests/generics/tbadgenericlambda.nim2
-rw-r--r--tests/generics/tmetafield.nim6
-rw-r--r--tests/showoff/tdrdobbs_examples.nim2
-rw-r--r--tests/template/ttempl5.nim11
-rw-r--r--tests/vm/tstaticprintseq.nim6
12 files changed, 182 insertions, 36 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 692f4bac6..14d155539 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -111,8 +111,9 @@ proc validateExternCName(s: PSym, info: TLineInfo) =
 
 proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
   setExternName(s, extname)
-  if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
-    validateExternCName(s, info)
+  # XXX to fix make it work with nimrtl.
+  #if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC}:
+  #  validateExternCName(s, info)
   incl(s.flags, sfExportc)
 
 proc processImportCompilerProc(s: PSym, extname: string) =
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 1fd9075e8..6743768a2 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -954,8 +954,10 @@ proc readTypeParameter(c: PContext, typ: PType,
 proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
   checkSonsLen(n, 2)
-  # early exit for this; see tests/compile/tbindoverload.nim:
-  if isSymChoice(n.sons[1]): return
+  # tests/bind/tbindoverload.nim wants an early exit here, but seems to
+  # work without now. template/tsymchoicefield doesn't like an early exit
+  # here at all!
+  #if isSymChoice(n.sons[1]): return
 
   var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
   if s != nil:
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index b71198119..1432b76f0 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -138,6 +138,18 @@ proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
   result = semTemplBody(c, n)
   closeScope(c)
 
+proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
+  result = n
+  if n.kind == nkIdent:
+    let s = qualifiedLookUp(c.c, n, {})
+    if s != nil:
+      if s.owner == c.owner and s.kind == skParam:
+        incl(s.flags, sfUsed)
+        result = newSymNode(s, n.info)
+  else:
+    for i in 0 .. <n.safeLen:
+      result.sons[i] = onlyReplaceParams(c, n.sons[i])
+
 proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
   result = newSym(kind, considerAcc(n), c.owner, n.info)
   incl(result.flags, sfGenSym)
@@ -154,7 +166,13 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
       of nkPostfix: x = x[1]
       of nkPragmaExpr: x = x[0]
       of nkIdent: break
-      else: illFormedAst(x)
+      of nkAccQuoted:
+        # consider:  type `T TemplParam` {.inject.}
+        # it suffices to return to treat it like 'inject':
+        n = onlyReplaceParams(c, n)
+        return
+      else:
+        illFormedAst(x)
     let ident = getIdentNode(c, x)
     if not isTemplParam(c, ident):
       c.toInject.incl(x.ident.id)
@@ -232,18 +250,6 @@ proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind) =
     for j in countup(0, L-3):
       addLocalDecl(c, a.sons[j], symKind)
 
-proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
-  result = n
-  if n.kind == nkIdent:
-    let s = qualifiedLookUp(c.c, n, {})
-    if s != nil:
-      if s.owner == c.owner and s.kind == skParam:
-        incl(s.flags, sfUsed)
-        result = newSymNode(s, n.info)
-  else:
-    for i in 0 .. <n.safeLen:
-      result.sons[i] = onlyReplaceParams(c, n.sons[i])
-
 proc semPattern(c: PContext, n: PNode): PNode
 proc semTemplBody(c: var TemplCtx, n: PNode): PNode = 
   result = n
@@ -380,7 +386,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   of nkPragma:
     result = onlyReplaceParams(c, n)
   else:
-    # dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
+    # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
     # so we use the generic code for nkDotExpr too
     if n.kind == nkDotExpr or n.kind == nkAccQuoted:
       let s = qualifiedLookUp(c.c, n, {})
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 3c0f8dbc9..85416f7bc 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -328,6 +328,7 @@ proc canonValue*(n: PNode): PNode =
 
 proc rawGenLiteral(c: PCtx; n: PNode): int =
   result = c.constants.len
+  assert(n.kind != nkCall)
   c.constants.add n.canonValue
   internalAssert result < 0x7fff
 
@@ -1285,16 +1286,13 @@ proc genVarSection(c: PCtx; n: PNode) =
         if s.position == 0:
           if sfImportc in s.flags: c.importcSym(a.info, s)
           else:
-            let sa = if s.ast.isNil: getNullValue(s.typ, a.info) 
-                     else: canonValue(s.ast)
+            let sa = getNullValue(s.typ, a.info)
+            #if s.ast.isNil: getNullValue(s.typ, a.info)
+            #else: canonValue(s.ast)
+            assert sa.kind != nkCall
             c.globals.add(sa)
             s.position = c.globals.len
-        if a.sons[2].kind == nkEmpty:
-          when false:
-            withTemp(tmp, s.typ):
-              c.gABx(a, opcLdNull, tmp, c.genType(s.typ))
-              c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
-        else:
+        if a.sons[2].kind != nkEmpty:
           let tmp = c.genx(a.sons[0], {gfAddrOf})
           let val = c.genx(a.sons[2])
           c.gABC(a, opcWrDeref, tmp, val)
diff --git a/lib/pure/events.nim b/lib/pure/events.nim
index e76b846cf..5830d9109 100644
--- a/lib/pure/events.nim
+++ b/lib/pure/events.nim
@@ -68,7 +68,7 @@ proc clearHandlers*(handler: var TEventHandler) =
   ## Clears all of the callbacks from the event handler.
   setLen(handler.handlers, 0)
 
-proc getEventhandler(emitter: var TEventEmitter, event: string): int =
+proc getEventHandler(emitter: var TEventEmitter, event: string): int =
   for k in 0..high(emitter.s):
     if emitter.s[k].name == event: return k
   return -1
@@ -94,8 +94,6 @@ proc emit*(emitter: var TEventEmitter, event: string, args: TEventArgs) =
   var i = getEventHandler(emitter, event)
   if i >= 0:
     emit(emitter, emitter.s[i], args)
-  else:
-    raise newException(EInvalidEvent, "invalid event: " & event)
 
 proc initEventEmitter*(): TEventEmitter =
   ## Creates and returns a new EventEmitter.
diff --git a/lib/wrappers/zip/zlib.nim b/lib/wrappers/zip/zlib.nim
index f505b95a7..cb61783d2 100644
--- a/lib/wrappers/zip/zlib.nim
+++ b/lib/wrappers/zip/zlib.nim
@@ -182,3 +182,129 @@ proc zlibAllocMem*(AppData: Pointer, Items, Size: int): Pointer {.cdecl.} =
 
 proc zlibFreeMem*(AppData, `Block`: Pointer) {.cdecl.} = 
   dealloc(`Block`)
+
+proc uncompress*(sourceBuf: cstring, sourceLen: int): string =
+  ## Given a deflated cstring returns its inflated version.
+  ##
+  ## Passing a nil cstring will crash this proc in release mode and assert in
+  ## debug mode.
+  ##
+  ## Returns nil on problems. Failure is a very loose concept, it could be you
+  ## passing a non deflated string, or it could mean not having enough memory
+  ## for the inflated version.
+  ##
+  ## The uncompression algorithm is based on
+  ## http://stackoverflow.com/questions/17820664 but does ignore some of the
+  ## original signed/unsigned checks, so may fail with big chunks of data
+  ## exceeding the positive size of an int32. The algorithm can deal with
+  ## concatenated deflated values properly.
+  assert (not sourceBuf.isNil)
+
+  var z: TZStream
+  # Initialize input.
+  z.next_in = sourceBuf
+
+  # Input left to decompress.
+  var left = zlib.Uint(sourceLen)
+  if left < 1:
+    # Incomplete gzip stream, or overflow?
+    return
+
+  # Create starting space for output (guess double the input size, will grow if
+  # needed -- in an extreme case, could end up needing more than 1000 times the
+  # input size)
+  var space = zlib.Uint(left shl 1)
+  if space < left:
+    space = left
+
+  var decompressed = newStringOfCap(space)
+
+  # Initialize output.
+  z.next_out = addr(decompressed[0])
+  # Output generated so far.
+  var have = 0
+
+  # Set up for gzip decoding.
+  z.avail_in = 0;
+  var status = inflateInit2(z, (15+16))
+  if status != Z_OK:
+    # Out of memory.
+    return
+
+  # Make sure memory allocated by inflateInit2() is freed eventually.
+  finally: discard inflateEnd(z)
+
+  # Decompress all of self.
+  while true:
+    # Allow for concatenated gzip streams (per RFC 1952).
+    if status == Z_STREAM_END:
+      discard inflateReset(z)
+
+    # Provide input for inflate.
+    if z.avail_in == 0:
+      # This only makes sense in the C version using unsigned values.
+      z.avail_in = left
+      left -= z.avail_in
+
+    # Decompress the available input.
+    while true:
+      # Allocate more output space if none left.
+      if space == have:
+        # Double space, handle overflow.
+        space = space shl 1
+        if space < have:
+          # Space was likely already maxed out.
+          discard inflateEnd(z)
+          return
+
+        # Increase space.
+        decompressed.setLen(space)
+        # Update output pointer (might have moved).
+        z.next_out = addr(decompressed[have])
+
+      # Provide output space for inflate.
+      z.avail_out = zlib.Uint(space - have)
+      have += z.avail_out;
+
+      # Inflate and update the decompressed size.
+      status = inflate(z, Z_SYNC_FLUSH);
+      have -= z.avail_out;
+
+      # Bail out if any errors.
+      if status != Z_OK and status != Z_BUF_ERROR and status != Z_STREAM_END:
+        # Invalid gzip stream.
+        discard inflateEnd(z)
+        return
+
+      # Repeat until all output is generated from provided input (note
+      # that even if z.avail_in is zero, there may still be pending
+      # output -- we're not done until the output buffer isn't filled)
+      if z.avail_out != 0:
+        break
+    # Continue until all input consumed.
+    if left == 0 and z.avail_in == 0:
+      break
+
+  # Verify that the input is a valid gzip stream.
+  if status != Z_STREAM_END:
+    # Incomplete gzip stream.
+    return
+
+  decompressed.setLen(have)
+  swap(result, decompressed)
+
+
+proc inflate*(buffer: var string): bool {.discardable.} =
+  ## Convenience proc which inflates a string containing compressed data.
+  ##
+  ## Passing a nil string will crash this proc in release mode and assert in
+  ## debug mode. It is ok to pass a buffer which doesn't contain deflated data,
+  ## in this case the proc won't modify the buffer.
+  ##
+  ## Returns true if `buffer` was successfully inflated.
+  assert (not buffer.isNil)
+  if buffer.len < 1: return
+  var temp = uncompress(addr(buffer[0]), buffer.len)
+  if not temp.isNil:
+    swap(buffer, temp)
+    result = true
diff --git a/tests/array/tarrayplus.nim b/tests/array/tarrayplus.nim
index 9e08bbb0a..0ea349f4f 100644
--- a/tests/array/tarrayplus.nim
+++ b/tests/array/tarrayplus.nim
@@ -1,5 +1,5 @@
 discard """
-  errmsg: "type mismatch: got (array[0..2, float], array[0..1, float])"
+  errormsg: "type mismatch: got (array[0..2, float], array[0..1, float])"
 """
 
 proc `+`*[R, T] (v1, v2: array[R, T]): array[R, T] =
diff --git a/tests/generics/tbadgenericlambda.nim b/tests/generics/tbadgenericlambda.nim
index 38e7f6cd7..2ab8e724d 100644
--- a/tests/generics/tbadgenericlambda.nim
+++ b/tests/generics/tbadgenericlambda.nim
@@ -1,5 +1,5 @@
 discard """
-  errmsg: "nested proc can have generic parameters only when"
+  errormsg: "nested proc can have generic parameters only when"
   line: 6
 """
 
diff --git a/tests/generics/tmetafield.nim b/tests/generics/tmetafield.nim
index 8e7f26549..f2fac8fdd 100644
--- a/tests/generics/tmetafield.nim
+++ b/tests/generics/tmetafield.nim
@@ -1,8 +1,8 @@
 discard """
   cmd: "nimrod check $# $#"
-  errmsg: "'proc' is not a concrete type"
-  errmsg: "'Foo' is not a concrete type."
-  errmsg: "invalid type: 'TBaseMed'"
+  errormsg: "'proc' is not a concrete type"
+  errormsg: "'Foo' is not a concrete type."
+  errormsg: "invalid type: 'TBaseMed'"
 """
 
 type
diff --git a/tests/showoff/tdrdobbs_examples.nim b/tests/showoff/tdrdobbs_examples.nim
index 0b3d86a05..8a39990ba 100644
--- a/tests/showoff/tdrdobbs_examples.nim
+++ b/tests/showoff/tdrdobbs_examples.nim
@@ -1,7 +1,7 @@
 discard """
   output: '''108
 11 -1 1936
-4.0000000000000002e-001
+4.0000000000000002e-01
 true
 truefalse'''
 """
diff --git a/tests/template/ttempl5.nim b/tests/template/ttempl5.nim
index 1f2378780..a020a8e2c 100644
--- a/tests/template/ttempl5.nim
+++ b/tests/template/ttempl5.nim
@@ -16,3 +16,14 @@ get_next_ident()
 
 
 #identifier expected, but found '(open|open|open)'
+
+#bug #880 (also example in the manual!)
+
+template typedef(name: expr, typ: typedesc) {.immediate.} =
+  type
+    `T name`* {.inject.} = typ
+    `P name`* {.inject.} = ref `T name`
+
+typedef(myint, int)
+var x: PMyInt
+
diff --git a/tests/vm/tstaticprintseq.nim b/tests/vm/tstaticprintseq.nim
index 3dfd0048d..b002d366c 100644
--- a/tests/vm/tstaticprintseq.nim
+++ b/tests/vm/tstaticprintseq.nim
@@ -17,7 +17,8 @@ bb
 22
 aa
 bb
-24'''
+24
+2147483647 2147483647'''
 """
 
 const s = @[1,2,3]
@@ -76,3 +77,6 @@ const y = fac()
 static:
   echo y
 
+static:
+  var foo2 = int32.high
+  echo foo2, " ", int32.high