diff options
-rw-r--r-- | compiler/ccgexprs.nim | 71 | ||||
-rw-r--r-- | tests/ccgbugs/tobjconstr_outoforder.nim | 38 |
2 files changed, 102 insertions, 7 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index ade2cb41f..95a7beada 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2158,17 +2158,72 @@ proc genNamedConstExpr(p: BProc, n: PNode): Rope = if n.kind == nkExprColonExpr: result = genConstExpr(p, n.sons[1]) else: result = genConstExpr(p, n) +proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope = + var t = skipTypes(typ, abstractRange-{tyTypeDesc}) + case t.kind + of tyBool: result = rope"NIM_FALSE" + of tyEnum, tyChar, tyInt..tyInt64, tyUInt..tyUInt64: result = rope"0" + of tyFloat..tyFloat128: result = rope"0.0" + of tyCString, tyString, tyVar, tyPointer, tyPtr, tySequence, tyExpr, + tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil: + result = rope"NIM_NIL" + of tyProc: + if t.callConv != ccClosure: + result = rope"NIM_NIL" + else: + result = rope"{NIM_NIL, NIM_NIL}" + of tyObject: + if not isObjLackingTypeField(t) and not p.module.compileToCpp: + result = "{{$1}}" % [genTypeInfo(p.module, t)] + else: + result = rope"{}" + of tyArray, tyTuple: result = rope"{}" + of tySet: + if mapType(t) == ctArray: result = rope"{}" + else: result = rope"0" + else: + globalError(info, "cannot create null element for: " & $t.kind) + +proc getNullValueAux(p: BProc; obj, cons: PNode, result: var Rope) = + case obj.kind + of nkRecList: + for i in countup(0, sonsLen(obj) - 1): getNullValueAux(p, obj.sons[i], cons, result) + of nkRecCase: + getNullValueAux(p, obj.sons[0], cons, result) + for i in countup(1, sonsLen(obj) - 1): + getNullValueAux(p, lastSon(obj.sons[i]), cons, result) + of nkSym: + if not result.isNil: result.add ", " + let field = obj.sym + for i in 1..<cons.len: + if cons[i].kind == nkExprColonExpr: + if cons[i][0].sym == field: + result.add genConstExpr(p, cons[i][1]) + return + elif i == field.position: + result.add genConstExpr(p, cons[i]) + return + # not found, produce default value: + result.add getDefaultValue(p, field.typ, cons.info) + else: + localError(cons.info, "cannot create null element for: " & $obj) + +proc genConstObjConstr(p: BProc; n: PNode): Rope = + var length = sonsLen(n) + result = nil + let t = n.typ.skipTypes(abstractInst) + if not isObjLackingTypeField(t) and not p.module.compileToCpp: + addf(result, "{$1}", [genTypeInfo(p.module, t)]) + getNullValueAux(p, t.n, n, result) + result = "{$1}$n" % [result] + proc genConstSimpleList(p: BProc, n: PNode): Rope = var length = sonsLen(n) result = rope("{") let t = n.typ.skipTypes(abstractInst) - if n.kind == nkObjConstr and not isObjLackingTypeField(t) and - not p.module.compileToCpp: - addf(result, "{$1}", [genTypeInfo(p.module, t)]) - if n.len > 1: add(result, ",") - for i in countup(ord(n.kind == nkObjConstr), length - 2): + for i in countup(0, length - 2): addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])]) - if length > ord(n.kind == nkObjConstr): + if length > 0: add(result, genNamedConstExpr(p, n.sons[length - 1])) addf(result, "}$n", []) @@ -2203,12 +2258,14 @@ proc genConstExpr(p: BProc, n: PNode): Rope = var cs: TBitSet toBitSet(n, cs) result = genRawSetData(cs, int(getSize(n.typ))) - of nkBracket, nkPar, nkClosure, nkObjConstr: + of nkBracket, nkPar, nkClosure: var t = skipTypes(n.typ, abstractInst) if t.kind == tySequence: result = genConstSeq(p, n, n.typ) else: result = genConstSimpleList(p, n) + of nkObjConstr: + result = genConstObjConstr(p, n) else: var d: TLoc initLocExpr(p, n, d) diff --git a/tests/ccgbugs/tobjconstr_outoforder.nim b/tests/ccgbugs/tobjconstr_outoforder.nim new file mode 100644 index 000000000..846a753d5 --- /dev/null +++ b/tests/ccgbugs/tobjconstr_outoforder.nim @@ -0,0 +1,38 @@ +discard """ + output: '''(left: 1, up: 0, right: 2, down: 0) +(left: 0, up: 1, right: 0, down: 2) +@[(left: 1, up: 0, right: 2, down: 0), (left: 0, up: 1, right: 0, down: 2)] +@[(left: 1, up: 0, right: 2, down: 0), (left: 0, up: 1, right: 0, down: 2)] +true''' +""" + +# bug #5339 +type + Dirs = object + left: int + up: int + right: int + down: int + +let + a = Dirs( + left: 1, + right: 2, + ) + b = Dirs( + up: 1, + down: 2, + ) + works = @[ + a, + b, + ] + fails = @[ + Dirs(left: 1, right: 2), + Dirs(up: 1, down: 2), + ] +echo a +echo b +echo works +echo fails +echo works == fails |