summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-02-09 17:40:24 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-02-09 17:40:24 +0100
commit733ed91d3377aee2d436b60da6a4d78afa2f9bc5 (patch)
treeab53799ec99bf2bdd21747856ffd95a8c0c56be3 /compiler
parent5ff6ff28bf9abf12fa9d82f0323954516a855b6a (diff)
downloadNim-733ed91d3377aee2d436b60da6a4d78afa2f9bc5.tar.gz
disable transitive closure computations; only semcheck procs that have the cursor
Diffstat (limited to 'compiler')
-rw-r--r--compiler/modulegraphs.nim2
-rw-r--r--compiler/semstmts.nim60
-rw-r--r--compiler/suggest.nim4
3 files changed, 41 insertions, 25 deletions
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index 87a35b290..fb8f5cf04 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -73,7 +73,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: int32) =
     deps.incl m.position.dependsOn(dep)
     # we compute the transitive closure later when quering the graph lazily.
     # this improve efficiency quite a lot:
-    invalidTransitiveClosure = true
+    #invalidTransitiveClosure = true
 
 proc addIncludeDep*(g: ModuleGraph; module, includeFile: int32) =
   discard hasKeyOrPut(inclToMod, includeFile, module)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 25d4b3c74..5a59a62c0 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1177,11 +1177,22 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
       localError(n.info, errGenerated,
                  "'destroy' or 'deepCopy' expected for 'override'")
 
+proc cursorInProcAux(n: PNode): bool =
+  if inCheckpoint(n.info) != cpNone: return true
+  for i in 0..<n.safeLen:
+    if cursorInProcAux(n[i]): return true
+
+proc cursorInProc(n: PNode): bool =
+  if n.info.fileIndex == gTrackPos.fileIndex:
+    result = cursorInProcAux(n)
+
 type
   TProcCompilationSteps = enum
     stepRegisterSymbol,
     stepDetermineType,
 
+import compilerlog
+
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
                 validPragmas: TSpecialWords,
                 phase = stepRegisterSymbol): PNode =
@@ -1303,29 +1314,34 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     # Macros and Templates can have generic parameters, but they are
     # only used for overload resolution (there is no instantiation of
     # the symbol, so we must process the body now)
-    pushProcCon(c, s)
-    if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
-      if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
-
-      c.p.wasForwarded = proto != nil
-      maybeAddResult(c, s, n)
-      if lfDynamicLib notin s.loc.flags:
-        # no semantic checking for importc:
-        let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
-        # unfortunately we cannot skip this step when in 'system.compiles'
-        # context as it may even be evaluated in 'system.compiles':
-        n.sons[bodyPos] = transformBody(c.module, semBody, s)
+    if not usePseudoGenerics and gIdeCmd in {ideSug, ideCon} and not
+        cursorInProc(n.sons[bodyPos]):
+      discard "speed up nimsuggest"
+      logStr "skipped " & s.name.s
     else:
-      if s.typ.sons[0] != nil and kind != skIterator:
-        addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
-      openScope(c)
-      n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
-      closeScope(c)
-      fixupInstantiatedSymbols(c, s)
-    if sfImportc in s.flags:
-      # so we just ignore the body after semantic checking for importc:
-      n.sons[bodyPos] = ast.emptyNode
-    popProcCon(c)
+      pushProcCon(c, s)
+      if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
+        if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
+
+        c.p.wasForwarded = proto != nil
+        maybeAddResult(c, s, n)
+        if lfDynamicLib notin s.loc.flags:
+          # no semantic checking for importc:
+          let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
+          # unfortunately we cannot skip this step when in 'system.compiles'
+          # context as it may even be evaluated in 'system.compiles':
+          n.sons[bodyPos] = transformBody(c.module, semBody, s)
+      else:
+        if s.typ.sons[0] != nil and kind != skIterator:
+          addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
+        openScope(c)
+        n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
+        closeScope(c)
+        fixupInstantiatedSymbols(c, s)
+      if sfImportc in s.flags:
+        # so we just ignore the body after semantic checking for importc:
+        n.sons[bodyPos] = ast.emptyNode
+      popProcCon(c)
   else:
     if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
     if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 66876b9b5..aea979d56 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -297,10 +297,10 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
       suggestOperations(c, n, typ, outputs)
 
 type
-  TCheckPointResult = enum
+  TCheckPointResult* = enum
     cpNone, cpFuzzy, cpExact
 
-proc inCheckpoint(current: TLineInfo): TCheckPointResult =
+proc inCheckpoint*(current: TLineInfo): TCheckPointResult =
   if current.fileIndex == gTrackPos.fileIndex:
     if current.line == gTrackPos.line and
         abs(current.col-gTrackPos.col) < 4:
