diff options
-rw-r--r-- | compiler/parser.nim | 15 | ||||
-rw-r--r-- | compiler/pragmas.nim | 11 | ||||
-rw-r--r-- | compiler/semstmts.nim | 28 | ||||
-rw-r--r-- | compiler/semtypes.nim | 6 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 3 | ||||
-rw-r--r-- | doc/grammar.txt | 4 |
6 files changed, 49 insertions, 18 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 560510b27..e5a381b07 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -804,20 +804,24 @@ proc parsePragma(p: var TParser): PNode = else: parMessage(p, errTokenExpected, ".}") dec p.inPragma -proc identVis(p: var TParser): PNode = +proc identVis(p: var TParser; allowDot=false): PNode = #| identVis = symbol opr? # postfix position + #| identVisDot = symbol '.' optInd symbol opr? var a = parseSymbol(p) if p.tok.tokType == tkOpr: result = newNodeP(nkPostfix, p) addSon(result, newIdentNodeP(p.tok.ident, p)) addSon(result, a) getTok(p) + elif p.tok.tokType == tkDot and allowDot: + result = dotExpr(p, a) else: result = a -proc identWithPragma(p: var TParser): PNode = +proc identWithPragma(p: var TParser; allowDot=false): PNode = #| identWithPragma = identVis pragma? - var a = identVis(p) + #| identWithPragmaDot = identVisDot pragma? + var a = identVis(p, allowDot) if p.tok.tokType == tkCurlyDotLe: result = newNodeP(nkPragmaExpr, p) addSon(result, a) @@ -1803,10 +1807,11 @@ proc parseTypeClass(p: var TParser): PNode = addSon(result, parseStmt(p)) proc parseTypeDef(p: var TParser): PNode = - #| typeDef = identWithPragma genericParamList? '=' optInd typeDefAux + #| + #| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux #| indAndComment? result = newNodeP(nkTypeDef, p) - addSon(result, identWithPragma(p)) + addSon(result, identWithPragma(p, allowDot=true)) if p.tok.tokType == tkBracketLe and p.validInd: addSon(result, parseGenericParamList(p)) else: diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d4996981d..2280ef712 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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} + wBorrow, wGcSafe, wExportNims, wPartial} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, wImportCpp, wImportObjC, wError, wGuard, wBitsize} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, @@ -835,6 +835,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, noVal(it) if sym.kind != skType or sym.typ == nil: invalidPragma(it) 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: # We check for errors, but do nothing with these pragmas otherwise # as they are handled directly in 'evalTemplate'. diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index d84415827..0790fc30c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -661,13 +661,22 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = if a.kind == nkCommentStmt: continue if a.kind != nkTypeDef: illFormedAst(a) checkSonsLen(a, 3) - var s = semIdentDef(c, a.sons[0], skType) - s.typ = newTypeS(tyForward, c) - s.typ.sym = s # process pragmas: - if a.sons[0].kind == nkPragmaExpr: - pragma(c, s, a.sons[0].sons[1], typePragmas) - # add it here, so that recursive types are possible: - if sfGenSym notin s.flags: addInterfaceDecl(c, s) + 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.sym = s # process pragmas: + if name.kind == nkPragmaExpr: + pragma(c, s, name.sons[1], typePragmas) + # add it here, so that recursive types are possible: + if sfGenSym notin s.flags: addInterfaceDecl(c, s) a.sons[0] = newSymNode(s) proc typeSectionRightSidePass(c: PContext, n: PNode) = @@ -676,8 +685,9 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = if a.kind == nkCommentStmt: continue if (a.kind != nkTypeDef): illFormedAst(a) checkSonsLen(a, 3) - if (a.sons[0].kind != nkSym): illFormedAst(a) - var s = a.sons[0].sym + let name = a.sons[0] + if (name.kind != nkSym): illFormedAst(a) + var s = name.sym if s.magic == mNone and a.sons[2].kind == nkEmpty: localError(a.info, errImplOfXexpected, s.name.s) if s.magic != mNone: processMagicType(c, s) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 6fa042bbb..62d02fe10 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -673,7 +673,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = if n.kind != nkObjectTy: internalError(n.info, "semObjectNode") result = newOrPrevType(tyObject, prev, c) rawAddSon(result, base) - result.n = newNodeI(nkRecList, n.info) + if result.n.isNil: + 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) if n.sons[0].kind != nkEmpty: # dummy symbol for `pragma`: diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 7fec140a2..62848c078 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -66,6 +66,7 @@ type wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wAsmNoStackFrame, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, + wPartial, wAuto, wBool, wCatch, wChar, wClass, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, @@ -151,7 +152,7 @@ const "computedgoto", "injectstmt", "experimental", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", - "guard", "locks", + "guard", "locks", "partial", "auto", "bool", "catch", "char", "class", "const_cast", "default", "delete", "double", diff --git a/doc/grammar.txt b/doc/grammar.txt index d967bf938..47f739174 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -67,7 +67,9 @@ ifExpr = 'if' condExpr whenExpr = 'when' condExpr pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}') identVis = symbol opr? # postfix position +identVisDot = symbol '.' optInd symbol opr? identWithPragma = identVis pragma? +identWithPragmaDot = identVisDot pragma? declColonEquals = identWithPragma (comma identWithPragma)* comma? (':' optInd typeDesc)? ('=' optInd expr)? identColonEquals = ident (comma ident)* comma? @@ -171,7 +173,7 @@ object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart typeClassParam = ('var' | 'out')? symbol typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? &IND{>} stmt -typeDef = identWithPragma genericParamList? '=' optInd typeDefAux +typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux indAndComment? varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr variable = (varTuple / identColonEquals) indAndComment |