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
parent c6235920cb
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 =
t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward}
template typeCompleted*(t: PType) =
incl t.sym.flags, sfNoForward
template typeCompleted*(s: PSym) =
incl s.flags, sfNoForward

View File

@@ -155,7 +155,7 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
var s = initTabIter(it, scope.symbols)
var missingImpls = 0
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
# and slow 'suggest' down:
if missingImpls == 0:

View File

@@ -55,7 +55,7 @@ const
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
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,
wImportCpp, wImportObjC, wError, wGuard, wBitsize, wUsed}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@@ -799,7 +799,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it)
if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it)
else: incl(sym.typ.flags, tfInheritable)
of wForward:
of wPackage:
noVal(it)
if sym.typ == nil: invalidPragma(it)
else: incl(sym.flags, sfForward)

View File

@@ -775,21 +775,52 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
checkSonsLen(a, 3)
let name = a.sons[0]
var s: PSym
if name.kind == nkDotExpr:
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")
if name.kind == nkDotExpr and a[2].kind == nkObjectTy:
let pkgName = considerQuotedIdent(name[0])
let typName = considerQuotedIdent(name[1])
let pkg = c.graph.packageSyms.strTableGet(pkgName)
if pkg.isNil or pkg.kind != skPackage:
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:
s = semIdentDef(c, name, skType)
s.typ = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas:
if name.kind == nkPragmaExpr:
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:
if sfGenSym notin s.flags: addInterfaceDecl(c, s)
a.sons[0] = newSymNode(s)
proc checkCovariantParamsUsages(genericType: PType) =

View File

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

View File

@@ -6,12 +6,8 @@ discard """
{.this: self.}
type
Foo {.partial.} = object
a, b: int
type
tupcomingfeatures.Foo = object
x: int
Foo = object
a, b, x: int
proc yay(self: Foo) =
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
'static[T]' mess in the compiler!
- ``not`` or ``~`` for the effects system
- document and stress test ``.partial`` object declarations
- figure out why C++ bootstrapping is so much slower
- The bitwise 'not' operator cold be renamed to 'bnot' to
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!