Merge branch 'devel' of https://github.com/Araq/Nim into devel

This commit is contained in:
Araq 2015-01-05 02:27:36 +01:00
commit 4316fdddf3
25 changed files with 582 additions and 380 deletions

View file

@ -399,6 +399,7 @@ const
tyPureObject* = tyTuple tyPureObject* = tyTuple
GcTypeKinds* = {tyRef, tySequence, tyString} GcTypeKinds* = {tyRef, tySequence, tyString}
tyError* = tyProxy # as an errornous node should match everything tyError* = tyProxy # as an errornous node should match everything
tyUnknown* = tyFromExpr
tyUnknownTypes* = {tyError, tyFromExpr} tyUnknownTypes* = {tyError, tyFromExpr}

View file

@ -277,16 +277,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
styleCheckUse(n.sons[0].info, finalCallee) styleCheckUse(n.sons[0].info, finalCallee)
if finalCallee.ast == nil: if finalCallee.ast == nil:
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check! internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty: if x.hasFauxMatch:
# a generic proc!
if not x.proxyMatch:
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
else:
result = x.call result = x.call
result.sons[0] = newSymNode(finalCallee, result.sons[0].info) result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
result.typ = finalCallee.typ.sons[0] if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
if containsGenericType(result.typ): result.typ = errorType(c) result.typ = newTypeS(x.fauxMatch, c)
return return
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
result = x.call result = x.call
instGenericConvertersSons(c, result, x) instGenericConvertersSons(c, result, x)
result.sons[0] = newSymNode(finalCallee, result.sons[0].info) result.sons[0] = newSymNode(finalCallee, result.sons[0].info)

View file

@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
template rangeHasStaticIf*(t: PType): bool = template rangeHasStaticIf*(t: PType): bool =
# this accepts the ranges's node # this accepts the ranges's node
t.n[1].kind == nkStaticExpr t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr
template getStaticTypeFromRange*(t: PType): PType = template getStaticTypeFromRange*(t: PType): PType =
t.n[1][0][1].typ t.n[1][0][1].typ

View file

@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode =
return n return n
result = newNodeI(nkConv, n.info) result = newNodeI(nkConv, n.info)
var targetType = semTypeNode(c, n.sons[0], nil) var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
maybeLiftType(targetType, c, n[0].info) maybeLiftType(targetType, c, n[0].info)
result.addSon copyTree(n.sons[0]) result.addSon copyTree(n.sons[0])
var op = semExprWithType(c, n.sons[1]) var op = semExprWithType(c, n.sons[1])
@ -780,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect) if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
elif t != nil and t.kind == tyTypeDesc: elif t != nil and t.kind == tyTypeDesc:
if n.len == 1: return semObjConstr(c, n, flags) if n.len == 1: return semObjConstr(c, n, flags)
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
return semConv(c, n) return semConv(c, n)
else: else:
result = overloadedCallOpr(c, n) result = overloadedCallOpr(c, n)
@ -928,7 +927,6 @@ proc readTypeParameter(c: PContext, typ: PType,
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
else: (internalAssert(typ.kind == tyCompositeTypeClass); else: (internalAssert(typ.kind == tyCompositeTypeClass);
typ.sons[1].skipGenericAlias) typ.sons[1].skipGenericAlias)
#debug ty
let tbody = ty.sons[0] let tbody = ty.sons[0]
for s in countup(0, tbody.len-2): for s in countup(0, tbody.len-2):
let tParam = tbody.sons[s] let tParam = tbody.sons[s]

View file

@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
return return
else: else:
n.sons[i] = semExpr(c, n.sons[i]) n.sons[i] = semExpr(c, n.sons[i])
if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool: if c.inTypeClass > 0 and n[i].typ != nil:
case n[i].typ.kind
of tyBool:
let verdict = semConstExpr(c, n[i]) let verdict = semConstExpr(c, n[i])
if verdict.intVal == 0: if verdict.intVal == 0:
localError(result.info, "type class predicate failed") localError(result.info, "type class predicate failed")
of tyUnknown: continue
else: discard
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]): if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
voidContext = true voidContext = true
n.typ = enforceVoidContext n.typ = enforceVoidContext

View file

