Merge remote-tracking branch 'nim-lang/devel' into emscripten-support
This commit is contained in:
commit
537aca327a
14 changed files with 150 additions and 20 deletions
|
|
@ -738,6 +738,8 @@ type
|
||||||
name*: Rope
|
name*: Rope
|
||||||
path*: PNode # can be a string literal!
|
path*: PNode # can be a string literal!
|
||||||
|
|
||||||
|
CompilesId* = int ## id that is used for the caching logic within
|
||||||
|
## ``system.compiles``. See the seminst module.
|
||||||
TInstantiation* = object
|
TInstantiation* = object
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
concreteTypes*: seq[PType]
|
concreteTypes*: seq[PType]
|
||||||
|
|
@ -745,6 +747,7 @@ type
|
||||||
# needed in caas mode for purging the cache
|
# needed in caas mode for purging the cache
|
||||||
# XXX: it's possible to switch to a
|
# XXX: it's possible to switch to a
|
||||||
# simple ref count here
|
# simple ref count here
|
||||||
|
compilesId*: CompilesId
|
||||||
|
|
||||||
PInstantiation* = ref TInstantiation
|
PInstantiation* = ref TInstantiation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
incl(result.flags, sfDiscardable)
|
incl(result.flags, sfDiscardable)
|
||||||
# pretend it's imported from some unknown module to prevent cascading errors:
|
# pretend it's imported from some unknown module to prevent cascading errors:
|
||||||
if gCmd != cmdInteractive and c.inCompilesContext == 0:
|
if gCmd != cmdInteractive and c.compilesContextId == 0:
|
||||||
c.importTable.addSym(result)
|
c.importTable.addSym(result)
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||||
# as semOverlodedCall is already pretty slow (and we need this information
|
# as semOverlodedCall is already pretty slow (and we need this information
|
||||||
# only in case of an error).
|
# only in case of an error).
|
||||||
if c.inCompilesContext > 0:
|
if c.compilesContextId > 0:
|
||||||
# fail fast:
|
# fail fast:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
if errors.isNil or errors.len == 0:
|
if errors.isNil or errors.len == 0:
|
||||||
|
|
@ -235,7 +235,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
internalAssert result.state == csMatch
|
internalAssert result.state == csMatch
|
||||||
#writeMatches(result)
|
#writeMatches(result)
|
||||||
#writeMatches(alt)
|
#writeMatches(alt)
|
||||||
if c.inCompilesContext > 0:
|
if c.compilesContextId > 0:
|
||||||
# quick error message for performance of 'compiles' built-in:
|
# quick error message for performance of 'compiles' built-in:
|
||||||
globalError(n.info, errGenerated, "ambiguous call")
|
globalError(n.info, errGenerated, "ambiguous call")
|
||||||
elif gErrorCounter == 0:
|
elif gErrorCounter == 0:
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ type
|
||||||
inTypeClass*: int # > 0 if we are in a user-defined type class
|
inTypeClass*: int # > 0 if we are in a user-defined type class
|
||||||
inGenericContext*: int # > 0 if we are in a generic type
|
inGenericContext*: int # > 0 if we are in a generic type
|
||||||
inUnrolledContext*: int # > 0 if we are unrolling a loop
|
inUnrolledContext*: int # > 0 if we are unrolling a loop
|
||||||
inCompilesContext*: int # > 0 if we are in a ``compiles`` magic
|
compilesContextId*: int # > 0 if we are in a ``compiles`` magic
|
||||||
|
compilesContextIdGenerator*: int
|
||||||
inGenericInst*: int # > 0 if we are instantiating a generic
|
inGenericInst*: int # > 0 if we are instantiating a generic
|
||||||
converters*: TSymSeq # sequence of converters
|
converters*: TSymSeq # sequence of converters
|
||||||
patterns*: TSymSeq # sequence of pattern matchers
|
patterns*: TSymSeq # sequence of pattern matchers
|
||||||
|
|
|
||||||
|
|
@ -818,7 +818,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# This is a proc variable, apply normal overload resolution
|
# This is a proc variable, apply normal overload resolution
|
||||||
let m = resolveIndirectCall(c, n, nOrig, t)
|
let m = resolveIndirectCall(c, n, nOrig, t)
|
||||||
if m.state != csMatch:
|
if m.state != csMatch:
|
||||||
if c.inCompilesContext > 0:
|
if c.compilesContextId > 0:
|
||||||
# speed up error generation:
|
# speed up error generation:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
return emptyNode
|
return emptyNode
|
||||||
|
|
@ -1636,7 +1636,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
# watch out, hacks ahead:
|
# watch out, hacks ahead:
|
||||||
let oldErrorCount = msgs.gErrorCounter
|
let oldErrorCount = msgs.gErrorCounter
|
||||||
let oldErrorMax = msgs.gErrorMax
|
let oldErrorMax = msgs.gErrorMax
|
||||||
inc c.inCompilesContext
|
let oldCompilesId = c.compilesContextId
|
||||||
|
inc c.compilesContextIdGenerator
|
||||||
|
c.compilesContextId = c.compilesContextIdGenerator
|
||||||
# do not halt after first error:
|
# do not halt after first error:
|
||||||
msgs.gErrorMax = high(int)
|
msgs.gErrorMax = high(int)
|
||||||
|
|
||||||
|
|
@ -1660,6 +1662,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
except ERecoverableError:
|
except ERecoverableError:
|
||||||
discard
|
discard
|
||||||
# undo symbol table changes (as far as it's possible):
|
# undo symbol table changes (as far as it's possible):
|
||||||
|
c.compilesContextId = oldCompilesId
|
||||||
c.generics = oldGenerics
|
c.generics = oldGenerics
|
||||||
c.inGenericContext = oldInGenericContext
|
c.inGenericContext = oldInGenericContext
|
||||||
c.inUnrolledContext = oldInUnrolledContext
|
c.inUnrolledContext = oldInUnrolledContext
|
||||||
|
|
@ -1668,7 +1671,6 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
msgs.setInfoContextLen(oldContextLen)
|
msgs.setInfoContextLen(oldContextLen)
|
||||||
setLen(gOwners, oldOwnerLen)
|
setLen(gOwners, oldOwnerLen)
|
||||||
c.currentScope = oldScope
|
c.currentScope = oldScope
|
||||||
dec c.inCompilesContext
|
|
||||||
errorOutputs = oldErrorOutputs
|
errorOutputs = oldErrorOutputs
|
||||||
msgs.gErrorCounter = oldErrorCount
|
msgs.gErrorCounter = oldErrorCount
|
||||||
msgs.gErrorMax = oldErrorMax
|
msgs.gErrorMax = oldErrorMax
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
of nkEnumFieldDef: a = n.sons[i].sons[0]
|
of nkEnumFieldDef: a = n.sons[i].sons[0]
|
||||||
of nkIdent: a = n.sons[i]
|
of nkIdent: a = n.sons[i]
|
||||||
else: illFormedAst(n)
|
else: illFormedAst(n)
|
||||||
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[i]), c))
|
addDecl(c, newSymS(skUnknown, getIdentNode(a), c))
|
||||||
of nkObjectTy, nkTupleTy, nkTupleClassTy:
|
of nkObjectTy, nkTupleTy, nkTupleClassTy:
|
||||||
discard
|
discard
|
||||||
of nkFormalParams:
|
of nkFormalParams:
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,11 @@ proc sameInstantiation(a, b: TInstantiation): bool =
|
||||||
flags = {ExactTypeDescValues}): return
|
flags = {ExactTypeDescValues}): return
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc genericCacheGet(genericSym: PSym, entry: TInstantiation): PSym =
|
proc genericCacheGet(genericSym: PSym, entry: TInstantiation;
|
||||||
|
id: CompilesId): PSym =
|
||||||
if genericSym.procInstCache != nil:
|
if genericSym.procInstCache != nil:
|
||||||
for inst in genericSym.procInstCache:
|
for inst in genericSym.procInstCache:
|
||||||
if sameInstantiation(entry, inst[]):
|
if inst.compilesId == id and sameInstantiation(entry, inst[]):
|
||||||
return inst.sym
|
return inst.sym
|
||||||
|
|
||||||
proc removeDefaultParamValues(n: PNode) =
|
proc removeDefaultParamValues(n: PNode) =
|
||||||
|
|
@ -249,13 +250,15 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
if tfTriggersCompileTime in result.typ.flags:
|
if tfTriggersCompileTime in result.typ.flags:
|
||||||
incl(result.flags, sfCompileTime)
|
incl(result.flags, sfCompileTime)
|
||||||
n.sons[genericParamsPos] = ast.emptyNode
|
n.sons[genericParamsPos] = ast.emptyNode
|
||||||
var oldPrc = genericCacheGet(fn, entry[])
|
var oldPrc = genericCacheGet(fn, entry[], c.compilesContextId)
|
||||||
if oldPrc == nil:
|
if oldPrc == nil:
|
||||||
# we MUST not add potentially wrong instantiations to the caching mechanism.
|
# we MUST not add potentially wrong instantiations to the caching mechanism.
|
||||||
# This means recursive instantiations behave differently when in
|
# This means recursive instantiations behave differently when in
|
||||||
# a ``compiles`` context but this is the lesser evil. See
|
# a ``compiles`` context but this is the lesser evil. See
|
||||||
# bug #1055 (tevilcompiles).
|
# bug #1055 (tevilcompiles).
|
||||||
if c.inCompilesContext == 0: fn.procInstCache.safeAdd(entry)
|
#if c.compilesContextId == 0:
|
||||||
|
entry.compilesId = c.compilesContextId
|
||||||
|
fn.procInstCache.safeAdd(entry)
|
||||||
c.generics.add(makeInstPair(fn, entry))
|
c.generics.add(makeInstPair(fn, entry))
|
||||||
if n.sons[pragmasPos].kind != nkEmpty:
|
if n.sons[pragmasPos].kind != nkEmpty:
|
||||||
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
|
pragma(c, result, n.sons[pragmasPos], allRoutinePragmas)
|
||||||
|
|
|
||||||
|
|
@ -986,7 +986,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
if r.sym == nil or sfAnon notin r.sym.flags:
|
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||||
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
||||||
n.sons[0].info)
|
n.sons[0].info)
|
||||||
if lifted != nil: r = lifted
|
if lifted != nil:
|
||||||
|
r = lifted
|
||||||
|
#if r.kind != tyGenericParam:
|
||||||
|
#echo "came here for ", typeToString(r)
|
||||||
r.flags.incl tfRetType
|
r.flags.incl tfRetType
|
||||||
r = skipIntLit(r)
|
r = skipIntLit(r)
|
||||||
if kind == skIterator:
|
if kind == skIterator:
|
||||||
|
|
|
||||||
|
|
@ -335,8 +335,8 @@ proc suggestExpr*(c: PContext, node: PNode) =
|
||||||
if cp == cpNone: return
|
if cp == cpNone: return
|
||||||
var outputs = 0
|
var outputs = 0
|
||||||
# This keeps semExpr() from coming here recursively:
|
# This keeps semExpr() from coming here recursively:
|
||||||
if c.inCompilesContext > 0: return
|
if c.compilesContextId > 0: return
|
||||||
inc(c.inCompilesContext)
|
inc(c.compilesContextId)
|
||||||
|
|
||||||
if gIdeCmd == ideSug:
|
if gIdeCmd == ideSug:
|
||||||
var n = if nfIsCursor in node.flags: node else: findClosestDot(node)
|
var n = if nfIsCursor in node.flags: node else: findClosestDot(node)
|
||||||
|
|
@ -365,7 +365,7 @@ proc suggestExpr*(c: PContext, node: PNode) =
|
||||||
addSon(a, x)
|
addSon(a, x)
|
||||||
suggestCall(c, a, n, outputs)
|
suggestCall(c, a, n, outputs)
|
||||||
|
|
||||||
dec(c.inCompilesContext)
|
dec(c.compilesContextId)
|
||||||
if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
|
if outputs > 0 and gIdeCmd != ideUse: suggestQuit()
|
||||||
|
|
||||||
proc suggestStmt*(c: PContext, n: PNode) =
|
proc suggestStmt*(c: PContext, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -992,8 +992,8 @@ else:
|
||||||
|
|
||||||
proc closeSocket*(sock: AsyncFD) =
|
proc closeSocket*(sock: AsyncFD) =
|
||||||
let disp = getGlobalDispatcher()
|
let disp = getGlobalDispatcher()
|
||||||
sock.SocketHandle.close()
|
|
||||||
disp.selector.unregister(sock.SocketHandle)
|
disp.selector.unregister(sock.SocketHandle)
|
||||||
|
sock.SocketHandle.close()
|
||||||
|
|
||||||
proc unregister*(fd: AsyncFD) =
|
proc unregister*(fd: AsyncFD) =
|
||||||
getGlobalDispatcher().selector.unregister(fd.SocketHandle)
|
getGlobalDispatcher().selector.unregister(fd.SocketHandle)
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ when defined(nimArrIdx):
|
||||||
# :array|openarray|string|seq|cstring|tuple
|
# :array|openarray|string|seq|cstring|tuple
|
||||||
proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
|
proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
|
||||||
noSideEffect, magic: "ArrGet".}
|
noSideEffect, magic: "ArrGet".}
|
||||||
proc `[]=`*[I: Ordinal;T,S](a: var T; i: I;
|
proc `[]=`*[I: Ordinal;T,S](a: T; i: I;
|
||||||
x: S) {.noSideEffect, magic: "ArrPut".}
|
x: S) {.noSideEffect, magic: "ArrPut".}
|
||||||
proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
|
proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
|
||||||
|
|
||||||
|
|
|
||||||
98
tests/compiles/trecursive_generic_in_compiles.nim
Normal file
98
tests/compiles/trecursive_generic_in_compiles.nim
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
# bug #3313
|
||||||
|
import unittest, future
|
||||||
|
|
||||||
|
type
|
||||||
|
ListNodeKind = enum
|
||||||
|
lnkNil, lnkCons
|
||||||
|
List*[T] = ref object
|
||||||
|
## List ADT
|
||||||
|
case kind: ListNodeKind
|
||||||
|
of lnkNil:
|
||||||
|
discard
|
||||||
|
of lnkCons:
|
||||||
|
value: T
|
||||||
|
next: List[T] not nil
|
||||||
|
|
||||||
|
proc Cons*[T](head: T, tail: List[T]): List[T] =
|
||||||
|
## Constructs non empty list
|
||||||
|
List[T](kind: lnkCons, value: head, next: tail)
|
||||||
|
|
||||||
|
proc Nil*[T](): List[T] =
|
||||||
|
## Constructs empty list
|
||||||
|
List[T](kind: lnkNil)
|
||||||
|
|
||||||
|
proc head*[T](xs: List[T]): T =
|
||||||
|
## Returns list's head
|
||||||
|
xs.value
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# proc headOption*[T](xs: List[T]): Option[T] = ???
|
||||||
|
|
||||||
|
proc tail*[T](xs: List[T]): List[T] =
|
||||||
|
## Returns list's tail
|
||||||
|
case xs.kind
|
||||||
|
of lnkCons: xs.next
|
||||||
|
else: xs
|
||||||
|
|
||||||
|
proc isEmpty*(xs: List): bool =
|
||||||
|
## Checks if list is empty
|
||||||
|
xs.kind == lnkNil
|
||||||
|
|
||||||
|
proc `==`*[T](xs, ys: List[T]): bool =
|
||||||
|
## Compares two lists
|
||||||
|
if (xs.isEmpty, ys.isEmpty) == (true, true): true
|
||||||
|
elif (xs.isEmpty, ys.isEmpty) == (false, false): xs.head == ys.head and xs.tail == ys.tail
|
||||||
|
else: false
|
||||||
|
|
||||||
|
proc asList*[T](xs: varargs[T]): List[T] =
|
||||||
|
## Creates list from varargs
|
||||||
|
proc initListImpl(i: int, xs: openarray[T]): List[T] =
|
||||||
|
if i > high(xs):
|
||||||
|
Nil[T]()
|
||||||
|
else:
|
||||||
|
Cons(xs[i], initListImpl(i+1, xs))
|
||||||
|
initListImpl(0, xs)
|
||||||
|
|
||||||
|
proc foldRight*[T,U](xs: List[T], z: U, f: (T, U) -> U): U =
|
||||||
|
case xs.isEmpty
|
||||||
|
of true: z
|
||||||
|
else: f(xs.head, xs.tail.foldRight(z, f))
|
||||||
|
|
||||||
|
proc dup*[T](xs: List[T]): List[T] =
|
||||||
|
## Duplicates the list
|
||||||
|
xs.foldRight(Nil[T](), (x: T, xs: List[T]) => Cons(x, xs))
|
||||||
|
|
||||||
|
type
|
||||||
|
ListFormat = enum
|
||||||
|
lfADT, lfSTD
|
||||||
|
|
||||||
|
proc asString[T](xs: List[T], f = lfSTD): string =
|
||||||
|
proc asAdt(xs: List[T]): string =
|
||||||
|
case xs.isEmpty
|
||||||
|
of true: "Nil"
|
||||||
|
else: "Cons(" & $xs.head & ", " & xs.tail.asAdt & ")"
|
||||||
|
|
||||||
|
proc asStd(xs: List[T]): string =
|
||||||
|
"List(" & xs.foldLeft("", (s: string, v: T) =>
|
||||||
|
(if s == "": $v else: s & ", " & $v)) & ")"
|
||||||
|
|
||||||
|
case f
|
||||||
|
of lfADT: xs.asAdt
|
||||||
|
else: xs.asStd
|
||||||
|
|
||||||
|
proc `$`*[T](xs: List[T]): string =
|
||||||
|
## Converts list to string
|
||||||
|
result = xs.asString
|
||||||
|
|
||||||
|
proc foldLeft*[T,U](xs: List[T], z: U, f: (U, T) -> U): U =
|
||||||
|
case xs.isEmpty
|
||||||
|
of true: z
|
||||||
|
else: foldLeft(xs.tail, f(z, xs.head), f)
|
||||||
|
|
||||||
|
suite "unittest compilation error":
|
||||||
|
|
||||||
|
test "issue 3313":
|
||||||
|
let lst = lc[$x | (x <- 'a'..'z'), string].asList
|
||||||
|
|
||||||
|
let lstCopy = lst.dup
|
||||||
|
check: lstCopy == lst
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
proc myFun[A,B](x: A): B =
|
proc myFun[A](x: A): auto =
|
||||||
result = float(x+10)
|
result = float(x+10)
|
||||||
|
|
||||||
proc myMap[T,S](sIn: seq[T], f: proc (q: T): S): seq[S] =
|
proc myMap[T,S](sIn: seq[T], f: proc (q: T): S): seq[S] =
|
||||||
|
|
|
||||||
20
tests/metatype/tunresolved_return_type.nim
Normal file
20
tests/metatype/tunresolved_return_type.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "cannot instantiate: 'T'"
|
||||||
|
line: 12
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #2594
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
ResultValue* = int64
|
||||||
|
|
||||||
|
proc toNumber[T: int|uint|int64|uint64](v: ResultValue): T =
|
||||||
|
if v < low(T) or v > high(T):
|
||||||
|
raise newException(RangeError, "protocol error")
|
||||||
|
return T(v)
|
||||||
|
|
||||||
|
#proc toNumber[T](v: int32): T =
|
||||||
|
# return (v)
|
||||||
|
|
||||||
|
echo toNumber(23)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue