fixes testament compilation
This commit is contained in:
commit
5526252fa0
41 changed files with 985 additions and 297 deletions
|
|
@ -1620,6 +1620,19 @@ proc originatingModule*(s: PSym): PSym =
|
|||
proc isRoutine*(s: PSym): bool {.inline.} =
|
||||
result = s.kind in skProcKinds
|
||||
|
||||
proc isCompileTimeProc*(s: PSym): bool {.inline.} =
|
||||
result = s.kind == skMacro or
|
||||
s.kind == skProc and sfCompileTime in s.flags
|
||||
|
||||
proc requiredParams*(s: PSym): int =
|
||||
# Returns the number of required params (without default values)
|
||||
# XXX: Perhaps we can store this in the `offset` field of the
|
||||
# symbol instead?
|
||||
for i in 1 ..< s.typ.len:
|
||||
if s.typ.n[i].sym.ast != nil:
|
||||
return i - 1
|
||||
return s.typ.len - 1
|
||||
|
||||
proc hasPattern*(s: PSym): bool {.inline.} =
|
||||
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
|
||||
|
||||
|
|
@ -1676,7 +1689,7 @@ proc isException*(t: PType): bool =
|
|||
|
||||
var base = t
|
||||
while base != nil:
|
||||
if base.sym.magic == mException:
|
||||
if base.sym != nil and base.sym.magic == mException:
|
||||
return true
|
||||
base = base.lastSon
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -69,22 +69,22 @@ proc debug*(n: PNode) {.deprecated.}
|
|||
|
||||
template mdbg*: bool {.dirty.} =
|
||||
when compiles(c.module):
|
||||
c.module.fileIdx == gProjectMainIdx
|
||||
c.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(c.c.module):
|
||||
c.c.module.fileIdx == gProjectMainIdx
|
||||
c.c.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(m.c.module):
|
||||
m.c.module.fileIdx == gProjectMainIdx
|
||||
m.c.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(cl.c.module):
|
||||
cl.c.module.fileIdx == gProjectMainIdx
|
||||
cl.c.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(p):
|
||||
when compiles(p.lex):
|
||||
p.lex.fileIdx == gProjectMainIdx
|
||||
p.lex.fileIdx.int32 == gProjectMainIdx
|
||||
else:
|
||||
p.module.module.fileIdx == gProjectMainIdx
|
||||
p.module.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(m.module.fileIdx):
|
||||
m.module.fileIdx == gProjectMainIdx
|
||||
m.module.fileIdx.int32 == gProjectMainIdx
|
||||
elif compiles(L.fileIdx):
|
||||
L.fileIdx == gProjectMainIdx
|
||||
L.fileIdx.int32 == gProjectMainIdx
|
||||
else:
|
||||
error()
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
|
|||
# if the template has zero arguments, it can be called without ``()``
|
||||
# `n` is then a nkSym or something similar
|
||||
var totalParams = case n.kind
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: n.len-1
|
||||
of nkCallKinds: n.len-1
|
||||
else: 0
|
||||
|
||||
var
|
||||
|
|
|
|||
|
|
@ -70,9 +70,9 @@ proc parseLine(p: var TTmplParser) =
|
|||
|
||||
while j <= hi and p.x[j] == ' ': inc(j)
|
||||
|
||||
if p.x[0] == p.nimDirective and p.x[1] == '?':
|
||||
if p.x.len >= 2 and p.x[0] == p.nimDirective and p.x[1] == '?':
|
||||
newLine(p)
|
||||
elif p.x[j] == p.nimDirective:
|
||||
elif j < p.x.len and p.x[j] == p.nimDirective:
|
||||
newLine(p)
|
||||
inc(j)
|
||||
while j <= hi and p.x[j] == ' ': inc(j)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ import
|
|||
proc evalImport*(c: PContext, n: PNode): PNode
|
||||
proc evalFrom*(c: PContext, n: PNode): PNode
|
||||
|
||||
proc readExceptSet*(c: PContext, n: PNode): IntSet =
|
||||
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
|
||||
result = initIntSet()
|
||||
for i in 1 ..< n.len:
|
||||
let ident = lookups.considerQuotedIdent(c.config, n[i])
|
||||
result.incl(ident.id)
|
||||
|
||||
proc importPureEnumField*(c: PContext; s: PSym) =
|
||||
var check = strTableGet(c.importTable.symbols, s.name)
|
||||
if check == nil:
|
||||
|
|
@ -199,9 +206,5 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
|
|||
if m != nil:
|
||||
n.sons[0] = newSymNode(m)
|
||||
addDecl(c, m, n.info) # add symbol to symbol table of module
|
||||
var exceptSet = initIntSet()
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
let ident = lookups.considerQuotedIdent(c.config, n.sons[i])
|
||||
exceptSet.incl(ident.id)
|
||||
importAllSymbolsExcept(c, m, exceptSet)
|
||||
importAllSymbolsExcept(c, m, readExceptSet(c, n))
|
||||
#importForwarded(c, m.ast, exceptSet)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; cache: IdentCache, f
|
|||
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex;
|
||||
cache: IdentCache): PSym {.procvar.} =
|
||||
# this is called by the semantic checking phase
|
||||
assert graph.config != nil
|
||||
result = compileModule(graph, fileIdx, cache, {})
|
||||
graph.addDep(s, fileIdx)
|
||||
#if sfSystemModule in result.flags:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#
|
||||
|
||||
import strutils, lexbase, streams
|
||||
import "../compiler" / [ast, msgs, idents]
|
||||
import ".." / [ast, msgs, idents]
|
||||
from os import splitFile
|
||||
|
||||
type
|
||||
|
|
|
|||
|
|
@ -713,10 +713,17 @@ proc namedParams(p: var TParser, callee: PNode,
|
|||
# progress guaranteed
|
||||
exprColonEqExprListAux(p, endTok, result)
|
||||
|
||||
proc commandParam(p: var TParser): PNode =
|
||||
proc commandParam(p: var TParser, isFirstParam: var bool): PNode =
|
||||
result = parseExpr(p)
|
||||
if p.tok.tokType == tkDo:
|
||||
result = postExprBlocks(p, result)
|
||||
elif p.tok.tokType == tkEquals and not isFirstParam:
|
||||
let lhs = result
|
||||
result = newNodeP(nkExprEqExpr, p)
|
||||
getTok(p)
|
||||
addSon(result, lhs)
|
||||
addSon(result, parseExpr(p))
|
||||
isFirstParam = false
|
||||
|
||||
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||
|
|
@ -759,10 +766,11 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
|
|||
let a = result
|
||||
result = newNodeP(nkCommand, p)
|
||||
addSon(result, a)
|
||||
var isFirstParam = true
|
||||
when true:
|
||||
# progress NOT guaranteed
|
||||
p.hasProgress = false
|
||||
addSon result, commandParam(p)
|
||||
addSon result, commandParam(p, isFirstParam)
|
||||
if not p.hasProgress: break
|
||||
else:
|
||||
while p.tok.tokType != tkEof:
|
||||
|
|
@ -1314,17 +1322,18 @@ proc parseExprStmt(p: var TParser): PNode =
|
|||
addSon(result, b)
|
||||
else:
|
||||
# simpleExpr parsed 'p a' from 'p a, b'?
|
||||
var isFirstParam = false
|
||||
if p.tok.indent < 0 and p.tok.tokType == tkComma and a.kind == nkCommand:
|
||||
result = a
|
||||
while true:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
addSon(result, commandParam(p))
|
||||
addSon(result, commandParam(p, isFirstParam))
|
||||
if p.tok.tokType != tkComma: break
|
||||
elif p.tok.indent < 0 and isExprStart(p):
|
||||
result = newNode(nkCommand, a.info, @[a])
|
||||
while true:
|
||||
addSon(result, commandParam(p))
|
||||
addSon(result, commandParam(p, isFirstParam))
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
|
|
|
|||
|
|
@ -781,7 +781,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
|||
incl(sym.flags, sfRegister)
|
||||
of wThreadVar:
|
||||
noVal(c, it)
|
||||
incl(sym.flags, sfThread)
|
||||
incl(sym.flags, {sfThread, sfGlobal})
|
||||
of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
|
||||
of wNoForward: pragmaNoForward(c, it)
|
||||
of wReorder: pragmaNoForward(c, it, sfReorder)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ type
|
|||
ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
|
||||
# store this info in the syms themselves!)
|
||||
inGenericContext*: int # > 0 if we are in a generic type
|
||||
inStaticContext*: int # > 0 if we are inside a static: block
|
||||
inUnrolledContext*: int # > 0 if we are unrolling a loop
|
||||
compilesContextId*: int # > 0 if we are in a ``compiles`` magic
|
||||
compilesContextIdGenerator*: int
|
||||
|
|
|
|||
|
|
@ -972,18 +972,20 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
|||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
of skMacro:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0):
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
styleCheckUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
result = semMacroExpr(c, n, n, s, flags)
|
||||
of skTemplate:
|
||||
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0 or
|
||||
(n.kind notin nkCallKinds and s.requiredParams > 0) or
|
||||
sfCustomPragma in sym.flags:
|
||||
markUsed(c.config, n.info, s, c.graph.usageSym)
|
||||
styleCheckUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
else:
|
||||
result = semTemplateExpr(c, n, s, flags)
|
||||
of skParam:
|
||||
|
|
@ -1785,6 +1787,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
let oldInGenericContext = c.inGenericContext
|
||||
let oldInUnrolledContext = c.inUnrolledContext
|
||||
let oldInGenericInst = c.inGenericInst
|
||||
let oldInStaticContext = c.inStaticContext
|
||||
let oldProcCon = c.p
|
||||
c.generics = @[]
|
||||
var err: string
|
||||
|
|
@ -1799,6 +1802,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
c.inGenericContext = oldInGenericContext
|
||||
c.inUnrolledContext = oldInUnrolledContext
|
||||
c.inGenericInst = oldInGenericInst
|
||||
c.inStaticContext = oldInStaticContext
|
||||
c.p = oldProcCon
|
||||
msgs.setInfoContextLen(oldContextLen)
|
||||
setLen(c.graph.owners, oldOwnerLen)
|
||||
|
|
@ -2163,9 +2167,25 @@ proc semBlock(c: PContext, n: PNode): PNode =
|
|||
closeScope(c)
|
||||
dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semExportExcept(c: PContext, n: PNode): PNode =
|
||||
let moduleName = semExpr(c, n[0])
|
||||
if moduleName.kind != nkSym or moduleName.sym.kind != skModule:
|
||||
localError(c.config, n.info, "The export/except syntax expects a module name")
|
||||
return n
|
||||
let exceptSet = readExceptSet(c, n)
|
||||
let exported = moduleName.sym
|
||||
strTableAdd(c.module.tab, exported)
|
||||
var i: TTabIter
|
||||
var s = initTabIter(i, exported.tab)
|
||||
while s != nil:
|
||||
if s.kind in ExportableSymKinds+{skModule} and
|
||||
s.name.id notin exceptSet:
|
||||
strTableAdd(c.module.tab, s)
|
||||
s = nextIter(i, exported.tab)
|
||||
result = n
|
||||
|
||||
proc semExport(c: PContext, n: PNode): PNode =
|
||||
var x = newNodeI(n.kind, n.info)
|
||||
#let L = if n.kind == nkExportExceptStmt: L = 1 else: n.len
|
||||
for i in 0..<n.len:
|
||||
let a = n.sons[i]
|
||||
var o: TOverloadIter
|
||||
|
|
@ -2451,9 +2471,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
of nkIncludeStmt:
|
||||
#if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "include")
|
||||
result = evalInclude(c, n)
|
||||
of nkExportStmt, nkExportExceptStmt:
|
||||
of nkExportStmt:
|
||||
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "export")
|
||||
result = semExport(c, n)
|
||||
of nkExportExceptStmt:
|
||||
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "export")
|
||||
result = semExportExcept(c, n)
|
||||
of nkPragmaBlock:
|
||||
result = semPragmaBlock(c, n)
|
||||
of nkStaticStmt:
|
||||
|
|
|
|||
|
|
@ -199,6 +199,10 @@ proc semBindSym(c: PContext, n: PNode): PNode =
|
|||
if s != nil:
|
||||
# we need to mark all symbols:
|
||||
var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
|
||||
if not (c.inStaticContext > 0 or getCurrOwner(c).isCompileTimeProc):
|
||||
# inside regular code, bindSym resolves to the sym-choice
|
||||
# nodes (see tinspectsymbol)
|
||||
return sc
|
||||
result.add(sc)
|
||||
else:
|
||||
errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal)
|
||||
|
|
|
|||
|
|
@ -1765,7 +1765,9 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
|
|||
proc semStaticStmt(c: PContext, n: PNode): PNode =
|
||||
#echo "semStaticStmt"
|
||||
#writeStackTrace()
|
||||
inc c.inStaticContext
|
||||
let a = semStmt(c, n.sons[0])
|
||||
dec c.inStaticContext
|
||||
n.sons[0] = a
|
||||
evalStaticStmt(c.module, c.cache, c.graph, a, c.p.owner)
|
||||
result = newNodeI(nkDiscardStmt, n.info, 1)
|
||||
|
|
|
|||
|
|
@ -1964,7 +1964,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
|||
inc(m.genericMatches)
|
||||
if arg.typ == nil:
|
||||
result = arg
|
||||
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
|
||||
elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple or
|
||||
m.inheritancePenalty > 0:
|
||||
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
|
||||
elif arg.typ.isEmptyContainer:
|
||||
result = arg.copyTree
|
||||
|
|
@ -2034,8 +2035,9 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
|||
y.calleeSym = m.calleeSym
|
||||
z.calleeSym = m.calleeSym
|
||||
var best = -1
|
||||
for i in countup(0, sonsLen(arg) - 1):
|
||||
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter, skIterator}:
|
||||
for i in 0 ..< arg.len:
|
||||
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
|
||||
skIterator, skMacro, skTemplate}:
|
||||
copyCandidate(z, m)
|
||||
z.callee = arg.sons[i].typ
|
||||
if tfUnresolved in z.callee.flags: continue
|
||||
|
|
@ -2064,6 +2066,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
|||
x = z
|
||||
elif cmp == 0:
|
||||
y = z # z is as good as x
|
||||
|
||||
if x.state == csEmpty:
|
||||
result = nil
|
||||
elif y.state == csMatch and cmpCandidates(x, y) == 0:
|
||||
|
|
@ -2072,7 +2075,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
|||
# ambiguous: more than one symbol fits!
|
||||
# See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match
|
||||
# anyway:
|
||||
if f.kind == tyExpr: result = arg
|
||||
if f.kind in {tyExpr, tyStmt}: result = arg
|
||||
else: result = nil
|
||||
else:
|
||||
# only one valid interpretation found:
|
||||
|
|
@ -2172,7 +2175,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
|||
var formal: PSym = if formalLen > 1: m.callee.n.sons[1].sym else: nil
|
||||
|
||||
while a < n.len:
|
||||
if a >= formalLen-1 and formal != nil and formal.typ.isVarargsUntyped:
|
||||
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
|
||||
formal = m.callee.n.sons[f].sym
|
||||
incl(marker, formal.position)
|
||||
if container.isNil:
|
||||
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
|
|||
of filtReplace:
|
||||
result = filterReplace(p.config, stdin, filename, n)
|
||||
if f != filtNone:
|
||||
assert p.config != nil
|
||||
if hintCodeBegin in p.config.notes:
|
||||
rawMessage(p.config, hintCodeBegin, [])
|
||||
msgWriteln(p.config, result.s)
|
||||
|
|
@ -124,6 +125,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
|
|||
|
||||
proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
||||
start: PLLStream): PLLStream =
|
||||
assert p.config != nil
|
||||
result = start
|
||||
if n.kind == nkEmpty: return
|
||||
if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "|":
|
||||
|
|
@ -139,10 +141,12 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string,
|
|||
|
||||
proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream;
|
||||
cache: IdentCache; config: ConfigRef) =
|
||||
assert config != nil
|
||||
var s: PLLStream
|
||||
p.skin = skinStandard
|
||||
let filename = fileIdx.toFullPathConsiderDirty
|
||||
var pipe = parsePipe(filename, inputstream, cache, config)
|
||||
p.config() = config
|
||||
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
|
||||
else: s = inputstream
|
||||
case p.skin
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ proc firstOrd*(t: PType): BiggestInt =
|
|||
else:
|
||||
assert(t.n.sons[0].kind == nkSym)
|
||||
result = t.n.sons[0].sym.position
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic:
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred:
|
||||
result = firstOrd(lastSon(t))
|
||||
of tyOrdinal:
|
||||
if t.len > 0: result = firstOrd(lastSon(t))
|
||||
|
|
@ -653,7 +653,7 @@ proc lastOrd*(t: PType; fixedUnsigned = false): BiggestInt =
|
|||
of tyEnum:
|
||||
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
||||
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic:
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tyStatic, tyInferred:
|
||||
result = lastOrd(lastSon(t))
|
||||
of tyProxy: result = 0
|
||||
of tyOrdinal:
|
||||
|
|
|
|||
|
|
@ -210,8 +210,14 @@ proc putIntoNode(n: var PNode; x: TFullReg) =
|
|||
of rkInt: n.intVal = x.intVal
|
||||
of rkFloat: n.floatVal = x.floatVal
|
||||
of rkNode:
|
||||
if nfIsRef in x.node.flags: n = x.node
|
||||
else: n[] = x.node[]
|
||||
if nfIsRef in x.node.flags:
|
||||
n = x.node
|
||||
else:
|
||||
let destIsRef = nfIsRef in n.flags
|
||||
n[] = x.node[]
|
||||
# Ref-ness must be kept for the destination
|
||||
if destIsRef:
|
||||
n.flags.incl nfIsRef
|
||||
of rkRegisterAddr: putIntoNode(n, x.regAddr[])
|
||||
of rkNodeAddr: n[] = x.nodeAddr[][]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue