first implementation of package level types that allow forwarding across module boundaries

This commit is contained in:
Andreas Rumpf 2017-10-28 15:28:59 +02:00
commit 7889692523
7 changed files with 47 additions and 21 deletions

View file

@ -1668,5 +1668,5 @@ template hasDestructor*(t: PType): bool = tfHasAsgn in t.flags
template incompleteType*(t: PType): bool = template incompleteType*(t: PType): bool =
t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward} t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward}
template typeCompleted*(t: PType) = template typeCompleted*(s: PSym) =
incl t.sym.flags, sfNoForward incl s.flags, sfNoForward

View file

@ -155,7 +155,7 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
var s = initTabIter(it, scope.symbols) var s = initTabIter(it, scope.symbols)
var missingImpls = 0 var missingImpls = 0
while s != nil: while s != nil:
if sfForward in s.flags: if sfForward in s.flags and s.kind != skType:
# too many 'implementation of X' errors are annoying # too many 'implementation of X' errors are annoying
# and slow 'suggest' down: # and slow 'suggest' down:
if missingImpls == 0: if missingImpls == 0:

View file

@ -55,7 +55,7 @@ const
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wForward} wBorrow, wGcSafe, wExportNims, wPartial, wUsed, wExplain, wPackage}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed} wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@ -799,7 +799,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it) noVal(it)
if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it)
else: incl(sym.typ.flags, tfInheritable) else: incl(sym.typ.flags, tfInheritable)
of wForward: of wPackage:
noVal(it) noVal(it)
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
else: incl(sym.flags, sfForward) else: incl(sym.flags, sfForward)

View file

@ -775,21 +775,52 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
checkSonsLen(a, 3) checkSonsLen(a, 3)
let name = a.sons[0] let name = a.sons[0]
var s: PSym var s: PSym
if name.kind == nkDotExpr: if name.kind == nkDotExpr and a[2].kind == nkObjectTy:
s = qualifiedLookUp(c, name, {checkUndeclared, checkModule}) let pkgName = considerQuotedIdent(name[0])
if s.kind != skType or let typName = considerQuotedIdent(name[1])
s.typ.skipTypes(abstractPtrs).kind != tyObject or let pkg = c.graph.packageSyms.strTableGet(pkgName)
tfPartial notin s.typ.skipTypes(abstractPtrs).flags: if pkg.isNil or pkg.kind != skPackage:
localError(name.info, "only .partial objects can be extended") localError(name.info, "unknown package name: " & pkgName.s)
else:
let typsym = pkg.tab.strTableGet(typName)
if typsym.isNil:
s = semIdentDef(c, name[1], skType)
s.typ = newTypeS(tyObject, c)
s.typ.sym = s
s.flags.incl sfForward
pkg.tab.strTableAdd s
addInterfaceDecl(c, s)
elif typsym.kind == skType and sfForward in typsym.flags:
s = typsym
addInterfaceDecl(c, s)
else:
localError(name.info, typsym.name.s & " is not a type that can be forwarded")
s = typsym
when false:
s = qualifiedLookUp(c, name, {checkUndeclared, checkModule})
if s.kind != skType or
s.typ.skipTypes(abstractPtrs).kind != tyObject or
tfPartial notin s.typ.skipTypes(abstractPtrs).flags:
localError(name.info, "only .partial objects can be extended")
else: else:
s = semIdentDef(c, name, skType) s = semIdentDef(c, name, skType)
s.typ = newTypeS(tyForward, c) s.typ = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas: s.typ.sym = s # process pragmas:
if name.kind == nkPragmaExpr: if name.kind == nkPragmaExpr:
pragma(c, s, name.sons[1], typePragmas) pragma(c, s, name.sons[1], typePragmas)
if sfForward in s.flags: strTableAdd(c.graph.forwardedTypes, s) if sfForward in s.flags:
# check if the symbol already exists:
let pkg = c.module.owner
if not isTopLevel(c) or pkg.isNil:
localError(name.info, "only top level types in a package can be 'forward'")
else:
let typsym = pkg.tab.strTableGet(s.name)
if typsym != nil:
typeCompleted(typsym)
s = typsym
# add it here, so that recursive types are possible: # add it here, so that recursive types are possible:
if sfGenSym notin s.flags: addInterfaceDecl(c, s) if sfGenSym notin s.flags: addInterfaceDecl(c, s)
a.sons[0] = newSymNode(s) a.sons[0] = newSymNode(s)
proc checkCovariantParamsUsages(genericType: PType) = proc checkCovariantParamsUsages(genericType: PType) =

View file

@ -55,7 +55,7 @@ type
wFloatchecks, wNanChecks, wInfChecks, wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wPatterns, wWarnings, wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
wDeadCodeElim, wSafecode, wForward, wNoForward, wReorder, wNoRewrite, wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite,
wPragma, wPragma,
wCompileTime, wNoInit, wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable, wPassc, wPassl, wBorrow, wDiscardable,
@ -143,7 +143,7 @@ const
"assertions", "patterns", "warnings", "hints", "assertions", "patterns", "warnings", "hints",
"optimization", "raises", "writes", "reads", "size", "effects", "tags", "optimization", "raises", "writes", "reads", "size", "effects", "tags",
"deadcodeelim", "safecode", "forward", "noforward", "reorder", "norewrite", "deadcodeelim", "safecode", "package", "noforward", "reorder", "norewrite",
"pragma", "pragma",
"compiletime", "noinit", "compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks", "passc", "passl", "borrow", "discardable", "fieldchecks",

View file

@ -6,12 +6,8 @@ discard """
{.this: self.} {.this: self.}
type type
Foo {.partial.} = object Foo = object
a, b: int a, b, x: int
type
tupcomingfeatures.Foo = object
x: int
proc yay(self: Foo) = proc yay(self: Foo) =
echo a, " ", b, " ", x echo a, " ", b, " ", x

View file

@ -23,7 +23,6 @@ Not critical for 1.0
- make '--implicitStatic:on' the default; then we can also clean up the - make '--implicitStatic:on' the default; then we can also clean up the
'static[T]' mess in the compiler! 'static[T]' mess in the compiler!
- ``not`` or ``~`` for the effects system - ``not`` or ``~`` for the effects system
- document and stress test ``.partial`` object declarations
- figure out why C++ bootstrapping is so much slower - figure out why C++ bootstrapping is so much slower
- The bitwise 'not' operator cold be renamed to 'bnot' to - The bitwise 'not' operator cold be renamed to 'bnot' to
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs! prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!