diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/parser.nim | 7 | ||||
-rw-r--r-- | compiler/semexprs.nim | 20 | ||||
-rw-r--r-- | compiler/semstmts.nim | 37 | ||||
-rw-r--r-- | compiler/semtypes.nim | 2 |
4 files changed, 46 insertions, 20 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index d4c44788e..8bd99acd3 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -846,6 +846,7 @@ type TDeclaredIdentFlag = enum withPragma, # identifier may have pragma withBothOptional # both ':' and '=' parts are optional + withDot # allow 'var ident.ident = value' TDeclaredIdentFlags = set[TDeclaredIdentFlag] proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode = @@ -859,7 +860,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode = while true: case p.tok.tokType of tkSymbol, tkAccent: - if withPragma in flags: a = identWithPragma(p) + if withPragma in flags: a = identWithPragma(p, allowDot=withdot in flags) else: a = parseSymbol(p) if a.kind == nkEmpty: return else: break @@ -1889,7 +1890,7 @@ proc parseVarTuple(p: var TParser): PNode = optInd(p, result) # progress guaranteed while p.tok.tokType in {tkSymbol, tkAccent}: - var a = identWithPragma(p) + var a = identWithPragma(p, allowDot=true) addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) @@ -1905,7 +1906,7 @@ proc parseVariable(p: var TParser): PNode = #| colonBody = colcom stmt doBlocks? #| variable = (varTuple / identColonEquals) colonBody? indAndComment if p.tok.tokType == tkParLe: result = parseVarTuple(p) - else: result = parseIdentColonEquals(p, {withPragma}) + else: result = parseIdentColonEquals(p, {withPragma, withDot}) result{-1} = postExprBlocks(p, result{-1}) indAndComment(p, result) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 59fa208d2..9c93d54a3 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -880,20 +880,6 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, if r.sym.name.id == field.id: result = r.sym else: illFormedAst(n) -proc makeDeref(n: PNode): PNode = - var t = skipTypes(n.typ, {tyGenericInst, tyAlias}) - result = n - if t.kind == tyVar: - result = newNodeIT(nkHiddenDeref, n.info, t.sons[0]) - addSon(result, n) - t = skipTypes(t.sons[0], {tyGenericInst, tyAlias}) - while t.kind in {tyPtr, tyRef}: - var a = result - let baseTyp = t.lastSon - result = newNodeIT(nkHiddenDeref, n.info, baseTyp) - addSon(result, a) - t = skipTypes(baseTyp, {tyGenericInst, tyAlias}) - const tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias} @@ -920,7 +906,7 @@ proc readTypeParameter(c: PContext, typ: PType, else: discard - + if typ.kind != tyUserTypeClass: let ty = if typ.kind == tyCompositeTypeClass: typ.sons[1].skipGenericAlias else: typ.skipGenericAlias @@ -2285,14 +2271,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = pragma = n[1] pragmaName = considerQuotedIdent(pragma[0]) flags = flags - + case whichKeyword(pragmaName) of wExplain: flags.incl efExplain else: # what other pragmas are allowed for expressions? `likely`, `unlikely` invalidPragma(n) - + result = semExpr(c, n[0], flags) of nkPar: case checkPar(n) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8f522ccc2..ad043a6ee 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -465,6 +465,38 @@ proc hasEmpty(typ: PType): bool = for s in typ.sons: result = result or hasEmpty(s) +proc makeDeref(n: PNode): PNode = + var t = skipTypes(n.typ, {tyGenericInst, tyAlias}) + result = n + if t.kind == tyVar: + result = newNodeIT(nkHiddenDeref, n.info, t.sons[0]) + addSon(result, n) + t = skipTypes(t.sons[0], {tyGenericInst, tyAlias}) + while t.kind in {tyPtr, tyRef}: + var a = result + let baseTyp = t.lastSon + result = newNodeIT(nkHiddenDeref, n.info, baseTyp) + addSon(result, a) + t = skipTypes(baseTyp, {tyGenericInst, tyAlias}) + +proc fillPartialObject(c: PContext; n: PNode; typ: PType) = + if n.len == 2: + let x = semExprWithType(c, n[0]) + let y = considerQuotedIdent(n[1]) + let obj = x.typ.skipTypes(abstractPtrs) + if obj.kind == tyObject and tfPartial in obj.flags: + let field = newSym(skField, getIdent(y.s & $obj.n.len), obj.sym, n[1].info) + field.typ = skipIntLit(typ) + field.position = sonsLen(obj.n) + addSon(obj.n, newSymNode(field)) + n.sons[0] = makeDeref x + n.sons[1] = newSymNode(field) + else: + localError(n.info, "implicit object field construction " & + "requires a .partial object, but got " & typeToString(obj)) + else: + localError(n.info, "nkDotNode requires 2 children") + proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var b: PNode result = copyNode(n) @@ -529,6 +561,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = message(a.info, warnEachIdentIsTuple) for j in countup(0, length-3): + if a[j].kind == nkDotExpr: + fillPartialObject(c, a[j], + if a.kind != nkVarTuple: typ else: tup.sons[j]) + addToVarSection(c, result, n, a) + continue var v = semIdentDef(c, a.sons[j], symkind) if sfGenSym notin v.flags and not isDiscardUnderscore(v): addInterfaceDecl(c, v) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 09f90d8d0..1e0a710c2 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -152,6 +152,8 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = message n[i].info, errGenerated, "region needs to be an object type" addSonSkipIntLit(result, region) addSonSkipIntLit(result, t) + if tfPartial in result.flags: + if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial) #if not isNilable: result.flags.incl tfNotNil proc semVarType(c: PContext, n: PNode, prev: PType): PType = |