From 418b41286310007f50891df2b0ec81c62326c5e7 Mon Sep 17 00:00:00 2001 From: DrSlump Date: Thu, 16 Aug 2018 19:01:13 +0200 Subject: [PATCH 1/2] Experimental typeImports --- compiler/importer.nim | 29 +++++++++++++++++++++++++++++ compiler/options.nim | 3 ++- doc/manual.rst | 18 ++++++++++++++++++ tests/modules/ttypeimport.nim | 11 +++++++++++ tests/modules/ttypeimportfail.nim | 11 +++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 tests/modules/ttypeimport.nim create mode 100644 tests/modules/ttypeimportfail.nim diff --git a/compiler/importer.nim b/compiler/importer.nim index c013b93ab1a21..674d13557188d 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -68,6 +68,22 @@ proc rawImportSymbol(c: PContext, s: PSym) = if s.kind == skConverter: addConverter(c, s) if hasPattern(s): addPattern(c, s) +proc maybeImportForType(c: PContext, s: PSym, t: PType) = + ## Imports a symbol only if it has a strict relation with a type: + ## + ## - Proc refers to the type on any of its input or output values. + ## + ## TODO: generics are not matched currently. + ## + case s.kind + of skProcKinds: + for tt in s.typ.sons.items: + if t == tt: + rawImportSymbol(c, s) + break + else: + discard + proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = let ident = lookups.considerQuotedIdent(c, n) let s = strTableGet(fromMod.tab, ident) @@ -88,6 +104,19 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3") rawImportSymbol(c, e) e = nextIdentIter(it, fromMod.tab) + + of skType: + # import the type as expected + rawImportSymbol(c, s) + + # types can bring attached their related symbols too + if typeImports in c.features: + var i: TTabIter + var ss = initTabIter(i, fromMod.tab) + while ss != nil: + maybeImportForType(c, ss, s.typ) + ss = nextIter(i, fromMod.tab) + else: rawImportSymbol(c, s) proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) = diff --git a/compiler/options.nim b/compiler/options.nim index 1873d9d5b4a43..053ac9be59a52 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -120,7 +120,8 @@ type notnil, dynamicBindSym, forLoopMacros, - caseStmtMacros + caseStmtMacros, + typeImports SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/doc/manual.rst b/doc/manual.rst index bb2650799b1d0..b54dc6d9f5892 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6333,6 +6333,24 @@ It's also possible to use ``from module import nil`` if one wants to import the module but wants to enforce fully qualified access to every symbol in ``module``. +By using the experimental feature ``typeImports`` it's possible to bring +all the symbols directly related to a type. Any callable that has the imported +type as one of its arguments or return type gets automatically included with the +import. + +.. code-block:: nim + :test: "nim c $1" + + {.experimental: "typeImports".} + + from colors import Color + + # to string and proc imported + let pink = rgb(255, 192, 203) + echo $pink + # color constants are not imported though, this would fail: + # echo $colBlue + Export statement ~~~~~~~~~~~~~~~~ diff --git a/tests/modules/ttypeimport.nim b/tests/modules/ttypeimport.nim new file mode 100644 index 0000000000000..5fd4ad8ff09c4 --- /dev/null +++ b/tests/modules/ttypeimport.nim @@ -0,0 +1,11 @@ +discard """ + output: "#FFC0CB" +""" + +{.experimental: "typeImports".} + +from colors import Color + +# to string and proc imported +let pink = rgb(255, 192, 203) +echo $pink diff --git a/tests/modules/ttypeimportfail.nim b/tests/modules/ttypeimportfail.nim new file mode 100644 index 0000000000000..9827817feab60 --- /dev/null +++ b/tests/modules/ttypeimportfail.nim @@ -0,0 +1,11 @@ +discard """ + file: "ttypeimportfail.nim" + errormsg: "undeclared identifier: 'colBlue'" +""" + +{.experimental: "typeImports".} + +from colors import Color + +# constants of the type not imported +discard colBlue From e9a0914c086437996f1f7efc568fbdb6161ce0d9 Mon Sep 17 00:00:00 2001 From: DrSlump Date: Fri, 17 Aug 2018 18:33:50 +0200 Subject: [PATCH 2/2] Support for generics on typeImports --- compiler/importer.nim | 13 +++++++++---- doc/manual.rst | 18 ++++++++---------- tests/modules/ttypeimportgen.nim | 12 ++++++++++++ 3 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 tests/modules/ttypeimportgen.nim diff --git a/compiler/importer.nim b/compiler/importer.nim index 674d13557188d..fdcf25c531bc0 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -71,14 +71,19 @@ proc rawImportSymbol(c: PContext, s: PSym) = proc maybeImportForType(c: PContext, s: PSym, t: PType) = ## Imports a symbol only if it has a strict relation with a type: ## - ## - Proc refers to the type on any of its input or output values. - ## - ## TODO: generics are not matched currently. + ## - callable signature refers to the type ## + var m: TCandidate + initCandidate(c, m, t) + case s.kind of skProcKinds: for tt in s.typ.sons.items: - if t == tt: + #FIXME no idea why we get nulls here + if tt == nil: + continue + + if typeRel(m, tt, t) >= isSubtype: rawImportSymbol(c, s) break else: diff --git a/doc/manual.rst b/doc/manual.rst index b54dc6d9f5892..9ceb16c4b06b3 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6333,23 +6333,21 @@ It's also possible to use ``from module import nil`` if one wants to import the module but wants to enforce fully qualified access to every symbol in ``module``. -By using the experimental feature ``typeImports`` it's possible to bring -all the symbols directly related to a type. Any callable that has the imported -type as one of its arguments or return type gets automatically included with the -import. +By using the experimental feature ``typeImports`` it's possible to bring any +callable that has an imported type on its signature bundled with it. .. code-block:: nim :test: "nim c $1" {.experimental: "typeImports".} - from colors import Color + from colors import Color, colBlue - # to string and proc imported - let pink = rgb(255, 192, 203) - echo $pink - # color constants are not imported though, this would fail: - # echo $colBlue + # related procs and operators like `$` are implicitly imported + let darker = intensity(colBlue, 0.3) + echo $darker + # values are not implicitly imported, this would fail: + #echo $colRed Export statement diff --git a/tests/modules/ttypeimportgen.nim b/tests/modules/ttypeimportgen.nim new file mode 100644 index 0000000000000..4de27f4c5892a --- /dev/null +++ b/tests/modules/ttypeimportgen.nim @@ -0,0 +1,12 @@ +discard """ + output: "10" +""" + +{.experimental: "typeImports".} + +from collections.deques import Deque + +var dq = initDeque[int]() +dq.addLast(10) +assert len(dq) == 1 +echo peekLast(dq)