diff --git a/build_all.bat b/build_all.bat index ef4a5f6a4e..bef7956f28 100644 --- a/build_all.bat +++ b/build_all.bat @@ -24,6 +24,6 @@ if not exist %nim_csources% ( cd .. copy /y bin\nim.exe %nim_csources% ) - bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch - koch boot -d:release --skipUserCfg --skipParentCfg --hints:off - koch tools --skipUserCfg --skipParentCfg --hints:off +bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch +koch boot -d:release --skipUserCfg --skipParentCfg --hints:off +koch tools --skipUserCfg --skipParentCfg --hints:off diff --git a/changelog.md b/changelog.md index e17b24b428..1310b6ae3f 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,11 @@ rounding guarantees (via the ## Standard library additions and changes +[//]: # "Additions:" +- `setutils.symmetricDifference` along with its operator version + `` setutils.`-+-` `` and in-place version `setutils.toggle` have been added + to more efficiently calculate the symmetric difference of bitsets. + [//]: # "Changes:" - `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type. diff --git a/compiler/ast.nim b/compiler/ast.nim index e2f335655b..6902d3a599 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -491,7 +491,7 @@ type mAnd, mOr, mImplies, mIff, mExists, mForall, mOld, mEqStr, mLeStr, mLtStr, - mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, + mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet, mConStrStr, mSlice, mDotDot, # this one is only necessary to give nice compile time warnings mFields, mFieldPairs, mOmpParFor, @@ -559,7 +559,7 @@ const mStrToStr, mEnumToStr, mAnd, mOr, mEqStr, mLeStr, mLtStr, - mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, + mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet, mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mInSet, mRepr, mOpenArrayToSeq} @@ -591,7 +591,7 @@ type TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes when defined(useNodeIds): id*: int - typ*: PType + typField: PType info*: TLineInfo flags*: TNodeFlags case kind*: TNodeKind @@ -708,7 +708,7 @@ type when defined(nimsuggest): endInfo*: TLineInfo hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints - owner*: PSym + ownerField: PSym flags*: TSymFlags ast*: PNode # syntax tree of proc, iterator, etc.: # the whole proc including header; this is used @@ -779,7 +779,7 @@ type # formal param list # for concepts, the concept body # else: unused - owner*: PSym # the 'owner' of the type + ownerField: PSym # the 'owner' of the type sym*: PSym # types have the sym associated with them # it is used for converting types to strings size*: BiggestInt # the size of the type in bytes @@ -818,6 +818,15 @@ type template nodeId(n: PNode): int = cast[int](n) +template typ*(n: PNode): PType = + n.typField + +proc owner*(s: PSym|PType): PSym {.inline.} = + result = s.ownerField + +proc setOwner*(s: PSym|PType, owner: PSym) {.inline.} = + s.ownerField = owner + type Gconfig = object # we put comments in a side channel to avoid increasing `sizeof(TNode)`, which # reduces memory usage given that `PNode` is the most allocated type by far. @@ -1136,7 +1145,7 @@ proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode = ## new node with line info, type, and no children result = newNode(kind) result.info = info - result.typ = typ + result.typ() = typ proc newNode*(kind: TNodeKind, info: TLineInfo): PNode = ## new node with line info, no type, and no children @@ -1201,7 +1210,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, idgen: IdGenerator; owner: PSym, assert not name.isNil let id = nextSymId idgen result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id, - options: options, owner: owner, offset: defaultOffset, + options: options, ownerField: owner, offset: defaultOffset, disamb: getOrDefault(idgen.disambTable, name).int32) idgen.disambTable.inc name when false: @@ -1282,13 +1291,13 @@ proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode = proc newSymNode*(sym: PSym): PNode = result = newNode(nkSym) result.sym = sym - result.typ = sym.typ + result.typ() = sym.typ result.info = sym.info proc newSymNode*(sym: PSym, info: TLineInfo): PNode = result = newNode(nkSym) result.sym = sym - result.typ = sym.typ + result.typ() = sym.typ result.info = info proc newOpenSym*(n: PNode): PNode {.inline.} = @@ -1368,7 +1377,7 @@ proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode = result = newNode(nkIntLit) else: raiseAssert $kind result.intVal = intVal - result.typ = typ + result.typ() = typ proc newIntTypeNode*(intVal: Int128, typ: PType): PNode = # XXX: introduce range check @@ -1507,7 +1516,7 @@ iterator signature*(t: PType): PType = proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType = nil): PType = let id = nextTypeId idgen - result = PType(kind: kind, owner: owner, size: defaultSize, + result = PType(kind: kind, ownerField: owner, size: defaultSize, align: defaultAlignment, itemId: id, uniqueId: id, sons: @[]) if son != nil: result.sons.add son @@ -1562,7 +1571,7 @@ proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType = result.sym = t.sym # backend-info should not be copied proc exactReplica*(t: PType): PType = - result = PType(kind: t.kind, owner: t.owner, size: defaultSize, + result = PType(kind: t.kind, ownerField: t.owner, size: defaultSize, align: defaultAlignment, itemId: t.itemId, uniqueId: t.uniqueId) assignType(result, t) @@ -1670,7 +1679,7 @@ proc copyNode*(src: PNode): PNode = return nil result = newNode(src.kind) result.info = src.info - result.typ = src.typ + result.typ() = src.typ result.flags = src.flags * PersistentNodeFlags result.comment = src.comment when defined(useNodeIds): @@ -1688,7 +1697,7 @@ proc copyNode*(src: PNode): PNode = template transitionNodeKindCommon(k: TNodeKind) = let obj {.inject.} = n[] - n[] = TNode(kind: k, typ: obj.typ, info: obj.info, flags: obj.flags) + n[] = TNode(kind: k, typField: n.typ, info: obj.info, flags: obj.flags) # n.comment = obj.comment # shouldn't be needed, the address doesnt' change when defined(useNodeIds): n.id = obj.id @@ -1711,7 +1720,7 @@ proc transitionNoneToSym*(n: PNode) = template transitionSymKindCommon*(k: TSymKind) = let obj {.inject.} = s[] s[] = TSym(kind: k, itemId: obj.itemId, magic: obj.magic, typ: obj.typ, name: obj.name, - info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast, + info: obj.info, ownerField: obj.ownerField, flags: obj.flags, ast: obj.ast, options: obj.options, position: obj.position, offset: obj.offset, loc: obj.loc, annex: obj.annex, constraint: obj.constraint) when hasFFI: @@ -1739,7 +1748,7 @@ template copyNodeImpl(dst, src, processSonsStmt) = dst.info = src.info when defined(nimsuggest): result.endInfo = src.endInfo - dst.typ = src.typ + dst.typ() = src.typ dst.flags = src.flags * PersistentNodeFlags dst.comment = src.comment when defined(useNodeIds): diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 4185c71826..1c54a85eb3 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -54,6 +54,32 @@ template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Loca initializerBody builder.add(";\n") +proc addArrayVar(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, initializer: Snippet = "") = + ## adds an array variable declaration to the builder + builder.addVarHeader(kind) + builder.add(elementType) + builder.add(" ") + builder.add(name) + builder.add("[") + builder.addInt(len) + builder.add("]") + if initializer.len != 0: + builder.add(" = ") + builder.add(initializer) + builder.add(";\n") + +template addArrayVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, body: typed) = + ## adds an array variable declaration to the builder with the initializer built according to `body` + builder.addVarHeader(kind) + builder.add(elementType) + builder.add(" ") + builder.add(name) + builder.add("[") + builder.addInt(len) + builder.add("] = ") + body + builder.add(";\n") + template addTypedef(builder: var Builder, name: string, typeBody: typed) = ## adds a typedef declaration to the builder with name `name` and type as ## built in `typeBody` @@ -63,41 +89,57 @@ template addTypedef(builder: var Builder, name: string, typeBody: typed) = builder.add(name) builder.add(";\n") -type StructInitializer = object - ## context for building struct initializers, i.e. `{ field1, field2 }` - # XXX use in genBracedInit - orderCompliant: bool - ## if true, fields will not be named, instead values are placed in order - needsComma: bool +type + StructInitializerKind = enum + siOrderedStruct ## struct constructor, but without named fields on C + siNamedStruct ## struct constructor, with named fields i.e. C99 designated initializer + siArray ## array constructor + siWrapper ## wrapper for a single field, generates it verbatim -proc initStructInitializer(builder: var Builder, orderCompliant: bool): StructInitializer = - ## starts building a struct initializer, `orderCompliant = true` means - ## built fields must be ordered correctly - doAssert orderCompliant, "named struct constructors unimplemented" - result = StructInitializer(orderCompliant: true, needsComma: false) - builder.add("{ ") + StructInitializer = object + ## context for building struct initializers, i.e. `{ field1, field2 }` + kind: StructInitializerKind + ## if true, fields will not be named, instead values are placed in order + needsComma: bool + +proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer = + ## starts building a struct initializer, i.e. braced initializer list + result = StructInitializer(kind: kind, needsComma: false) + if kind != siWrapper: + builder.add("{") template addField(builder: var Builder, constr: var StructInitializer, name: string, valueBody: typed) = ## adds a field to a struct initializer, with the value built in `valueBody` if constr.needsComma: + assert constr.kind != siWrapper, "wrapper constructor cannot have multiple fields" builder.add(", ") else: constr.needsComma = true - if constr.orderCompliant: + case constr.kind + of siArray, siWrapper: # no name, can just add value valueBody - else: - doAssert false, "named struct constructors unimplemented" + of siOrderedStruct: + # no name, can just add value on C + assert name.len != 0, "name has to be given for struct initializer field" + valueBody + of siNamedStruct: + assert name.len != 0, "name has to be given for struct initializer field" + builder.add(".") + builder.add(name) + builder.add(" = ") + valueBody proc finishStructInitializer(builder: var Builder, constr: StructInitializer) = ## finishes building a struct initializer - builder.add(" }") + if constr.kind != siWrapper: + builder.add("}") -template addStructInitializer(builder: var Builder, constr: out StructInitializer, orderCompliant: bool, body: typed) = +template addStructInitializer(builder: var Builder, constr: out StructInitializer, kind: StructInitializerKind, body: typed) = ## builds a struct initializer, i.e. `{ field1, field2 }` ## a `var StructInitializer` must be declared and passed as a parameter so ## that it can be used with `addField` - constr = builder.initStructInitializer(orderCompliant) + constr = builder.initStructInitializer(kind) body builder.finishStructInitializer(constr) diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index 16caaa0215..f381944ecc 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -15,5 +15,11 @@ const proc procPtrType(conv: TCallingConvention, rettype: Snippet, name: string): Snippet = CallingConvToStr[conv] & "_PTR(" & rettype & ", " & name & ")" +proc cCast(typ, value: Snippet): Snippet = + "((" & typ & ") " & value & ")" + +proc cAddr(value: Snippet): Snippet = + "&" & value + proc bitOr(a, b: Snippet): Snippet = - a & " | " & b + "(" & a & " | " & b & ")" diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index ac607e3ada..788f7a470b 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -336,7 +336,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need # variable. Thus, we create a temporary pointer variable instead. let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray if needsIndirect: - n.typ = n.typ.exactReplica + n.typ() = n.typ.exactReplica n.typ.flags.incl tfVarIsPtr a = initLocExprSingleUse(p, n) a = withTmpIfNeeded(p, a, needsTmp) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index a344816ba8..c954e6057b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -13,7 +13,7 @@ when defined(nimCompilerStacktraceHints): import std/stackframes proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode, - result: var Rope; count: var int; + result: var Builder; init: var StructInitializer; isConst: bool, info: TLineInfo) # -------------------------- constant expressions ------------------------ @@ -1626,7 +1626,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = var elem, arr: TLoc if n[1].kind == nkBracket: - n[1].typ = n.typ + n[1].typ() = n.typ genSeqConstr(p, n[1], d) return if d.k == locNone: @@ -2044,7 +2044,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) = proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = const - lookupOpr: array[mLeSet..mMinusSet, string] = [ + lookupOpr: array[mLeSet..mXorSet, string] = [ "for ($1 = 0; $1 < $2; $1++) { $n" & " $3 = (($4[$1] & ~ $5[$1]) == 0);$n" & " if (!$3) break;}$n", @@ -2054,7 +2054,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = "if ($3) $3 = (#nimCmpMem($4, $5, $2) != 0);$n", "&", "|", - "& ~"] + "& ~", + "^"] var a, b: TLoc var i: TLoc var setType = skipTypes(e[1].typ, abstractVar) @@ -2085,6 +2086,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mMulSet: binaryExpr(p, e, d, "($1 & $2)") of mPlusSet: binaryExpr(p, e, d, "($1 | $2)") of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)") + of mXorSet: binaryExpr(p, e, d, "($1 ^ $2)") of mInSet: genInOp(p, e, d) else: internalError(p.config, e.info, "genSetOp()") @@ -2112,7 +2114,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var a = initLocExpr(p, e[1]) var b = initLocExpr(p, e[2]) putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size])) - of mMulSet, mPlusSet, mMinusSet: + of mMulSet, mPlusSet, mMinusSet, mXorSet: # we inline the simple for loop for better code generation: i = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter a = initLocExpr(p, e[1]) @@ -2321,7 +2323,7 @@ proc genWasMoved(p: BProc; n: PNode) = # [addrLoc(p.config, a), getTypeDesc(p.module, a.t)]) proc genMove(p: BProc; n: PNode; d: var TLoc) = - var a: TLoc = initLocExpr(p, n[1].skipAddr) + var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref}) if n.len == 4: # generated by liftdestructors: var src: TLoc = initLocExpr(p, n[2]) @@ -2548,7 +2550,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mSetLengthStr: genSetLengthStr(p, e, d) of mSetLengthSeq: genSetLengthSeq(p, e, d) of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, - mInSet: + mInSet, mXorSet: genSetOp(p, e, d, op) of mNewString, mNewStringOfCap, mExit, mParseBiggestFloat: var opr = e[0].sym @@ -3077,7 +3079,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = # addr ( deref ( x )) --> x var x = n[0][0] if n.typ.skipTypes(abstractVar).kind != tyOpenArray: - x.typ = n.typ + x.typ() = n.typ expr(p, x, d) return genAddr(p, n, d) @@ -3193,7 +3195,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkMixinStmt, nkBindStmt: discard else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind") -proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) = +proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Builder) = var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc}) case t.kind of tyBool: result.add rope"NIM_FALSE" @@ -3204,38 +3206,56 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) = result.add rope"NIM_NIL" of tyString, tySequence: if optSeqDestructors in p.config.globalOptions: - result.add "{0, NIM_NIL}" + var seqInit: StructInitializer + result.addStructInitializer(seqInit, kind = siOrderedStruct): + result.addField(seqInit, name = "len"): + result.add("0") + result.addField(seqInit, name = "p"): + result.add("NIM_NIL") else: result.add "NIM_NIL" of tyProc: if t.callConv != ccClosure: result.add "NIM_NIL" else: - result.add "{NIM_NIL, NIM_NIL}" + var closureInit: StructInitializer + result.addStructInitializer(closureInit, kind = siOrderedStruct): + result.addField(closureInit, name = "ClP_0"): + result.add("NIM_NIL") + result.addField(closureInit, name = "ClE_0"): + result.add("NIM_NIL") of tyObject: - var count = 0 - result.add "{" - getNullValueAuxT(p, t, t, t.n, nil, result, count, true, info) - result.add "}" + var objInit: StructInitializer + result.addStructInitializer(objInit, kind = siOrderedStruct): + getNullValueAuxT(p, t, t, t.n, nil, result, objInit, true, info) of tyTuple: - result.add "{" - if p.vccAndC and t.isEmptyTupleType: - result.add "0" - for i, a in t.ikids: - if i > 0: result.add ", " - getDefaultValue(p, a, info, result) - result.add "}" + var tupleInit: StructInitializer + result.addStructInitializer(tupleInit, kind = siOrderedStruct): + if p.vccAndC and t.isEmptyTupleType: + result.addField(tupleInit, name = "dummy"): + result.add "0" + for i, a in t.ikids: + result.addField(tupleInit, name = "Field" & $i): + getDefaultValue(p, a, info, result) of tyArray: - result.add "{" - for i in 0.. 0: result.add ", " - getDefaultValue(p, t.elementType, info, result) - result.add "}" + var arrInit: StructInitializer + result.addStructInitializer(arrInit, kind = siArray): + for i in 0.. 0: res.add ", " + getNullValueAux(p, t, obj[0], constOrNil, result, init, isConst, info) var branch = Zero if constOrNil != nil: ## find kind value, default is zero if not specified @@ -3269,140 +3291,186 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, break let selectedBranch = caseObjDefaultBranch(obj, branch) - res.add "{" - var countB = 0 let b = lastSon(obj[selectedBranch]) # designated initilization is the only way to init non first element of unions # branches are allowed to have no members (b.len == 0), in this case they don't need initializer + var fieldName: string = "" if b.kind == nkRecList and not isEmptyCaseObjectBranch(b): - res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {" - getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info) - res.add "}" + fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch + result.addField(init, name = ""): + # XXX figure out name for the union, see use of `addAnonUnion` + var branchInit: StructInitializer + result.addStructInitializer(branchInit, kind = siNamedStruct): + result.addField(branchInit, name = fieldName): + var branchObjInit: StructInitializer + result.addStructInitializer(branchObjInit, kind = siOrderedStruct): + getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info) elif b.kind == nkSym: - res.add "." & mangleRecFieldName(p.module, b.sym) & " = " - getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info) + fieldName = mangleRecFieldName(p.module, b.sym) + result.addField(init, name = ""): + # XXX figure out name for the union, see use of `addAnonUnion` + var branchInit: StructInitializer + result.addStructInitializer(branchInit, kind = siNamedStruct): + result.addField(branchInit, name = fieldName): + # we need to generate the default value of the single sym, + # to do this create a dummy wrapper initializer and recurse + var branchFieldInit: StructInitializer + result.addStructInitializer(branchFieldInit, kind = siWrapper): + getNullValueAux(p, t, b, constOrNil, result, branchFieldInit, isConst, info) else: + # no fields, don't initialize return - result.add res - result.add "}" of nkSym: - if count > 0: result.add ", " - inc count let field = obj.sym - if constOrNil != nil: - for i in 1.. 0: result.add ",\n" - if it.kind == nkExprColonExpr: genBracedInit(p, it[1], isConst, it[0].typ, result) - else: genBracedInit(p, it, isConst, it.typ, result) - result.add("}\n") - -proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Rope) = - result.add "{" - if p.vccAndC and n.len == 0: - result.add "0" - for i in 0.. 0: result.add ",\n" - if it.kind == nkExprColonExpr: genBracedInit(p, it[1], isConst, tup[i], result) - else: genBracedInit(p, it, isConst, tup[i], result) - result.add("}\n") - -proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var 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(", {") +proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Builder) = + var arrInit: StructInitializer + result.addStructInitializer(arrInit, kind = siArray): + if p.vccAndC and n.len == 0 and n.typ.kind == tyArray: + result.addField(arrInit, name = ""): + getDefaultValue(p, n.typ.elementType, n.info, result) for i in 0.. 0: data.addf(",$n", []) - genBracedInit(p, n[i], isConst, base, data) - data.add("}") - data.add("}") + let it = n[i] + var ind, val: PNode + if it.kind == nkExprColonExpr: + ind = it[0] + val = it[1] + else: + ind = it + val = it + result.addField(arrInit, name = ""): + genBracedInit(p, val, isConst, ind.typ, result) +proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Builder) = + var tupleInit: StructInitializer + result.addStructInitializer(tupleInit, kind = siOrderedStruct): + if p.vccAndC and n.len == 0: + result.addField(tupleInit, name = "dummy"): + result.add("0") + for i in 0.. 0: + def.addField(structInit, name = "data"): + var arrInit: StructInitializer + def.addStructInitializer(arrInit, kind = siArray): + for i in 0.. 0: - data.add(", {") - for i in 0.. 0: data.addf(",$n", []) - genBracedInit(p, n[i], isConst, base, data) - data.add("}") - let payload = getTempName(p.module) - appcg(p.module, cfsStrData, - "static $5 struct {$n" & - " NI cap; $1 data[$2];$n" & - "} $3 = {$2 | NIM_STRLIT_FLAG$4};$n", [ - getTypeDesc(p.module, base), n.len, payload, data, - if isConst: "const" else: ""]) - result.add "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload] -proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Rope) = + var def = newBuilder("") + def.addVarWithTypeAndInitializer( + if isConst: AlwaysConst else: Global, + name = payload): + def.addSimpleStruct(p.module, name = "", baseType = ""): + def.addField(name = "cap", typ = "NI") + def.addArrayField(name = "data", elementType = getTypeDesc(p.module, base), len = n.len) + do: + var structInit: StructInitializer + def.addStructInitializer(structInit, kind = siOrderedStruct): + def.addField(structInit, name = "cap"): + def.add(bitOr(rope(n.len), "NIM_STRLIT_FLAG")) + if n.len > 0: + def.addField(structInit, name = "data"): + var arrInit: StructInitializer + def.addStructInitializer(arrInit, kind = siArray): + for i in 0..