first version of .partial objects

This commit is contained in:
Andreas Rumpf 2016-02-28 23:22:47 +01:00
commit 0baa1d9955
6 changed files with 49 additions and 18 deletions

View file

@ -804,20 +804,24 @@ proc parsePragma(p: var TParser): PNode =
else: parMessage(p, errTokenExpected, ".}") else: parMessage(p, errTokenExpected, ".}")
dec p.inPragma dec p.inPragma
proc identVis(p: var TParser): PNode = proc identVis(p: var TParser; allowDot=false): PNode =
#| identVis = symbol opr? # postfix position #| identVis = symbol opr? # postfix position
#| identVisDot = symbol '.' optInd symbol opr?
var a = parseSymbol(p) var a = parseSymbol(p)
if p.tok.tokType == tkOpr: if p.tok.tokType == tkOpr:
result = newNodeP(nkPostfix, p) result = newNodeP(nkPostfix, p)
addSon(result, newIdentNodeP(p.tok.ident, p)) addSon(result, newIdentNodeP(p.tok.ident, p))
addSon(result, a) addSon(result, a)
getTok(p) getTok(p)
elif p.tok.tokType == tkDot and allowDot:
result = dotExpr(p, a)
else: else:
result = a result = a
proc identWithPragma(p: var TParser): PNode = proc identWithPragma(p: var TParser; allowDot=false): PNode =
#| identWithPragma = identVis pragma? #| identWithPragma = identVis pragma?
var a = identVis(p) #| identWithPragmaDot = identVisDot pragma?
var a = identVis(p, allowDot)
if p.tok.tokType == tkCurlyDotLe: if p.tok.tokType == tkCurlyDotLe:
result = newNodeP(nkPragmaExpr, p) result = newNodeP(nkPragmaExpr, p)
addSon(result, a) addSon(result, a)
@ -1803,10 +1807,11 @@ proc parseTypeClass(p: var TParser): PNode =
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
proc parseTypeDef(p: var TParser): PNode = proc parseTypeDef(p: var TParser): PNode =
#| typeDef = identWithPragma genericParamList? '=' optInd typeDefAux #|
#| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
#| indAndComment? #| indAndComment?
result = newNodeP(nkTypeDef, p) result = newNodeP(nkTypeDef, p)
addSon(result, identWithPragma(p)) addSon(result, identWithPragma(p, allowDot=true))
if p.tok.tokType == tkBracketLe and p.validInd: if p.tok.tokType == tkBracketLe and p.validInd:
addSon(result, parseGenericParamList(p)) addSon(result, parseGenericParamList(p))
else: else:

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} wBorrow, wGcSafe, wExportNims, wPartial}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard, wBitsize} wImportCpp, wImportObjC, wError, wGuard, wBitsize}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
@ -835,6 +835,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it) noVal(it)
if sym.kind != skType or sym.typ == nil: invalidPragma(it) if sym.kind != skType or sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfByCopy) else: incl(sym.typ.flags, tfByCopy)
of wPartial:
noVal(it)
if sym.kind != skType or sym.typ == nil: invalidPragma(it)
else:
incl(sym.typ.flags, tfPartial)
# .partial types can only work with dead code elimination
# to prevent the codegen from doing anything before we compiled
# the whole program:
incl gGlobalOptions, optDeadCodeElim
of wInject, wGensym: of wInject, wGensym:
# We check for errors, but do nothing with these pragmas otherwise # We check for errors, but do nothing with these pragmas otherwise
# as they are handled directly in 'evalTemplate'. # as they are handled directly in 'evalTemplate'.

View file

@ -661,11 +661,20 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind != nkTypeDef: illFormedAst(a) if a.kind != nkTypeDef: illFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
var s = semIdentDef(c, a.sons[0], skType) let name = a.sons[0]
var s: PSym
if name.kind == nkDotExpr:
s = qualifiedLookUp(c, name)
debug s
debug s.typ.skipTypes(abstractPtrs)
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 = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas: s.typ.sym = s # process pragmas:
if a.sons[0].kind == nkPragmaExpr: if name.kind == nkPragmaExpr:
pragma(c, s, a.sons[0].sons[1], typePragmas) pragma(c, s, name.sons[1], typePragmas)
# 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)
@ -676,8 +685,9 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a) if (a.kind != nkTypeDef): illFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
if (a.sons[0].kind != nkSym): illFormedAst(a) let name = a.sons[0]
var s = a.sons[0].sym if (name.kind != nkSym): illFormedAst(a)
var s = name.sym
if s.magic == mNone and a.sons[2].kind == nkEmpty: if s.magic == mNone and a.sons[2].kind == nkEmpty:
localError(a.info, errImplOfXexpected, s.name.s) localError(a.info, errImplOfXexpected, s.name.s)
if s.magic != mNone: processMagicType(c, s) if s.magic != mNone: processMagicType(c, s)

View file

@ -673,7 +673,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
if n.kind != nkObjectTy: internalError(n.info, "semObjectNode") if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c) result = newOrPrevType(tyObject, prev, c)
rawAddSon(result, base) rawAddSon(result, base)
if result.n.isNil:
result.n = newNodeI(nkRecList, n.info) result.n = newNodeI(nkRecList, n.info)
else:
# partial object so add things to the check
addInheritedFields(c, check, pos, result)
semRecordNodeAux(c, n.sons[2], check, pos, result.n, result) semRecordNodeAux(c, n.sons[2], check, pos, result.n, result)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
# dummy symbol for `pragma`: # dummy symbol for `pragma`:

View file

@ -66,6 +66,7 @@ type
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
wAsmNoStackFrame, wAsmNoStackFrame,
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
wPartial,
wAuto, wBool, wCatch, wChar, wClass, wAuto, wBool, wCatch, wChar, wClass,
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@ -151,7 +152,7 @@ const
"computedgoto", "injectstmt", "experimental", "computedgoto", "injectstmt", "experimental",
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
"asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
"guard", "locks", "guard", "locks", "partial",
"auto", "bool", "catch", "char", "class", "auto", "bool", "catch", "char", "class",
"const_cast", "default", "delete", "double", "const_cast", "default", "delete", "double",

View file

@ -67,7 +67,9 @@ ifExpr = 'if' condExpr
whenExpr = 'when' condExpr whenExpr = 'when' condExpr
pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}') pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
identVis = symbol opr? # postfix position identVis = symbol opr? # postfix position
identVisDot = symbol '.' optInd symbol opr?
identWithPragma = identVis pragma? identWithPragma = identVis pragma?
identWithPragmaDot = identVisDot pragma?
declColonEquals = identWithPragma (comma identWithPragma)* comma? declColonEquals = identWithPragma (comma identWithPragma)* comma?
(':' optInd typeDesc)? ('=' optInd expr)? (':' optInd typeDesc)? ('=' optInd expr)?
identColonEquals = ident (comma ident)* comma? identColonEquals = ident (comma ident)* comma?
@ -171,7 +173,7 @@ object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
typeClassParam = ('var' | 'out')? symbol typeClassParam = ('var' | 'out')? symbol
typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
&IND{>} stmt &IND{>} stmt
typeDef = identWithPragma genericParamList? '=' optInd typeDefAux typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
indAndComment? indAndComment?
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
variable = (varTuple / identColonEquals) indAndComment variable = (varTuple / identColonEquals) indAndComment