diff options
-rw-r--r-- | compiler/pragmas.nim | 5 | ||||
-rw-r--r-- | compiler/semexprs.nim | 6 | ||||
-rw-r--r-- | compiler/semtempl.nim | 34 | ||||
-rw-r--r-- | compiler/vmgen.nim | 14 | ||||
-rw-r--r-- | lib/pure/events.nim | 4 | ||||
-rw-r--r-- | lib/wrappers/zip/zlib.nim | 126 | ||||
-rw-r--r-- | tests/array/tarrayplus.nim | 2 | ||||
-rw-r--r-- | tests/generics/tbadgenericlambda.nim | 2 | ||||
-rw-r--r-- | tests/generics/tmetafield.nim | 6 | ||||
-rw-r--r-- | tests/showoff/tdrdobbs_examples.nim | 2 | ||||
-rw-r--r-- | tests/template/ttempl5.nim | 11 | ||||
-rw-r--r-- | tests/vm/tstaticprintseq.nim | 6 |
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 |