mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
const view types; fixes some cases from https://github.com/nim-lang/Nim/issues/15428 (#15488)
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
26
tests/views/tconst_views.nim
Normal file
26
tests/views/tconst_views.nim
Normal file
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user