@ -225,11 +225,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
elif e.kind == nkSym and e.typ.kind == tyStatic: elif e.kind == nkSym and e.typ.kind == tyStatic:
if e.sym.ast != nil: if e.sym.ast != nil:
return semArrayIndex(c, e.sym.ast) return semArrayIndex(c, e.sym.ast)
internalAssert c.inGenericContext > 0
if not isOrdinalType(e.typ.lastSon): if not isOrdinalType(e.typ.lastSon):
localError(n[1].info, errOrdinalTypeExpected) localError(n[1].info, errOrdinalTypeExpected)
result = makeRangeWithStaticExpr(c, e) result = makeRangeWithStaticExpr(c, e)
result.flags.incl tfUnresolved if c.inGenericContext >0: result.flags.incl tfUnresolved
elif e.kind in nkCallKinds and hasGenericArguments(e): elif e.kind in nkCallKinds and hasGenericArguments(e):
if not isOrdinalType(e.typ): if not isOrdinalType(e.typ):
localError(n[1].info, errOrdinalTypeExpected) localError(n[1].info, errOrdinalTypeExpected)
@ -782,9 +781,11 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericBody: of tyGenericBody:
result = newTypeS(tyGenericInvokation, c) result = newTypeS(tyGenericInvokation, c)
result.rawAddSon(paramType) result.rawAddSon(paramType)
for i in 0 .. paramType.sonsLen - 2: for i in 0 .. paramType.sonsLen - 2:
result.rawAddSon newTypeS(tyAnything, c) let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true)) else: tyAnything
result.rawAddSon newTypeS(dummyType, c)
if paramType.lastSon.kind == tyUserTypeClass: if paramType.lastSon.kind == tyUserTypeClass:
result.kind = tyUserTypeClassInst result.kind = tyUserTypeClassInst

View file

@ -39,7 +39,9 @@ type
bindings*: TIdTable # maps types to types bindings*: TIdTable # maps types to types
baseTypeMatch: bool # needed for conversions from T to openarray[T] baseTypeMatch: bool # needed for conversions from T to openarray[T]
# for example # for example
proxyMatch*: bool # to prevent instantiations fauxMatch*: TTypeKind # the match was successful only due to the use
# of error or wildcard (unknown) types.
# this is used to prevent instantiations.
genericConverter*: bool # true if a generic converter needs to genericConverter*: bool # true if a generic converter needs to
# be instantiated # be instantiated
coerceDistincts*: bool # this is an explicit coercion that can strip away coerceDistincts*: bool # this is an explicit coercion that can strip away
@ -66,6 +68,8 @@ const
proc markUsed*(info: TLineInfo, s: PSym) proc markUsed*(info: TLineInfo, s: PSym)
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
proc initCandidateAux(ctx: PContext, proc initCandidateAux(ctx: PContext,
c: var TCandidate, callee: PType) {.inline.} = c: var TCandidate, callee: PType) {.inline.} =
c.c = ctx c.c = ctx
@ -109,9 +113,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1): for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
var formalTypeParam = typeParams.sons[i-1].typ var formalTypeParam = typeParams.sons[i-1].typ
var bound = binding[i].typ var bound = binding[i].typ
if bound != nil and formalTypeParam.kind != tyTypeDesc: internalAssert bound != nil
if formalTypeParam.kind == tyTypeDesc:
if bound.kind != tyTypeDesc:
bound = makeTypeDesc(ctx, bound)
else:
bound = bound.skipTypes({tyTypeDesc}) bound = bound.skipTypes({tyTypeDesc})
assert bound != nil
put(c.bindings, formalTypeParam, bound) put(c.bindings, formalTypeParam, bound)
proc newCandidate*(ctx: PContext, callee: PSym, proc newCandidate*(ctx: PContext, callee: PSym,
@ -462,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
var var
typeParamName = ff.base.sons[i-1].sym.name typeParamName = ff.base.sons[i-1].sym.name
typ = ff.sons[i] typ = ff.sons[i]
param = newSym(skType, typeParamName, body.sym, body.sym.info) param: PSym
template paramSym(kind): expr =
newSym(kind, typeParamName, body.sym, body.sym.info)
case typ.kind
of tyStatic:
param = paramSym skConst
param.typ = typ.base
param.ast = typ.n
of tyUnknown:
param = paramSym skVar
param.typ = typ
else:
param = paramSym skType
param.typ = makeTypeDesc(c, typ) param.typ = makeTypeDesc(c, typ)
addDecl(c, param) addDecl(c, param)
for param in body.n[0]: for param in body.n[0]:
@ -626,6 +647,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
of tyRange: of tyRange:
if a.kind == f.kind: if a.kind == f.kind:
if f.base.kind == tyNone: return isGeneric
result = typeRel(c, base(f), base(a)) result = typeRel(c, base(f), base(a))
# bugfix: accept integer conversions here # bugfix: accept integer conversions here
#if result < isGeneric: result = isNone #if result < isGeneric: result = isNone
@ -672,10 +694,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else: else:
fRange = prev fRange = prev
result = typeRel(c, f.sons[1], a.sons[1]) result = typeRel(c, f.sons[1], a.sons[1])
if result < isGeneric: if result < isGeneric: return isNone
result = isNone if rangeHasStaticIf(fRange):
elif tfUnresolved in fRange.flags and if tfUnresolved in fRange.flags:
rangeHasStaticIf(fRange):
# This is a range from an array instantiated with a generic # This is a range from an array instantiated with a generic
# static param. We must extract the static param here and bind # static param. We must extract the static param here and bind
# it to the size of the currently supplied array. # it to the size of the currently supplied array.
@ -687,7 +708,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# ranges and static params: # ranges and static params:
replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1) replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
put(c.bindings, rangeStaticT, replacementT) put(c.bindings, rangeStaticT, replacementT)
result = isGeneric return isGeneric
let len = tryResolvingStaticExpr(c, fRange.n[1])
if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a):
return # if we get this far, the result is already good
else:
return isNone
elif lengthOrd(fRange) != lengthOrd(a): elif lengthOrd(fRange) != lengthOrd(a):
result = isNone result = isNone
else: discard else: discard
@ -945,7 +972,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else: else:
internalAssert a.sons != nil and a.sons.len > 0 internalAssert a.sons != nil and a.sons.len > 0
c.typedescMatched = true c.typedescMatched = true
result = typeRel(c, f.base, a.base) result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
else: else:
result = isNone result = isNone
else: else:
@ -980,7 +1007,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if aOrig.kind == tyStatic: if aOrig.kind == tyStatic:
result = typeRel(c, f.lastSon, a) result = typeRel(c, f.lastSon, a)
if result != isNone and f.n != nil: if result != isNone and f.n != nil:
if not exprStructuralEquivalent(f.n, a.n): if not exprStructuralEquivalent(f.n, aOrig.n):
result = isNone result = isNone
if result != isNone: put(c.bindings, f, aOrig) if result != isNone: put(c.bindings, f, aOrig)
else: else:
@ -1058,7 +1085,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
c: PContext): PNode = c: PContext): PNode =
result = newNodeI(kind, arg.info) result = newNodeI(kind, arg.info)
if containsGenericType(f): if containsGenericType(f):
if not m.proxyMatch: if not m.hasFauxMatch:
result.typ = getInstantiatedType(c, arg, m, f) result.typ = getInstantiatedType(c, arg, m, f)
else: else:
result.typ = errorType(c) result.typ = errorType(c)
@ -1144,7 +1171,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
return argSemantized return argSemantized
if argType.kind == tyStatic: if argType.kind == tyStatic:
if m.callee.kind == tyGenericBody: if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags:
result = newNodeI(nkType, argOrig.info) result = newNodeI(nkType, argOrig.info)
result.typ = makeTypeFromExpr(c, arg) result.typ = makeTypeFromExpr(c, arg)
return return
@ -1237,9 +1264,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
of isNone: of isNone:
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``: # do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
if a.kind == tyProxy: if a.kind in {tyProxy, tyUnknown}:
inc(m.genericMatches) inc(m.genericMatches)
m.proxyMatch = true m.fauxMatch = a.kind
return copyTree(arg) return copyTree(arg)
result = userConvMatch(c, m, f, a, arg) result = userConvMatch(c, m, f, a, arg)
# check for a base type match, which supports varargs[T] without [] # check for a base type match, which supports varargs[T] without []

