const view types; fixes some cases from https://github.com/nim-lang/Nim/issues/15428 (#15488)

This commit is contained in:
Andreas Rumpf
2020-10-05 18:31:46 +02:00
committed by GitHub
parent 1e28cea0d1
commit 4e438f9096
7 changed files with 94 additions and 47 deletions

View File

@@ -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"

View File

@@ -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:

View File

@@ -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

View File

@@ -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])

View File

@@ -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:

View File

@@ -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)

View 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