diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 15 | ||||
-rw-r--r-- | compiler/astalgo.nim | 16 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 2 | ||||
-rw-r--r-- | compiler/filter_tmpl.nim | 4 | ||||
-rw-r--r-- | compiler/importer.nim | 13 | ||||
-rw-r--r-- | compiler/modules.nim | 1 | ||||
-rw-r--r-- | compiler/nimfix/prettybase.nim | 2 | ||||
-rw-r--r-- | compiler/parser.nim | 17 | ||||
-rw-r--r-- | compiler/pragmas.nim | 2 | ||||
-rw-r--r-- | compiler/semdata.nim | 1 | ||||
-rw-r--r-- | compiler/semexprs.nim | 33 | ||||
-rw-r--r-- | compiler/semmagic.nim | 4 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 14 | ||||
-rw-r--r-- | compiler/syntaxes.nim | 4 | ||||
-rw-r--r-- | compiler/types.nim | 4 | ||||
-rw-r--r-- | compiler/vm.nim | 10 |
17 files changed, 107 insertions, 37 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 5e65fbff9..5a84b2b02 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index f9311d4ce..d98a42b34 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -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() diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 311bb6539..01c56ec9c 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -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 diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim index 9bdc41016..f93355e6b 100644 --- a/compiler/filter_tmpl.nim +++ b/compiler/filter_tmpl.nim @@ -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) diff --git a/compiler/importer.nim b/compiler/importer.nim index ed988cea7..90e774a50 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -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) diff --git a/compiler/modules.nim b/compiler/modules.nim index 7bc32d42c..5d1eba1f2 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -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: diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim index ecb4b0093..c32dbe623 100644 --- a/compiler/nimfix/prettybase.nim +++ b/compiler/nimfix/prettybase.nim @@ -8,7 +8,7 @@ # import strutils, lexbase, streams -import "../compiler" / [ast, msgs, idents] +import ".." / [ast, msgs, idents] from os import splitFile type diff --git a/compiler/parser.nim b/compiler/parser.nim index 7a23ed6a9..082dcd9ed 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -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) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1bb10b80e..de98a5e42 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index ad5bdfd49..12ac19ca3 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -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 diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 2a2a8b72a..6b32fa66c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 93d56b603..8515e971d 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 7282ea58c..2d4b5ae77 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 74c944d51..1d4515875 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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)) diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim index 18d68bd2d..4bc153e46 100644 --- a/compiler/syntaxes.nim +++ b/compiler/syntaxes.nim @@ -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 diff --git a/compiler/types.nim b/compiler/types.nim index a5c053488..9c2ad71c5 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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: diff --git a/compiler/vm.nim b/compiler/vm.nim index b001cdc07..dcb4cefd7 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -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[][] |