View file

@ -37,4 +37,4 @@ Options:
--advanced show advanced command line switches --advanced show advanced command line switches
-h, --help show this help -h, --help show this help
Note: Even single letter options require the colon: -p:PATH. Note, single letter options that take an argument require a colon. E.g. -p:PATH.

View file

@ -145,7 +145,7 @@ The ``--usages`` idetools switch lists all usages of the symbol at
a position. IDEs can use this to find all the places in the file a position. IDEs can use this to find all the places in the file
where the symbol is used and offer the user to rename it in all where the symbol is used and offer the user to rename it in all
places at the same time. Again, a pure string based search and places at the same time. Again, a pure string based search and
replace may catch symbols out of the scope of a funcion/loop. replace may catch symbols out of the scope of a function/loop.
For this kind of query the IDE will most likely ignore all the For this kind of query the IDE will most likely ignore all the
type/signature info provided by idetools and concentrate on the type/signature info provided by idetools and concentrate on the

View file

@ -390,7 +390,7 @@ string from a cstring:
.. code-block:: nim .. code-block:: nim
var str: string = "Hello!" var str: string = "Hello!"
var cstr: cstring = s var cstr: cstring = str
var newstr: string = $cstr var newstr: string = $cstr

View file

@ -139,7 +139,7 @@ Numbers
Numerical literals are written as in most other languages. As a special twist, Numerical literals are written as in most other languages. As a special twist,
underscores are allowed for better readability: ``1_000_000`` (one million). underscores are allowed for better readability: ``1_000_000`` (one million).
A number that contains a dot (or 'e' or 'E') is a floating point literal: A number that contains a dot (or 'e' or 'E') is a floating point literal:
``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``, ``1.0e9`` (one billion). Hexadecimal literals are prefixed with ``0x``,
binary literals with ``0b`` and octal literals with ``0o``. A leading zero binary literals with ``0b`` and octal literals with ``0o``. A leading zero
alone does not produce an octal. alone does not produce an octal.
@ -1070,7 +1070,7 @@ Operation Comment
``dec(x, n)`` decrements `x` by `n`; `n` is an integer ``dec(x, n)`` decrements `x` by `n`; `n` is an integer
``succ(x)`` returns the successor of `x` ``succ(x)`` returns the successor of `x`
``succ(x, n)`` returns the `n`'th successor of `x` ``succ(x, n)`` returns the `n`'th successor of `x`
``prec(x)`` returns the predecessor of `x` ``pred(x)`` returns the predecessor of `x`
``pred(x, n)`` returns the `n`'th predecessor of `x` ``pred(x, n)`` returns the `n`'th predecessor of `x`
----------------- -------------------------------------------------------- ----------------- --------------------------------------------------------
@ -1323,7 +1323,7 @@ define operators which accept TSlice objects to define ranges.
a = "Nim is a progamming language" a = "Nim is a progamming language"
b = "Slices are useless." b = "Slices are useless."
echo a[10..15] # --> 'a prog' echo a[7..12] # --> 'a prog'
b[11.. -2] = "useful" b[11.. -2] = "useful"
echo b # --> 'Slices are useful.' echo b # --> 'Slices are useful.'

View file

@ -35,7 +35,7 @@ Object Oriented Programming
=========================== ===========================
While Nim's support for object oriented programming (OOP) is minimalistic, While Nim's support for object oriented programming (OOP) is minimalistic,
powerful OOP technics can be used. OOP is seen as *one* way to design a powerful OOP techniques can be used. OOP is seen as *one* way to design a
program, not *the only* way. Often a procedural approach leads to simpler program, not *the only* way. Often a procedural approach leads to simpler
and more efficient code. In particular, prefering composition over inheritance and more efficient code. In particular, prefering composition over inheritance
is often the better design. is often the better design.
@ -56,7 +56,7 @@ Objects have access to their type at runtime. There is an
.. code-block:: nim .. code-block:: nim
type type
TPerson = object of TObject TPerson = object of RootObj
name*: string # the * means that `name` is accessible from other modules name*: string # the * means that `name` is accessible from other modules
age: int # no * means that the field is hidden from other modules age: int # no * means that the field is hidden from other modules
@ -76,10 +76,10 @@ never *equivalent*. New object types can only be defined within a type
section. section.
Inheritance is done with the ``object of`` syntax. Multiple inheritance is Inheritance is done with the ``object of`` syntax. Multiple inheritance is
currently not supported. If an object type has no suitable ancestor, ``TObject`` currently not supported. If an object type has no suitable ancestor, ``RootObj``
can be used as its ancestor, but this is only a convention. Objects that have can be used as its ancestor, but this is only a convention. Objects that have
no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma
to introduce new object roots apart from ``system.TObject``. (This is used to introduce new object roots apart from ``system.RootObj``. (This is used
in the GTK wrapper for instance.) in the GTK wrapper for instance.)
@ -228,7 +228,7 @@ is needed:
.. code-block:: nim .. code-block:: nim
type type
TSocket* = object of TObject TSocket* = object of RootObj
FHost: int # cannot be accessed from the outside of the module FHost: int # cannot be accessed from the outside of the module
# the `F` prefix is a convention to avoid clashes since # the `F` prefix is a convention to avoid clashes since
# the accessors are named `host` # the accessors are named `host`
@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
.. code-block:: nim .. code-block:: nim
type type
PExpr = ref object of TObject ## abstract base class for an expression PExpr = ref object of RootObj ## abstract base class for an expression
PLiteral = ref object of PExpr PLiteral = ref object of PExpr
x: int x: int
PPlusExpr = ref object of PExpr PPlusExpr = ref object of PExpr
@ -313,7 +313,7 @@ dispatching:
.. code-block:: nim .. code-block:: nim
type type
TThing = object of TObject TThing = object of RootObj
TUnit = object of TThing TUnit = object of TThing
x: int x: int

View file

@ -17,6 +17,8 @@
## as the response body. ## as the response body.
## ##
## .. code-block::nim ## .. code-block::nim
## import asynchttpserver, asyncdispatch
##
## var server = newAsyncHttpServer() ## var server = newAsyncHttpServer()
## proc cb(req: Request) {.async.} = ## proc cb(req: Request) {.async.} =
## await req.respond(Http200, "Hello World") ## await req.respond(Http200, "Hello World")

View file

@ -294,7 +294,9 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
var r = if proxy == nil: parseUri(url) else: proxy.url var r = if proxy == nil: parseUri(url) else: proxy.url
var headers = substr($httpMethod, len("http")) var headers = substr($httpMethod, len("http"))
if proxy == nil: if proxy == nil:
headers.add(" /" & r.path & r.query) headers.add(" " & r.path)
if r.query.len > 0:
headers.add("?" & r.query)
else: else:
headers.add(" " & url) headers.add(" " & url)
@ -442,7 +444,9 @@ proc generateHeaders(r: Uri, httpMethod: HttpMethod,
headers: StringTableRef): string = headers: StringTableRef): string =
result = substr($httpMethod, len("http")) result = substr($httpMethod, len("http"))
# TODO: Proxies # TODO: Proxies
result.add(" /" & r.path & r.query) result.add(" " & r.path)
if r.query.len > 0:
result.add("?" & r.query)
result.add(" HTTP/1.1\c\L") result.add(" HTTP/1.1\c\L")
add(result, "Host: " & r.hostname & "\c\L") add(result, "Host: " & r.hostname & "\c\L")

View file

@ -9,15 +9,17 @@
## Module for computing MD5 checksums. ## Module for computing MD5 checksums.
import unsigned
type type
MD5State = array[0..3, int32] MD5State = array[0..3, uint32]
MD5Block = array[0..15, int32] MD5Block = array[0..15, uint32]
MD5CBits = array[0..7, int8] MD5CBits = array[0..7, uint8]
MD5Digest* = array[0..15, int8] MD5Digest* = array[0..15, uint8]
MD5Buffer = array[0..63, int8] MD5Buffer = array[0..63, uint8]
MD5Context* {.final.} = object MD5Context* {.final.} = object
state: MD5State state: MD5State
count: array[0..1, int32] count: array[0..1, uint32]
buffer: MD5Buffer buffer: MD5Buffer
const const
@ -31,57 +33,57 @@ const
"\0\0\0\0\0\0\0\0" & "\0\0\0\0\0\0\0\0" &
"\0\0\0\0" "\0\0\0\0"
proc F(x, y, z: int32): int32 {.inline.} = proc F(x, y, z: uint32): uint32 {.inline.} =
result = (x and y) or ((not x) and z) result = (x and y) or ((not x) and z)
proc G(x, y, z: int32): int32 {.inline.} = proc G(x, y, z: uint32): uint32 {.inline.} =
result = (x and z) or (y and (not z)) result = (x and z) or (y and (not z))
proc H(x, y, z: int32): int32 {.inline.} = proc H(x, y, z: uint32): uint32 {.inline.} =
result = x xor y xor z result = x xor y xor z
proc I(x, y, z: int32): int32 {.inline.} = proc I(x, y, z: uint32): uint32 {.inline.} =
result = y xor (x or (not z)) result = y xor (x or (not z))
proc rot(x: var int32, n: int8) {.inline.} = proc rot(x: var uint32, n: uint8) {.inline.} =
x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n))) x = (x shl n) or (x shr (32'u32 - n))
proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a +% F(b, c, d) +% x +% ac a = a + F(b, c, d) + x + ac
rot(a, s) rot(a, s)
a = a +% b a = a + b
proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a +% G(b, c, d) +% x +% ac a = a + G(b, c, d) + x + ac
rot(a, s) rot(a, s)
a = a +% b a = a + b
proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a +% H(b, c, d) +% x +% ac a = a + H(b, c, d) + x + ac
rot(a, s) rot(a, s)
a = a +% b a = a + b
proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a +% I(b, c, d) +% x +% ac a = a + I(b, c, d) + x + ac
rot(a, s) rot(a, s)
a = a +% b a = a + b
proc encode(dest: var MD5Block, src: cstring) = proc encode(dest: var MD5Block, src: cstring) =
var j = 0 var j = 0
for i in 0..high(dest): for i in 0..high(dest):
dest[i] = toU32(ord(src[j]) or dest[i] = uint32(ord(src[j])) or
ord(src[j+1]) shl 8 or uint32(ord(src[j+1])) shl 8 or
ord(src[j+2]) shl 16 or uint32(ord(src[j+2])) shl 16 or
ord(src[j+3]) shl 24) uint32(ord(src[j+3])) shl 24
inc(j, 4) inc(j, 4)
proc decode(dest: var openArray[int8], src: openArray[int32]) = proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
var i = 0 var i = 0
for j in 0..high(src): for j in 0..high(src):
dest[i] = toU8(src[j] and 0xff'i32) dest[i] = src[j] and 0xff'u32
dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32) dest[i+1] = src[j] shr 8 and 0xff'u32
dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32) dest[i+2] = src[j] shr 16 and 0xff'u32
dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32) dest[i+3] = src[j] shr 24 and 0xff'u32
inc(i, 4) inc(i, 4)
proc transform(buffer: pointer, state: var MD5State) = proc transform(buffer: pointer, state: var MD5State) =
@ -92,92 +94,92 @@ proc transform(buffer: pointer, state: var MD5State) =
var b = state[1] var b = state[1]
var c = state[2] var c = state[2]
var d = state[3] var d = state[3]
FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32) FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32) FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32) FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32) FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32) FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32) FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32) FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32) FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32) FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32) FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32) FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32) FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32) FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32) FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32) FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32) FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32) GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32) GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32) GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32) GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32) GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32) GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32) GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32) GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32) GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32) GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32) GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32) GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32) GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32) GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32) GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32) GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32) HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32) HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32) HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32) HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32) HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32) HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32) HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32) HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32) HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32) HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32) HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32) HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32) HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32) HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32) HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32) HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32) II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32) II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32) II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32) II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32) II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32) II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32) II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32) II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32) II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32) II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32) II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32) II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32) II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32) II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32) II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32) II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
state[0] = state[0] +% a state[0] = state[0] + a
state[1] = state[1] +% b state[1] = state[1] + b
state[2] = state[2] +% c state[2] = state[2] + c
state[3] = state[3] +% d state[3] = state[3] + d
proc md5Init*(c: var MD5Context) = proc md5Init*(c: var MD5Context) =
## initializes a MD5Context ## initializes a MD5Context
c.state[0] = 0x67452301'i32 c.state[0] = 0x67452301'u32
c.state[1] = 0xEFCDAB89'i32 c.state[1] = 0xEFCDAB89'u32
c.state[2] = 0x98BADCFE'i32 c.state[2] = 0x98BADCFE'u32
c.state[3] = 0x10325476'i32 c.state[3] = 0x10325476'u32
c.count[0] = 0'i32 c.count[0] = 0'u32
c.count[1] = 0'i32 c.count[1] = 0'u32
zeroMem(addr(c.buffer), sizeof(MD5buffer)) zeroMem(addr(c.buffer), sizeof(MD5buffer))
proc md5Update*(c: var MD5Context, input: cstring, len: int) = proc md5Update*(c: var MD5Context, input: cstring, len: int) =
## updates the MD5Context with the `input` data of length `len` ## updates the MD5Context with the `input` data of length `len`
var input = input var input = input
var Index = (c.count[0] shr 3) and 0x3F var Index = int((c.count[0] shr 3) and 0x3F)
c.count[0] = c.count[0] +% toU32(len shl 3) c.count[0] = c.count[0] + (uint32(len) shl 3)
if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32 if c.count[0] < (uint32(len) shl 3): c.count[1] = c.count[1] + 1'u32
c.count[1] = c.count[1] +% toU32(len shr 29) c.count[1] = c.count[1] + (uint32(len) shr 29)
var PartLen = 64 - Index var PartLen = 64 - Index
if len >= PartLen: if len >= PartLen:
copyMem(addr(c.buffer[Index]), input, PartLen) copyMem(addr(c.buffer[Index]), input, PartLen)
@ -196,7 +198,7 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
Bits: MD5CBits Bits: MD5CBits
PadLen: int PadLen: int
decode(Bits, c.count) decode(Bits, c.count)
var Index = (c.count[0] shr 3) and 0x3F var Index = int((c.count[0] shr 3) and 0x3F)
if Index < 56: PadLen = 56 - Index if Index < 56: PadLen = 56 - Index
else: PadLen = 120 - Index else: PadLen = 120 - Index
md5Update(c, padding, PadLen) md5Update(c, padding, PadLen)
@ -241,5 +243,3 @@ when isMainModule:
assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") == assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
"7e716d0e702df0505fc72e2b89467910") "7e716d0e702df0505fc72e2b89467910")
assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e") assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")

View file

@ -16,6 +16,7 @@ type
Uri* = object Uri* = object
scheme*, username*, password*: string scheme*, username*, password*: string
hostname*, port*, path*, query*, anchor*: string hostname*, port*, path*, query*, anchor*: string
opaque*: bool
{.deprecated: [TUrl: Url, TUri: Uri].} {.deprecated: [TUrl: Url, TUri: Uri].}
@ -115,6 +116,8 @@ proc parseUri*(uri: string): Uri =
if authority == "": if authority == "":
raise newException(ValueError, "Expected authority got nothing.") raise newException(ValueError, "Expected authority got nothing.")
parseAuthority(authority, result) parseAuthority(authority, result)
else:
result.opaque = true
# Path # Path
parsePath(uri, i, result) parsePath(uri, i, result)
@ -256,6 +259,9 @@ proc `$`*(u: Uri): string =
result = "" result = ""
if u.scheme.len > 0: if u.scheme.len > 0:
result.add(u.scheme) result.add(u.scheme)
if u.opaque:
result.add(":")
else:
result.add("://") result.add("://")
if u.username.len > 0: if u.username.len > 0:
result.add(u.username) result.add(u.username)
@ -268,22 +274,28 @@ proc `$`*(u: Uri): string =
result.add(":") result.add(":")
result.add(u.port) result.add(u.port)
if u.path.len > 0: if u.path.len > 0:
if u.path[0] != '/': result.add("/")
result.add(u.path) result.add(u.path)
if u.query.len > 0:
result.add("?")
result.add(u.query) result.add(u.query)
if u.anchor.len > 0:
result.add("#")
result.add(u.anchor) result.add(u.anchor)
when isMainModule: when isMainModule:
block: block:
let test = parseUri("http://localhost:8080/test") let str = "http://localhost:8080/test"
let test = parseUri(str)
doAssert test.scheme == "http" doAssert test.scheme == "http"
doAssert test.port == "8080" doAssert test.port == "8080"
doAssert test.path == "/test" doAssert test.path == "/test"
doAssert test.hostname == "localhost" doAssert test.hostname == "localhost"
doAssert($test == str)
block: block:
let test = parseUri("foo://username:password@example.com:8042/over/there" & let str = "foo://username:password@example.com:8042/over/there" &
"/index.dtb?type=animal&name=narwhal#nose") "/index.dtb?type=animal&name=narwhal#nose"
let test = parseUri(str)
doAssert test.scheme == "foo" doAssert test.scheme == "foo"
doAssert test.username == "username" doAssert test.username == "username"
doAssert test.password == "password" doAssert test.password == "password"
@ -292,34 +304,45 @@ when isMainModule:
doAssert test.path == "/over/there/index.dtb" doAssert test.path == "/over/there/index.dtb"
doAssert test.query == "type=animal&name=narwhal" doAssert test.query == "type=animal&name=narwhal"
doAssert test.anchor == "nose" doAssert test.anchor == "nose"
doAssert($test == str)
block: block:
let test = parseUri("urn:example:animal:ferret:nose") let str = "urn:example:animal:ferret:nose"
let test = parseUri(str)
doAssert test.scheme == "urn" doAssert test.scheme == "urn"
doAssert test.path == "example:animal:ferret:nose" doAssert test.path == "example:animal:ferret:nose"
doAssert($test == str)
block: block:
let test = parseUri("mailto:username@example.com?subject=Topic") let str = "mailto:username@example.com?subject=Topic"
let test = parseUri(str)
doAssert test.scheme == "mailto" doAssert test.scheme == "mailto"
doAssert test.username == "username" doAssert test.username == "username"
doAssert test.hostname == "example.com" doAssert test.hostname == "example.com"
doAssert test.query == "subject=Topic" doAssert test.query == "subject=Topic"
doAssert($test == str)
block: block:
let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar") let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
let test = parseUri(str)
doAssert test.scheme == "magnet" doAssert test.scheme == "magnet"
doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar" doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
doAssert($test == str)
block: block:
let test = parseUri("/test/foo/bar?q=2#asdf") let str = "/test/foo/bar?q=2#asdf"
let test = parseUri(str)
doAssert test.scheme == "" doAssert test.scheme == ""
doAssert test.path == "/test/foo/bar" doAssert test.path == "/test/foo/bar"
doAssert test.query == "q=2" doAssert test.query == "q=2"
doAssert test.anchor == "asdf" doAssert test.anchor == "asdf"
doAssert($test == str)
block: block:
let test = parseUri("test/no/slash") let str = "test/no/slash"
let test = parseUri(str)
doAssert test.path == "test/no/slash" doAssert test.path == "test/no/slash"
doAssert($test == str)
# Remove dot segments tests # Remove dot segments tests
block: block:
@ -371,5 +394,3 @@ when isMainModule:
block: block:
let test = parseUri("http://example.com/foo/") / "/bar/asd" let test = parseUri("http://example.com/foo/") / "/bar/asd"
doAssert test.path == "/foo/bar/asd" doAssert test.path == "/foo/bar/asd"

View file

@ -233,6 +233,7 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
var q = cast[PRawChannel](addr(c)) var q = cast[PRawChannel](addr(c))
if q.mask != ChannelDeadMask: if q.mask != ChannelDeadMask:
if tryAcquireSys(q.lock): if tryAcquireSys(q.lock):
if q.count > 0:
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
result.dataAvailable = true result.dataAvailable = true
releaseSys(q.lock) releaseSys(q.lock)

16
tests/generics/t1050.nim Normal file
View file

@ -0,0 +1,16 @@
discard """
msg: "int"
output: "4"
"""
import typetraits
type ArrayType[T] = distinct T
proc arrayItem(a: ArrayType): auto =
static: echo(name(type(a).T))
result = (type(a).T)(4)
var arr: ArrayType[int]
echo arrayItem(arr)

View file

@ -1,9 +1,15 @@
discard """ discard """
msg: "static 10\ndynamic\nstatic 20\n" msg: "static 10\ndynamic\nstatic 20\n"
output: "s\nd\nd\ns" output: "s\nd\nd\ns"
disabled: "true"
""" """
type
semistatic[T] =
static[T] or T
template isStatic*(x): expr =
compiles(static(x))
proc foo(x: semistatic[int]) = proc foo(x: semistatic[int]) =
when isStatic(x): when isStatic(x):
static: echo "static ", x static: echo "static ", x

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tstaticparams.nim" file: "tstaticparams.nim"
output: "abracadabra\ntest\n3\n15\n4\n2" output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang"
""" """
type type
@ -56,3 +56,66 @@ type TTestSub[N: static[int]] = TTest[1, N]
var z: TTestSub[2] var z: TTestSub[2]
echo z.high echo z.high
# issue 1049
proc matrix_1*[M, N, T](mat: Matrix[M,N,T], a: array[N, int]) = discard
proc matrix_2*[M, N, T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = discard
proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard
var
tmat: Matrix[4,4,int]
ar1: array[4, int]
ar2: array[5, int]
matrix_1(tmat, ar1)
matrix_2(tmat, ar2)
matrix_3(tmat, ar1)
matrix_4(tmat, ar2)
template reject(x): stmt =
static: assert(not compiles(x))
# test with arrays of wrong size
reject matrix_1(tmat, ar2)
reject matrix_2(tmat, ar1)
reject matrix_3(tmat, ar2)
reject matrix_4(tmat, ar1)
# bug 1820
type
T1820_1[T; Y: static[int]] = object
bar: T
proc intOrFloat*[Y](f: T1820_1[int, Y]) = echo "int"
proc intOrFloat*[Y](f: T1820_1[float, Y]) = echo "float"
proc threeOrFour*[T](f: T1820_1[T, 3]) = echo "3"
proc threeOrFour*[T](f: T1820_1[T, 4]) = echo "4"
var foo_1: T1820_1[float, 3]
foo_1.intOrFloat
foo_1.threeOrFour
type
YinAndYang = enum
Yin,
Yang
T1820_2[T; Y: static[YinAndYang]] = object
bar: T
proc intOrFloat*[Y](f: T1820_2[int, Y]) = echo "int"
proc intOrFloat*[Y](f: T1820_2[float, Y]) = echo "float"
proc yinOrYang*[T](f: T1820_2[T, YinAndYang.Yin]) = echo "yin"
proc yinOrYang*[T](f: T1820_2[T, Yang]) = echo "yang"
var foo_2: T1820_2[float, Yin]
var foo_3: T1820_2[float, YinAndYang.Yang]
foo_2.intOrFloat
foo_2.yinOrYang
foo_3.yinOrYang

View file

@ -1,5 +1,13 @@
discard """ discard """
output: "Sortable\nSortable\nContainer" output: '''Sortable
Sortable
Container
true
true
false
false
false
'''
""" """
import typetraits import typetraits
@ -41,3 +49,20 @@ proc y(x: TObj): int = 10
proc testFoo(x: TFoo) = discard proc testFoo(x: TFoo) = discard
testFoo(TObj(x: 10)) testFoo(TObj(x: 10))
type
Matrix[Rows, Cols: static[int]; T] = generic M
M.M == Rows
M.N == Cols
M.T is T
MyMatrix[M, N: static[int]; T] = object
data: array[M*N, T]
var x: MyMatrix[3, 3, int]
echo x is Matrix
echo x is Matrix[3, 3, int]
echo x is Matrix[3, 3, float]
echo x is Matrix[4, 3, int]
echo x is Matrix[3, 4, int]

View file

@ -51,16 +51,16 @@ while i < s.len:
write(stdout, "Du heißt " & s) write(stdout, "Du heißt " & s)
# bug #544 # bug #544
when false:
# yay, fails again # yay, fails again
type Bar [T; I:range] = array[I, T] type Bar [T; I:range] = array[I, T]
proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] = proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] =
when len(a) != 3: when len(a) != 3:
# Error: constant expression expected # Error: constant expression expected
{.fatal:"Dimensions have to be 3".} {.fatal:"Dimensions have to be 3".}
#... #...
block: block:
var a, b: Bar[int, 0..2] var a, b: Bar[int, range[0..2]]
discard foo(a, b) discard foo(a, b)
# bug #1788 # bug #1788

View file

@ -0,0 +1,35 @@
discard """
outputsub: "channel is empty"
"""
# bug #1816
from math import random
from os import sleep
type PComm = ptr TChannel[int]
proc doAction(outC: PComm) {.thread.} =
for i in 0.. <5:
sleep(random(100))
send(outC[], i)
var
thr: TThread[PComm]
chan: TChannel[int]
open(chan)
createThread[PComm](thr, doAction, addr(chan))
while true:
let (flag, x) = tryRecv(chan)
if flag:
echo("received from chan: " & $x)
else:
echo "channel is empty"
break
echo "Finished listening"
joinThread(thr)
close(chan)

View file

@ -63,7 +63,7 @@
<span class="tab end"> </span>count += <span class="val">1</span> <span class="tab end"> </span>count += <span class="val">1</span>
echo(<span class="val">"Average line length: "</span>, echo(<span class="val">"Average line length: "</span>,
<span class="kwd">if</span> count: sum / count <span class="kwd">else</span>: <span class="val">0</span>) <span class="kwd">if</span> count &gt; <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
</pre> </pre>
</div> </div>
<div> <div>

View file

@ -42,7 +42,7 @@ Nim is efficient
Nim is expressive Nim is expressive
================= =================
* **The Nim compiler and all of the standard library are implemented in * **The Nim compiler and all of the standard libraries are implemented in
Nim.** Nim.**
* Built-in high level datatypes: strings, sets, sequences, etc. * Built-in high level datatypes: strings, sets, sequences, etc.
* Modern type system with local type inference, tuples, variants, * Modern type system with local type inference, tuples, variants,