summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim15
-rw-r--r--compiler/astalgo.nim16
-rw-r--r--compiler/evaltempl.nim2
-rw-r--r--compiler/filter_tmpl.nim4
-rw-r--r--compiler/importer.nim13
-rw-r--r--compiler/modules.nim1
-rw-r--r--compiler/nimfix/prettybase.nim2
-rw-r--r--compiler/parser.nim17
-rw-r--r--compiler/pragmas.nim2
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semexprs.nim33
-rw-r--r--compiler/semmagic.nim4
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/sigmatch.nim14
-rw-r--r--compiler/syntaxes.nim4
-rw-r--r--compiler/types.nim4
-rw-r--r--compiler/vm.nim10
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[][]