mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-08 05:53:22 +00:00
Merge branch 'devel' into fix_15097
This commit is contained in:
@@ -1,44 +1,56 @@
|
||||
import ropes, int128
|
||||
|
||||
type
|
||||
Snippet = string
|
||||
Builder = string
|
||||
Snippet* = string
|
||||
Builder* = object
|
||||
buf*: string
|
||||
|
||||
template newBuilder(s: string): Builder =
|
||||
s
|
||||
template newBuilder*(s: string): Builder =
|
||||
Builder(buf: s)
|
||||
|
||||
proc addIntValue(builder: var Builder, val: int) =
|
||||
builder.addInt(val)
|
||||
proc extract*(builder: Builder): Snippet =
|
||||
builder.buf
|
||||
|
||||
proc addIntValue(builder: var Builder, val: int64) =
|
||||
builder.addInt(val)
|
||||
proc add*(builder: var Builder, s: string) =
|
||||
builder.buf.add(s)
|
||||
|
||||
proc addIntValue(builder: var Builder, val: uint64) =
|
||||
builder.addInt(val)
|
||||
proc add*(builder: var Builder, s: char) =
|
||||
builder.buf.add(s)
|
||||
|
||||
proc addIntValue(builder: var Builder, val: Int128) =
|
||||
builder.addInt128(val)
|
||||
proc addIntValue*(builder: var Builder, val: int) =
|
||||
builder.buf.addInt(val)
|
||||
|
||||
template cIntValue(val: int): Snippet = $val
|
||||
template cIntValue(val: int64): Snippet = $val
|
||||
template cIntValue(val: uint64): Snippet = $val
|
||||
template cIntValue(val: Int128): Snippet = $val
|
||||
proc addIntValue*(builder: var Builder, val: int64) =
|
||||
builder.buf.addInt(val)
|
||||
|
||||
proc addIntValue*(builder: var Builder, val: uint64) =
|
||||
builder.buf.addInt(val)
|
||||
|
||||
proc addIntValue*(builder: var Builder, val: Int128) =
|
||||
builder.buf.addInt128(val)
|
||||
|
||||
template cIntValue*(val: int): Snippet = $val
|
||||
template cIntValue*(val: int64): Snippet = $val
|
||||
template cIntValue*(val: uint64): Snippet = $val
|
||||
template cIntValue*(val: Int128): Snippet = $val
|
||||
|
||||
import std/formatfloat
|
||||
|
||||
proc addFloatValue(builder: var Builder, val: float) =
|
||||
builder.addFloat(val)
|
||||
proc addFloatValue*(builder: var Builder, val: float) =
|
||||
builder.buf.addFloat(val)
|
||||
|
||||
template cFloatValue(val: float): Snippet = $val
|
||||
template cFloatValue*(val: float): Snippet = $val
|
||||
|
||||
proc int64Literal(i: BiggestInt; result: var Builder) =
|
||||
proc addInt64Literal*(result: var Builder; i: BiggestInt) =
|
||||
if i > low(int64):
|
||||
result.add "IL64($1)" % [rope(i)]
|
||||
else:
|
||||
result.add "(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc uint64Literal(i: uint64; result: var Builder) =
|
||||
proc addUint64Literal*(result: var Builder; i: uint64) =
|
||||
result.add rope($i & "ULL")
|
||||
|
||||
proc intLiteral(i: BiggestInt; result: var Builder) =
|
||||
proc addIntLiteral*(result: var Builder; i: BiggestInt) =
|
||||
if i > low(int32) and i <= high(int32):
|
||||
result.addIntValue(i)
|
||||
elif i == low(int32):
|
||||
@@ -49,19 +61,19 @@ proc intLiteral(i: BiggestInt; result: var Builder) =
|
||||
else:
|
||||
result.add "(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc intLiteral(i: Int128; result: var Builder) =
|
||||
intLiteral(toInt64(i), result)
|
||||
proc addIntLiteral*(result: var Builder; i: Int128) =
|
||||
addIntLiteral(result, toInt64(i))
|
||||
|
||||
proc cInt64Literal(i: BiggestInt): Snippet =
|
||||
proc cInt64Literal*(i: BiggestInt): Snippet =
|
||||
if i > low(int64):
|
||||
result = "IL64($1)" % [rope(i)]
|
||||
else:
|
||||
result = "(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc cUint64Literal(i: uint64): Snippet =
|
||||
proc cUint64Literal*(i: uint64): Snippet =
|
||||
result = $i & "ULL"
|
||||
|
||||
proc cIntLiteral(i: BiggestInt): Snippet =
|
||||
proc cIntLiteral*(i: BiggestInt): Snippet =
|
||||
if i > low(int32) and i <= high(int32):
|
||||
result = rope(i)
|
||||
elif i == low(int32):
|
||||
@@ -72,5 +84,5 @@ proc cIntLiteral(i: BiggestInt): Snippet =
|
||||
else:
|
||||
result = "(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc cIntLiteral(i: Int128): Snippet =
|
||||
proc cIntLiteral*(i: Int128): Snippet =
|
||||
result = cIntLiteral(toInt64(i))
|
||||
|
||||
@@ -42,6 +42,18 @@ template addVarWithType(builder: var Builder, kind: VarKind = Local, name: strin
|
||||
builder.add(name)
|
||||
builder.add(";\n")
|
||||
|
||||
template addVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string,
|
||||
typ: Snippet, initializerBody: typed) =
|
||||
## adds a variable declaration to the builder, with
|
||||
## `initializerBody` building the initializer. initializer must be provided
|
||||
builder.addVarHeader(kind)
|
||||
builder.add(typ)
|
||||
builder.add(" ")
|
||||
builder.add(name)
|
||||
builder.add(" = ")
|
||||
initializerBody
|
||||
builder.add(";\n")
|
||||
|
||||
template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Local, name: string,
|
||||
typeBody, initializerBody: typed) =
|
||||
## adds a variable declaration to the builder, with `typeBody` building the type, and
|
||||
@@ -252,12 +264,12 @@ proc startSimpleStruct(obj: var Builder; m: BModule; name: string; baseType: Sni
|
||||
obj.add(baseType)
|
||||
obj.add(" ")
|
||||
obj.add("{\n")
|
||||
result.preFieldsLen = obj.len
|
||||
result.preFieldsLen = obj.buf.len
|
||||
if result.baseKind == bcSupField:
|
||||
obj.addField(name = "Sup", typ = baseType)
|
||||
|
||||
proc finishSimpleStruct(obj: var Builder; m: BModule; info: StructBuilderInfo) =
|
||||
if info.baseKind == bcNone and info.preFieldsLen == obj.len:
|
||||
if info.baseKind == bcNone and info.preFieldsLen == obj.buf.len:
|
||||
# no fields were added, add dummy field
|
||||
obj.addField(name = "dummy", typ = "char")
|
||||
if info.named:
|
||||
@@ -308,7 +320,7 @@ proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType:
|
||||
obj.add(baseType)
|
||||
obj.add(" ")
|
||||
obj.add("{\n")
|
||||
result.preFieldsLen = obj.len
|
||||
result.preFieldsLen = obj.buf.len
|
||||
case result.baseKind
|
||||
of bcNone:
|
||||
# rest of the options add a field or don't need it due to inheritance,
|
||||
@@ -328,7 +340,7 @@ proc startStruct(obj: var Builder; m: BModule; t: PType; name: string; baseType:
|
||||
obj.addField(name = "Sup", typ = baseType)
|
||||
|
||||
proc finishStruct(obj: var Builder; m: BModule; t: PType; info: StructBuilderInfo) =
|
||||
if info.baseKind == bcNone and info.preFieldsLen == obj.len and
|
||||
if info.baseKind == bcNone and info.preFieldsLen == obj.buf.len and
|
||||
t.itemId notin m.g.graph.memberProcsPerType:
|
||||
# no fields were added, add dummy field
|
||||
obj.addField(name = "dummy", typ = "char")
|
||||
|
||||
@@ -93,6 +93,32 @@ template addElseBranch(builder: var Builder, stmt: var IfStmt, body: typed) =
|
||||
body
|
||||
builder.add("}")
|
||||
|
||||
proc addForRangeHeader(builder: var Builder, i, start, bound: Snippet, inclusive: bool = false) =
|
||||
builder.add("for (")
|
||||
builder.add(i)
|
||||
builder.add(" = ")
|
||||
builder.add(start)
|
||||
builder.add("; ")
|
||||
builder.add(i)
|
||||
if inclusive:
|
||||
builder.add(" <= ")
|
||||
else:
|
||||
builder.add(" < ")
|
||||
builder.add(bound)
|
||||
builder.add("; ")
|
||||
builder.add(i)
|
||||
builder.add("++) {\n")
|
||||
|
||||
template addForRangeExclusive(builder: var Builder, i, start, bound: Snippet, body: typed) =
|
||||
addForRangeHeader(builder, i, start, bound, false)
|
||||
body
|
||||
builder.add("}\n")
|
||||
|
||||
template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, body: typed) =
|
||||
addForRangeHeader(builder, i, start, bound, true)
|
||||
body
|
||||
builder.add("}\n")
|
||||
|
||||
template addScope(builder: var Builder, body: typed) =
|
||||
builder.add("{")
|
||||
body
|
||||
|
||||
@@ -209,8 +209,7 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareF
|
||||
result = ("($3*)(($1)+($2))" % [rdLoc(a), rdLoc(b), dest],
|
||||
lengthExpr)
|
||||
else:
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(first, lit)
|
||||
let lit = cIntLiteral(first)
|
||||
result = ("($4*)($1)+(($2)-($3))" %
|
||||
[rdLoc(a), rdLoc(b), lit, dest],
|
||||
lengthExpr)
|
||||
|
||||
@@ -34,15 +34,15 @@ proc genLiteral(p: BProc, n: PNode, ty: PType; result: var Builder) =
|
||||
else: k = tyNil # don't go into the case variant that uses 'ty'
|
||||
case k
|
||||
of tyChar, tyNil:
|
||||
intLiteral(n.intVal, result)
|
||||
result.addIntLiteral(n.intVal)
|
||||
of tyBool:
|
||||
if n.intVal != 0: result.add "NIM_TRUE"
|
||||
else: result.add "NIM_FALSE"
|
||||
of tyInt64: int64Literal(n.intVal, result)
|
||||
of tyUInt64: uint64Literal(uint64(n.intVal), result)
|
||||
of tyInt64: result.addInt64Literal(n.intVal)
|
||||
of tyUInt64: result.addUint64Literal(uint64(n.intVal))
|
||||
else:
|
||||
result.addCast(getTypeDesc(p.module, ty)):
|
||||
intLiteral(n.intVal, result)
|
||||
result.addIntLiteral(n.intVal)
|
||||
of nkNilLit:
|
||||
let k = if ty == nil: tyPointer else: skipTypes(ty, abstractVarRange).kind
|
||||
if k == tyProc and skipTypes(ty, abstractVarRange).callConv == ccClosure:
|
||||
@@ -51,17 +51,14 @@ proc genLiteral(p: BProc, n: PNode, ty: PType; result: var Builder) =
|
||||
if id == p.module.labels:
|
||||
# not found in cache:
|
||||
inc(p.module.labels)
|
||||
var data = newBuilder("")
|
||||
data.addVarWithTypeAndInitializer(kind = Const, name = tmpName):
|
||||
data.add(getTypeDesc(p.module, ty))
|
||||
do:
|
||||
let t = getTypeDesc(p.module, ty)
|
||||
p.module.s[cfsStrData].addVarWithInitializer(kind = Const, name = tmpName, typ = t):
|
||||
var closureInit: StructInitializer
|
||||
data.addStructInitializer(closureInit, kind = siOrderedStruct):
|
||||
data.addField(closureInit, name = "ClP_0"):
|
||||
data.add("NIM_NIL")
|
||||
data.addField(closureInit, name = "ClE_0"):
|
||||
data.add("NIM_NIL")
|
||||
p.module.s[cfsStrData].add(data)
|
||||
p.module.s[cfsStrData].addStructInitializer(closureInit, kind = siOrderedStruct):
|
||||
p.module.s[cfsStrData].addField(closureInit, name = "ClP_0"):
|
||||
p.module.s[cfsStrData].add("NIM_NIL")
|
||||
p.module.s[cfsStrData].addField(closureInit, name = "ClE_0"):
|
||||
p.module.s[cfsStrData].add("NIM_NIL")
|
||||
result.add tmpName
|
||||
elif k in {tyPointer, tyNil, tyProc}:
|
||||
result.add rope("NIM_NIL")
|
||||
@@ -107,7 +104,7 @@ proc genRawSetData(cs: TBitSet, size: int; result: var Builder) =
|
||||
result.add "0123456789abcdef"[cs[i] div 16]
|
||||
result.add "0123456789abcdef"[cs[i] mod 16]
|
||||
else:
|
||||
intLiteral(cast[BiggestInt](bitSetToWord(cs, size)), result)
|
||||
result.addIntLiteral(cast[BiggestInt](bitSetToWord(cs, size)))
|
||||
|
||||
proc genSetNode(p: BProc, n: PNode; result: var Builder) =
|
||||
var size = int(getSize(p.config, n.typ))
|
||||
@@ -118,12 +115,9 @@ proc genSetNode(p: BProc, n: PNode; result: var Builder) =
|
||||
if id == p.module.labels:
|
||||
# not found in cache:
|
||||
inc(p.module.labels)
|
||||
var data = newBuilder("")
|
||||
data.addVarWithTypeAndInitializer(kind = Const, name = tmpName):
|
||||
data.add(getTypeDesc(p.module, n.typ))
|
||||
do:
|
||||
genRawSetData(cs, size, data)
|
||||
p.module.s[cfsStrData].add(data)
|
||||
let td = getTypeDesc(p.module, n.typ)
|
||||
p.module.s[cfsStrData].addVarWithInitializer(kind = Const, name = tmpName, typ = td):
|
||||
genRawSetData(cs, size, p.module.s[cfsStrData])
|
||||
result.add tmpName
|
||||
else:
|
||||
genRawSetData(cs, size, result)
|
||||
@@ -1065,8 +1059,9 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
|
||||
# passing around `TLineInfo` + the set of files in the project.
|
||||
msg.add toFileLineCol(p.config, e.info) & " "
|
||||
msg.add genFieldDefect(p.config, field.name.s, disc.sym)
|
||||
var strLit = newRopeAppender()
|
||||
genStringLiteral(p.module, newStrNode(nkStrLit, msg), strLit)
|
||||
var strLitBuilder = newBuilder("")
|
||||
genStringLiteral(p.module, newStrNode(nkStrLit, msg), strLitBuilder)
|
||||
let strLit = extract(strLitBuilder)
|
||||
|
||||
## discriminant check
|
||||
let rt = rdLoc(test)
|
||||
@@ -1456,7 +1451,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
var tmp: TLoc = getTemp(p, e.typ)
|
||||
var L = 0
|
||||
var appends = newBuilder("")
|
||||
var appends: seq[Snippet] = @[]
|
||||
var lens: seq[Snippet] = @[]
|
||||
for i in 0..<e.len - 1:
|
||||
# compute the length expression:
|
||||
@@ -1465,23 +1460,21 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||
let ra = rdLoc(a)
|
||||
if skipTypes(e[i + 1].typ, abstractVarRange).kind == tyChar:
|
||||
inc(L)
|
||||
appends.addCallStmt(cgsymValue(p.module, "appendChar"),
|
||||
rstmp,
|
||||
ra)
|
||||
appends.add(cCall(cgsymValue(p.module, "appendChar"), rstmp, ra))
|
||||
else:
|
||||
if e[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||
inc(L, e[i + 1].strVal.len)
|
||||
else:
|
||||
lens.add(lenExpr(p, a))
|
||||
appends.addCallStmt(cgsymValue(p.module, "appendString"),
|
||||
rstmp,
|
||||
ra)
|
||||
appends.add(cCall(cgsymValue(p.module, "appendString"), rstmp, ra))
|
||||
var exprL = cIntValue(L)
|
||||
for len in lens:
|
||||
exprL = cOp(Add, "NI", exprL, len)
|
||||
p.s(cpsStmts).addAssignmentWithValue(tmp.snippet):
|
||||
p.s(cpsStmts).addCall(cgsymValue(p.module, "rawNewString"), exprL)
|
||||
p.s(cpsStmts).add appends
|
||||
for append in appends:
|
||||
p.s(cpsStmts).addStmt():
|
||||
p.s(cpsStmts).add(append)
|
||||
if d.k == locNone:
|
||||
d = tmp
|
||||
else:
|
||||
@@ -1502,7 +1495,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
# }
|
||||
var
|
||||
a, call: TLoc
|
||||
appends = newBuilder("")
|
||||
appends: seq[Snippet] = @[]
|
||||
assert(d.k == locNone)
|
||||
var L = 0
|
||||
var lens: seq[Snippet] = @[]
|
||||
@@ -1514,17 +1507,13 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
let ra = rdLoc(a)
|
||||
if skipTypes(e[i + 2].typ, abstractVarRange).kind == tyChar:
|
||||
inc(L)
|
||||
appends.addCallStmt(cgsymValue(p.module, "appendChar"),
|
||||
rsd,
|
||||
ra)
|
||||
appends.add(cCall(cgsymValue(p.module, "appendChar"), rsd, ra))
|
||||
else:
|
||||
if e[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||
inc(L, e[i + 2].strVal.len)
|
||||
else:
|
||||
lens.add(lenExpr(p, a))
|
||||
appends.addCallStmt(cgsymValue(p.module, "appendString"),
|
||||
rsd,
|
||||
ra)
|
||||
appends.add(cCall(cgsymValue(p.module, "appendString"), rsd, ra))
|
||||
var exprL = cIntValue(L)
|
||||
for len in lens:
|
||||
exprL = cOp(Add, "NI", exprL, len)
|
||||
@@ -1535,15 +1524,15 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
exprL)
|
||||
else:
|
||||
call = initLoc(locCall, e, OnHeap)
|
||||
var callRes = newBuilder("")
|
||||
let rd = rdLoc(dest)
|
||||
callRes.addCall(cgsymValue(p.module, "resizeString"),
|
||||
call.snippet = cCall(cgsymValue(p.module, "resizeString"),
|
||||
rd,
|
||||
exprL)
|
||||
call.snippet = callRes
|
||||
genAssignment(p, dest, call, {})
|
||||
gcUsage(p.config, e)
|
||||
p.s(cpsStmts).add appends
|
||||
for append in appends:
|
||||
p.s(cpsStmts).addStmt():
|
||||
p.s(cpsStmts).add(append)
|
||||
|
||||
proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
# seq &= x -->
|
||||
@@ -1553,13 +1542,11 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||
var b = initLocExpr(p, e[2])
|
||||
let seqType = skipTypes(e[1].typ, {tyVar})
|
||||
var call = initLoc(locCall, e, OnHeap)
|
||||
var callRes = newBuilder("")
|
||||
let ra = rdLoc(a)
|
||||
callRes.addCast(getTypeDesc(p.module, e[1].typ)):
|
||||
callRes.addCall(cgsymValue(p.module, "incrSeqV3"),
|
||||
call.snippet = cCast(getTypeDesc(p.module, e[1].typ),
|
||||
cCall(cgsymValue(p.module, "incrSeqV3"),
|
||||
if not p.module.compileToCpp: cCast(ptrType("TGenericSeq"), ra) else: ra,
|
||||
genTypeInfoV1(p.module, seqType, e.info))
|
||||
call.snippet = callRes
|
||||
genTypeInfoV1(p.module, seqType, e.info)))
|
||||
# emit the write barrier if required, but we can always move here, so
|
||||
# use 'genRefAssign' for the seq.
|
||||
genRefAssign(p, a, call)
|
||||
@@ -1589,12 +1576,10 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
let fnName = cgsymValue(p.module, if needsInit: "nimNewObj" else: "nimNewObjUninit")
|
||||
var bres = newBuilder("")
|
||||
bres.addCast(getTypeDesc(p.module, typ)):
|
||||
bres.addCall(fnName,
|
||||
b.snippet = cCast(getTypeDesc(p.module, typ),
|
||||
cCall(fnName,
|
||||
sizeExpr,
|
||||
cAlignof(getTypeDesc(p.module, bt)))
|
||||
b.snippet = bres
|
||||
cAlignof(getTypeDesc(p.module, bt))))
|
||||
genAssignment(p, a, b, {})
|
||||
else:
|
||||
let ti = genTypeInfoV1(p.module, typ, a.lode.info)
|
||||
@@ -1625,12 +1610,10 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||
if p.config.selectedGC == gcGo:
|
||||
# newObjRC1() would clash with unsureAsgnRef() - which is used by gcGo to
|
||||
# implement the write barrier
|
||||
var bres = newBuilder("")
|
||||
bres.addCast(getTypeDesc(p.module, typ)):
|
||||
bres.addCall(cgsymValue(p.module, "newObj"),
|
||||
b.snippet = cCast(getTypeDesc(p.module, typ),
|
||||
cCall(cgsymValue(p.module, "newObj"),
|
||||
ti,
|
||||
sizeExpr)
|
||||
b.snippet = bres
|
||||
sizeExpr))
|
||||
let raa = addrLoc(p.config, a)
|
||||
let rb = b.rdLoc
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
|
||||
@@ -1638,22 +1621,18 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
|
||||
rb)
|
||||
else:
|
||||
# use newObjRC1 as an optimization
|
||||
var bres = newBuilder("")
|
||||
bres.addCast(getTypeDesc(p.module, typ)):
|
||||
bres.addCall(cgsymValue(p.module, "newObjRC1"),
|
||||
b.snippet = cCast(getTypeDesc(p.module, typ),
|
||||
cCall(cgsymValue(p.module, "newObjRC1"),
|
||||
ti,
|
||||
sizeExpr)
|
||||
b.snippet = bres
|
||||
sizeExpr))
|
||||
let ra = a.rdLoc
|
||||
let rb = b.rdLoc
|
||||
p.s(cpsStmts).addAssignment(ra, rb)
|
||||
else:
|
||||
var bres = newBuilder("")
|
||||
bres.addCast(getTypeDesc(p.module, typ)):
|
||||
bres.addCall(cgsymValue(p.module, "newObj"),
|
||||
b.snippet = cCast(getTypeDesc(p.module, typ),
|
||||
cCall(cgsymValue(p.module, "newObj"),
|
||||
ti,
|
||||
sizeExpr)
|
||||
b.snippet = bres
|
||||
sizeExpr))
|
||||
genAssignment(p, a, b, {})
|
||||
# set the object type:
|
||||
genObjectInit(p, cpsStmts, bt, a, constructRefObj)
|
||||
@@ -1686,20 +1665,16 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
|
||||
let typinfo = genTypeInfoV1(p.module, seqtype, dest.lode.info)
|
||||
if p.config.selectedGC == gcGo:
|
||||
# we need the write barrier
|
||||
var callRes = newBuilder("")
|
||||
callRes.addCast(st):
|
||||
callRes.addCall(cgsymValue(p.module, "newSeq"), typinfo, length)
|
||||
call.snippet = callRes
|
||||
call.snippet = cCast(st,
|
||||
cCall(cgsymValue(p.module, "newSeq"), typinfo, length))
|
||||
let rad = addrLoc(p.config, dest)
|
||||
let rc = call.rdLoc
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
|
||||
cCast("void**", rad),
|
||||
rc)
|
||||
else:
|
||||
var callRes = newBuilder("")
|
||||
callRes.addCast(st):
|
||||
callRes.addCall(cgsymValue(p.module, "newSeqRC1"), typinfo, length)
|
||||
call.snippet = callRes
|
||||
call.snippet = cCast(st,
|
||||
cCall(cgsymValue(p.module, "newSeqRC1"), typinfo, length))
|
||||
let rd = dest.rdLoc
|
||||
let rc = call.rdLoc
|
||||
p.s(cpsStmts).addAssignment(rd, rc)
|
||||
@@ -1709,10 +1684,8 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
|
||||
else:
|
||||
let st = getTypeDesc(p.module, seqtype)
|
||||
let typinfo = genTypeInfoV1(p.module, seqtype, dest.lode.info)
|
||||
var callRes = newBuilder("")
|
||||
callRes.addCast(st):
|
||||
callRes.addCall(cgsymValue(p.module, "newSeq"), typinfo, length)
|
||||
call.snippet = callRes
|
||||
call.snippet = cCast(st,
|
||||
cCall(cgsymValue(p.module, "newSeq"), typinfo, length))
|
||||
genAssignment(p, dest, call, {})
|
||||
|
||||
proc genNewSeq(p: BProc, e: PNode) =
|
||||
@@ -1755,11 +1728,10 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
|
||||
else:
|
||||
if d.k == locNone: d = getTemp(p, e.typ, needsInit=false) # bug #22560
|
||||
let ra = a.rdLoc
|
||||
var dres = newBuilder("")
|
||||
dres.addCast(getTypeDesc(p.module, seqtype)):
|
||||
dres.addCall(cgsymValue(p.module, "nimNewSeqOfCap"),
|
||||
let dres = cCast(getTypeDesc(p.module, seqtype),
|
||||
cCall(cgsymValue(p.module, "nimNewSeqOfCap"),
|
||||
genTypeInfoV1(p.module, seqtype, e.info),
|
||||
ra)
|
||||
ra))
|
||||
putIntoDest(p, d, e, dres)
|
||||
gcUsage(p.config, e)
|
||||
|
||||
@@ -1771,15 +1743,14 @@ proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
|
||||
if id == p.module.labels:
|
||||
# expression not found in the cache:
|
||||
inc(p.module.labels)
|
||||
let td = getTypeDesc(p.module, t)
|
||||
var data = newBuilder("")
|
||||
data.addVarWithTypeAndInitializer(kind = Const, name = d.snippet):
|
||||
data.add(getTypeDesc(p.module, t))
|
||||
do:
|
||||
data.addVarWithInitializer(kind = Const, name = d.snippet, typ = td):
|
||||
# bug #23627; when generating const object fields, it's likely that
|
||||
# we need to generate type infos for the object, which may be an object with
|
||||
# custom hooks. We need to generate potential consts in the hooks first.
|
||||
genBracedInit(p, n, isConst = true, t, data)
|
||||
p.module.s[cfsData].add data
|
||||
p.module.s[cfsData].add(extract(data))
|
||||
|
||||
proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||
if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr:
|
||||
@@ -1942,8 +1913,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
if L < 10:
|
||||
for i in 0..<L:
|
||||
elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(i, lit)
|
||||
let lit = cIntLiteral(i)
|
||||
elem.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(d), lit, dataField(p)])
|
||||
elem.storage = OnHeap # we know that sequences are on the heap
|
||||
arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage)
|
||||
@@ -2518,12 +2488,12 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
|
||||
|
||||
# emit range check:
|
||||
if n0t.kind in {tyUInt, tyUInt64}:
|
||||
var first = newRopeAppender()
|
||||
var first = newBuilder("")
|
||||
genLiteral(p, n[1], dest, first)
|
||||
var last = newRopeAppender()
|
||||
var last = newBuilder("")
|
||||
genLiteral(p, n[2], dest, last)
|
||||
linefmt(p, cpsStmts, "if ($1 > ($5)($3)){ #raiseRangeErrorNoArgs(); ",
|
||||
[rdCharLoc(a), first, last,
|
||||
[rdCharLoc(a), extract(first), extract(last),
|
||||
raiser, getTypeDesc(p.module, n0t)])
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
linefmt p, cpsStmts, "}$n", []
|
||||
@@ -2541,12 +2511,12 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
|
||||
"(NI64)"
|
||||
else:
|
||||
""
|
||||
var first = newRopeAppender()
|
||||
var first = newBuilder("")
|
||||
genLiteral(p, n[1], dest, first)
|
||||
var last = newRopeAppender()
|
||||
var last = newBuilder("")
|
||||
genLiteral(p, n[2], dest, last)
|
||||
linefmt(p, cpsStmts, "if ($5($1) < $2 || $5($1) > $3){ $4($1, $2, $3); ",
|
||||
[rdCharLoc(a), first, last,
|
||||
[rdCharLoc(a), extract(first), extract(last),
|
||||
raiser, boundaryCast])
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
linefmt p, cpsStmts, "}$n", []
|
||||
@@ -2952,9 +2922,9 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
a, b: TLoc
|
||||
var idx: TLoc
|
||||
if nfAllConst in e.flags:
|
||||
var elem = newRopeAppender()
|
||||
var elem = newBuilder("")
|
||||
genSetNode(p, e, elem)
|
||||
putIntoDest(p, d, e, elem)
|
||||
putIntoDest(p, d, e, extract(elem))
|
||||
else:
|
||||
if d.k == locNone: d = getTemp(p, e.typ)
|
||||
if getSize(p.config, e.typ) > 8:
|
||||
@@ -3043,12 +3013,11 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||
if isConstClosure(n):
|
||||
inc(p.module.labels)
|
||||
var tmp = "CNSTCLOSURE" & rope(p.module.labels)
|
||||
let td = getTypeDesc(p.module, n.typ)
|
||||
var data = newBuilder("")
|
||||
data.addVarWithTypeAndInitializer(kind = Const, name = tmp):
|
||||
data.add(getTypeDesc(p.module, n.typ))
|
||||
do:
|
||||
data.addVarWithInitializer(kind = Const, name = tmp, typ = td):
|
||||
genBracedInit(p, n, isConst = true, n.typ, data)
|
||||
p.module.s[cfsData].add data
|
||||
p.module.s[cfsData].add(extract(data))
|
||||
putIntoDest(p, d, n, tmp, OnStatic)
|
||||
else:
|
||||
var tmp: TLoc
|
||||
@@ -3075,8 +3044,7 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
if d.k == locNone: d = getTemp(p, n.typ)
|
||||
for i in 0..<n.len:
|
||||
arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(i, lit)
|
||||
let lit = cIntLiteral(i)
|
||||
arr.snippet = subscript(rdLoc(d), lit)
|
||||
expr(p, n[i], arr)
|
||||
|
||||
@@ -3215,11 +3183,12 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||
if id == p.module.labels:
|
||||
# expression not found in the cache:
|
||||
inc(p.module.labels)
|
||||
p.module.s[cfsData].addVarWithTypeAndInitializer(
|
||||
kind = Const, name = tmp):
|
||||
p.module.s[cfsData].add(getTypeDesc(p.module, t, dkConst))
|
||||
do:
|
||||
genBracedInit(p, n, isConst = true, t, p.module.s[cfsData])
|
||||
let td = getTypeDesc(p.module, t, dkConst)
|
||||
var data = newBuilder("")
|
||||
data.addVarWithInitializer(
|
||||
kind = Const, name = tmp, typ = td):
|
||||
genBracedInit(p, n, isConst = true, t, data)
|
||||
p.module.s[cfsData].add(extract(data))
|
||||
|
||||
if d.k == locNone:
|
||||
fillLoc(d, locData, n, tmp, OnStatic)
|
||||
@@ -3258,20 +3227,19 @@ proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) =
|
||||
headerDecl.addDeclWithVisibility(Extern):
|
||||
headerDecl.addVar(kind = Local, name = sym.loc.snippet,
|
||||
typ = constType(getTypeDesc(m, sym.loc.t, dkVar)))
|
||||
m.s[cfsData].add(headerDecl)
|
||||
m.s[cfsData].add(extract(headerDecl))
|
||||
if sfExportc in sym.flags and p.module.g.generatedHeader != nil:
|
||||
p.module.g.generatedHeader.s[cfsData].add(headerDecl)
|
||||
p.module.g.generatedHeader.s[cfsData].add(extract(headerDecl))
|
||||
|
||||
proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
|
||||
# add a suffix for hcr - will later init the global pointer with this data
|
||||
let actualConstName = if q.hcrOn: sym.loc.snippet & "_const" else: sym.loc.snippet
|
||||
var data = newRopeAppender()
|
||||
let td = constType(getTypeDesc(q, sym.typ))
|
||||
var data = newBuilder("")
|
||||
data.addDeclWithVisibility(Private):
|
||||
data.addVarWithTypeAndInitializer(Local, actualConstName):
|
||||
data.add(constType(getTypeDesc(q, sym.typ)))
|
||||
do:
|
||||
data.addVarWithInitializer(Local, actualConstName, typ = td):
|
||||
genBracedInit(q.initProc, sym.astdef, isConst = true, sym.typ, data)
|
||||
q.s[cfsData].add data
|
||||
q.s[cfsData].add(extract(data))
|
||||
if q.hcrOn:
|
||||
# generate the global pointer with the real name
|
||||
q.s[cfsVars].addVar(kind = Global, name = sym.loc.snippet,
|
||||
@@ -3348,9 +3316,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
of skConst:
|
||||
if isSimpleConst(sym.typ):
|
||||
var lit = newRopeAppender()
|
||||
var lit = newBuilder("")
|
||||
genLiteral(p, sym.astdef, sym.typ, lit)
|
||||
putIntoDest(p, d, n, lit, OnStatic)
|
||||
putIntoDest(p, d, n, extract(lit), OnStatic)
|
||||
elif useAliveDataFromDce in p.module.flags:
|
||||
genConstHeader(p.module, p.module, p, sym)
|
||||
assert((sym.loc.snippet != "") and (sym.loc.t != nil))
|
||||
@@ -3402,17 +3370,17 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
else: internalError(p.config, n.info, "expr(" & $sym.kind & "); unknown symbol")
|
||||
of nkNilLit:
|
||||
if not isEmptyType(n.typ):
|
||||
var lit = newRopeAppender()
|
||||
var lit = newBuilder("")
|
||||
genLiteral(p, n, lit)
|
||||
putIntoDest(p, d, n, lit)
|
||||
putIntoDest(p, d, n, extract(lit))
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
var lit = newRopeAppender()
|
||||
var lit = newBuilder("")
|
||||
genLiteral(p, n, lit)
|
||||
putDataIntoDest(p, d, n, lit)
|
||||
putDataIntoDest(p, d, n, extract(lit))
|
||||
of nkIntLit..nkUInt64Lit, nkFloatLit..nkFloat128Lit, nkCharLit:
|
||||
var lit = newRopeAppender()
|
||||
var lit = newBuilder("")
|
||||
genLiteral(p, n, lit)
|
||||
putIntoDest(p, d, n, lit)
|
||||
putIntoDest(p, d, n, extract(lit))
|
||||
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit:
|
||||
genLineDir(p, n) # may be redundant, it is generated in fixupCall as well
|
||||
@@ -3432,9 +3400,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
genCall(p, n, d)
|
||||
of nkCurly:
|
||||
if isDeepConstExpr(n) and n.len != 0:
|
||||
var lit = newRopeAppender()
|
||||
var lit = newBuilder("")
|
||||
genSetNode(p, n, lit)
|
||||
putIntoDest(p, d, n, lit)
|
||||
putIntoDest(p, d, n, extract(lit))
|
||||
else:
|
||||
genSetConstr(p, n, d)
|
||||
of nkBracket:
|
||||
@@ -3781,6 +3749,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builde
|
||||
let base = t.skipTypes(abstractInst)[0]
|
||||
let tmpName = getTempName(p.module)
|
||||
|
||||
# genBracedInit can modify cfsStrData, we need an intermediate builder:
|
||||
var def = newBuilder("")
|
||||
def.addVarWithTypeAndInitializer(
|
||||
if isConst: Const else: Global,
|
||||
@@ -3805,7 +3774,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builde
|
||||
for i in 0..<n.len:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
p.module.s[cfsStrData].add def
|
||||
p.module.s[cfsStrData].add extract(def)
|
||||
|
||||
result.add cCast(typ = getTypeDesc(p.module, t), value = cAddr(tmpName))
|
||||
|
||||
@@ -3813,6 +3782,7 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Buil
|
||||
let base = t.skipTypes(abstractInst)[0]
|
||||
let payload = getTempName(p.module)
|
||||
|
||||
# genBracedInit can modify cfsStrData, we need an intermediate builder:
|
||||
var def = newBuilder("")
|
||||
def.addVarWithTypeAndInitializer(
|
||||
if isConst: AlwaysConst else: Global,
|
||||
@@ -3832,7 +3802,7 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Buil
|
||||
for i in 0..<n.len:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
p.module.s[cfsStrData].add def
|
||||
p.module.s[cfsStrData].add extract(def)
|
||||
|
||||
var resultInit: StructInitializer
|
||||
result.addStructInitializer(resultInit, kind = siOrderedStruct):
|
||||
@@ -3900,12 +3870,13 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
|
||||
let payload = getTempName(p.module)
|
||||
let ctype = getTypeDesc(p.module, typ.elementType)
|
||||
let arrLen = n.len
|
||||
# genConstSimpleList can modify cfsStrData, we need an intermediate builder:
|
||||
var data = newBuilder("")
|
||||
data.addArrayVarWithInitializer(
|
||||
kind = if isConst: AlwaysConst else: Global,
|
||||
name = payload, elementType = ctype, len = arrLen):
|
||||
genConstSimpleList(p, n, isConst, data)
|
||||
p.module.s[cfsStrData].add(data)
|
||||
p.module.s[cfsStrData].add(extract(data))
|
||||
var openArrInit: StructInitializer
|
||||
result.addStructInitializer(openArrInit, kind = siOrderedStruct):
|
||||
result.addField(openArrInit, name = "Field0"):
|
||||
|
||||
@@ -53,9 +53,9 @@ proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) =
|
||||
res.add(cCast("NI", bitOr(cCast("NU", rope(s.len)), "NIM_STRLIT_FLAG")))
|
||||
res.addField(strInit, name = "data"):
|
||||
res.add(makeCString(s))
|
||||
m.s[cfsStrData].add(res)
|
||||
m.s[cfsStrData].add(extract(res))
|
||||
|
||||
proc genStringLiteralV1(m: BModule; n: PNode; result: var Rope) =
|
||||
proc genStringLiteralV1(m: BModule; n: PNode; result: var Builder) =
|
||||
if s.isNil:
|
||||
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), "NIM_NIL"))
|
||||
else:
|
||||
@@ -85,9 +85,9 @@ proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bo
|
||||
res.add(bitOr(rope(s.len), "NIM_STRLIT_FLAG"))
|
||||
res.addField(structInit, name = "data"):
|
||||
res.add(makeCString(s))
|
||||
m.s[cfsStrData].add(res)
|
||||
m.s[cfsStrData].add(extract(res))
|
||||
|
||||
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Builder) =
|
||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||
var litName: string
|
||||
if id == m.labels:
|
||||
@@ -101,20 +101,19 @@ proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||
let tmp = getTempName(m)
|
||||
result.add tmp
|
||||
var res = newBuilder("")
|
||||
res.addVarWithTypeAndInitializer(
|
||||
res.addVarWithInitializer(
|
||||
if isConst: AlwaysConst else: Global,
|
||||
name = tmp):
|
||||
res.add("NimStringV2")
|
||||
do:
|
||||
name = tmp,
|
||||
typ = "NimStringV2"):
|
||||
var strInit: StructInitializer
|
||||
res.addStructInitializer(strInit, kind = siOrderedStruct):
|
||||
res.addField(strInit, name = "len"):
|
||||
res.addIntValue(n.strVal.len)
|
||||
res.addField(strInit, name = "p"):
|
||||
res.add(cCast(ptrType("NimStrPayload"), cAddr(litName)))
|
||||
m.s[cfsStrData].add(res)
|
||||
m.s[cfsStrData].add(extract(res))
|
||||
|
||||
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Builder) =
|
||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||
var pureLit: Rope
|
||||
if id == m.labels:
|
||||
@@ -145,10 +144,10 @@ proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
||||
else:
|
||||
localError(m.config, info, "cannot determine how to produce code for string literal")
|
||||
|
||||
proc genNilStringLiteral(m: BModule; info: TLineInfo; result: var Rope) =
|
||||
proc genNilStringLiteral(m: BModule; info: TLineInfo; result: var Builder) =
|
||||
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), "NIM_NIL"))
|
||||
|
||||
proc genStringLiteral(m: BModule; n: PNode; result: var Rope) =
|
||||
proc genStringLiteral(m: BModule; n: PNode; result: var Builder) =
|
||||
case detectStrVersion(m)
|
||||
of 0, 1: genStringLiteralV1(m, n, result)
|
||||
of 2: genStringLiteralV2(m, n, isConst = true, result)
|
||||
|
||||
@@ -146,16 +146,16 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||
a.flags.incl(lfEnforceDeref)
|
||||
expr(p, ri, a)
|
||||
|
||||
proc assignLabel(b: var TBlock; result: var Rope) {.inline.} =
|
||||
proc assignLabel(b: var TBlock; result: var Builder) {.inline.} =
|
||||
b.label = "LA" & b.id.rope
|
||||
result.add b.label
|
||||
|
||||
proc blockBody(b: var TBlock; result: var Rope) =
|
||||
result.add b.sections[cpsLocals]
|
||||
proc blockBody(b: var TBlock; result: var Builder) =
|
||||
result.add extract(b.sections[cpsLocals])
|
||||
if b.frameLen > 0:
|
||||
result.addf("FR_.len+=$1;$n", [b.frameLen.rope])
|
||||
result.add(b.sections[cpsInit])
|
||||
result.add(b.sections[cpsStmts])
|
||||
result.add(extract(b.sections[cpsInit]))
|
||||
result.add(extract(b.sections[cpsStmts]))
|
||||
|
||||
proc endBlock(p: BProc, blockEnd: Rope) =
|
||||
let topBlock = p.blocks.len-1
|
||||
@@ -281,7 +281,7 @@ proc genGotoVar(p: BProc; value: PNode) =
|
||||
|
||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Builder)
|
||||
|
||||
proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Rope) =
|
||||
proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Builder) =
|
||||
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
|
||||
discard "nothing to do"
|
||||
elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and
|
||||
@@ -330,8 +330,9 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
value.kind in nkCallKinds and value[0].kind == nkSym and
|
||||
v.typ.kind != tyPtr and sfConstructor in value[0].sym.flags
|
||||
var targetProc = p
|
||||
var valueAsRope = ""
|
||||
potentialValueInit(p, v, value, valueAsRope)
|
||||
var valueBuilder = newBuilder("")
|
||||
potentialValueInit(p, v, value, valueBuilder)
|
||||
let valueAsRope = extract(valueBuilder)
|
||||
if sfGlobal in v.flags:
|
||||
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||
value.kind == nkEmpty and
|
||||
@@ -594,8 +595,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
return
|
||||
|
||||
let val = getOrdValue(it[j])
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(toInt64(val)+id+1, lit)
|
||||
let lit = cIntLiteral(toInt64(val)+id+1)
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [lit])
|
||||
|
||||
genStmts(p, it.lastSon)
|
||||
@@ -775,7 +775,7 @@ proc finallyActions(p: BProc) =
|
||||
if finallyBlock != nil:
|
||||
genSimpleBlock(p, finallyBlock[0])
|
||||
|
||||
proc raiseInstr(p: BProc; result: var Rope) =
|
||||
proc raiseInstr(p: BProc; result: var Builder) =
|
||||
if p.config.exc == excGoto:
|
||||
let L = p.nestedTryStmts.len
|
||||
if L == 0:
|
||||
@@ -925,8 +925,7 @@ proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
|
||||
[rdLoc(a), bitMask])
|
||||
for j in 0..high(branches):
|
||||
if branches[j] != "":
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(j, lit)
|
||||
let lit = cIntLiteral(j)
|
||||
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||
[lit, branches[j]])
|
||||
lineF(p, cpsStmts, "}$n", []) # else statement:
|
||||
@@ -964,22 +963,22 @@ proc genCaseRange(p: BProc, branch: PNode) =
|
||||
for j in 0..<branch.len-1:
|
||||
if branch[j].kind == nkRange:
|
||||
if hasSwitchRange in CC[p.config.cCompiler].props:
|
||||
var litA = newRopeAppender()
|
||||
var litB = newRopeAppender()
|
||||
var litA = newBuilder("")
|
||||
var litB = newBuilder("")
|
||||
genLiteral(p, branch[j][0], litA)
|
||||
genLiteral(p, branch[j][1], litB)
|
||||
lineF(p, cpsStmts, "case $1 ... $2:$n", [litA, litB])
|
||||
lineF(p, cpsStmts, "case $1 ... $2:$n", [extract(litA), extract(litB)])
|
||||
else:
|
||||
var v = copyNode(branch[j][0])
|
||||
while v.intVal <= branch[j][1].intVal:
|
||||
var litA = newRopeAppender()
|
||||
var litA = newBuilder("")
|
||||
genLiteral(p, v, litA)
|
||||
lineF(p, cpsStmts, "case $1:$n", [litA])
|
||||
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
|
||||
inc(v.intVal)
|
||||
else:
|
||||
var litA = newRopeAppender()
|
||||
var litA = newBuilder("")
|
||||
genLiteral(p, branch[j], litA)
|
||||
lineF(p, cpsStmts, "case $1:$n", [litA])
|
||||
lineF(p, cpsStmts, "case $1:$n", [extract(litA)])
|
||||
|
||||
proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||
# analyse 'case' statement:
|
||||
@@ -1641,8 +1640,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||
if not containsOrIncl(p.module.declaredThings, field.id):
|
||||
appcg(p.module, cfsVars, "extern $1",
|
||||
[discriminatorTableDecl(p.module, t, field)])
|
||||
var lit = newRopeAppender()
|
||||
intLiteral(toInt64(lengthOrd(p.config, field.typ))+1, lit)
|
||||
let lit = cIntLiteral(toInt64(lengthOrd(p.config, field.typ))+1)
|
||||
lineCg(p, cpsStmts,
|
||||
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
||||
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
||||
|
||||
@@ -47,11 +47,9 @@ proc generateThreadLocalStorage(m: BModule) =
|
||||
if m.g.nimtv != "" and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
|
||||
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
|
||||
finishTypeDescriptions(m)
|
||||
var typedef = newBuilder("")
|
||||
typedef.addTypedef(name = "NimThreadVars"):
|
||||
typedef.addSimpleStruct(m, name = "", baseType = ""):
|
||||
typedef.add(m.g.nimtv)
|
||||
m.s[cfsSeqTypes].add(typedef)
|
||||
m.s[cfsSeqTypes].addTypedef(name = "NimThreadVars"):
|
||||
m.s[cfsSeqTypes].addSimpleStruct(m, name = "", baseType = ""):
|
||||
m.s[cfsSeqTypes].add(m.g.nimtv)
|
||||
|
||||
proc generateThreadVarsSize(m: BModule) =
|
||||
if m.g.nimtv != "":
|
||||
|
||||
@@ -76,12 +76,11 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||
let arraySize = lengthOrd(c.p.config, typ.indexType)
|
||||
var i: TLoc = getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt))
|
||||
var oldCode = p.s(cpsStmts)
|
||||
freeze oldCode
|
||||
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||
[i.snippet, arraySize])
|
||||
let oldLen = p.s(cpsStmts).len
|
||||
let oldLen = p.s(cpsStmts).buf.len
|
||||
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.snippet]), typ.elementType)
|
||||
if p.s(cpsStmts).len == oldLen:
|
||||
if p.s(cpsStmts).buf.len == oldLen:
|
||||
# do not emit dummy long loops for faster debug builds:
|
||||
p.s(cpsStmts) = oldCode
|
||||
else:
|
||||
@@ -119,14 +118,13 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||
assert typ.kind == tySequence
|
||||
var i = getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt))
|
||||
var oldCode = p.s(cpsStmts)
|
||||
freeze oldCode
|
||||
var a = TLoc(snippet: accessor)
|
||||
|
||||
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||
[i.snippet, lenExpr(c.p, a)])
|
||||
let oldLen = p.s(cpsStmts).len
|
||||
let oldLen = p.s(cpsStmts).buf.len
|
||||
genTraverseProc(c, "$1$3[$2]" % [accessor, i.snippet, dataField(c.p)], typ.elementType)
|
||||
if p.s(cpsStmts).len == oldLen:
|
||||
if p.s(cpsStmts).buf.len == oldLen:
|
||||
# do not emit dummy long loops for faster debug builds:
|
||||
p.s(cpsStmts) = oldCode
|
||||
else:
|
||||
@@ -160,7 +158,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
|
||||
genTraverseProc(c, "(*a)".rope, typ.elementType)
|
||||
|
||||
let generatedProc = "$1 {$n$2$3$4}\n" %
|
||||
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
|
||||
[header, extract(p.s(cpsLocals)), extract(p.s(cpsInit)), extract(p.s(cpsStmts))]
|
||||
|
||||
m.s[cfsProcHeaders].addf("$1;\n", [header])
|
||||
m.s[cfsProcs].add(generatedProc)
|
||||
@@ -189,7 +187,7 @@ proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =
|
||||
genTraverseProc(c, sLoc, s.loc.t)
|
||||
|
||||
let generatedProc = "$1 {$n$2$3$4}$n" %
|
||||
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
|
||||
[header, extract(p.s(cpsLocals)), extract(p.s(cpsInit)), extract(p.s(cpsStmts))]
|
||||
|
||||
m.s[cfsProcHeaders].addf("$1;$n", [header])
|
||||
m.s[cfsProcs].add(generatedProc)
|
||||
|
||||
@@ -427,11 +427,9 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TypeDescKind
|
||||
if cacheGetType(m.typeCache, sig) == "":
|
||||
m.typeCache[sig] = result
|
||||
#echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s
|
||||
var struct = newBuilder("")
|
||||
struct.addSimpleStruct(m, name = result, baseType = ""):
|
||||
struct.addField(name = "len", typ = "NI")
|
||||
struct.addField(name = "p", typ = ptrType(result & "_Content"))
|
||||
m.s[cfsTypes].add(struct)
|
||||
m.s[cfsTypes].addSimpleStruct(m, name = result, baseType = ""):
|
||||
m.s[cfsTypes].addField(name = "len", typ = "NI")
|
||||
m.s[cfsTypes].addField(name = "p", typ = ptrType(result & "_Content"))
|
||||
pushType(m, t)
|
||||
else:
|
||||
result = getTypeForward(m, t, sig) & seqStar(m)
|
||||
@@ -450,13 +448,12 @@ proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
|
||||
if result == "":
|
||||
discard getTypeDescAux(m, t, check, dkVar)
|
||||
else:
|
||||
var struct = newBuilder("")
|
||||
struct.addSimpleStruct(m, name = result & "_Content", baseType = ""):
|
||||
struct.addField(name = "cap", typ = "NI")
|
||||
struct.addField(name = "data",
|
||||
typ = getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, dkVar),
|
||||
let dataTyp = getTypeDescAux(m, t.skipTypes(abstractInst)[0], check, dkVar)
|
||||
m.s[cfsTypes].addSimpleStruct(m, name = result & "_Content", baseType = ""):
|
||||
m.s[cfsTypes].addField(name = "cap", typ = "NI")
|
||||
m.s[cfsTypes].addField(name = "data",
|
||||
typ = dataTyp,
|
||||
isFlexArray = true)
|
||||
m.s[cfsTypes].add(struct)
|
||||
|
||||
proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||
if param.typ.skipTypes({tyVar, tyLent, tyTypeDesc}).kind notin {
|
||||
@@ -685,7 +682,7 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
genRecordFieldsAux(m, n[0], rectype, check, result, unionPrefix)
|
||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||
# since identifiers are not allowed to start with '_'
|
||||
var unionBody: Rope = ""
|
||||
var unionBody = newBuilder("")
|
||||
for i in 1..<n.len:
|
||||
case n[i].kind
|
||||
of nkOfBranch, nkElse:
|
||||
@@ -694,16 +691,16 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
let structName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i
|
||||
var a = newBuilder("")
|
||||
genRecordFieldsAux(m, k, rectype, check, a, unionPrefix & $structName & ".")
|
||||
if a.len != 0:
|
||||
if a.buf.len != 0:
|
||||
unionBody.addFieldWithStructType(m, rectype, structName):
|
||||
unionBody.add(a)
|
||||
unionBody.add(extract(a))
|
||||
else:
|
||||
genRecordFieldsAux(m, k, rectype, check, unionBody, unionPrefix)
|
||||
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
||||
if unionBody.len != 0:
|
||||
if unionBody.buf.len != 0:
|
||||
result.addAnonUnion:
|
||||
# XXX this has to be a named field for NIFC
|
||||
result.add(unionBody)
|
||||
result.add(extract(unionBody))
|
||||
of nkSym:
|
||||
let field = n.sym
|
||||
if field.typ.kind == tyVoid: return
|
||||
@@ -735,7 +732,7 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
result.addField(field, sname, typ, isFlexArray, initializer)
|
||||
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
||||
|
||||
proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = false, isFwdDecl:bool = false)
|
||||
proc genMemberProcHeader(m: BModule; prc: PSym; result: var Builder; asPtr: bool = false, isFwdDecl:bool = false)
|
||||
|
||||
proc addRecordFields(result: var Builder; m: BModule; typ: PType, check: var IntSet) =
|
||||
genRecordFieldsAux(m, typ.n, typ, check, result)
|
||||
@@ -743,14 +740,15 @@ proc addRecordFields(result: var Builder; m: BModule; typ: PType, check: var Int
|
||||
let procs = m.g.graph.memberProcsPerType[typ.itemId]
|
||||
var isDefaultCtorGen, isCtorGen: bool = false
|
||||
for prc in procs:
|
||||
var header: Rope = ""
|
||||
if sfConstructor in prc.flags:
|
||||
isCtorGen = true
|
||||
if prc.typ.n.len == 1:
|
||||
isDefaultCtorGen = true
|
||||
if lfNoDecl in prc.loc.flags: continue
|
||||
var header = newBuilder("")
|
||||
genMemberProcHeader(m, prc, header, false, true)
|
||||
result.addf "$1;$n", [header]
|
||||
result.addStmt():
|
||||
result.add(extract(header))
|
||||
if isCtorGen and not isDefaultCtorGen:
|
||||
var ch: IntSet = default(IntSet)
|
||||
result.addf "$1() = default;$n", [getTypeDescAux(m, typ, ch, dkOther)]
|
||||
@@ -771,22 +769,24 @@ proc getRecordDesc(m: BModule; typ: PType, name: Rope,
|
||||
if typ.baseClass != nil:
|
||||
baseType = getTypeDescAux(m, typ.baseClass.skipTypes(skipPtrs), check, dkField)
|
||||
if typ.sym == nil or sfCodegenDecl notin typ.sym.flags:
|
||||
result = newBuilder("")
|
||||
result.addStruct(m, typ, name, baseType):
|
||||
result.addRecordFields(m, typ, check)
|
||||
var res = newBuilder("")
|
||||
res.addStruct(m, typ, name, baseType):
|
||||
res.addRecordFields(m, typ, check)
|
||||
result = extract(res)
|
||||
else:
|
||||
var desc = newBuilder("")
|
||||
desc.addRecordFields(m, typ, check)
|
||||
result = runtimeFormat(typ.sym.cgDeclFrmt, [name, desc, baseType])
|
||||
result = runtimeFormat(typ.sym.cgDeclFrmt, [name, extract(desc), baseType])
|
||||
|
||||
proc getTupleDesc(m: BModule; typ: PType, name: Rope,
|
||||
check: var IntSet): Rope =
|
||||
result = newBuilder("")
|
||||
result.addStruct(m, typ, name, ""):
|
||||
var res = newBuilder("")
|
||||
res.addStruct(m, typ, name, ""):
|
||||
for i, a in typ.ikids:
|
||||
result.addField(
|
||||
res.addField(
|
||||
name = "Field" & $i,
|
||||
typ = getTypeDescAux(m, a, check, dkField))
|
||||
result = extract(res)
|
||||
|
||||
proc scanCppGenericSlot(pat: string, cursor, outIdx, outStars: var int): bool =
|
||||
# A helper proc for handling cppimport patterns, involving numeric
|
||||
@@ -827,12 +827,10 @@ proc getOpenArrayDesc(m: BModule; t: PType, check: var IntSet; kind: TypeDescKin
|
||||
result = getTypeName(m, t, sig)
|
||||
m.typeCache[sig] = result
|
||||
let elemType = getTypeDescWeak(m, t.elementType, check, kind)
|
||||
var typedef = newBuilder("")
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.addSimpleStruct(m, name = "", baseType = ""):
|
||||
typedef.addField(name = "Field0", typ = ptrType(elemType))
|
||||
typedef.addField(name = "Field1", typ = "NI")
|
||||
m.s[cfsTypes].add(typedef)
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].addSimpleStruct(m, name = "", baseType = ""):
|
||||
m.s[cfsTypes].addField(name = "Field0", typ = ptrType(elemType))
|
||||
m.s[cfsTypes].addField(name = "Field1", typ = "NI")
|
||||
|
||||
proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDescKind): Rope =
|
||||
# returns only the type's name
|
||||
@@ -904,28 +902,26 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
|
||||
m.typeCache[sig] = result
|
||||
var size: int
|
||||
var typedef = newBuilder("")
|
||||
if firstOrd(m.config, t) < 0:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.add("NI32")
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].add("NI32")
|
||||
size = 4
|
||||
else:
|
||||
size = int(getSize(m.config, t))
|
||||
case size
|
||||
of 1:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.add("NU8")
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].add("NU8")
|
||||
of 2:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.add("NU16")
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].add("NU16")
|
||||
of 4:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.add("NI32")
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].add("NI32")
|
||||
of 8:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.add("NI64")
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].add("NI64")
|
||||
else: internalError(m.config, t.sym.info, "getTypeDescAux: enum")
|
||||
m.s[cfsTypes].add(typedef)
|
||||
when false:
|
||||
let owner = hashOwner(t.sym)
|
||||
if not gDebugInfo.hasEnum(t.sym.name.s, t.sym.info.line, owner):
|
||||
@@ -942,16 +938,15 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
var rettype: Snippet = ""
|
||||
var desc = newBuilder("")
|
||||
genProcParams(m, t, rettype, desc, check, true, true)
|
||||
let params = extract(desc)
|
||||
if not isImportedType(t):
|
||||
var typedef = newBuilder("")
|
||||
if t.callConv != ccClosure: # procedure vars may need a closure!
|
||||
typedef.addProcTypedef(callConv = t.callConv, name = result, rettype = rettype, params = desc)
|
||||
m.s[cfsTypes].addProcTypedef(callConv = t.callConv, name = result, rettype = rettype, params = params)
|
||||
else:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.addSimpleStruct(m, name = "", baseType = ""):
|
||||
typedef.addProcField(name = "ClP_0", callConv = ccNimCall, rettype = rettype, params = desc)
|
||||
typedef.addField(name = "ClE_0", typ = "void*")
|
||||
m.s[cfsTypes].add(typedef)
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].addSimpleStruct(m, name = "", baseType = ""):
|
||||
m.s[cfsTypes].addProcField(name = "ClP_0", callConv = ccNimCall, rettype = rettype, params = params)
|
||||
m.s[cfsTypes].addField(name = "ClE_0", typ = "void*")
|
||||
of tySequence:
|
||||
if optSeqDestructors in m.config.globalOptions:
|
||||
result = getTypeDescWeak(m, t, check, kind)
|
||||
@@ -968,14 +963,13 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
m.typeCache[sig] = result & seqStar(m)
|
||||
if not isImportedType(t):
|
||||
if skipTypes(t.elementType, typedescInst).kind != tyEmpty:
|
||||
var struct = newBuilder("")
|
||||
let et = getTypeDescAux(m, t.elementType, check, kind)
|
||||
let baseType = cgsymValue(m, "TGenericSeq")
|
||||
struct.addSimpleStruct(m, name = result, baseType = baseType):
|
||||
struct.addField(
|
||||
m.s[cfsSeqTypes].addSimpleStruct(m, name = result, baseType = baseType):
|
||||
m.s[cfsSeqTypes].addField(
|
||||
name = "data",
|
||||
typ = getTypeDescAux(m, t.elementType, check, kind),
|
||||
typ = et,
|
||||
isFlexArray = true)
|
||||
m.s[cfsSeqTypes].add struct
|
||||
else:
|
||||
result = rope("TGenericSeq")
|
||||
result.add(seqStar(m))
|
||||
@@ -983,11 +977,9 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
result = getTypeName(m, origTyp, sig)
|
||||
m.typeCache[sig] = result
|
||||
if not isImportedType(t):
|
||||
let foo = getTypeDescAux(m, t.elementType, check, kind)
|
||||
var typedef = newBuilder("")
|
||||
typedef.addArrayTypedef(name = result, len = 1):
|
||||
typedef.add(foo)
|
||||
m.s[cfsTypes].add(typedef)
|
||||
let et = getTypeDescAux(m, t.elementType, check, kind)
|
||||
m.s[cfsTypes].addArrayTypedef(name = result, len = 1):
|
||||
m.s[cfsTypes].add(et)
|
||||
of tyArray:
|
||||
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
@@ -995,10 +987,8 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
m.typeCache[sig] = result
|
||||
if not isImportedType(t):
|
||||
let e = getTypeDescAux(m, t.elementType, check, kind)
|
||||
var typedef = newBuilder("")
|
||||
typedef.addArrayTypedef(name = result, len = n):
|
||||
typedef.add(e)
|
||||
m.s[cfsTypes].add(typedef)
|
||||
m.s[cfsTypes].addArrayTypedef(name = result, len = n):
|
||||
m.s[cfsTypes].add(e)
|
||||
of tyObject, tyTuple:
|
||||
let tt = origTyp.skipTypes({tyDistinct})
|
||||
if isImportedCppType(t) and tt.kind == tyGenericInst:
|
||||
@@ -1106,16 +1096,15 @@ proc getClosureType(m: BModule; t: PType, kind: TClosureTypeKind): Rope =
|
||||
var rettype: Snippet = ""
|
||||
var desc = newBuilder("")
|
||||
genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf)
|
||||
let params = extract(desc)
|
||||
if not isImportedType(t):
|
||||
var typedef = newBuilder("")
|
||||
if t.callConv != ccClosure or kind != clFull:
|
||||
typedef.addProcTypedef(callConv = t.callConv, name = result, rettype = rettype, params = desc)
|
||||
m.s[cfsTypes].addProcTypedef(callConv = t.callConv, name = result, rettype = rettype, params = params)
|
||||
else:
|
||||
typedef.addTypedef(name = result):
|
||||
typedef.addSimpleStruct(m, name = "", baseType = ""):
|
||||
typedef.addProcField(name = "ClP_0", callConv = ccNimCall, rettype = rettype, params = desc)
|
||||
typedef.addField(name = "ClE_0", typ = "void*")
|
||||
m.s[cfsTypes].add(typedef)
|
||||
m.s[cfsTypes].addTypedef(name = result):
|
||||
m.s[cfsTypes].addSimpleStruct(m, name = "", baseType = ""):
|
||||
m.s[cfsTypes].addProcField(name = "ClP_0", callConv = ccNimCall, rettype = rettype, params = params)
|
||||
m.s[cfsTypes].addField(name = "ClE_0", typ = "void*")
|
||||
|
||||
proc finishTypeDescriptions(m: BModule) =
|
||||
var i = 0
|
||||
@@ -1158,7 +1147,7 @@ proc parseVFunctionDecl(val: string; name, params, retType, superCall: var strin
|
||||
|
||||
params = "(" & params & ")"
|
||||
|
||||
proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = false, isFwdDecl: bool = false) =
|
||||
proc genMemberProcHeader(m: BModule; prc: PSym; result: var Builder; asPtr: bool = false, isFwdDecl: bool = false) =
|
||||
assert sfCppMember * prc.flags != {}
|
||||
let isCtor = sfConstructor in prc.flags
|
||||
var check = initIntSet()
|
||||
@@ -1206,14 +1195,15 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool =
|
||||
[rope(CallingConvToStr[prc.typ.callConv]), asPtrStr, rettype, name,
|
||||
params, fnConst, override, superCall])
|
||||
|
||||
proc genProcHeader(m: BModule; prc: PSym; result: var Rope; visibility: var DeclVisibility, asPtr: bool, addAttributes: bool) =
|
||||
proc genProcHeader(m: BModule; prc: PSym; result: var Builder; visibility: var DeclVisibility, asPtr: bool, addAttributes: bool) =
|
||||
# using static is needed for inline procs
|
||||
var check = initIntSet()
|
||||
fillBackendName(m, prc)
|
||||
fillLoc(prc.loc, locProc, prc.ast[namePos], OnUnknown)
|
||||
var rettype: Snippet = ""
|
||||
var params = newBuilder("")
|
||||
genProcParams(m, prc.typ, rettype, params, check, true, false)
|
||||
var desc = newBuilder("")
|
||||
genProcParams(m, prc.typ, rettype, desc, check, true, false)
|
||||
let params = extract(desc)
|
||||
# handle the 2 options for hotcodereloading codegen - function pointer
|
||||
# (instead of forward declaration) or header for function body with "_actual" postfix
|
||||
var name = prc.loc.snippet
|
||||
@@ -1513,14 +1503,21 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
|
||||
m.s[cfsTypeInit1].addArrayVarWithInitializer(
|
||||
kind = Global,
|
||||
name = enumArray,
|
||||
elementType = "char* NIM_CONST", # XXX maybe do this in `addVar`
|
||||
elementType = constPtrType("char"),
|
||||
len = typ.n.len):
|
||||
m.s[cfsTypeInit1].add(enumNames)
|
||||
m.s[cfsTypeInit3].addf("for ($1 = 0; $1 < $2; $1++) {$n" &
|
||||
"$3[$1+$4].kind = 1;$n" & "$3[$1+$4].offset = $1;$n" &
|
||||
"$3[$1+$4].name = $5[$1];$n" & "$6[$1] = &$3[$1+$4];$n" & "}$n", [counter,
|
||||
rope(typ.n.len), m.typeNodesName, rope(firstNimNode), enumArray, nodePtrs])
|
||||
m.s[cfsTypeInit3].add(specialCases)
|
||||
m.s[cfsTypeInit1].add(extract(enumNames))
|
||||
m.s[cfsTypeInit3].addForRangeExclusive(i = counter,
|
||||
start = cIntValue(0),
|
||||
bound = cIntValue(typ.n.len)):
|
||||
let nodeLoc = subscript(m.typeNodesName,
|
||||
cOp(Add, "NI", counter, cIntValue(firstNimNode)))
|
||||
m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "kind", cIntValue(1))
|
||||
m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "offset", counter)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(nodeLoc, "name",
|
||||
subscript(enumArray, counter))
|
||||
m.s[cfsTypeInit3].addSubscriptAssignment(nodePtrs, counter,
|
||||
cAddr(nodeLoc))
|
||||
m.s[cfsTypeInit3].add(extract(specialCases))
|
||||
let n = getNimNode(m)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(n, "len", typ.n.len)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(n, "kind", 0)
|
||||
@@ -1528,8 +1525,9 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
|
||||
cAddr(subscript(nodePtrs, cIntValue(0))))
|
||||
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(n))
|
||||
if hasHoles:
|
||||
# 1 << 2 is {ntfEnumHole}
|
||||
m.s[cfsTypeInit3].addf("$1.flags = 1<<2;$n", [tiNameForHcr(m, name)])
|
||||
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "flags",
|
||||
# 1 << 2 is {ntfEnumHole}
|
||||
cOp(Shl, "NU8", cIntValue(1), cIntValue(2)))
|
||||
|
||||
proc genSetInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
|
||||
assert(typ.elementType != nil)
|
||||
@@ -1555,10 +1553,11 @@ include ccgtrav
|
||||
|
||||
proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
|
||||
genProc(m, s)
|
||||
var params = newBuilder("")
|
||||
var desc = newBuilder("")
|
||||
var paramBuilder: ProcParamBuilder
|
||||
params.addProcParams(paramBuilder):
|
||||
params.addUnnamedParam(paramBuilder, typ = "void*")
|
||||
desc.addProcParams(paramBuilder):
|
||||
desc.addUnnamedParam(paramBuilder, typ = "void*")
|
||||
let params = extract(desc)
|
||||
let pt = procPtrTypeUnnamedNimCall(rettype = "void*", params = params)
|
||||
m.s[cfsTypeInit3].addFieldAssignmentWithValue(result, "deepcopy"):
|
||||
m.s[cfsTypeInit3].add(cCast(pt, s.loc.snippet))
|
||||
@@ -1643,7 +1642,7 @@ proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TType
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result: var Rope) =
|
||||
proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result: var Builder) =
|
||||
let theProc = getAttachedOp(m.g.graph, t, op)
|
||||
if theProc != nil and not isTrivialProc(m.g.graph, theProc):
|
||||
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
||||
@@ -1719,7 +1718,7 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
|
||||
var flags = 0
|
||||
if not canFormAcycle(m.g.graph, t): flags = flags or 1
|
||||
|
||||
var typeEntry = newRopeAppender()
|
||||
var typeEntry = newBuilder("")
|
||||
typeEntry.addFieldAssignmentWithValue(name, "destructor"):
|
||||
typeEntry.addCast("void*"):
|
||||
genHook(m, t, info, attachedDestructor, typeEntry)
|
||||
@@ -1771,7 +1770,7 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
|
||||
genProcPrototype(m, i)
|
||||
typeEntry.addFieldAssignment(name, "vTable", vTablePointerName)
|
||||
|
||||
m.s[cfsTypeInit3].add typeEntry
|
||||
m.s[cfsTypeInit3].add extract(typeEntry)
|
||||
|
||||
if t.kind == tyObject and t.baseClass != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
@@ -1784,11 +1783,9 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
var flags = 0
|
||||
if not canFormAcycle(m.g.graph, t): flags = flags or 1
|
||||
|
||||
var typeEntry = newRopeAppender()
|
||||
var typeEntry = newBuilder("")
|
||||
typeEntry.addDeclWithVisibility(Private):
|
||||
typeEntry.addVarWithTypeAndInitializer(kind = Local, name = name):
|
||||
typeEntry.add("TNimTypeV2")
|
||||
do:
|
||||
typeEntry.addVarWithInitializer(kind = Local, name = name, typ = "TNimTypeV2"):
|
||||
var typeInit: StructInitializer
|
||||
typeEntry.addStructInitializer(typeInit, kind = siNamedStruct):
|
||||
typeEntry.addField(typeInit, name = "destructor"):
|
||||
@@ -1843,7 +1840,7 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
else:
|
||||
typeEntry.addField(typeInit, name = "flags"):
|
||||
typeEntry.addIntValue(flags)
|
||||
m.s[cfsVars].add typeEntry
|
||||
m.s[cfsVars].add extract(typeEntry)
|
||||
|
||||
if t.kind == tyObject and t.baseClass != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||
discard genTypeInfoV1(m, t, info)
|
||||
|
||||
@@ -16,7 +16,7 @@ import
|
||||
rodutils, renderer, cgendata, aliases,
|
||||
lowerings, lineinfos, pathutils, transf,
|
||||
injectdestructors, astmsgs, modulepaths, pushpoppragmas,
|
||||
mangleutils
|
||||
mangleutils, cbuilderbase
|
||||
|
||||
from expanddefaults import caseObjDefaultBranch
|
||||
|
||||
@@ -138,6 +138,9 @@ proc cgFormatValue(result: var string; value: BiggestInt) =
|
||||
proc cgFormatValue(result: var string; value: Int128) =
|
||||
result.addInt128 value
|
||||
|
||||
template addf(result: var Builder, args: varargs[untyped]) =
|
||||
result.buf.addf(args)
|
||||
|
||||
# TODO: please document
|
||||
macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||
args.expectKind nnkBracket
|
||||
@@ -237,7 +240,15 @@ proc addIndent(p: BProc; result: var Rope) =
|
||||
result[i] = '\t'
|
||||
inc i
|
||||
|
||||
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
|
||||
proc addIndent(p: BProc; result: var Builder) =
|
||||
var i = result.buf.len
|
||||
let newLen = i + p.blocks.len
|
||||
result.buf.setLen newLen
|
||||
while i < newLen:
|
||||
result.buf[i] = '\t'
|
||||
inc i
|
||||
|
||||
template appcg(m: BModule, c: var (Rope | Builder), frmt: FormatStr,
|
||||
args: untyped) =
|
||||
c.add(ropecg(m, frmt, args))
|
||||
|
||||
@@ -275,7 +286,7 @@ proc safeLineNm(info: TLineInfo): int =
|
||||
proc genPostprocessDir(field1, field2, field3: string): string =
|
||||
result = postprocessDirStart & field1 & postprocessDirSep & field2 & postprocessDirSep & field3 & postprocessDirEnd
|
||||
|
||||
proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; conf: ConfigRef) =
|
||||
proc genCLineDir(r: var Builder, fileIdx: FileIndex, line: int; conf: ConfigRef) =
|
||||
assert line >= 0
|
||||
if optLineDir in conf.options and line > 0:
|
||||
if fileIdx == InvalidFileIdx:
|
||||
@@ -283,7 +294,7 @@ proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; conf: ConfigRef) =
|
||||
else:
|
||||
r.add(rope("\n#line " & $line & " FX_" & $fileIdx.int32 & "\n"))
|
||||
|
||||
proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; p: BProc; info: TLineInfo; lastFileIndex: FileIndex) =
|
||||
proc genCLineDir(r: var Builder, fileIdx: FileIndex, line: int; p: BProc; info: TLineInfo; lastFileIndex: FileIndex) =
|
||||
assert line >= 0
|
||||
if optLineDir in p.config.options and line > 0:
|
||||
if fileIdx == InvalidFileIdx:
|
||||
@@ -291,7 +302,7 @@ proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; p: BProc; info: TLi
|
||||
else:
|
||||
r.add(rope("\n#line " & $line & " FX_" & $fileIdx.int32 & "\n"))
|
||||
|
||||
proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) =
|
||||
proc genCLineDir(r: var Builder, info: TLineInfo; conf: ConfigRef) =
|
||||
if optLineDir in conf.options:
|
||||
genCLineDir(r, info.fileIndex, info.safeLineNm, conf)
|
||||
|
||||
@@ -304,7 +315,7 @@ proc freshLineInfo(p: BProc; info: TLineInfo): bool =
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc genCLineDir(r: var Rope, p: BProc, info: TLineInfo; conf: ConfigRef) =
|
||||
proc genCLineDir(r: var Builder, p: BProc, info: TLineInfo; conf: ConfigRef) =
|
||||
if optLineDir in conf.options:
|
||||
let lastFileIndex = p.lastLineInfo.fileIndex
|
||||
if freshLineInfo(p, info):
|
||||
@@ -328,7 +339,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||
proc accessThreadLocalVar(p: BProc, s: PSym)
|
||||
proc emulatedThreadVars(conf: ConfigRef): bool {.inline.}
|
||||
proc genProc(m: BModule, prc: PSym)
|
||||
proc raiseInstr(p: BProc; result: var Rope)
|
||||
proc raiseInstr(p: BProc; result: var Builder)
|
||||
|
||||
template compileToCpp(m: BModule): untyped =
|
||||
m.config.backend == backendCpp or sfCompileToCpp in m.module.flags
|
||||
@@ -340,7 +351,6 @@ proc getTempName(m: BModule): Rope =
|
||||
proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
|
||||
sfNoReturn in s.flags and m.config.exc != excGoto
|
||||
|
||||
include cbuilderbase
|
||||
include cbuilderexprs
|
||||
include cbuilderdecls
|
||||
include cbuilderstmts
|
||||
@@ -613,28 +623,29 @@ proc getIntTemp(p: BProc): TLoc =
|
||||
linefmt(p, cpsLocals, "NI $1;$n", [result.snippet])
|
||||
|
||||
proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||
result = ""
|
||||
var res = newBuilder("")
|
||||
let s = n.sym
|
||||
if s.loc.k == locNone:
|
||||
fillLocalName(p, s)
|
||||
fillLoc(s.loc, locLocalVar, n, OnStack)
|
||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
||||
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
||||
res.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
||||
|
||||
genCLineDir(result, p, n.info, p.config)
|
||||
genCLineDir(res, p, n.info, p.config)
|
||||
|
||||
result.add getTypeDesc(p.module, s.typ, dkVar)
|
||||
res.add getTypeDesc(p.module, s.typ, dkVar)
|
||||
if sfCodegenDecl notin s.flags:
|
||||
if sfRegister in s.flags: result.add(" register")
|
||||
if sfRegister in s.flags: res.add(" register")
|
||||
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
|
||||
# decl.add(" GC_GUARD")
|
||||
if sfVolatile in s.flags: result.add(" volatile")
|
||||
if sfNoalias in s.flags: result.add(" NIM_NOALIAS")
|
||||
result.add(" ")
|
||||
result.add(s.loc.snippet)
|
||||
if sfVolatile in s.flags: res.add(" volatile")
|
||||
if sfNoalias in s.flags: res.add(" NIM_NOALIAS")
|
||||
res.add(" ")
|
||||
res.add(s.loc.snippet)
|
||||
result = extract(res)
|
||||
else:
|
||||
result = runtimeFormat(s.cgDeclFrmt, [result, s.loc.snippet])
|
||||
result = runtimeFormat(s.cgDeclFrmt, [extract(res), s.loc.snippet])
|
||||
|
||||
proc assignLocalVar(p: BProc, n: PNode) =
|
||||
#assert(s.loc.k == locNone) # not yet assigned
|
||||
@@ -770,7 +781,7 @@ proc genStmts(p: BProc, t: PNode)
|
||||
proc expr(p: BProc, n: PNode, d: var TLoc)
|
||||
|
||||
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
|
||||
proc genLiteral(p: BProc, n: PNode; result: var Rope)
|
||||
proc genLiteral(p: BProc, n: PNode; result: var Builder)
|
||||
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
|
||||
proc raiseExit(p: BProc)
|
||||
proc raiseExitCleanup(p: BProc, destroy: string)
|
||||
@@ -807,7 +818,7 @@ $1define nimlf_(n, file) \
|
||||
FR_.line = n; FR_.filename = file;
|
||||
|
||||
"""
|
||||
if p.module.s[cfsFrameDefines].len == 0:
|
||||
if p.module.s[cfsFrameDefines].buf.len == 0:
|
||||
appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"])
|
||||
|
||||
cgsym(p.module, "nimFrame")
|
||||
@@ -848,7 +859,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
var s: TStringSeq = @[]
|
||||
libCandidates(lib.path.strVal, s)
|
||||
rawMessage(m.config, hintDependency, lib.path.strVal)
|
||||
var loadlib: Rope = ""
|
||||
var loadlib = newBuilder("")
|
||||
for i in 0..high(s):
|
||||
inc(m.labels)
|
||||
if i > 0: loadlib.add("||")
|
||||
@@ -859,7 +870,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
loadlib.addf "))$n", []
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1)) #nimLoadLibraryError(",
|
||||
[loadlib])
|
||||
[extract(loadlib)])
|
||||
genStringLiteral(m, lib.path, m.s[cfsDynLibInit])
|
||||
m.s[cfsDynLibInit].addf ");$n", []
|
||||
|
||||
@@ -873,9 +884,9 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
[getTypeDesc(m, lib.path.typ, dkVar), rdLoc(dest)])
|
||||
expr(p, lib.path, dest)
|
||||
|
||||
m.s[cfsVars].add(p.s(cpsLocals))
|
||||
m.s[cfsDynLibInit].add(p.s(cpsInit))
|
||||
m.s[cfsDynLibInit].add(p.s(cpsStmts))
|
||||
m.s[cfsVars].add(extract(p.s(cpsLocals)))
|
||||
m.s[cfsDynLibInit].add(extract(p.s(cpsInit)))
|
||||
m.s[cfsDynLibInit].add(extract(p.s(cpsStmts)))
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
|
||||
[tmp, rdLoc(dest)])
|
||||
@@ -995,12 +1006,12 @@ proc generateHeaders(m: BModule) =
|
||||
#undef unix
|
||||
""")
|
||||
|
||||
proc openNamespaceNim(namespace: string; result: var Rope) =
|
||||
proc openNamespaceNim(namespace: string; result: var Builder) =
|
||||
result.add("namespace ")
|
||||
result.add(namespace)
|
||||
result.add(" {\L")
|
||||
|
||||
proc closeNamespaceNim(result: var Rope) =
|
||||
proc closeNamespaceNim(result: var Builder) =
|
||||
result.add("}\L")
|
||||
|
||||
proc closureSetup(p: BProc, prc: PSym) =
|
||||
@@ -1185,9 +1196,10 @@ proc getProcTypeCast(m: BModule, prc: PSym): Rope =
|
||||
result = getTypeDesc(m, prc.loc.t)
|
||||
if prc.typ.callConv == ccClosure:
|
||||
var rettype: Snippet = ""
|
||||
var params = newBuilder("")
|
||||
var desc = newBuilder("")
|
||||
var check = initIntSet()
|
||||
genProcParams(m, prc.typ, rettype, params, check)
|
||||
genProcParams(m, prc.typ, rettype, desc, check)
|
||||
let params = extract(desc)
|
||||
result = procPtrTypeUnnamed(rettype = rettype, params = params)
|
||||
|
||||
proc genProcBody(p: BProc; procBody: PNode) =
|
||||
@@ -1201,14 +1213,14 @@ proc genProcBody(p: BProc; procBody: PNode) =
|
||||
|
||||
proc genProcAux*(m: BModule, prc: PSym) =
|
||||
var p = newProc(prc, m)
|
||||
var header = newRopeAppender()
|
||||
var header = newBuilder("")
|
||||
let isCppMember = m.config.backend == backendCpp and sfCppMember * prc.flags != {}
|
||||
var visibility: DeclVisibility = None
|
||||
if isCppMember:
|
||||
genMemberProcHeader(m, prc, header)
|
||||
else:
|
||||
genProcHeader(m, prc, header, visibility, asPtr = false, addAttributes = false)
|
||||
var returnStmt: Rope = ""
|
||||
var returnStmt: Snippet = ""
|
||||
assert(prc.ast != nil)
|
||||
|
||||
var procBody = transformBody(m.g.graph, m.idgen, prc, {})
|
||||
@@ -1241,9 +1253,10 @@ proc genProcAux*(m: BModule, prc: PSym) =
|
||||
discard "result init optimized out"
|
||||
else:
|
||||
initLocalVar(p, res, immediateAsgn=false)
|
||||
returnStmt = "\t"
|
||||
var returnBuilder = newBuilder("\t")
|
||||
let rres = rdLoc(res.loc)
|
||||
returnStmt.addReturn(rres)
|
||||
returnBuilder.addReturn(rres)
|
||||
returnStmt = extract(returnBuilder)
|
||||
elif sfConstructor in prc.flags:
|
||||
resNode.sym.loc.flags.incl lfIndirect
|
||||
fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)
|
||||
@@ -1278,27 +1291,27 @@ proc genProcAux*(m: BModule, prc: PSym) =
|
||||
generatedProc.genCLineDir prc.info, m.config
|
||||
generatedProc.addDeclWithVisibility(visibility):
|
||||
if sfPure in prc.flags:
|
||||
generatedProc.add(header)
|
||||
generatedProc.add(extract(header))
|
||||
generatedProc.finishProcHeaderWithBody():
|
||||
generatedProc.add(p.s(cpsLocals))
|
||||
generatedProc.add(p.s(cpsInit))
|
||||
generatedProc.add(p.s(cpsStmts))
|
||||
generatedProc.add(extract(p.s(cpsLocals)))
|
||||
generatedProc.add(extract(p.s(cpsInit)))
|
||||
generatedProc.add(extract(p.s(cpsStmts)))
|
||||
else:
|
||||
if m.hcrOn and isReloadable(m, prc):
|
||||
m.s[cfsProcHeaders].addDeclWithVisibility(visibility):
|
||||
# Add forward declaration for "_actual"-suffixed functions defined in the same module (or inline).
|
||||
# This fixes the use of methods and also the case when 2 functions within the same module
|
||||
# call each other using directly the "_actual" versions (an optimization) - see issue #11608
|
||||
m.s[cfsProcHeaders].add(header)
|
||||
m.s[cfsProcHeaders].add(extract(header))
|
||||
m.s[cfsProcHeaders].finishProcHeaderAsProto()
|
||||
generatedProc.add(header)
|
||||
generatedProc.add(extract(header))
|
||||
generatedProc.finishProcHeaderWithBody():
|
||||
if optStackTrace in prc.options:
|
||||
generatedProc.add(p.s(cpsLocals))
|
||||
generatedProc.add(extract(p.s(cpsLocals)))
|
||||
var procname = makeCString(prc.name.s)
|
||||
generatedProc.add(initFrame(p, procname, quotedFilename(p.config, prc.info)))
|
||||
else:
|
||||
generatedProc.add(p.s(cpsLocals))
|
||||
generatedProc.add(extract(p.s(cpsLocals)))
|
||||
if optProfiler in prc.options:
|
||||
# invoke at proc entry for recursion:
|
||||
p.s(cpsInit).add('\t')
|
||||
@@ -1307,15 +1320,15 @@ proc genProcAux*(m: BModule, prc: PSym) =
|
||||
# this pair of {} is required for C++ (C++ is weird with its
|
||||
# control flow integrity checks):
|
||||
generatedProc.addScope():
|
||||
generatedProc.add(p.s(cpsInit))
|
||||
generatedProc.add(p.s(cpsStmts))
|
||||
generatedProc.add(extract(p.s(cpsInit)))
|
||||
generatedProc.add(extract(p.s(cpsStmts)))
|
||||
generatedProc.addLabel("BeforeRet_")
|
||||
else:
|
||||
generatedProc.add(p.s(cpsInit))
|
||||
generatedProc.add(p.s(cpsStmts))
|
||||
generatedProc.add(extract(p.s(cpsInit)))
|
||||
generatedProc.add(extract(p.s(cpsStmts)))
|
||||
if optStackTrace in prc.options: generatedProc.add(deinitFrame(p))
|
||||
generatedProc.add(returnStmt)
|
||||
m.s[cfsProcs].add(generatedProc)
|
||||
m.s[cfsProcs].add(extract(generatedProc))
|
||||
if isReloadable(m, prc):
|
||||
m.s[cfsDynLibInit].add('\t')
|
||||
m.s[cfsDynLibInit].addAssignmentWithValue(prc.loc.snippet):
|
||||
@@ -1356,13 +1369,13 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
'"' & name & '"')
|
||||
elif not containsOrIncl(m.declaredProtos, sym.id):
|
||||
let asPtr = isReloadable(m, sym)
|
||||
var header = newRopeAppender()
|
||||
var header = newBuilder("")
|
||||
var visibility: DeclVisibility = None
|
||||
genProcHeader(m, sym, header, visibility, asPtr = asPtr, addAttributes = true)
|
||||
if asPtr:
|
||||
m.s[cfsProcHeaders].addDeclWithVisibility(visibility):
|
||||
# genProcHeader would give variable declaration, add it directly
|
||||
m.s[cfsProcHeaders].add(header)
|
||||
m.s[cfsProcHeaders].add(extract(header))
|
||||
else:
|
||||
let extraVis =
|
||||
if sym.typ.callConv != ccInline and requiresExternC(m, sym):
|
||||
@@ -1371,7 +1384,7 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
None
|
||||
m.s[cfsProcHeaders].addDeclWithVisibility(extraVis):
|
||||
m.s[cfsProcHeaders].addDeclWithVisibility(visibility):
|
||||
m.s[cfsProcHeaders].add(header)
|
||||
m.s[cfsProcHeaders].add(extract(header))
|
||||
m.s[cfsProcHeaders].finishProcHeaderAsProto()
|
||||
|
||||
# TODO: figure out how to rename this - it DOES generate a forward declaration
|
||||
@@ -1498,7 +1511,7 @@ proc genVarPrototype(m: BModule, n: PNode) =
|
||||
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.snippet,
|
||||
getTypeDesc(m, sym.loc.t, dkVar), getModuleDllPath(m, sym)])
|
||||
|
||||
proc addNimDefines(result: var Rope; conf: ConfigRef) {.inline.} =
|
||||
proc addNimDefines(result: var Builder; conf: ConfigRef) {.inline.} =
|
||||
result.addf("#define NIM_INTBITS $1\L", [
|
||||
platform.CPU[conf.target.targetCPU].intSize.rope])
|
||||
if conf.cppCustomNamespace.len > 0:
|
||||
@@ -1522,9 +1535,10 @@ proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope =
|
||||
rope(getCompileCFileCmd(conf, cfile))]
|
||||
|
||||
proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
|
||||
result = getCopyright(conf, cfile)
|
||||
if conf.hcrOn: result.add("#define NIM_HOT_CODE_RELOADING\L")
|
||||
addNimDefines(result, conf)
|
||||
var res = newBuilder(getCopyright(conf, cfile))
|
||||
if conf.hcrOn: res.add("#define NIM_HOT_CODE_RELOADING\L")
|
||||
addNimDefines(res, conf)
|
||||
result = extract(res)
|
||||
|
||||
proc getSomeNameForModule(conf: ConfigRef, filename: AbsoluteFile): Rope =
|
||||
## Returns a mangled module name.
|
||||
@@ -1567,8 +1581,9 @@ proc genMainProc(m: BModule) =
|
||||
assert prc != nil
|
||||
let n = newStrNode(nkStrLit, prc.annex.path.strVal)
|
||||
n.info = prc.annex.path.info
|
||||
var strLit = newRopeAppender()
|
||||
genStringLiteral(m, n, strLit)
|
||||
var strLitBuilder = newBuilder("")
|
||||
genStringLiteral(m, n, strLitBuilder)
|
||||
let strLit = extract(strLitBuilder)
|
||||
appcg(m, result, "\tif (!($1 = #nimLoadLibrary($2)))$N" &
|
||||
"\t\t#nimLoadLibraryError($2);$N",
|
||||
[handle, strLit])
|
||||
@@ -1780,10 +1795,10 @@ proc registerInitProcs*(g: BModuleList; m: PSym; flags: set[ModuleBackendFlag])
|
||||
proc whichInitProcs*(m: BModule): set[ModuleBackendFlag] =
|
||||
# called from IC.
|
||||
result = {}
|
||||
if m.hcrOn or m.preInitProc.s(cpsInit).len > 0 or m.preInitProc.s(cpsStmts).len > 0:
|
||||
if m.hcrOn or m.preInitProc.s(cpsInit).buf.len > 0 or m.preInitProc.s(cpsStmts).buf.len > 0:
|
||||
result.incl HasModuleInitProc
|
||||
for i in cfsTypeInit1..cfsDynLibInit:
|
||||
if m.s[i].len != 0:
|
||||
if m.s[i].buf.len != 0:
|
||||
result.incl HasDatInitProc
|
||||
break
|
||||
|
||||
@@ -1836,7 +1851,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
m.s[cfsInitProc].add(hcrModuleMeta)
|
||||
return
|
||||
|
||||
if m.s[cfsDatInitProc].len > 0:
|
||||
if m.s[cfsDatInitProc].buf.len > 0:
|
||||
g.mainModProcs.addf("N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [datInit])
|
||||
g.mainDatInit.addf("\t$1();$N", [datInit])
|
||||
|
||||
@@ -1848,7 +1863,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcAtomicArc, gcOrc}:
|
||||
g.mainDatInit.add(ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", []))
|
||||
|
||||
if m.s[cfsInitProc].len > 0:
|
||||
if m.s[cfsInitProc].buf.len > 0:
|
||||
g.mainModProcs.addf("N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [init])
|
||||
let initCall = "\t$1();$N" % [init]
|
||||
if sfMainModule in m.module.flags:
|
||||
@@ -1865,22 +1880,22 @@ proc genDatInitCode(m: BModule) =
|
||||
|
||||
var moduleDatInitRequired = m.hcrOn
|
||||
|
||||
var prc = "$1 N_NIMCALL(void, $2)(void) {$N" %
|
||||
[rope(if m.hcrOn: "N_LIB_EXPORT" else: "N_LIB_PRIVATE"), getDatInitName(m)]
|
||||
var prc = newBuilder("$1 N_NIMCALL(void, $2)(void) {$N" %
|
||||
[rope(if m.hcrOn: "N_LIB_EXPORT" else: "N_LIB_PRIVATE"), getDatInitName(m)])
|
||||
|
||||
# we don't want to break into such init code - could happen if a line
|
||||
# directive from a function written by the user spills after itself
|
||||
genCLineDir(prc, InvalidFileIdx, 999999, m.config)
|
||||
|
||||
for i in cfsTypeInit1..cfsDynLibInit:
|
||||
if m.s[i].len != 0:
|
||||
if m.s[i].buf.len != 0:
|
||||
moduleDatInitRequired = true
|
||||
prc.add(m.s[i])
|
||||
prc.add(extract(m.s[i]))
|
||||
|
||||
prc.addf("}$N$N", [])
|
||||
|
||||
if moduleDatInitRequired:
|
||||
m.s[cfsDatInitProc].add(prc)
|
||||
m.s[cfsDatInitProc].add(extract(prc))
|
||||
#rememberFlag(m.g.graph, m.module, HasDatInitProc)
|
||||
|
||||
# Very similar to the contents of symInDynamicLib - basically only the
|
||||
@@ -1907,8 +1922,8 @@ proc genInitCode(m: BModule) =
|
||||
## into other modules, only simple rope manipulations are allowed
|
||||
var moduleInitRequired = m.hcrOn
|
||||
let initname = getInitName(m)
|
||||
var prc = "$1 N_NIMCALL(void, $2)(void) {$N" %
|
||||
[rope(if m.hcrOn: "N_LIB_EXPORT" else: "N_LIB_PRIVATE"), initname]
|
||||
var prc = newBuilder("$1 N_NIMCALL(void, $2)(void) {$N" %
|
||||
[rope(if m.hcrOn: "N_LIB_EXPORT" else: "N_LIB_PRIVATE"), initname])
|
||||
# we don't want to break into such init code - could happen if a line
|
||||
# directive from a function written by the user spills after itself
|
||||
genCLineDir(prc, InvalidFileIdx, 999999, m.config)
|
||||
@@ -1931,13 +1946,13 @@ proc genInitCode(m: BModule) =
|
||||
[getModuleDllPath(m, m.module)])
|
||||
|
||||
template writeSection(thing: untyped, section: TCProcSection, addHcrGuards = false) =
|
||||
if m.thing.s(section).len > 0:
|
||||
if m.thing.s(section).buf.len > 0:
|
||||
moduleInitRequired = true
|
||||
if addHcrGuards: prc.add("\tif (nim_hcr_do_init_) {\n\n")
|
||||
prc.add(m.thing.s(section))
|
||||
prc.add(extract(m.thing.s(section)))
|
||||
if addHcrGuards: prc.add("\n\t} // nim_hcr_do_init_\n")
|
||||
|
||||
if m.preInitProc.s(cpsInit).len > 0 or m.preInitProc.s(cpsStmts).len > 0:
|
||||
if m.preInitProc.s(cpsInit).buf.len > 0 or m.preInitProc.s(cpsStmts).buf.len > 0:
|
||||
# Give this small function its own scope
|
||||
prc.addf("{$N", [])
|
||||
# Keep a bogus frame in case the code needs one
|
||||
@@ -1957,7 +1972,7 @@ proc genInitCode(m: BModule) =
|
||||
prc.addf("{$N", [])
|
||||
writeSection(initProc, cpsLocals)
|
||||
|
||||
if m.initProc.s(cpsInit).len > 0 or m.initProc.s(cpsStmts).len > 0:
|
||||
if m.initProc.s(cpsInit).buf.len > 0 or m.initProc.s(cpsStmts).buf.len > 0:
|
||||
moduleInitRequired = true
|
||||
if optStackTrace in m.initProc.options and frameDeclared notin m.flags:
|
||||
# BUT: the generated init code might depend on a current frame, so
|
||||
@@ -2011,14 +2026,14 @@ proc genInitCode(m: BModule) =
|
||||
prc.add(ex)
|
||||
|
||||
if moduleInitRequired or sfMainModule in m.module.flags:
|
||||
m.s[cfsInitProc].add(prc)
|
||||
m.s[cfsInitProc].add(extract(prc))
|
||||
#rememberFlag(m.g.graph, m.module, HasModuleInitProc)
|
||||
|
||||
genDatInitCode(m)
|
||||
|
||||
if m.hcrOn:
|
||||
m.s[cfsInitProc].addf("N_LIB_EXPORT N_NIMCALL(void, HcrCreateTypeInfos)(void) {$N", [])
|
||||
m.s[cfsInitProc].add(m.hcrCreateTypeInfosProc)
|
||||
m.s[cfsInitProc].add(extract(m.hcrCreateTypeInfosProc))
|
||||
m.s[cfsInitProc].addf("}$N$N", [])
|
||||
|
||||
registerModuleToMain(m.g, m)
|
||||
@@ -2060,31 +2075,32 @@ proc postprocessCode(conf: ConfigRef, r: var Rope) =
|
||||
proc genModule(m: BModule, cfile: Cfile): Rope =
|
||||
var moduleIsEmpty = true
|
||||
|
||||
result = getFileHeader(m.config, cfile)
|
||||
var res = newBuilder(getFileHeader(m.config, cfile))
|
||||
|
||||
generateThreadLocalStorage(m)
|
||||
generateHeaders(m)
|
||||
result.add(m.s[cfsHeaders])
|
||||
res.add(extract(m.s[cfsHeaders]))
|
||||
if m.config.cppCustomNamespace.len > 0:
|
||||
openNamespaceNim(m.config.cppCustomNamespace, result)
|
||||
if m.s[cfsFrameDefines].len > 0:
|
||||
result.add(m.s[cfsFrameDefines])
|
||||
openNamespaceNim(m.config.cppCustomNamespace, res)
|
||||
if m.s[cfsFrameDefines].buf.len > 0:
|
||||
res.add(extract(m.s[cfsFrameDefines]))
|
||||
|
||||
for i in cfsForwardTypes..cfsProcs:
|
||||
if m.s[i].len > 0:
|
||||
if m.s[i].buf.len > 0:
|
||||
moduleIsEmpty = false
|
||||
result.add(m.s[i])
|
||||
res.add(extract(m.s[i]))
|
||||
|
||||
if m.s[cfsInitProc].len > 0:
|
||||
if m.s[cfsInitProc].buf.len > 0:
|
||||
moduleIsEmpty = false
|
||||
result.add(m.s[cfsInitProc])
|
||||
if m.s[cfsDatInitProc].len > 0 or m.hcrOn:
|
||||
res.add(extract(m.s[cfsInitProc]))
|
||||
if m.s[cfsDatInitProc].buf.len > 0 or m.hcrOn:
|
||||
moduleIsEmpty = false
|
||||
result.add(m.s[cfsDatInitProc])
|
||||
res.add(extract(m.s[cfsDatInitProc]))
|
||||
|
||||
if m.config.cppCustomNamespace.len > 0:
|
||||
closeNamespaceNim(result)
|
||||
closeNamespaceNim(res)
|
||||
|
||||
result = extract(res)
|
||||
if optLineDir in m.config.options:
|
||||
var srcFileDefs = ""
|
||||
for fi in 0..m.config.m.fileInfos.high:
|
||||
@@ -2115,11 +2131,12 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
|
||||
result.typeInfoMarker = initTable[SigHash, Rope]()
|
||||
result.sigConflicts = initCountTable[SigHash]()
|
||||
result.initProc = newProc(nil, result)
|
||||
for i in low(result.s)..high(result.s): result.s[i] = newRopeAppender()
|
||||
for i in low(result.s)..high(result.s): result.s[i] = newBuilder("")
|
||||
result.initProc.options = initProcOptions(result)
|
||||
result.preInitProc = newProc(nil, result)
|
||||
result.preInitProc.flags.incl nimErrorFlagDisabled
|
||||
result.preInitProc.labels = 100_000 # little hack so that unique temporaries are generated
|
||||
result.hcrCreateTypeInfosProc = newBuilder("")
|
||||
result.dataCache = initNodeTable()
|
||||
result.typeStack = @[]
|
||||
result.typeNodesName = getTempName(result)
|
||||
@@ -2158,7 +2175,7 @@ proc setupCgen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassCont
|
||||
incl g.generatedHeader.flags, isHeaderFile
|
||||
|
||||
proc writeHeader(m: BModule) =
|
||||
var result = headerTop()
|
||||
var result = newBuilder(headerTop())
|
||||
var guard = "__$1__" % [m.filename.splitFile.name.rope]
|
||||
result.addf("#ifndef $1$n#define $1$n", [guard])
|
||||
addNimDefines(result, m.config)
|
||||
@@ -2166,17 +2183,17 @@ proc writeHeader(m: BModule) =
|
||||
|
||||
generateThreadLocalStorage(m)
|
||||
for i in cfsHeaders..cfsProcs:
|
||||
result.add(m.s[i])
|
||||
result.add(extract(m.s[i]))
|
||||
if m.config.cppCustomNamespace.len > 0 and i == cfsHeaders:
|
||||
openNamespaceNim(m.config.cppCustomNamespace, result)
|
||||
result.add(m.s[cfsInitProc])
|
||||
result.add(extract(m.s[cfsInitProc]))
|
||||
|
||||
if optGenDynLib in m.config.globalOptions:
|
||||
result.add("N_LIB_IMPORT ")
|
||||
result.addf("N_CDECL(void, $1NimMain)(void);$n", [rope m.config.nimMainPrefix])
|
||||
if m.config.cppCustomNamespace.len > 0: closeNamespaceNim(result)
|
||||
result.addf("#endif /* $1 */$n", [guard])
|
||||
if not writeRope(result, m.filename):
|
||||
if not writeRope(extract(result), m.filename):
|
||||
rawMessage(m.config, errCannotOpenFile, m.filename.string)
|
||||
|
||||
proc getCFile(m: BModule): AbsoluteFile =
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
ast, ropes, options,
|
||||
lineinfos, pathutils, modulegraphs
|
||||
lineinfos, pathutils, modulegraphs, cbuilderbase
|
||||
|
||||
import std/[intsets, tables, sets]
|
||||
|
||||
@@ -43,12 +43,12 @@ type
|
||||
ctUInt, ctUInt8, ctUInt16, ctUInt32, ctUInt64,
|
||||
ctArray, ctPtrToArray, ctStruct, ctPtr, ctNimStr, ctNimSeq, ctProc,
|
||||
ctCString
|
||||
TCFileSections* = array[TCFileSection, Rope] # represents a generated C file
|
||||
TCFileSections* = array[TCFileSection, Builder] # represents a generated C file
|
||||
TCProcSection* = enum # the sections a generated C proc consists of
|
||||
cpsLocals, # section of local variables for C proc
|
||||
cpsInit, # section for init of variables for C proc
|
||||
cpsStmts # section of local statements for C proc
|
||||
TCProcSections* = array[TCProcSection, Rope] # represents a generated C proc
|
||||
TCProcSections* = array[TCProcSection, Builder] # represents a generated C proc
|
||||
BModule* = ref TCGen
|
||||
BProc* = ref TCProc
|
||||
TBlock* = object
|
||||
@@ -161,7 +161,7 @@ type
|
||||
typeInfoMarkerV2*: TypeCache
|
||||
initProc*: BProc # code for init procedure
|
||||
preInitProc*: BProc # code executed before the init proc
|
||||
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
|
||||
hcrCreateTypeInfosProc*: Builder # type info globals are in here when HCR=on
|
||||
inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
|
||||
typeStack*: TTypeSeq # used for type generation
|
||||
dataCache*: TNodeTable
|
||||
@@ -181,18 +181,18 @@ proc includeHeader*(this: BModule; header: string) =
|
||||
if not this.headerFiles.contains header:
|
||||
this.headerFiles.add header
|
||||
|
||||
proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
|
||||
proc s*(p: BProc, s: TCProcSection): var Builder {.inline.} =
|
||||
# section in the current block
|
||||
result = p.blocks[^1].sections[s]
|
||||
|
||||
proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
|
||||
proc procSec*(p: BProc, s: TCProcSection): var Builder {.inline.} =
|
||||
# top level proc sections
|
||||
result = p.blocks[0].sections[s]
|
||||
|
||||
proc initBlock*(): TBlock =
|
||||
result = TBlock()
|
||||
for i in low(result.sections)..high(result.sections):
|
||||
result.sections[i] = newRopeAppender()
|
||||
result.sections[i] = newBuilder("")
|
||||
|
||||
proc newProc*(prc: PSym, module: BModule): BProc =
|
||||
result = BProc(
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
## validated to the server.
|
||||
##
|
||||
## ```Nim
|
||||
## import std/[httpclient]
|
||||
## var client = newHttpClient()
|
||||
## var data = newMultipartData()
|
||||
## data["output"] = "soap12"
|
||||
@@ -79,6 +80,7 @@
|
||||
## it, you can pass your own via the `mimeDb` parameter to avoid this.
|
||||
##
|
||||
## ```Nim
|
||||
## import std/[httpclient, mimetypes]
|
||||
## let mimes = newMimetypes()
|
||||
## var client = newHttpClient()
|
||||
## var data = newMultipartData()
|
||||
@@ -160,7 +162,7 @@
|
||||
## Example of setting SSL verification parameters in a new client:
|
||||
##
|
||||
## ```Nim
|
||||
## import httpclient
|
||||
## import std/[net, httpclient]
|
||||
## var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
|
||||
## ```
|
||||
##
|
||||
|
||||
@@ -507,12 +507,14 @@ type
|
||||
nkAsgn,
|
||||
nkFrom,
|
||||
nkFromItemPair,
|
||||
nkJoin,
|
||||
nkNaturalJoin,
|
||||
nkUsing,
|
||||
nkGroup,
|
||||
nkLimit,
|
||||
nkOffset,
|
||||
nkHaving,
|
||||
nkOrder,
|
||||
nkJoin,
|
||||
nkDesc,
|
||||
nkUnion,
|
||||
nkIntersect,
|
||||
@@ -936,18 +938,75 @@ proc parseWhere(p: var SqlParser): SqlNode =
|
||||
result = newNode(nkWhere)
|
||||
result.add(parseExpr(p))
|
||||
|
||||
proc parseJoinType(p: var SqlParser): SqlNode =
|
||||
## parse [ INNER ] JOIN | ( LEFT | RIGHT | FULL ) [ OUTER ] JOIN
|
||||
if isKeyw(p, "inner"):
|
||||
getTok(p)
|
||||
eat(p, "join")
|
||||
return newNode(nkIdent, "inner")
|
||||
elif isKeyw(p, "join"):
|
||||
getTok(p)
|
||||
return newNode(nkIdent, "")
|
||||
elif isKeyw(p, "left") or isKeyw(p, "full") or isKeyw(p, "right"):
|
||||
var joinType = newNode(nkIdent, p.tok.literal.toLowerAscii())
|
||||
getTok(p)
|
||||
optKeyw(p, "outer")
|
||||
eat(p, "join")
|
||||
return joinType
|
||||
else:
|
||||
sqlError(p, "join type expected")
|
||||
|
||||
proc parseFromItem(p: var SqlParser): SqlNode =
|
||||
result = newNode(nkFromItemPair)
|
||||
var expectAs = true
|
||||
if p.tok.kind == tkParLe:
|
||||
getTok(p)
|
||||
var select = parseSelect(p)
|
||||
result.add(select)
|
||||
if isKeyw(p, "select"):
|
||||
result.add(parseSelect(p))
|
||||
else:
|
||||
result = parseFromItem(p)
|
||||
expectAs = false
|
||||
eat(p, tkParRi)
|
||||
else:
|
||||
result.add(parseExpr(p))
|
||||
if isKeyw(p, "as"):
|
||||
if expectAs and isKeyw(p, "as"):
|
||||
getTok(p)
|
||||
result.add(parseExpr(p))
|
||||
while true:
|
||||
if isKeyw(p, "cross"):
|
||||
var join = newNode(nkJoin)
|
||||
join.add(newNode(nkIdent, "cross"))
|
||||
join.add(result)
|
||||
getTok(p)
|
||||
eat(p, "join")
|
||||
join.add(parseFromItem(p))
|
||||
result = join
|
||||
elif isKeyw(p, "natural"):
|
||||
var join = newNode(nkNaturalJoin)
|
||||
getTok(p)
|
||||
join.add(parseJoinType(p))
|
||||
join.add(result)
|
||||
join.add(parseFromItem(p))
|
||||
result = join
|
||||
elif isKeyw(p, "inner") or isKeyw(p, "join") or isKeyw(p, "left") or
|
||||
iskeyw(p, "full") or isKeyw(p, "right"):
|
||||
var join = newNode(nkJoin)
|
||||
join.add(parseJoinType(p))
|
||||
join.add(result)
|
||||
join.add(parseFromItem(p))
|
||||
if isKeyw(p, "on"):
|
||||
getTok(p)
|
||||
join.add(parseExpr(p))
|
||||
elif isKeyw(p, "using"):
|
||||
getTok(p)
|
||||
var n = newNode(nkUsing)
|
||||
parseParIdentList(p, n)
|
||||
join.add n
|
||||
else:
|
||||
sqlError(p, "ON or USING expected")
|
||||
result = join
|
||||
else:
|
||||
break
|
||||
|
||||
proc parseIndexDef(p: var SqlParser): SqlNode =
|
||||
result = parseIfNotExists(p, nkCreateIndex)
|
||||
@@ -1109,19 +1168,6 @@ proc parseSelect(p: var SqlParser): SqlNode =
|
||||
elif isKeyw(p, "except"):
|
||||
result.add(newNode(nkExcept))
|
||||
getTok(p)
|
||||
if isKeyw(p, "join") or isKeyw(p, "inner") or isKeyw(p, "outer") or isKeyw(p, "cross"):
|
||||
var join = newNode(nkJoin)
|
||||
result.add(join)
|
||||
if isKeyw(p, "join"):
|
||||
join.add(newNode(nkIdent, ""))
|
||||
getTok(p)
|
||||
else:
|
||||
join.add(newNode(nkIdent, p.tok.literal.toLowerAscii()))
|
||||
getTok(p)
|
||||
eat(p, "join")
|
||||
join.add(parseFromItem(p))
|
||||
eat(p, "on")
|
||||
join.add(parseExpr(p))
|
||||
if isKeyw(p, "limit"):
|
||||
getTok(p)
|
||||
var l = newNode(nkLimit)
|
||||
@@ -1388,6 +1434,30 @@ proc ra(n: SqlNode, s: var SqlWriter) =
|
||||
of nkFrom:
|
||||
s.addKeyw("from")
|
||||
s.addMulti(n)
|
||||
of nkJoin, nkNaturalJoin:
|
||||
var joinType = n.sons[0].strVal
|
||||
if joinType == "":
|
||||
joinType = "join"
|
||||
else:
|
||||
joinType &= " " & "join"
|
||||
if n.kind == nkNaturalJoin:
|
||||
joinType = "natural " & joinType
|
||||
ra(n.sons[1], s)
|
||||
s.addKeyw(joinType)
|
||||
# If the right part of the join is not leaf, parenthesize it
|
||||
if n.sons[2].kind != nkFromItemPair:
|
||||
s.add('(')
|
||||
ra(n.sons[2], s)
|
||||
s.add(')')
|
||||
else:
|
||||
ra(n.sons[2], s)
|
||||
if n.sons.len > 3:
|
||||
if n.sons[3].kind != nkUsing:
|
||||
s.addKeyw("on")
|
||||
ra(n.sons[3], s)
|
||||
of nkUsing:
|
||||
s.addKeyw("using")
|
||||
rs(n, s)
|
||||
of nkGroup:
|
||||
s.addKeyw("group by")
|
||||
s.addMulti(n)
|
||||
@@ -1403,16 +1473,6 @@ proc ra(n: SqlNode, s: var SqlWriter) =
|
||||
of nkOrder:
|
||||
s.addKeyw("order by")
|
||||
s.addMulti(n)
|
||||
of nkJoin:
|
||||
var joinType = n.sons[0].strVal
|
||||
if joinType == "":
|
||||
joinType = "join"
|
||||
else:
|
||||
joinType &= " " & "join"
|
||||
s.addKeyw(joinType)
|
||||
ra(n.sons[1], s)
|
||||
s.addKeyw("on")
|
||||
ra(n.sons[2], s)
|
||||
of nkDesc:
|
||||
ra(n.sons[0], s)
|
||||
s.addKeyw("desc")
|
||||
|
||||
@@ -159,17 +159,76 @@ INNER JOIN b
|
||||
ON a.id == b.id
|
||||
""") == "select id from a inner join b on a.id == b.id;"
|
||||
|
||||
doAssert $parseSql("""
|
||||
# For OUTER joins, LEFT | RIGHT | FULL specifier is not optional
|
||||
doAssertRaises(SqlParseError): discard parseSql("""
|
||||
SELECT id FROM a
|
||||
OUTER JOIN b
|
||||
ON a.id == b.id
|
||||
""") == "select id from a outer join b on a.id == b.id;"
|
||||
ON a.id = b.id
|
||||
""")
|
||||
|
||||
doAssert $parseSql("""
|
||||
# For NATURAL JOIN and CROSS JOIN, ON and USING clauses are forbidden
|
||||
doAssertRaises(SqlParseError): discard parseSql("""
|
||||
SELECT id FROM a
|
||||
CROSS JOIN b
|
||||
ON a.id == b.id
|
||||
""") == "select id from a cross join b on a.id == b.id;"
|
||||
ON a.id = b.id
|
||||
""")
|
||||
|
||||
# JOIN should parse as part of FROM, not after WHERE
|
||||
doAssertRaises(SqlParseError): discard parseSql("""
|
||||
SELECT id FROM a
|
||||
WHERE a.id IS NOT NULL
|
||||
INNER JOIN b
|
||||
ON a.id = b.id
|
||||
""")
|
||||
|
||||
# JOIN should parse as part of FROM, other fromItems may follow
|
||||
doAssert $parseSql("""
|
||||
SELECT id
|
||||
FROM
|
||||
a JOIN b ON a.id = b.id,
|
||||
c
|
||||
""") == "select id from a join b on a.id = b.id, c;"
|
||||
|
||||
# LEFT JOIN should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id FROM a
|
||||
LEFT JOIN b
|
||||
ON a.id = b.id
|
||||
""") == "select id from a left join b on a.id = b.id;"
|
||||
|
||||
# NATURAL JOIN should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id FROM a
|
||||
NATURAL JOIN b
|
||||
""") == "select id from a natural join b;"
|
||||
|
||||
# USING should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id FROM a
|
||||
JOIN b
|
||||
USING (id)
|
||||
""") == "select id from a join b using (id );"
|
||||
|
||||
# Multiple JOINs should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id FROM a
|
||||
JOIN b
|
||||
ON a.id = b.id
|
||||
LEFT JOIN c
|
||||
USING (id)
|
||||
""") == "select id from a join b on a.id = b.id left join c using (id );"
|
||||
|
||||
# Parenthesized JOIN expressions should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id
|
||||
FROM a JOIN (b JOIN c USING (id)) ON a.id = b.id
|
||||
""") == "select id from a join(b join c using (id )) on a.id = b.id;"
|
||||
|
||||
# Left-side parenthesized JOIN expressions should parse
|
||||
doAssert $parseSql("""
|
||||
SELECT id
|
||||
FROM (b JOIN c USING (id)) JOIN a ON a.id = b.id
|
||||
""") == "select id from b join c using (id ) join a on a.id = b.id;"
|
||||
|
||||
doAssert $parseSql("""
|
||||
CREATE TYPE happiness AS ENUM ('happy', 'very happy', 'ecstatic');
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
## nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:nimDisableCertificateValidation -d:ssl -p:. tests/untestable/thttpclient_ssl_disabled.nim
|
||||
|
||||
from stdtest/testutils import enableRemoteNetworking
|
||||
when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(openbsd)):
|
||||
# badssl tests disabled indefinitely
|
||||
when false and enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(openbsd)):
|
||||
import httpclient, net, unittest
|
||||
|
||||
const expired = "https://expired.badssl.com/"
|
||||
|
||||
@@ -19,7 +19,6 @@ from net import newSocket, newContext, wrapSocket, connect, close, Port,
|
||||
from strutils import contains
|
||||
|
||||
const
|
||||
expired = "https://expired.badssl.com/"
|
||||
good = "https://google.com/"
|
||||
|
||||
|
||||
@@ -56,12 +55,13 @@ suite "SSL certificate check":
|
||||
var ctx = newContext(verifyMode=CVerifyPeerUseEnvVars)
|
||||
ctx.wrapSocket(sock)
|
||||
checkpoint("Socket created")
|
||||
try:
|
||||
sock.connect("expired.badssl.com", 443.Port)
|
||||
fail()
|
||||
except:
|
||||
sock.close
|
||||
check getCurrentExceptionMsg().contains("certificate verify failed")
|
||||
when false: # badssl tests disabled indefinitely
|
||||
try:
|
||||
sock.connect("expired.badssl.com", 443.Port)
|
||||
fail()
|
||||
except:
|
||||
sock.close
|
||||
check getCurrentExceptionMsg().contains("certificate verify failed")
|
||||
|
||||
elif existsEnv("SSL_CERT_DIR"):
|
||||
var sock = newSocket()
|
||||
|
||||
@@ -33,7 +33,8 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win
|
||||
CertTest = tuple[url:string, category:Category, desc: string]
|
||||
|
||||
# badssl certs sometimes expire, set to false when that happens
|
||||
when true:
|
||||
# badssl now disabled indefinitely
|
||||
when false:
|
||||
const certificate_tests: array[0..54, CertTest] = [
|
||||
("https://wrong.host.badssl.com/", bad, "wrong.host"),
|
||||
("https://captive-portal.badssl.com/", bad, "captive-portal"),
|
||||
@@ -197,7 +198,7 @@ when enableRemoteNetworking and (defined(nimTestsEnableFlaky) or not defined(win
|
||||
|
||||
type NetSocketTest = tuple[hostname: string, port: Port, category:Category, desc: string]
|
||||
# badssl certs sometimes expire, set to false when that happens
|
||||
when true:
|
||||
when false:
|
||||
const net_tests:array[0..3, NetSocketTest] = [
|
||||
("imap.gmail.com", 993.Port, good, "IMAP"),
|
||||
("wrong.host.badssl.com", 443.Port, bad, "wrong.host"),
|
||||
|
||||
Reference in New Issue
Block a user