Merge branch 'master' into vm2
Conflicts: compiler/sem.nim
This commit is contained in:
commit
5eba93d584
135 changed files with 2221 additions and 90065 deletions
|
|
@ -713,7 +713,6 @@ type
|
|||
# -1 means that the size is unkwown
|
||||
align*: int # the type's alignment requirements
|
||||
loc*: TLoc
|
||||
testeeName*: PIdent # the test variable in user-defined type classes
|
||||
|
||||
TPair*{.final.} = object
|
||||
key*, val*: PObject
|
||||
|
|
@ -1089,7 +1088,6 @@ proc assignType(dest, src: PType) =
|
|||
dest.size = src.size
|
||||
dest.align = src.align
|
||||
dest.destructor = src.destructor
|
||||
dest.testeeName = src.testeeName
|
||||
# this fixes 'type TLock = TSysLock':
|
||||
if src.sym != nil:
|
||||
if dest.sym != nil:
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
|||
if needToCopy notin flags or
|
||||
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
||||
if dest.s == OnStack or not usesNativeGC():
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||
addrLoc(dest), addrLoc(src), rdLoc(dest))
|
||||
|
|
@ -316,6 +317,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
|||
if needsComplexAssignment(dest.t):
|
||||
genGenericAsgn(p, dest, src, flags)
|
||||
else:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n",
|
||||
rdLoc(dest), rdLoc(src))
|
||||
|
|
@ -327,11 +329,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
|||
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len0, $3);$n",
|
||||
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
||||
else:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len0);$n",
|
||||
rdLoc(dest), rdLoc(src))
|
||||
of tySet:
|
||||
if mapType(ty) == ctArray:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memcpy((void*)$1, (NIM_CONST void*)$2, $3);$n",
|
||||
rdLoc(dest), rdLoc(src), toRope(getSize(dest.t)))
|
||||
else:
|
||||
|
|
@ -1361,6 +1365,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
lineF(p, cpsStmts, lookupOpr[op],
|
||||
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
|
||||
of mEqSet:
|
||||
useStringh(p.module)
|
||||
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
|
||||
of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
|
||||
# we inline the simple for loop for better code generation:
|
||||
|
|
@ -1612,6 +1617,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
|||
if d.k == locNone: getTemp(p, e.typ, d)
|
||||
if getSize(e.typ) > 8:
|
||||
# big set:
|
||||
useStringh(p.module)
|
||||
lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
|
||||
for i in countup(0, sonsLen(e) - 1):
|
||||
if e.sons[i].kind == nkRange:
|
||||
|
|
|
|||
|
|
@ -72,6 +72,11 @@ proc isSimpleConst(typ: PType): bool =
|
|||
{tyTuple, tyObject, tyArray, tyArrayConstr, tySet, tySequence} and not
|
||||
(t.kind == tyProc and t.callConv == ccClosure)
|
||||
|
||||
proc useStringh(m: BModule) =
|
||||
if not m.includesStringh:
|
||||
m.includesStringh = true
|
||||
discard lists.IncludeStr(m.headerFiles, "<string.h>")
|
||||
|
||||
proc useHeader(m: BModule, sym: PSym) =
|
||||
if lfHeader in sym.loc.Flags:
|
||||
assert(sym.annex != nil)
|
||||
|
|
@ -358,19 +363,24 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
|||
# field, so disabling this should be safe:
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||
else:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
# XXX: We can be extra clever here and call memset only
|
||||
# on the bytes following the m_type field?
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||
|
||||
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
|
||||
proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
|
||||
if not isComplexValueType(skipTypes(loc.t, abstractRange)):
|
||||
linefmt(p, section, "$1 = 0;$n", rdLoc(loc))
|
||||
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
|
||||
else:
|
||||
linefmt(p, section, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
genObjectInit(p, section, loc.t, loc, true)
|
||||
if not isTemp or containsGarbageCollectedRef(loc.t):
|
||||
# don't use memset for temporary values for performance if we can
|
||||
# avoid it:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||
|
||||
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||
if sfNoInit notin v.flags:
|
||||
|
|
@ -396,7 +406,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
|
|||
result.t = getUniqueType(t)
|
||||
result.s = OnStack
|
||||
result.flags = {}
|
||||
constructLoc(p, result)
|
||||
constructLoc(p, result, isTemp=true)
|
||||
|
||||
proc keepAlive(p: BProc, toKeepAlive: TLoc) =
|
||||
when false:
|
||||
|
|
@ -418,6 +428,7 @@ proc keepAlive(p: BProc, toKeepAlive: TLoc) =
|
|||
if not isComplexValueType(skipTypes(toKeepAlive.t, abstractVarRange)):
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(result), rdLoc(toKeepAlive))
|
||||
else:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts,
|
||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||
addrLoc(result), addrLoc(toKeepAlive), rdLoc(result))
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ type
|
|||
FrameDeclared*: bool # hack for ROD support so that we don't declare
|
||||
# a frame var twice in an init proc
|
||||
isHeaderFile*: bool # C source file is the header file
|
||||
includesStringh*: bool # C source file already includes ``<string.h>``
|
||||
cfilename*: string # filename of the module (including path,
|
||||
# without extension)
|
||||
typeCache*: TIdTable # cache the generated types
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ proc CallCCompiler*(projectfile: string) =
|
|||
else:
|
||||
rawMessage(errGenerated, " execution of an external program failed; " &
|
||||
"rerun with --parallelBuild:1 to see the error message")
|
||||
if optNoLinking notin gGlobalOptions and cmds.len > 0:
|
||||
if optNoLinking notin gGlobalOptions:
|
||||
# call the linker:
|
||||
var it = PStrEntry(toLink.head)
|
||||
var objfiles = ""
|
||||
|
|
|
|||
|
|
@ -91,13 +91,17 @@ proc Remove*(list: var TLinkedList, entry: PListEntry) =
|
|||
if entry.prev != nil: entry.prev.next = entry.next
|
||||
|
||||
proc bringToFront*(list: var TLinkedList, entry: PListEntry) =
|
||||
if entry == list.head: return
|
||||
if entry == list.tail: list.tail = entry.prev
|
||||
if entry.next != nil: entry.next.prev = entry.prev
|
||||
if entry.prev != nil: entry.prev.next = entry.next
|
||||
entry.prev = nil
|
||||
entry.next = list.head
|
||||
list.head = entry
|
||||
when true:
|
||||
list.remove entry
|
||||
list.prepend entry
|
||||
else:
|
||||
if entry == list.head: return
|
||||
if entry == list.tail: list.tail = entry.prev
|
||||
if entry.next != nil: entry.next.prev = entry.prev
|
||||
if entry.prev != nil: entry.prev.next = entry.next
|
||||
entry.prev = nil
|
||||
entry.next = list.head
|
||||
list.head = entry
|
||||
|
||||
proc ExcludeStr*(list: var TLinkedList, data: string) =
|
||||
var it = list.head
|
||||
|
|
|
|||
|
|
@ -436,7 +436,14 @@ type
|
|||
# only 8 bytes.
|
||||
line*, col*: int16
|
||||
fileIndex*: int32
|
||||
|
||||
|
||||
TErrorOutput* = enum
|
||||
eStdOut
|
||||
eStdErr
|
||||
eInMemory
|
||||
|
||||
TErrorOutputs* = set[TErrorOutput]
|
||||
|
||||
ERecoverableError* = object of EInvalidValue
|
||||
ESuggestDone* = object of EBase
|
||||
|
||||
|
|
@ -534,13 +541,27 @@ var
|
|||
gHintCounter*: int = 0
|
||||
gWarnCounter*: int = 0
|
||||
gErrorMax*: int = 1 # stop after gErrorMax errors
|
||||
gSilence*: int # == 0 if we produce any output at all
|
||||
|
||||
when useCaas:
|
||||
var stdoutSocket*: TSocket
|
||||
|
||||
proc UnknownLineInfo*(): TLineInfo =
|
||||
result.line = int16(-1)
|
||||
result.col = int16(-1)
|
||||
result.fileIndex = -1
|
||||
|
||||
var
|
||||
msgContext: seq[TLineInfo] = @[]
|
||||
lastError = UnknownLineInfo()
|
||||
bufferedMsgs*: seq[string]
|
||||
|
||||
errorOutputs* = {eStdOut, eStdErr}
|
||||
|
||||
proc clearBufferedMsgs* =
|
||||
bufferedMsgs = nil
|
||||
|
||||
proc SuggestWriteln*(s: string) =
|
||||
if gSilence == 0:
|
||||
if eStdOut in errorOutputs:
|
||||
when useCaas:
|
||||
if isNil(stdoutSocket): Writeln(stdout, s)
|
||||
else:
|
||||
|
|
@ -548,6 +569,9 @@ proc SuggestWriteln*(s: string) =
|
|||
stdoutSocket.send(s & "\c\L")
|
||||
else:
|
||||
Writeln(stdout, s)
|
||||
|
||||
if eInMemory in errorOutputs:
|
||||
bufferedMsgs.safeAdd(s)
|
||||
|
||||
proc SuggestQuit*() =
|
||||
if not isServing:
|
||||
|
|
@ -570,14 +594,6 @@ const
|
|||
RawWarningFormat* = "Warning: $1"
|
||||
RawHintFormat* = "Hint: $1"
|
||||
|
||||
proc UnknownLineInfo*(): TLineInfo =
|
||||
result.line = int16(-1)
|
||||
result.col = int16(-1)
|
||||
result.fileIndex = -1
|
||||
|
||||
var
|
||||
msgContext: seq[TLineInfo] = @[]
|
||||
|
||||
proc getInfoContextLen*(): int = return msgContext.len
|
||||
proc setInfoContextLen*(L: int) = setLen(msgContext, L)
|
||||
|
||||
|
|
@ -642,14 +658,18 @@ proc addCheckpoint*(filename: string, line: int) =
|
|||
|
||||
proc OutWriteln*(s: string) =
|
||||
## Writes to stdout. Always.
|
||||
if gSilence == 0: Writeln(stdout, s)
|
||||
if eStdOut in errorOutputs: Writeln(stdout, s)
|
||||
|
||||
proc MsgWriteln*(s: string) =
|
||||
## Writes to stdout. If --stdout option is given, writes to stderr instead.
|
||||
if gSilence == 0:
|
||||
if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
|
||||
if optStdout in gGlobalOptions: Writeln(stderr, s)
|
||||
else: Writeln(stdout, s)
|
||||
if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
|
||||
|
||||
if optStdout in gGlobalOptions:
|
||||
if eStdErr in errorOutputs: Writeln(stderr, s)
|
||||
else:
|
||||
if eStdOut in errorOutputs: Writeln(stdout, s)
|
||||
|
||||
if eInMemory in errorOutputs: bufferedMsgs.safeAdd(s)
|
||||
|
||||
proc coordToStr(coord: int): string =
|
||||
if coord == -1: result = "???"
|
||||
|
|
@ -736,9 +756,6 @@ proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
|
|||
proc rawMessage*(msg: TMsgKind, arg: string) =
|
||||
rawMessage(msg, [arg])
|
||||
|
||||
var
|
||||
lastError = UnknownLineInfo()
|
||||
|
||||
proc writeSurroundingSrc(info: TLineInfo) =
|
||||
const indent = " "
|
||||
MsgWriteln(indent & info.sourceLine.ropeToStr)
|
||||
|
|
|
|||
|
|
@ -243,11 +243,6 @@ proc LoadConfigs*(cfg: string) =
|
|||
readConfigFile(pd / cfg)
|
||||
|
||||
if gProjectName.len != 0:
|
||||
var conffile = changeFileExt(gProjectFull, "cfg")
|
||||
if conffile != pd / cfg and existsFile(conffile):
|
||||
readConfigFile(conffile)
|
||||
rawMessage(warnConfigDeprecated, conffile)
|
||||
|
||||
# new project wide config file:
|
||||
readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg"))
|
||||
|
||||
|
|
|
|||
|
|
@ -1624,10 +1624,23 @@ proc parseObject(p: var TParser): PNode =
|
|||
return
|
||||
addSon(result, parseObjectPart(p))
|
||||
|
||||
proc parseTypeClassParam(p: var TParser): PNode =
|
||||
if p.tok.tokType == tkVar:
|
||||
getTok(p)
|
||||
result = newNode(nkVarTy)
|
||||
result.addSon(p.parseSymbol)
|
||||
else:
|
||||
result = p.parseSymbol
|
||||
|
||||
proc parseTypeClass(p: var TParser): PNode =
|
||||
result = newNodeP(nkTypeClassTy, p)
|
||||
getTok(p)
|
||||
addSon(result, p.parseSymbol)
|
||||
var args = newNode(nkArgList)
|
||||
addSon(result, args)
|
||||
addSon(args, p.parseTypeClassParam)
|
||||
while p.tok.TokType == tkComma:
|
||||
getTok(p)
|
||||
addSon(args, p.parseTypeClassParam)
|
||||
if p.tok.tokType == tkCurlyDotLe and p.validInd:
|
||||
addSon(result, parsePragma(p))
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym)
|
|||
proc addParams(c: PContext, n: PNode, kind: TSymKind)
|
||||
proc maybeAddResult(c: PContext, s: PSym, n: PNode)
|
||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
||||
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc tryExpr(c: PContext, n: PNode,
|
||||
flags: TExprFlags = {}, bufferErrors = false): PNode
|
||||
proc fixImmediateParams(n: PNode): PNode
|
||||
proc activate(c: PContext, n: PNode)
|
||||
proc semQuoteAst(c: PContext, n: PNode): PNode
|
||||
|
|
@ -89,6 +90,24 @@ proc commonType*(x, y: PType): PType =
|
|||
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
||||
if a.sons[idx].kind == tyEmpty: return y
|
||||
#elif b.sons[idx].kind == tyEmpty: return x
|
||||
elif a.kind == tyRange and b.kind == tyRange:
|
||||
# consider: (range[0..3], range[0..4]) here. We should make that
|
||||
# range[0..4]. But then why is (range[0..4], 6) not range[0..6]?
|
||||
# But then why is (2,4) not range[2..4]? But I think this would break
|
||||
# too much code. So ... it's the same range or the base type. This means
|
||||
# type(if b: 0 else 1) == int and not range[0..1]. For now. In the long
|
||||
# run people expect ranges to work properly within a tuple.
|
||||
if not sameType(a, b):
|
||||
result = skipTypes(a, {tyRange}).skipIntLit
|
||||
when false:
|
||||
if a.kind != tyRange and b.kind == tyRange:
|
||||
# XXX This really needs a better solution, but a proper fix now breaks
|
||||
# code.
|
||||
result = a #.skipIntLit
|
||||
elif a.kind == tyRange and b.kind != tyRange:
|
||||
result = b #.skipIntLit
|
||||
elif a.kind in IntegralTypes and a.n != nil:
|
||||
result = a #.skipIntLit
|
||||
else:
|
||||
var k = tyNone
|
||||
if a.kind in {tyRef, tyPtr}:
|
||||
|
|
@ -102,7 +121,7 @@ proc commonType*(x, y: PType): PType =
|
|||
if result.isNil: return x
|
||||
if k != tyNone:
|
||||
let r = result
|
||||
result = NewType(k, r.owner)
|
||||
result = newType(k, r.owner)
|
||||
result.addSonSkipIntLit(r)
|
||||
|
||||
proc isTopLevel(c: PContext): bool {.inline.} =
|
||||
|
|
@ -139,27 +158,28 @@ proc IsOpImpl(c: PContext, n: PNode): PNode
|
|||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode
|
||||
|
||||
proc symFromType(t: PType, info: TLineInfo): PSym =
|
||||
if t.sym != nil: return t.sym
|
||||
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
||||
result.flags.incl sfAnon
|
||||
result.typ = t
|
||||
when false:
|
||||
proc symFromType(t: PType, info: TLineInfo): PSym =
|
||||
if t.sym != nil: return t.sym
|
||||
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
||||
result.flags.incl sfAnon
|
||||
result.typ = t
|
||||
|
||||
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||
result = newSymNode(symFromType(t, info), info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||
result = newSymNode(symFromType(t, info), info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
|
||||
when false:
|
||||
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
|
||||
result = newEvalContext(c.module, mode)
|
||||
result.getType = proc (n: PNode): PNode =
|
||||
var e = tryExpr(c, n)
|
||||
if e == nil:
|
||||
result = symNodeFromType(c, errorType(c), n.info)
|
||||
elif e.typ == nil:
|
||||
result = tryExpr(c, n)
|
||||
if result == nil:
|
||||
result = newSymNode(errorSym(c, n))
|
||||
elif result.typ == nil:
|
||||
result = newSymNode(getSysSym"void")
|
||||
else:
|
||||
result = symNodeFromType(c, e.typ, n.info)
|
||||
result.typ = makeTypeDesc(c, result.typ)
|
||||
|
||||
result.handleIsOperator = proc (n: PNode): PNode =
|
||||
result = IsOpImpl(c, n)
|
||||
|
|
@ -215,7 +235,8 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
|||
of tyTypeDesc:
|
||||
if n.kind == nkStmtList: result.kind = nkStmtListType
|
||||
var typ = semTypeNode(c, result, nil)
|
||||
result = symNodeFromType(c, typ, n.info)
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
else:
|
||||
result = semExpr(c, result)
|
||||
result = fitNode(c, s.typ.sons[0], result)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ type
|
|||
threadEntries*: TSymSeq # list of thread entries to check
|
||||
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
|
||||
# store this info in the syms themselves!)
|
||||
InTypeClass*: int # > 0 if we are in a user-defined type class
|
||||
InGenericContext*: int # > 0 if we are in a generic type
|
||||
InUnrolledContext*: int # > 0 if we are unrolling a loop
|
||||
InCompilesContext*: int # > 0 if we are in a ``compiles`` magic
|
||||
|
|
@ -72,7 +73,8 @@ type
|
|||
libs*: TLinkedList # all libs used by this module
|
||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {},
|
||||
bufferErrors = false): PNode {.nimcall.}
|
||||
semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
||||
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ proc isCastable(dst, src: PType): bool =
|
|||
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||
result = n.kind in nkSymChoices
|
||||
|
||||
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc semConv(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) != 2:
|
||||
LocalError(n.info, errConvNeedsOneArg)
|
||||
return n
|
||||
|
|
@ -299,7 +299,7 @@ proc semOf(c: PContext, n: PNode): PNode =
|
|||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc IsOpImpl(c: PContext, n: PNode): PNode =
|
||||
proc isOpImpl(c: PContext, n: PNode): PNode =
|
||||
InternalAssert n.sonsLen == 3 and
|
||||
n[1].kind == nkSym and n[1].sym.kind == skType and
|
||||
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||
|
|
@ -321,10 +321,19 @@ proc IsOpImpl(c: PContext, n: PNode): PNode =
|
|||
else:
|
||||
var match: bool
|
||||
let t2 = n[2].typ
|
||||
if t2.kind == tyTypeClass:
|
||||
case t2.kind
|
||||
of tyTypeClass:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
match = matchUserTypeClass(c, m, emptyNode, t2, t1) != nil
|
||||
of tyOrdinal:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
match = isOrdinalType(t1)
|
||||
of tySequence, tyArray, tySet:
|
||||
var m: TCandidate
|
||||
InitCandidate(m, t2)
|
||||
match = typeRel(m, t2, t1) != isNone
|
||||
else:
|
||||
match = sameType(t1, t2)
|
||||
|
||||
|
|
@ -353,7 +362,7 @@ proc semIs(c: PContext, n: PNode): PNode =
|
|||
|
||||
let t1 = n[1].typ.sons[0]
|
||||
# BUGFIX: don't evaluate this too early: ``T is void``
|
||||
if not containsGenericType(t1): result = IsOpImpl(c, n)
|
||||
if not containsGenericType(t1): result = isOpImpl(c, n)
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
const flags = {efDetermineType}
|
||||
|
|
@ -729,8 +738,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
elif t != nil and t.kind == tyTypeDesc:
|
||||
if n.len == 1: return semObjConstr(c, n, flags)
|
||||
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
||||
result = semConv(c, n, symFromType(destType, n.info))
|
||||
return
|
||||
return semConv(c, n)
|
||||
else:
|
||||
result = overloadedCallOpr(c, n)
|
||||
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
||||
|
|
@ -763,7 +771,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
|||
analyseIfAddressTakenInCall(c, result)
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
result = evalAtCompileTime(c, result)
|
||||
if c.InTypeClass == 0:
|
||||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# this seems to be a hotspot in the compiler!
|
||||
|
|
@ -814,7 +823,7 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
|
|||
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, n, {efWantStmt})
|
||||
discardCheck(result)
|
||||
discardCheck(c, result)
|
||||
|
||||
proc isTypeExpr(n: PNode): bool =
|
||||
case n.kind
|
||||
|
|
@ -1038,7 +1047,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
# The result so far is a tyTypeDesc bound
|
||||
# a tyGenericBody. The line below will substitute
|
||||
# it with the instantiated type.
|
||||
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
result = n
|
||||
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||
#result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
of tyTuple:
|
||||
checkSonsLen(n, 2)
|
||||
n.sons[0] = makeDeref(n.sons[0])
|
||||
|
|
@ -1208,7 +1219,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
|||
a.sons[1] = result
|
||||
result = semAsgn(c, a)
|
||||
else:
|
||||
discardCheck(result)
|
||||
discardCheck(c, result)
|
||||
closeScope(c)
|
||||
|
||||
proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||
|
|
@ -1429,12 +1440,12 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
|
|||
newNode(nkCall, n.info, quotes)])
|
||||
result = semExpandToAst(c, result)
|
||||
|
||||
proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
proc tryExpr(c: PContext, n: PNode,
|
||||
flags: TExprFlags = {}, bufferErrors = false): PNode =
|
||||
# watch out, hacks ahead:
|
||||
let oldErrorCount = msgs.gErrorCounter
|
||||
let oldErrorMax = msgs.gErrorMax
|
||||
inc c.InCompilesContext
|
||||
inc msgs.gSilence
|
||||
# do not halt after first error:
|
||||
msgs.gErrorMax = high(int)
|
||||
|
||||
|
|
@ -1443,6 +1454,8 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
openScope(c)
|
||||
let oldOwnerLen = len(gOwners)
|
||||
let oldGenerics = c.generics
|
||||
let oldErrorOutputs = errorOutputs
|
||||
errorOutputs = if bufferErrors: {eInMemory} else: {}
|
||||
let oldContextLen = msgs.getInfoContextLen()
|
||||
|
||||
let oldInGenericContext = c.InGenericContext
|
||||
|
|
@ -1465,7 +1478,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
setlen(gOwners, oldOwnerLen)
|
||||
c.currentScope = oldScope
|
||||
dec c.InCompilesContext
|
||||
dec msgs.gSilence
|
||||
errorOutputs = oldErrorOutputs
|
||||
msgs.gErrorCounter = oldErrorCount
|
||||
msgs.gErrorMax = oldErrorMax
|
||||
|
||||
|
|
@ -1871,7 +1884,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
result = semExpr(c, n.sons[0], flags)
|
||||
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result = symNodeFromType(c, typ, n.info)
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
# check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1)
|
||||
|
|
@ -1894,7 +1908,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of skType:
|
||||
# XXX think about this more (``set`` procs)
|
||||
if n.len == 2:
|
||||
result = semConv(c, n, s)
|
||||
result = semConv(c, n)
|
||||
elif n.len == 1:
|
||||
result = semObjConstr(c, n, flags)
|
||||
elif Contains(c.AmbiguousSymbols, s.id):
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ proc fixNilType(n: PNode) =
|
|||
for it in n: fixNilType(it)
|
||||
n.typ = nil
|
||||
|
||||
proc discardCheck(result: PNode) =
|
||||
proc discardCheck(c: PContext, result: PNode) =
|
||||
if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
|
||||
if result.kind == nkNilLit:
|
||||
result.typ = nil
|
||||
|
|
@ -142,6 +142,10 @@ proc discardCheck(result: PNode) =
|
|||
while n.kind in skipForDiscardable:
|
||||
n = n.lastSon
|
||||
n.typ = nil
|
||||
elif c.InTypeClass > 0 and result.typ.kind == tyBool:
|
||||
let verdict = semConstExpr(c, result)
|
||||
if verdict.intVal == 0:
|
||||
localError(result.info, "type class predicate failed.")
|
||||
elif result.typ.kind != tyError and gCmd != cmdInteractive:
|
||||
if result.typ.kind == tyNil:
|
||||
fixNilType(result)
|
||||
|
|
@ -169,7 +173,7 @@ proc semIf(c: PContext, n: PNode): PNode =
|
|||
typ = commonType(typ, it.sons[0].typ)
|
||||
else: illFormedAst(it)
|
||||
if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
|
||||
for it in n: discardCheck(it.lastSon)
|
||||
for it in n: discardCheck(c, it.lastSon)
|
||||
result.kind = nkIfStmt
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == EnforceVoidContext: result.typ = EnforceVoidContext
|
||||
|
|
@ -230,7 +234,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
|||
localError(n.info, errNotAllCasesCovered)
|
||||
closeScope(c)
|
||||
if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
|
||||
for i in 1..n.len-1: discardCheck(n.sons[i].lastSon)
|
||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == EnforceVoidContext:
|
||||
result.typ = EnforceVoidContext
|
||||
|
|
@ -275,8 +279,8 @@ proc semTry(c: PContext, n: PNode): PNode =
|
|||
typ = commonType(typ, a.sons[length-1].typ)
|
||||
dec c.p.inTryStmt
|
||||
if isEmptyType(typ) or typ.kind == tyNil:
|
||||
discardCheck(n.sons[0])
|
||||
for i in 1..n.len-1: discardCheck(n.sons[i].lastSon)
|
||||
discardCheck(c, n.sons[0])
|
||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
|
||||
if typ == EnforceVoidContext:
|
||||
result.typ = EnforceVoidContext
|
||||
else:
|
||||
|
|
@ -881,8 +885,9 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
openScope(c)
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
illFormedAst(n) # process parameters:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[ParamsPos], nil, s)
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
var gp = newNodeI(nkGenericParams, n.info)
|
||||
semParamList(c, n.sons[ParamsPos], gp, s)
|
||||
ParamsTypeCheck(c, s.typ)
|
||||
else:
|
||||
s.typ = newTypeS(tyProc, c)
|
||||
|
|
@ -1084,6 +1089,8 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
|||
# -- at least for 0.9.2.
|
||||
if s.typ.callConv == ccClosure:
|
||||
incl(s.typ.flags, tfCapturesEnv)
|
||||
else:
|
||||
s.typ.callConv = ccInline
|
||||
when false:
|
||||
if s.typ.callConv != ccInline:
|
||||
s.typ.callConv = ccClosure
|
||||
|
|
@ -1106,24 +1113,24 @@ proc finishMethod(c: PContext, s: PSym) =
|
|||
methodDef(s, false)
|
||||
|
||||
proc semMethod(c: PContext, n: PNode): PNode =
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
|
||||
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
|
||||
result = semProcAux(c, n, skMethod, methodPragmas)
|
||||
|
||||
var s = result.sons[namePos].sym
|
||||
if not isGenericRoutine(s):
|
||||
if not isGenericRoutine(s) and result.sons[bodyPos].kind != nkEmpty:
|
||||
if hasObjParam(s):
|
||||
methodDef(s, false)
|
||||
methodDef(s, fromCache=false)
|
||||
else:
|
||||
LocalError(n.info, errXNeedsParamObjectType, "method")
|
||||
localError(n.info, errXNeedsParamObjectType, "method")
|
||||
|
||||
proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
|
||||
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter")
|
||||
checkSonsLen(n, bodyPos + 1)
|
||||
result = semProcAux(c, n, skConverter, converterPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
|
||||
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
|
||||
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "converter")
|
||||
if sonsLen(t) != 2: localError(n.info, errXRequiresOneArgument, "converter")
|
||||
addConverter(c, s)
|
||||
|
||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
|
|
@ -1131,9 +1138,9 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
|
|||
result = semProcAux(c, n, skMacro, macroPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
|
||||
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "macro")
|
||||
if n.sons[bodyPos].kind == nkEmpty:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
localError(n.info, errImplOfXexpected, s.name.s)
|
||||
|
||||
proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
|
@ -1223,7 +1230,7 @@ proc semStmtList(c: PContext, n: PNode): PNode =
|
|||
voidContext = true
|
||||
n.typ = EnforceVoidContext
|
||||
if i != last or voidContext:
|
||||
discardCheck(n.sons[i])
|
||||
discardCheck(c, n.sons[i])
|
||||
else:
|
||||
n.typ = n.sons[i].typ
|
||||
if not isEmptyType(n.typ):
|
||||
|
|
|
|||
|
|
@ -876,8 +876,7 @@ proc freshType(res, prev: PType): PType {.inline.} =
|
|||
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
|
||||
result = newOrPrevType(tyTypeClass, prev, c)
|
||||
result.testeeName = considerAcc(n[0])
|
||||
result.n = n[3]
|
||||
result.n = n
|
||||
|
||||
let
|
||||
pragmas = n[1]
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
|
|||
c.calleeSym = callee
|
||||
c.calleeScope = calleeScope
|
||||
initIdTable(c.bindings)
|
||||
c.errors = nil
|
||||
if binding != nil and callee.kind in RoutineKinds:
|
||||
var typeParams = callee.ast[genericParamsPos]
|
||||
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
|
||||
|
|
@ -202,7 +203,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
|
|||
add(result, argTypeToString(arg))
|
||||
if i != sonsLen(n) - 1: add(result, ", ")
|
||||
|
||||
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
|
||||
proc typeRel*(c: var TCandidate, f, a: PType): TTypeRelation
|
||||
proc concreteType(c: TCandidate, t: PType): PType =
|
||||
case t.kind
|
||||
of tyArrayConstr:
|
||||
|
|
@ -750,40 +751,55 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
|||
|
||||
# pushInfoContext(arg.info)
|
||||
openScope(c)
|
||||
inc c.InTypeClass
|
||||
|
||||
var testee = newSym(skParam, f.testeeName, f.sym, f.sym.info)
|
||||
testee.typ = a
|
||||
addDecl(c, testee)
|
||||
finally:
|
||||
dec c.InTypeClass
|
||||
closeScope(c)
|
||||
|
||||
for param in f.n[0]:
|
||||
var
|
||||
dummyName: PNode
|
||||
dummyType: PType
|
||||
|
||||
if param.kind == nkVarTy:
|
||||
dummyName = param[0]
|
||||
dummyType = makeVarType(c, a)
|
||||
else:
|
||||
dummyName = param
|
||||
dummyType = a
|
||||
|
||||
InternalAssert dummyName.kind == nkIdent
|
||||
var dummyParam = newSym(skType, dummyName.ident, f.sym, f.sym.info)
|
||||
dummyParam.typ = dummyType
|
||||
addDecl(c, dummyParam)
|
||||
|
||||
for stmt in f.n[3]:
|
||||
var e = c.semTryExpr(c, copyTree(stmt), bufferErrors = false)
|
||||
m.errors = bufferedMsgs
|
||||
clearBufferedMsgs()
|
||||
if e == nil: return nil
|
||||
|
||||
for stmt in f.n:
|
||||
var e = c.semTryExpr(c, copyTree(stmt))
|
||||
if e == nil:
|
||||
let expStr = renderTree(stmt, {renderNoComments})
|
||||
m.errors.safeAdd("can't compile " & expStr & " for " & a.typeToString)
|
||||
return nil
|
||||
case e.kind
|
||||
of nkReturnStmt:
|
||||
nil
|
||||
of nkReturnStmt: nil
|
||||
of nkTypeSection: nil
|
||||
of nkConstDef: nil
|
||||
else:
|
||||
if e.typ.kind == tyBool:
|
||||
let verdict = c.semConstExpr(c, e)
|
||||
if verdict.intVal == 0:
|
||||
let expStr = renderTree(stmt, {renderNoComments})
|
||||
m.errors.safeAdd(expStr & " doesn't hold for " & a.typeToString)
|
||||
return nil
|
||||
|
||||
closeScope(c)
|
||||
|
||||
else: nil
|
||||
|
||||
result = arg
|
||||
put(m.bindings, f, a)
|
||||
|
||||
proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||
proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, argType: PType,
|
||||
argSemantized, argOrig: PNode): PNode =
|
||||
var arg = argSemantized
|
||||
var r: TTypeRelation
|
||||
let fMaybeExpr = f.skipTypes({tyDistinct})
|
||||
var
|
||||
r: TTypeRelation
|
||||
arg = argSemantized
|
||||
|
||||
let
|
||||
a = if c.InTypeClass > 0: argType.skipTypes({tyTypeDesc})
|
||||
else: argType
|
||||
fMaybeExpr = f.skipTypes({tyDistinct})
|
||||
|
||||
case fMaybeExpr.kind
|
||||
of tyExpr:
|
||||
if fMaybeExpr.sonsLen == 0:
|
||||
|
|
|
|||
|
|
@ -621,7 +621,7 @@ type
|
|||
proc initSameTypeClosure: TSameTypeClosure =
|
||||
# we do the initialization lazily for performance (avoids memory allocations)
|
||||
nil
|
||||
|
||||
|
||||
proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
|
||||
result = not IsNil(c.s) and c.s.contains((a.id, b.id))
|
||||
if not result:
|
||||
|
|
@ -750,9 +750,9 @@ template IfFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
|
|||
|
||||
proc sameObjectTypes*(a, b: PType): bool =
|
||||
# specialized for efficiency (sigmatch uses it)
|
||||
IfFastObjectTypeCheckFailed(a, b):
|
||||
IfFastObjectTypeCheckFailed(a, b):
|
||||
var c = initSameTypeClosure()
|
||||
result = sameTypeAux(a, b, c)
|
||||
result = sameTypeAux(a, b, c)
|
||||
|
||||
proc sameDistinctTypes*(a, b: PType): bool {.inline.} =
|
||||
result = sameObjectTypes(a, b)
|
||||
|
|
@ -808,11 +808,11 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
if containsOrIncl(c, a, b): return true
|
||||
|
||||
proc sameFlags(a, b: PType): bool {.inline.} =
|
||||
result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
|
||||
|
||||
result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
|
||||
|
||||
if x == y: return true
|
||||
var a = skipTypes(x, {tyGenericInst})
|
||||
var b = skipTypes(y, {tyGenericInst})
|
||||
var b = skipTypes(y, {tyGenericInst})
|
||||
assert(a != nil)
|
||||
assert(b != nil)
|
||||
if a.kind != b.kind:
|
||||
|
|
@ -824,7 +824,7 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
if a.kind != b.kind: return false
|
||||
of dcEqOrDistinctOf:
|
||||
while a.kind == tyDistinct: a = a.sons[0]
|
||||
if a.kind != b.kind: return false
|
||||
if a.kind != b.kind: return false
|
||||
case a.Kind
|
||||
of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
|
||||
tyInt..tyBigNum, tyStmt:
|
||||
|
|
@ -837,15 +837,19 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
result = sameObjectStructures(a, b, c) and sameFlags(a, b)
|
||||
of tyDistinct:
|
||||
CycleCheck()
|
||||
if c.cmp == dcEq: result = sameDistinctTypes(a, b) and sameFlags(a, b)
|
||||
else: result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
|
||||
if c.cmp == dcEq:
|
||||
if sameFlags(a, b):
|
||||
IfFastObjectTypeCheckFailed(a, b):
|
||||
result = sameTypeAux(a.sons[0], b.sons[0], c)
|
||||
else:
|
||||
result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
|
||||
of tyEnum, tyForward, tyProxy:
|
||||
# XXX generic enums do not make much sense, but require structural checking
|
||||
result = a.id == b.id and sameFlags(a, b)
|
||||
of tyTuple:
|
||||
CycleCheck()
|
||||
result = sameTuple(a, b, c) and sameFlags(a, b)
|
||||
of tyGenericInst:
|
||||
of tyGenericInst:
|
||||
result = sameTypeAux(lastSon(a), lastSon(b), c)
|
||||
of tyTypeDesc:
|
||||
if c.cmp == dcEqIgnoreDistinct: result = false
|
||||
|
|
@ -858,7 +862,7 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
|
||||
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
|
||||
tyOrdinal, tyTypeClass:
|
||||
CycleCheck()
|
||||
CycleCheck()
|
||||
result = sameChildrenAux(a, b, c) and sameFlags(a, b)
|
||||
if result and (a.kind == tyProc):
|
||||
result = a.callConv == b.callConv
|
||||
|
|
@ -867,7 +871,7 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||
result = SameTypeOrNilAux(a.sons[0], b.sons[0], c) 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 sameType*(x, y: PType): bool =
|
||||
var c = initSameTypeClosure()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue