diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-10-05 18:31:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-05 18:31:46 +0200 |
commit | 4e438f9096fc413824bdbe8377a4ca376d63be35 (patch) | |
tree | 3f3dd5907e3b8469423da747418e3d7abbdd4d81 | |
parent | 1e28cea0d102afd43a62f6f7fcabd65cd8996762 (diff) | |
download | Nim-4e438f9096fc413824bdbe8377a4ca376d63be35.tar.gz |
const view types; fixes some cases from https://github.com/nim-lang/Nim/issues/15428 (#15488)
-rw-r--r-- | compiler/astalgo.nim | 9 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 95 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 4 | ||||
-rw-r--r-- | compiler/cgen.nim | 3 | ||||
-rw-r--r-- | compiler/typeallowed.nim | 2 | ||||
-rw-r--r-- | compiler/vmgen.nim | 2 | ||||
-rw-r--r-- | tests/views/tconst_views.nim | 26 |
7 files changed, 94 insertions, 47 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 5e23d2284..6aecb1dcb 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -591,10 +591,17 @@ proc value(this: var DebugPrinter; value: PNode) = if this.conf != nil: this.key "info" this.value $lineInfoToStr(this.conf, value.info) - if card(value.flags) > 0: + if value.flags != {}: this.key "flags" this.value value.flags + if value.typ != nil: + this.key "typ" + this.value value.typ.kind + else: + this.key "typ" + this.value "nil" + case value.kind of nkCharLit..nkUInt64Lit: this.key "intVal" diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index b58519614..364bcc143 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1400,7 +1400,7 @@ proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) = # expression not found in the cache: inc(p.module.labels) p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true)]) + [getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true, t)]) proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr: @@ -2485,7 +2485,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) = inc(p.module.labels) var tmp = "CNSTCLOSURE" & rope(p.module.labels) p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, n.typ), tmp, genBracedInit(p, n, isConst = true)]) + [getTypeDesc(p.module, n.typ), tmp, genBracedInit(p, n, isConst = true, n.typ)]) putIntoDest(p, d, n, tmp, OnStatic) else: var tmp, a, b: TLoc @@ -2624,7 +2624,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) = # expression not found in the cache: inc(p.module.labels) p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, t), tmp, genBracedInit(p, n, isConst = true)]) + [getTypeDesc(p.module, t, skConst), tmp, genBracedInit(p, n, isConst = true, t)]) if d.k == locNone: fillLoc(d, locData, n, tmp, OnStatic) @@ -2847,8 +2847,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind") proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope = - if n.kind == nkExprColonExpr: result = genBracedInit(p, n[1], isConst) - else: result = genBracedInit(p, n, isConst) + if n.kind == nkExprColonExpr: result = genBracedInit(p, n[1], isConst, n[0].typ) + else: result = genBracedInit(p, n, isConst, n.typ) proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope = var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc}) @@ -2955,10 +2955,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, for i in 1..<constOrNil.len: if constOrNil[i].kind == nkExprColonExpr: if constOrNil[i][0].sym.name.id == field.name.id: - result.add genBracedInit(p, constOrNil[i][1], isConst) + result.add genBracedInit(p, constOrNil[i][1], isConst, field.typ) return elif i == field.position: - result.add genBracedInit(p, constOrNil[i], isConst) + result.add genBracedInit(p, constOrNil[i], isConst, field.typ) return # not found, produce default value: result.add getDefaultValue(p, field.typ, info) @@ -2999,25 +2999,35 @@ proc genConstObjConstr(p: BProc; n: PNode; isConst: bool): Rope = proc genConstSimpleList(p: BProc, n: PNode; isConst: bool): Rope = result = rope("{") - for i in 0..<n.len - 1: - result.addf("$1,$n", [genNamedConstExpr(p, n[i], isConst)]) - if n.len > 0: - result.add(genNamedConstExpr(p, n[^1], isConst)) - result.addf("}$n", []) + for i in 0..<n.len: + let it = n[i] + if i > 0: result.add ",\n" + if it.kind == nkExprColonExpr: result.add genBracedInit(p, it[1], isConst, it[0].typ) + else: result.add genBracedInit(p, it, isConst, it.typ) + result.add("}\n") + +proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType): Rope = + result = rope("{") + for i in 0..<n.len: + let it = n[i] + if i > 0: result.add ",\n" + if it.kind == nkExprColonExpr: result.add genBracedInit(p, it[1], isConst, tup[i]) + else: result.add genBracedInit(p, it, isConst, tup[i]) + result.add("}\n") proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope = var data = "{{$1, $1 | NIM_STRLIT_FLAG}" % [n.len.rope] + let base = t.skipTypes(abstractInst)[0] if n.len > 0: # array part needs extra curlies: data.add(", {") for i in 0..<n.len: if i > 0: data.addf(",$n", []) - data.add genBracedInit(p, n[i], isConst) + data.add genBracedInit(p, n[i], isConst, base) data.add("}") data.add("}") result = getTempName(p.module) - let base = t.skipTypes(abstractInst)[0] appcg(p.module, cfsData, "static $5 struct {$n" & @@ -3030,14 +3040,14 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope = result = "(($1)&$2)" % [getTypeDesc(p.module, t), result] proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope = + let base = t.skipTypes(abstractInst)[0] var data = rope"{" for i in 0..<n.len: if i > 0: data.addf(",$n", []) - data.add genBracedInit(p, n[i], isConst) + data.add genBracedInit(p, n[i], isConst, base) data.add("}") let payload = getTempName(p.module) - let base = t.skipTypes(abstractInst)[0] appcg(p.module, cfsData, "static $5 struct {$n" & @@ -3047,46 +3057,32 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope = if isConst: "const" else: ""]) result = "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload] -proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope = +proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType): Rope = case n.kind of nkHiddenStdConv, nkHiddenSubConv: - when false: - # XXX The frontend doesn't keep conversions to openArray for us. :-( - # We need to change 'transformConv' first, but that is hard. - if n.typ.kind == tyOpenArray: - assert n[1].kind == nkBracket - let data = genBracedInit(p, n[1], isConst) - - let payload = getTempName(p.module) - let ctype = getTypeDesc(p.module, n.typ.skipTypes(abstractInst)[0]) - let arrLen = n[1].len - appcg(p.module, cfsData, - "static $5 $1 $3[$2] = $4;$n", [ - ctype, arrLen, payload, data, - if isConst: "const" else: ""]) - result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen] - else: - result = genBracedInit(p, n[1], isConst) + result = genBracedInit(p, n[1], isConst, n.typ) else: var ty = tyNone - if n.typ == nil: + var typ: PType = nil + if optionalType == nil: if n.kind in nkStrKinds: ty = tyString else: internalError(p.config, n.info, "node has no type") else: - ty = skipTypes(n.typ, abstractInstOwned + {tyStatic}).kind + typ = skipTypes(optionalType, abstractInstOwned + {tyStatic}) + ty = typ.kind case ty of tySet: let cs = toBitSet(p.config, n) result = genRawSetData(cs, int(getSize(p.config, n.typ))) of tySequence: if optSeqDestructors in p.config.globalOptions: - result = genConstSeqV2(p, n, n.typ, isConst) + result = genConstSeqV2(p, n, typ, isConst) else: - result = genConstSeq(p, n, n.typ, isConst) + result = genConstSeq(p, n, typ, isConst) of tyProc: - if n.typ.callConv == ccClosure and n.len > 1 and n[1].kind == nkNilLit: + if typ.callConv == ccClosure and n.len > 1 and n[1].kind == nkNilLit: # Conversion: nimcall -> closure. # this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL} # this behaviour is needed since closure_var = nil must be @@ -3099,13 +3095,30 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope = else: var d: TLoc initLocExpr(p, n[0], d) - result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, n.typ, clHalfWithEnv), rdLoc(d)] + result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, typ, clHalfWithEnv), rdLoc(d)] else: var d: TLoc initLocExpr(p, n, d) result = rdLoc(d) - of tyArray, tyTuple, tyOpenArray, tyVarargs: + of tyArray, tyVarargs: result = genConstSimpleList(p, n, isConst) + of tyTuple: + result = genConstTuple(p, n, isConst, typ) + of tyOpenArray: + if n.kind != nkBracket: + internalError(p.config, n.info, "const openArray expression is not an array construction") + + let data = genConstSimpleList(p, n, isConst) + + let payload = getTempName(p.module) + let ctype = getTypeDesc(p.module, typ[0]) + let arrLen = n.len + appcg(p.module, cfsData, + "static $5 $1 $3[$2] = $4;$n", [ + ctype, arrLen, payload, data, + if isConst: "const" else: ""]) + result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen] + of tyObject: result = genConstObjConstr(p, n, isConst) of tyString, tyCString: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 5bed7cf32..1282cf11f 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -272,7 +272,7 @@ proc genGotoVar(p: BProc; value: PNode) = else: lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope]) -proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope +proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType): Rope proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope = if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn: @@ -280,7 +280,7 @@ proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope = elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and p.withinLoop == 0 and not containsGarbageCollectedRef(v.typ): #echo "New code produced for ", v.name.s, " ", p.config $ value.info - result = genBracedInit(p, value, isConst = false) + result = genBracedInit(p, value, isConst = false, v.typ) else: result = nil diff --git a/compiler/cgen.nim b/compiler/cgen.nim index f50676647..9a50b718c 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1195,7 +1195,8 @@ proc requestConstImpl(p: BProc, sym: PSym) = # add a suffix for hcr - will later init the global pointer with this data let actualConstName = if m.hcrOn: sym.loc.r & "_const" else: sym.loc.r q.s[cfsData].addf("N_LIB_PRIVATE NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(q, sym.typ), actualConstName, genBracedInit(q.initProc, sym.ast, isConst = true)]) + [getTypeDesc(q, sym.typ), actualConstName, + genBracedInit(q.initProc, sym.ast, isConst = true, sym.typ)]) if m.hcrOn: # generate the global pointer with the real name q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, skVar), sym.loc.r]) diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index 13eff35be..a8210508c 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -217,7 +217,7 @@ proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind = case t.kind of tyVar: result = mutableView - of tyLent, tyVarargs, tyOpenArray: + of tyLent, tyOpenArray: result = immutableView of tyGenericInst, tyDistinct, tyAlias, tyInferred, tySink, tyOwned, tyUncheckedArray, tySequence, tyArray, tyRef, tyStatic: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index ad5023aeb..6f81c6a9c 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1807,7 +1807,7 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode = result.add getNullValue(t[i], info, conf) of tySet: result = newNodeIT(nkCurly, info, t) - of tySequence: + of tySequence, tyOpenArray: result = newNodeIT(nkBracket, info, t) else: globalError(conf, info, "cannot create null element for: " & $t.kind) diff --git a/tests/views/tconst_views.nim b/tests/views/tconst_views.nim new file mode 100644 index 000000000..d7f1fc481 --- /dev/null +++ b/tests/views/tconst_views.nim @@ -0,0 +1,26 @@ +discard """ + cmd: "nim c --experimental:views $file" + output: '''(data: [1, 2, 3], other: 4) +[1, 20, 3]''' +""" + +type + Foo = object + data: openArray[int] + other: int + +const + c = Foo(data: [1, 2, 3], other: 4) + + c2 = Foo(data: [1, 20, 3], other: 4) + +proc `$`(x: openArray[int]): string = + result = "[" + for i in x: + if result.len > 1: result.add ", " + result.add $i + result.add "]" + +echo c +echo c2.data + |