an> discard proc generic2[T]() = typedTempl(1): let x = generic1[T] generic2[int]() import std/macros when not compiles(len((1, 2))): import std/typetraits func len(x: tuple): int = arity(type(x)) block: # full issue example type FieldDescription = object name: NimNode func isTuple(t: NimNode): bool = t.kind == nnkBracketExpr and t[0].kind == nnkSym and eqIdent(t[0], "tuple") proc collectFieldsFromRecList(result: var seq[FieldDescription], n: NimNode, parentCaseField: NimNode = nil, parentCaseBranch: NimNode = nil, isDiscriminator = false) = case n.kind of nnkRecList: for entry in n: collectFieldsFromRecList result, entry, parentCaseField, parentCaseBranch of nnkIdentDefs: for i in 0 ..< n.len - 2: var field: FieldDescription field.name = n[i] if field.name.kind == nnkPragmaExpr: field.name = field.name[0] if field.name.kind == nnkPostfix: field.name = field.name[1] result.add field of nnkNilLit, nnkDiscardStmt, nnkCommentStmt, nnkEmpty: discard else: doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr proc collectFieldsInHierarchy(result: var seq[FieldDescription], objectType: NimNode) = var objectType = objectType if objectType.kind == nnkRefTy: objectType = objectType[0] let recList = objectType[2] collectFieldsFromRecList result, recList proc recordFields(typeImpl: NimNode): seq[FieldDescription] = let objectType = case typeImpl.kind of nnkObjectTy: typeImpl of nnkTypeDef: typeImpl[2] else: macros.error("object type expected", typeImpl) return collectFieldsInHierarchy(result, objectType) proc skipPragma(n: NimNode): NimNode = if n.kind == nnkPragmaExpr: n[0] else: n func declval(T: type): T = doAssert false, "declval should be used only in `typeof` expressions and concepts" default(ptr T)[] macro enumAllSerializedFieldsImpl(T: type, body: untyped): untyped = var typeAst = getType(T)[1] var typeImpl: NimNode let isSymbol = not typeAst.isTuple if not isSymbol: typeImpl = typeAst else: typeImpl = getImpl(typeAst) result = newStmtList() var i = 0 for field in recordFields(typeImpl): let fieldIdent = field.name realFieldName = newLit($fieldIdent.skipPragma) fieldName = realFieldName fieldIndex = newLit(i) let fieldNameDefs = if isSymbol: quote: const fieldName {.inject, used.} = `fieldName` const realFieldName {.inject, used.} = `realFieldName` else: quote: const fieldName {.inject, used.} = $`fieldIndex` const realFieldName {.inject, used.} = $`fieldIndex` # we can't access .Fieldn, so our helper knows # to parseInt this let field = if isSymbol: quote do: declval(`T`).`fieldIdent` else: quote do: declval(`T`)[`fieldIndex`] result.add quote do: block: `fieldNameDefs` type FieldType {.inject, used.} = type(`field`) `body` i += 1 template enumAllSerializedFields(T: type, body): untyped = when T is ref|ptr: type TT = type(default(T)[]) enumAllSerializedFieldsImpl(TT, body) else: enumAllSerializedFieldsImpl(T, body) type MemRange = object startAddr: ptr byte length: int SszNavigator[T] = object m: MemRange func sszMount(data: openArray[byte], T: type): SszNavigator[T] = let startAddr = unsafeAddr data[0] SszNavigator[T](m: MemRange(startAddr: startAddr, length: data.len)) func sszMount(data: openArray[char], T: type): SszNavigator[T] = let startAddr = cast[ptr byte](unsafeAddr data[0]) SszNavigator[T](m: MemRange(startAddr: startAddr, length: data.len)) template sszMount(data: MemRange, T: type): SszNavigator[T] = SszNavigator[T](m: data) func navigateToField[T]( n: SszNavigator[T], FieldType: type): SszNavigator[FieldType] = default(SszNavigator[FieldType]) type FieldInfo = ref object navigator: proc (m: MemRange): MemRange {. gcsafe, noSideEffect, raises: [IOError] .} func fieldNavigatorImpl[RecordType; FieldType; fieldName: static string]( m: MemRange): MemRange = var typedNavigator = sszMount(m, RecordType) discard navigateToField(typedNavigator, FieldType) default(MemRange) func genTypeInfo(T: type) = when T is object: enumAllSerializedFields(T): discard FieldInfo(navigator: fieldNavigatorImpl[T, FieldType, fieldName]) type Foo = object bar: Bar BarList = seq[uint64] Bar = object b: BarList baz: Baz Baz = object i: uint64 genTypeInfo(Foo)