Merge branch 'devel' into araq
This commit is contained in:
commit
39f0195ebf
334 changed files with 4636 additions and 2763 deletions
|
|
@ -292,6 +292,8 @@ const
|
|||
|
||||
sfNoForward* = sfRegister
|
||||
# forward declarations are not required (per module)
|
||||
sfReorder* = sfForward
|
||||
# reordering pass is enabled
|
||||
|
||||
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
|
||||
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
|
||||
|
|
|
|||
|
|
@ -744,14 +744,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
|||
addf(r, ".Field$1", [rope(i)])
|
||||
putIntoDest(p, d, tupType.sons[i], r, a.s)
|
||||
|
||||
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
|
||||
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope;
|
||||
resTyp: ptr PType = nil): PSym =
|
||||
var ty = ty
|
||||
assert r != nil
|
||||
while ty != nil:
|
||||
ty = ty.skipTypes(skipPtrs)
|
||||
assert(ty.kind in {tyTuple, tyObject})
|
||||
result = lookupInRecord(ty.n, field.name)
|
||||
if result != nil: break
|
||||
if result != nil:
|
||||
if resTyp != nil: resTyp[] = ty
|
||||
break
|
||||
if not p.module.compileToCpp: add(r, ".Sup")
|
||||
ty = ty.sons[0]
|
||||
if result == nil: internalError(field.info, "genCheckedRecordField")
|
||||
|
|
@ -768,8 +771,9 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
|||
addf(r, ".Field$1", [rope(f.position)])
|
||||
putIntoDest(p, d, f.typ, r, a.s)
|
||||
else:
|
||||
let field = lookupFieldAgain(p, ty, f, r)
|
||||
if field.loc.r == nil: fillObjectFields(p.module, ty)
|
||||
var rtyp: PType
|
||||
let field = lookupFieldAgain(p, ty, f, r, addr rtyp)
|
||||
if field.loc.r == nil and rtyp != nil: fillObjectFields(p.module, rtyp)
|
||||
if field.loc.r == nil: internalError(e.info, "genRecordField 3 " & typeToString(ty))
|
||||
addf(r, ".$1", [field.loc.r])
|
||||
putIntoDest(p, d, field.typ, r, a.s)
|
||||
|
|
@ -1057,7 +1061,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
|||
"$1 = ($2) #incrSeqV2(&($1)->Sup, sizeof($3));$n"
|
||||
else:
|
||||
"$1 = ($2) #incrSeqV2($1, sizeof($3));$n"
|
||||
var a, b, dest: TLoc
|
||||
var a, b, dest, tmpL: TLoc
|
||||
initLocExpr(p, e.sons[1], a)
|
||||
initLocExpr(p, e.sons[2], b)
|
||||
let bt = skipTypes(e.sons[2].typ, {tyVar})
|
||||
|
|
@ -1068,9 +1072,10 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
|||
#if bt != b.t:
|
||||
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
|
||||
initLoc(dest, locExpr, bt, OnHeap)
|
||||
dest.r = rfmt(nil, "$1->data[$1->$2]", rdLoc(a), lenField(p))
|
||||
getIntTemp(p, tmpL)
|
||||
lineCg(p, cpsStmts, "$1 = $2->$3++;$n", tmpL.r, rdLoc(a), lenField(p))
|
||||
dest.r = rfmt(nil, "$1->data[$2]", rdLoc(a), tmpL.r)
|
||||
genAssignment(p, dest, b, {needToCopy, afDestIsNil})
|
||||
lineCg(p, cpsStmts, "++$1->$2;$n", rdLoc(a), lenField(p))
|
||||
gcUsage(e)
|
||||
|
||||
proc genReset(p: BProc, n: PNode) =
|
||||
|
|
@ -1096,9 +1101,9 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
|
|||
if a.s == OnHeap and usesNativeGC():
|
||||
# use newObjRC1 as an optimization
|
||||
if canFormAcycle(a.t):
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc)
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", a.rdLoc)
|
||||
b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args)
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
|
||||
else:
|
||||
|
|
@ -1126,9 +1131,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope) =
|
|||
initLoc(call, locExpr, dest.t, OnHeap)
|
||||
if dest.s == OnHeap and usesNativeGC():
|
||||
if canFormAcycle(dest.t):
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc)
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc)
|
||||
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", dest.rdLoc)
|
||||
call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
|
||||
linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
|
||||
else:
|
||||
|
|
@ -1170,7 +1175,10 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
|||
|
||||
proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
#echo rendertree e, " ", e.isDeepConstExpr
|
||||
if handleConstExpr(p, e, d): return
|
||||
# inheritance in C++ does not allow struct initialization so
|
||||
# we skip this step here:
|
||||
if not p.module.compileToCpp:
|
||||
if handleConstExpr(p, e, d): return
|
||||
var tmp: TLoc
|
||||
var t = e.typ.skipTypes(abstractInst)
|
||||
getTemp(p, t, tmp)
|
||||
|
|
@ -1378,13 +1386,30 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
useStringh(p.module)
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1 ? (strlen($1)-1) : -1)")
|
||||
else: unaryExpr(p, e, d, "($1 ? strlen($1) : 0)")
|
||||
of tyString, tySequence:
|
||||
of tyString:
|
||||
if not p.module.compileToCpp:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->Sup.len-1) : -1)")
|
||||
else: unaryExpr(p, e, d, "($1 ? $1->Sup.len : 0)")
|
||||
else:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1 ? ($1->len-1) : -1)")
|
||||
else: unaryExpr(p, e, d, "($1 ? $1->len : 0)")
|
||||
of tySequence:
|
||||
var a, tmp: TLoc
|
||||
initLocExpr(p, e[1], a)
|
||||
getIntTemp(p, tmp)
|
||||
var frmt: FormatStr
|
||||
if not p.module.compileToCpp:
|
||||
if op == mHigh:
|
||||
frmt = "$1 = ($2 ? ($2->Sup.len-1) : -1);$n"
|
||||
else:
|
||||
frmt = "$1 = ($2 ? $2->Sup.len : 0);$n"
|
||||
else:
|
||||
if op == mHigh:
|
||||
frmt = "$1 = ($2 ? ($2->len-1) : -1);$n"
|
||||
else:
|
||||
frmt = "$1 = ($2 ? $2->len : 0);$n"
|
||||
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
|
||||
putIntoDest(p, d, e.typ, tmp.r)
|
||||
of tyArray:
|
||||
# YYY: length(sideeffect) is optimized away incorrectly?
|
||||
if op == mHigh: putIntoDest(p, d, e.typ, rope(lastOrd(typ)))
|
||||
|
|
@ -1742,11 +1767,23 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
of mOrd: genOrd(p, e, d)
|
||||
of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray:
|
||||
genArrayLen(p, e, d, op)
|
||||
of mXLenStr, mXLenSeq:
|
||||
of mXLenStr:
|
||||
if not p.module.compileToCpp:
|
||||
unaryExpr(p, e, d, "($1->Sup.len)")
|
||||
else:
|
||||
unaryExpr(p, e, d, "$1->len")
|
||||
of mXLenSeq:
|
||||
# see 'taddhigh.nim' for why we need to use a temporary here:
|
||||
var a, tmp: TLoc
|
||||
initLocExpr(p, e[1], a)
|
||||
getIntTemp(p, tmp)
|
||||
var frmt: FormatStr
|
||||
if not p.module.compileToCpp:
|
||||
frmt = "$1 = $2->Sup.len;$n"
|
||||
else:
|
||||
frmt = "$1 = $2->len;$n"
|
||||
lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a))
|
||||
putIntoDest(p, d, e.typ, tmp.r)
|
||||
of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n")
|
||||
of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n")
|
||||
of mSetLengthStr: genSetLengthStr(p, e, d)
|
||||
|
|
@ -2123,17 +2160,19 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
|||
# See tests/run/tcnstseq3 for an example that would fail otherwise.
|
||||
genAsgn(p, n, fastAsgn=p.prc != nil)
|
||||
of nkDiscardStmt:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
let ex = n[0]
|
||||
if ex.kind != nkEmpty:
|
||||
genLineDir(p, n)
|
||||
var a: TLoc
|
||||
if n[0].kind in nkCallKinds:
|
||||
if ex.kind in nkCallKinds and (ex[0].kind != nkSym or
|
||||
ex[0].sym.magic == mNone):
|
||||
# bug #6037: do not assign to a temp in C++ mode:
|
||||
incl a.flags, lfSingleUse
|
||||
genCall(p, n[0], a)
|
||||
genCall(p, ex, a)
|
||||
if lfSingleUse notin a.flags:
|
||||
line(p, cpsStmts, a.r & ";" & tnl)
|
||||
else:
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
initLocExpr(p, ex, a)
|
||||
of nkAsmStmt: genAsmStmt(p, n)
|
||||
of nkTryStmt:
|
||||
if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions:
|
||||
|
|
@ -2201,20 +2240,22 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
|
|||
else:
|
||||
globalError(info, "cannot create null element for: " & $t.kind)
|
||||
|
||||
proc getNullValueAux(p: BProc; obj, cons: PNode, result: var Rope) =
|
||||
proc getNullValueAux(p: BProc; t: PType; obj, cons: PNode, result: var Rope; count: var int) =
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(p, obj.sons[i], cons, result)
|
||||
for i in countup(0, sonsLen(obj) - 1):
|
||||
getNullValueAux(p, t, obj.sons[i], cons, result, count)
|
||||
of nkRecCase:
|
||||
getNullValueAux(p, obj.sons[0], cons, result)
|
||||
getNullValueAux(p, t, obj.sons[0], cons, result, count)
|
||||
for i in countup(1, sonsLen(obj) - 1):
|
||||
getNullValueAux(p, lastSon(obj.sons[i]), cons, result)
|
||||
getNullValueAux(p, t, lastSon(obj.sons[i]), cons, result, count)
|
||||
of nkSym:
|
||||
if not result.isNil: result.add ", "
|
||||
if count > 0: result.add ", "
|
||||
inc count
|
||||
let field = obj.sym
|
||||
for i in 1..<cons.len:
|
||||
if cons[i].kind == nkExprColonExpr:
|
||||
if cons[i][0].sym.name == field.name:
|
||||
if cons[i][0].sym.name.id == field.name.id:
|
||||
result.add genConstExpr(p, cons[i][1])
|
||||
return
|
||||
elif i == field.position:
|
||||
|
|
@ -2225,14 +2266,32 @@ proc getNullValueAux(p: BProc; obj, cons: PNode, result: var Rope) =
|
|||
else:
|
||||
localError(cons.info, "cannot create null element for: " & $obj)
|
||||
|
||||
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, cons: PNode, result: var Rope; count: var int) =
|
||||
var base = t.sons[0]
|
||||
let oldRes = result
|
||||
if not p.module.compileToCpp: result.add "{"
|
||||
let oldcount = count
|
||||
if base != nil:
|
||||
base = skipTypes(base, skipPtrs)
|
||||
getNullValueAuxT(p, orig, base, base.n, cons, result, count)
|
||||
elif not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||
addf(result, "$1", [genTypeInfo(p.module, orig)])
|
||||
inc count
|
||||
getNullValueAux(p, t, obj, cons, result, count)
|
||||
# do not emit '{}' as that is not valid C:
|
||||
if oldcount == count: result = oldres
|
||||
elif not p.module.compileToCpp: result.add "}"
|
||||
|
||||
proc genConstObjConstr(p: BProc; n: PNode): Rope =
|
||||
var length = sonsLen(n)
|
||||
result = nil
|
||||
let t = n.typ.skipTypes(abstractInst)
|
||||
if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||
addf(result, "{$1}", [genTypeInfo(p.module, t)])
|
||||
getNullValueAux(p, t.n, n, result)
|
||||
result = "{$1}$n" % [result]
|
||||
var count = 0
|
||||
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||
# addf(result, "{$1}", [genTypeInfo(p.module, t)])
|
||||
# inc count
|
||||
getNullValueAuxT(p, t, t, t.n, n, result, count)
|
||||
if p.module.compileToCpp:
|
||||
result = "{$1}$n" % [result]
|
||||
|
||||
proc genConstSimpleList(p: BProc, n: PNode): Rope =
|
||||
var length = sonsLen(n)
|
||||
|
|
@ -2279,6 +2338,15 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
|
|||
var t = skipTypes(n.typ, abstractInst)
|
||||
if t.kind == tySequence:
|
||||
result = genConstSeq(p, n, n.typ)
|
||||
elif t.kind == tyProc and t.callConv == ccClosure and not n.sons.isNil and
|
||||
n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit:
|
||||
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
|
||||
# this behaviour is needed since closure_var = nil must be
|
||||
# expanded to {NIM_NIL,NIM_NIL}
|
||||
# in VM closures are initialized with nkPar(nkNilLit, nkNilLit)
|
||||
# leading to duplicate code like this:
|
||||
# "{NIM_NIL,NIM_NIL}, {NIM_NIL,NIM_NIL}"
|
||||
result = ~"{NIM_NIL,NIM_NIL}"
|
||||
else:
|
||||
result = genConstSimpleList(p, n)
|
||||
of nkObjConstr:
|
||||
|
|
|
|||
|
|
@ -164,11 +164,11 @@ proc genBreakState(p: BProc, n: PNode) =
|
|||
if n.sons[0].kind == nkClosure:
|
||||
# XXX this produces quite inefficient code!
|
||||
initLocExpr(p, n.sons[0].sons[1], a)
|
||||
lineF(p, cpsStmts, "if (((NI*) $1)[0] < 0) break;$n", [rdLoc(a)])
|
||||
lineF(p, cpsStmts, "if (((NI*) $1)[1] < 0) break;$n", [rdLoc(a)])
|
||||
else:
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
# the environment is guaranteed to contain the 'state' field at offset 0:
|
||||
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[0]) < 0) break;$n", [rdLoc(a)])
|
||||
# the environment is guaranteed to contain the 'state' field at offset 1:
|
||||
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)])
|
||||
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
|
||||
|
||||
proc genVarPrototypeAux(m: BModule, sym: PSym)
|
||||
|
|
|
|||
|
|
@ -72,10 +72,16 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
|
|||
let arraySize = lengthOrd(typ.sons[0])
|
||||
var i: TLoc
|
||||
getTemp(p, getSysType(tyInt), i)
|
||||
let oldCode = p.s(cpsStmts)
|
||||
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||
i.r, arraySize.rope)
|
||||
let oldLen = p.s(cpsStmts).len
|
||||
genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1])
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
if p.s(cpsStmts).len == oldLen:
|
||||
# do not emit dummy long loops for faster debug builds:
|
||||
p.s(cpsStmts) = oldCode
|
||||
else:
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
of tyObject:
|
||||
for i in countup(0, sonsLen(typ) - 1):
|
||||
var x = typ.sons[i]
|
||||
|
|
@ -99,10 +105,16 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: Rope, typ: PType) =
|
|||
assert typ.kind == tySequence
|
||||
var i: TLoc
|
||||
getTemp(p, getSysType(tyInt), i)
|
||||
let oldCode = p.s(cpsStmts)
|
||||
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2->$3; $1++) {$n",
|
||||
[i.r, accessor, rope(if c.p.module.compileToCpp: "len" else: "Sup.len")])
|
||||
let oldLen = p.s(cpsStmts).len
|
||||
genTraverseProc(c, "$1->data[$2]" % [accessor, i.r], typ.sons[0])
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
if p.s(cpsStmts).len == oldLen:
|
||||
# do not emit dummy long loops for faster debug builds:
|
||||
p.s(cpsStmts) = oldCode
|
||||
else:
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
|
||||
proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash;
|
||||
reason: TTypeInfoReason): Rope =
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
# ------------------------- Name Mangling --------------------------------
|
||||
|
||||
import sighashes
|
||||
from lowerings import createObj
|
||||
|
||||
proc isKeyword(w: PIdent): bool =
|
||||
# Nim and C++ share some keywords
|
||||
|
|
@ -122,10 +123,11 @@ const
|
|||
|
||||
proc typeName(typ: PType): Rope =
|
||||
let typ = typ.skipTypes(irrelevantForBackend)
|
||||
result = if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
|
||||
typ.sym.name.s.mangle.rope
|
||||
else:
|
||||
~"TY"
|
||||
result =
|
||||
if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
|
||||
rope($typ.kind & '_' & typ.sym.name.s.mangle)
|
||||
else:
|
||||
rope($typ.kind)
|
||||
|
||||
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||
var t = typ
|
||||
|
|
@ -335,6 +337,7 @@ proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
|
|||
if result == nil: result = cacheGetType(m.typeCache, sig)
|
||||
|
||||
proc structOrUnion(t: PType): Rope =
|
||||
let t = t.skipTypes({tyAlias})
|
||||
(if tfUnion in t.flags: rope("union") else: rope("struct"))
|
||||
|
||||
proc getForwardStructFormat(m: BModule): string =
|
||||
|
|
@ -473,11 +476,14 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
|||
if tfPacked notin rectype.flags:
|
||||
add(unionBody, "struct {")
|
||||
else:
|
||||
addf(unionBody, CC[cCompiler].structStmtFmt,
|
||||
[rope"struct", nil, rope(CC[cCompiler].packedPragma)])
|
||||
add(unionBody, "{")
|
||||
if hasAttribute in CC[cCompiler].props:
|
||||
add(unionBody, "struct __attribute__((__packed__)){" )
|
||||
else:
|
||||
addf(unionBody, "#pragma pack(1)$nstruct{", [])
|
||||
add(unionBody, a)
|
||||
addf(unionBody, "} $1;$n", [sname])
|
||||
if tfPacked in rectype.flags and hasAttribute notin CC[cCompiler].props:
|
||||
addf(unionBody, "#pragma pack(pop)$n", [])
|
||||
else:
|
||||
add(unionBody, genRecordFieldsAux(m, k, ae, rectype, check))
|
||||
else: internalError("genRecordFieldsAux(record case branch)")
|
||||
|
|
@ -524,12 +530,16 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
|||
# declare the record:
|
||||
var hasField = false
|
||||
|
||||
var attribute: Rope =
|
||||
if tfPacked in typ.flags: rope(CC[cCompiler].packedPragma)
|
||||
else: nil
|
||||
if tfPacked in typ.flags:
|
||||
if hasAttribute in CC[cCompiler].props:
|
||||
result = structOrUnion(typ) & " __attribute__((__packed__))"
|
||||
else:
|
||||
result = "#pragma pack(1)" & tnl & structOrUnion(typ)
|
||||
else:
|
||||
result = structOrUnion(typ)
|
||||
|
||||
result = ropecg(m, CC[cCompiler].structStmtFmt,
|
||||
[structOrUnion(typ), name, attribute])
|
||||
result.add " "
|
||||
result.add name
|
||||
|
||||
if typ.kind == tyObject:
|
||||
|
||||
|
|
@ -537,7 +547,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
|||
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
|
||||
appcg(m, result, " {$n", [])
|
||||
else:
|
||||
appcg(m, result, " {$n#TNimType* m_type;$n", [name, attribute])
|
||||
appcg(m, result, " {$n#TNimType* m_type;$n", [])
|
||||
hasField = true
|
||||
elif m.compileToCpp:
|
||||
appcg(m, result, " : public $1 {$n",
|
||||
|
|
@ -556,6 +566,8 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
|||
else:
|
||||
add(result, desc)
|
||||
add(result, "};" & tnl)
|
||||
if tfPacked in typ.flags and hasAttribute notin CC[cCompiler].props:
|
||||
result.add "#pragma pack(pop)" & tnl
|
||||
|
||||
proc getTupleDesc(m: BModule, typ: PType, name: Rope,
|
||||
check: var IntSet): Rope =
|
||||
|
|
@ -787,7 +799,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
|||
add(m.s[cfsTypes], recdesc)
|
||||
elif tfIncompleteStruct notin t.flags: addAbiCheck(m, t, result)
|
||||
of tySet:
|
||||
result = getTypeName(m, t.lastSon, hashType t.lastSon) & "_Set"
|
||||
result = $t.kind & '_' & getTypeName(m, t.lastSon, hashType t.lastSon)
|
||||
m.typeCache[sig] = result
|
||||
if not isImportedType(t):
|
||||
let s = int(getSize(t))
|
||||
|
|
@ -1083,7 +1095,8 @@ proc fakeClosureType(owner: PSym): PType =
|
|||
result = newType(tyTuple, owner)
|
||||
result.rawAddSon(newType(tyPointer, owner))
|
||||
var r = newType(tyRef, owner)
|
||||
r.rawAddSon(newType(tyTuple, owner))
|
||||
let obj = createObj(owner, owner.info, final=false)
|
||||
r.rawAddSon(obj)
|
||||
result.rawAddSon(r)
|
||||
|
||||
type
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
|||
if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags):
|
||||
if freshLineInfo(p, tt.info):
|
||||
linefmt(p, cpsStmts, "#endb($1, $2);$n",
|
||||
linefmt(p, cpsStmts, "#endb($1, $2);$N",
|
||||
line.rope, makeCString(toFilename(tt.info)))
|
||||
elif ({optLineTrace, optStackTrace} * p.options ==
|
||||
{optLineTrace, optStackTrace}) and
|
||||
|
|
@ -345,6 +345,15 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
|||
result.flags = {}
|
||||
constructLoc(p, result, not needsInit)
|
||||
|
||||
proc getIntTemp(p: BProc, result: var TLoc) =
|
||||
inc(p.labels)
|
||||
result.r = "T" & rope(p.labels) & "_"
|
||||
linefmt(p, cpsLocals, "NI $1;$n", result.r)
|
||||
result.k = locTemp
|
||||
result.s = OnStack
|
||||
result.t = getSysType(tyInt)
|
||||
result.flags = {}
|
||||
|
||||
proc initGCFrame(p: BProc): Rope =
|
||||
if p.gcFrameId > 0: result = "struct {$1} GCFRAME_;$n" % [p.gcFrameType]
|
||||
|
||||
|
|
@ -385,7 +394,8 @@ proc assignLocalVar(p: BProc, s: PSym) =
|
|||
#assert(s.loc.k == locNone) # not yet assigned
|
||||
# this need not be fulfilled for inline procs; they are regenerated
|
||||
# for each module that uses them!
|
||||
let decl = localVarDecl(p, s) & ";" & tnl
|
||||
let nl = if optLineDir in gOptions: "" else: tnl
|
||||
let decl = localVarDecl(p, s) & ";" & nl
|
||||
line(p, cpsLocals, decl)
|
||||
localDebugInfo(p, s)
|
||||
|
||||
|
|
@ -618,11 +628,11 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope =
|
|||
discard cgsym(p.module, "nimFrame")
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "VarSlot")
|
||||
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4)$N",
|
||||
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n",
|
||||
procname, filename, p.maxFrameLen.rope,
|
||||
p.blocks[0].frameLen.rope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr_($1, $2)$N", procname, filename)
|
||||
result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename)
|
||||
|
||||
proc deinitFrame(p: BProc): Rope =
|
||||
result = rfmt(p.module, "\t#popFrame();$n")
|
||||
|
|
@ -1302,6 +1312,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
|||
if b == nil or passes.skipCodegen(n): return
|
||||
var m = BModule(b)
|
||||
m.initProc.options = initProcOptions(m)
|
||||
softRnl = if optLineDir in gOptions: noRnl else: rnl
|
||||
genStmts(m.initProc, n)
|
||||
|
||||
proc finishModule(m: BModule) =
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
|||
of "generational": result = gSelectedGC == gcGenerational
|
||||
of "go": result = gSelectedGC == gcGo
|
||||
of "none": result = gSelectedGC == gcNone
|
||||
of "stack": result = gSelectedGC == gcStack
|
||||
of "stack", "regions": result = gSelectedGC == gcRegions
|
||||
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
of "opt":
|
||||
case arg.normalize
|
||||
|
|
@ -429,9 +429,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
of "none":
|
||||
gSelectedGC = gcNone
|
||||
defineSymbol("nogc")
|
||||
of "stack":
|
||||
gSelectedGC= gcStack
|
||||
defineSymbol("gcstack")
|
||||
of "stack", "regions":
|
||||
gSelectedGC= gcRegions
|
||||
defineSymbol("gcregions")
|
||||
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
of "warnings", "w":
|
||||
if processOnOffSwitchOrList({optWarns}, arg, pass, info): listWarnings()
|
||||
|
|
@ -454,6 +454,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
|||
of "native", "gdb":
|
||||
incl(gGlobalOptions, optCDebug)
|
||||
gOptions = gOptions + {optLineDir} - {optEndb}
|
||||
defineSymbol("nimTypeNames", nil) # type names are used in gdb pretty printing
|
||||
undefSymbol("endb")
|
||||
else:
|
||||
localError(info, "expected endb|gdb but found " & arg)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,10 @@ proc isDefined*(symbol: string): bool =
|
|||
result = targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
|
||||
osQnx, osAtari, osAix,
|
||||
osHaiku, osVxWorks, osSolaris, osNetbsd,
|
||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx}
|
||||
osFreebsd, osOpenbsd, osDragonfly, osMacosx,
|
||||
osAndroid}
|
||||
of "linux":
|
||||
result = targetOS in {osLinux, osAndroid}
|
||||
of "bsd":
|
||||
result = targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly}
|
||||
of "emulatedthreadvars":
|
||||
|
|
|
|||
|
|
@ -462,12 +462,14 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
|||
var path = n.info.toFullPath
|
||||
if path.startsWith(cwd):
|
||||
path = path[cwd.len+1 .. ^1].replace('\\', '/')
|
||||
var commit = getConfigVar("git.commit")
|
||||
if commit.len == 0: commit = "master"
|
||||
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
|
||||
["path", "line", "url", "commit"], [rope path,
|
||||
rope($n.info.line), rope getConfigVar("git.url"),
|
||||
rope commit])])
|
||||
let gitUrl = getConfigVar("git.url")
|
||||
if gitUrl.len > 0:
|
||||
var commit = getConfigVar("git.commit")
|
||||
if commit.len == 0: commit = "master"
|
||||
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
|
||||
["path", "line", "url", "commit"], [rope path,
|
||||
rope($n.info.line), rope gitUrl,
|
||||
rope commit])])
|
||||
|
||||
add(d.section[k], ropeFormatNamedVars(getConfigVar("doc.item"),
|
||||
["name", "header", "desc", "itemID", "header_plain", "itemSym",
|
||||
|
|
|
|||
|
|
@ -104,9 +104,9 @@ proc mapCallConv(cc: TCallingConvention, info: TLineInfo): TABI =
|
|||
else:
|
||||
globalError(info, "cannot map calling convention to FFI")
|
||||
|
||||
template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[]
|
||||
template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v
|
||||
template `+!`(x, y: expr): expr {.immediate.} =
|
||||
template rd(T, p: untyped): untyped = (cast[ptr T](p))[]
|
||||
template wr(T, p, v: untyped): untyped = (cast[ptr T](p))[] = v
|
||||
template `+!`(x, y: untyped): untyped =
|
||||
cast[pointer](cast[ByteAddress](x) + y)
|
||||
|
||||
proc packSize(v: PNode, typ: PType): int =
|
||||
|
|
@ -171,7 +171,7 @@ const maxPackDepth = 20
|
|||
var packRecCheck = 0
|
||||
|
||||
proc pack(v: PNode, typ: PType, res: pointer) =
|
||||
template awr(T, v: expr) {.immediate, dirty.} =
|
||||
template awr(T, v: untyped): untyped =
|
||||
wr(T, res, v)
|
||||
|
||||
case typ.kind
|
||||
|
|
@ -302,7 +302,7 @@ proc canonNodeKind(k: TNodeKind): TNodeKind =
|
|||
else: result = k
|
||||
|
||||
proc unpack(x: pointer, typ: PType, n: PNode): PNode =
|
||||
template aw(k, v, field: expr) {.immediate, dirty.} =
|
||||
template aw(k, v, field: untyped): untyped =
|
||||
if n.isNil:
|
||||
result = newNode(k)
|
||||
result.typ = typ
|
||||
|
|
@ -326,9 +326,9 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
|
|||
result.kind = nkNilLit
|
||||
result.typ = typ
|
||||
|
||||
template awi(kind, v: expr) {.immediate, dirty.} = aw(kind, v, intVal)
|
||||
template awf(kind, v: expr) {.immediate, dirty.} = aw(kind, v, floatVal)
|
||||
template aws(kind, v: expr) {.immediate, dirty.} = aw(kind, v, strVal)
|
||||
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
|
||||
template awf(kind, v: untyped): untyped = aw(kind, v, floatVal)
|
||||
template aws(kind, v: untyped): untyped = aw(kind, v, strVal)
|
||||
|
||||
case typ.kind
|
||||
of tyBool: awi(nkIntLit, rd(bool, x).ord)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ type
|
|||
# used on some platforms
|
||||
asmStmtFrmt: string, # format of ASM statement
|
||||
structStmtFmt: string, # Format for struct statement
|
||||
packedPragma: string, # Attribute/pragma to make struct packed (1-byte aligned)
|
||||
props: TInfoCCProps] # properties of the C compiler
|
||||
|
||||
|
||||
|
|
@ -86,7 +85,6 @@ compiler gcc:
|
|||
pic: "-fPIC",
|
||||
asmStmtFrmt: "asm($1);$n",
|
||||
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
|
||||
packedPragma: "__attribute__((__packed__))",
|
||||
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
|
||||
hasAttribute})
|
||||
|
||||
|
|
@ -129,7 +127,6 @@ compiler vcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$3$n$1 $2",
|
||||
packedPragma: "#pragma pack(1)",
|
||||
props: {hasCpp, hasAssume, hasDeclspec})
|
||||
|
||||
# Intel C/C++ Compiler
|
||||
|
|
@ -166,7 +163,6 @@ compiler lcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "_asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {})
|
||||
|
||||
# Borland C Compiler
|
||||
|
|
@ -191,7 +187,6 @@ compiler bcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {hasCpp})
|
||||
|
||||
# Digital Mars C Compiler
|
||||
|
|
@ -216,7 +211,6 @@ compiler dmc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$3$n$1 $2",
|
||||
packedPragma: "#pragma pack(1)",
|
||||
props: {hasCpp})
|
||||
|
||||
# Watcom C Compiler
|
||||
|
|
@ -241,7 +235,6 @@ compiler wcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {hasCpp})
|
||||
|
||||
# Tiny C Compiler
|
||||
|
|
@ -266,7 +259,6 @@ compiler tcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {hasSwitchRange, hasComputedGoto})
|
||||
|
||||
# Pelles C Compiler
|
||||
|
|
@ -292,7 +284,6 @@ compiler pcc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {})
|
||||
|
||||
# Your C Compiler
|
||||
|
|
@ -317,7 +308,6 @@ compiler ucc:
|
|||
pic: "",
|
||||
asmStmtFrmt: "__asm{$n$1$n}$n",
|
||||
structStmtFmt: "$1 $2",
|
||||
packedPragma: "", # XXX: not supported yet
|
||||
props: {})
|
||||
|
||||
const
|
||||
|
|
@ -687,11 +677,14 @@ proc getLinkCmd(projectfile, objfiles: string): string =
|
|||
exefile = quoteShell(exefile)
|
||||
let linkOptions = getLinkOptions() & " " &
|
||||
getConfigVar(cCompiler, ".options.linker")
|
||||
var linkTmpl = getConfigVar(cCompiler, ".linkTmpl")
|
||||
if linkTmpl.len == 0:
|
||||
linkTmpl = CC[cCompiler].linkTmpl
|
||||
result = quoteShell(result % ["builddll", builddll,
|
||||
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
||||
"exefile", exefile, "nim", getPrefixDir(), "lib", libpath])
|
||||
result.add ' '
|
||||
addf(result, CC[cCompiler].linkTmpl, ["builddll", builddll,
|
||||
addf(result, linkTmpl, ["builddll", builddll,
|
||||
"buildgui", buildgui, "options", linkOptions,
|
||||
"objfiles", objfiles, "exefile", exefile,
|
||||
"nim", quoteShell(getPrefixDir()),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Name: "Nim"
|
|||
Version: "$version"
|
||||
Platforms: """
|
||||
windows: i386;amd64
|
||||
linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc;powerpc64el;arm64
|
||||
linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64
|
||||
macosx: i386;amd64;powerpc64
|
||||
solaris: i386;amd64;sparc;sparc64
|
||||
freebsd: i386;amd64
|
||||
|
|
@ -14,6 +14,7 @@ Platforms: """
|
|||
openbsd: i386;amd64
|
||||
dragonfly: i386;amd64
|
||||
haiku: i386;amd64
|
||||
android: i386;arm;arm64
|
||||
"""
|
||||
|
||||
Authors: "Andreas Rumpf"
|
||||
|
|
@ -47,7 +48,7 @@ Start: "doc/html/overview.html"
|
|||
|
||||
|
||||
[Other]
|
||||
Files: "readme.txt;copying.txt"
|
||||
Files: "readme.txt;copying.txt;install.txt"
|
||||
Files: "makefile"
|
||||
Files: "koch.nim"
|
||||
Files: "install_nimble.nims"
|
||||
|
|
|
|||
|
|
@ -2340,7 +2340,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
|||
of nkPragma: genPragma(p, n)
|
||||
of nkProcDef, nkMethodDef, nkConverterDef:
|
||||
var s = n.sons[namePos].sym
|
||||
if sfExportc in s.flags and compilingLib:
|
||||
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
||||
genSym(p, n.sons[namePos], r)
|
||||
r.res = nil
|
||||
of nkGotoState, nkState:
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ proc createStateField(iter: PSym): PSym =
|
|||
proc createEnvObj(owner: PSym; info: TLineInfo): PType =
|
||||
# YYY meh, just add the state field for every closure for now, it's too
|
||||
# hard to figure out if it comes from a closure iterator:
|
||||
result = createObj(owner, info)
|
||||
result = createObj(owner, info, final=false)
|
||||
rawAddField(result, createStateField(owner))
|
||||
|
||||
proc getIterResult(iter: PSym): PSym =
|
||||
|
|
|
|||
|
|
@ -109,17 +109,19 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode =
|
|||
result.add newFastAsgnStmt(n[1], n[2])
|
||||
result.add newFastAsgnStmt(n[2], tempAsNode)
|
||||
|
||||
proc createObj*(owner: PSym, info: TLineInfo): PType =
|
||||
proc createObj*(owner: PSym, info: TLineInfo; final=true): PType =
|
||||
result = newType(tyObject, owner)
|
||||
rawAddSon(result, nil)
|
||||
incl result.flags, tfFinal
|
||||
if final:
|
||||
rawAddSon(result, nil)
|
||||
incl result.flags, tfFinal
|
||||
else:
|
||||
rawAddSon(result, getCompilerProc("RootObj").typ)
|
||||
result.n = newNodeI(nkRecList, info)
|
||||
when true:
|
||||
let s = newSym(skType, getIdent("Env_" & info.toFilename),
|
||||
owner, info)
|
||||
incl s.flags, sfAnon
|
||||
s.typ = result
|
||||
result.sym = s
|
||||
let s = newSym(skType, getIdent("Env_" & info.toFilename),
|
||||
owner, info)
|
||||
incl s.flags, sfAnon
|
||||
s.typ = result
|
||||
result.sym = s
|
||||
|
||||
proc rawAddField*(obj: PType; field: PSym) =
|
||||
assert field.kind == skField
|
||||
|
|
|
|||
|
|
@ -746,7 +746,7 @@ proc toFileLine*(info: TLineInfo): string {.inline.} =
|
|||
result = info.toFilename & ":" & $info.line
|
||||
|
||||
proc toFileLineCol*(info: TLineInfo): string {.inline.} =
|
||||
result = info.toFilename & "(" & $info.line & "," & $info.col & ")"
|
||||
result = info.toFilename & "(" & $info.line & ", " & $info.col & ")"
|
||||
|
||||
proc `$`*(info: TLineInfo): string = toFileLineCol(info)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
## Implements some helper procs for Nimble (Nim's package manager) support.
|
||||
|
||||
import parseutils, strutils, strtabs, os, options, msgs
|
||||
import parseutils, strutils, strtabs, os, options, msgs, sequtils
|
||||
|
||||
proc addPath*(path: string, info: TLineInfo) =
|
||||
if not options.searchPaths.contains(path):
|
||||
|
|
@ -21,51 +21,76 @@ proc versionSplitPos(s: string): int =
|
|||
while result > 1 and s[result] != '-': dec result
|
||||
if s[result] != '-': result = s.len
|
||||
|
||||
const
|
||||
latest = ""
|
||||
type
|
||||
Version = distinct string
|
||||
|
||||
proc `<.`(a, b: string): bool =
|
||||
# wether a has a smaller version than b:
|
||||
if a == latest: return true
|
||||
elif b == latest: return false
|
||||
var i = 0
|
||||
var j = 0
|
||||
var verA = 0
|
||||
var verB = 0
|
||||
while true:
|
||||
let ii = parseInt(a, verA, i)
|
||||
let jj = parseInt(b, verB, j)
|
||||
if ii <= 0 or jj <= 0:
|
||||
# if A has no number and B has but A has no number whatsoever ("#head"),
|
||||
# A is preferred:
|
||||
if ii > 0 and jj <= 0 and j == 0: return true
|
||||
if ii <= 0 and jj > 0 and i == 0: return false
|
||||
# if A has no number left, but B has, B is preferred: 0.8 vs 0.8.3
|
||||
return jj > 0
|
||||
if verA < verB: return true
|
||||
elif verA > verB: return false
|
||||
# else: same version number; continue:
|
||||
inc i, ii
|
||||
inc j, jj
|
||||
if a[i] == '.': inc i
|
||||
if b[j] == '.': inc j
|
||||
proc `$`(ver: Version): string {.borrow.}
|
||||
|
||||
proc newVersion(ver: string): Version =
|
||||
doAssert(ver.len == 0 or ver[0] in {'#', '\0'} + Digits,
|
||||
"Wrong version: " & ver)
|
||||
return Version(ver)
|
||||
|
||||
proc isSpecial(ver: Version): bool =
|
||||
return ($ver).len > 0 and ($ver)[0] == '#'
|
||||
|
||||
proc `<`(ver: Version, ver2: Version): bool =
|
||||
## This is synced from Nimble's version module.
|
||||
|
||||
# Handling for special versions such as "#head" or "#branch".
|
||||
if ver.isSpecial or ver2.isSpecial:
|
||||
if ver2.isSpecial and ($ver2).normalize == "#head":
|
||||
return ($ver).normalize != "#head"
|
||||
|
||||
if not ver2.isSpecial:
|
||||
# `#aa111 < 1.1`
|
||||
return ($ver).normalize != "#head"
|
||||
|
||||
# Handling for normal versions such as "0.1.0" or "1.0".
|
||||
var sVer = string(ver).split('.')
|
||||
var sVer2 = string(ver2).split('.')
|
||||
for i in 0..max(sVer.len, sVer2.len)-1:
|
||||
var sVerI = 0
|
||||
if i < sVer.len:
|
||||
discard parseInt(sVer[i], sVerI)
|
||||
var sVerI2 = 0
|
||||
if i < sVer2.len:
|
||||
discard parseInt(sVer2[i], sVerI2)
|
||||
if sVerI < sVerI2:
|
||||
return true
|
||||
elif sVerI == sVerI2:
|
||||
discard
|
||||
else:
|
||||
return false
|
||||
|
||||
proc addPackage(packages: StringTableRef, p: string) =
|
||||
let x = versionSplitPos(p)
|
||||
let name = p.substr(0, x-1)
|
||||
let version = if x < p.len: p.substr(x+1) else: ""
|
||||
if packages.getOrDefault(name) <. version:
|
||||
packages[name] = version
|
||||
let version = newVersion(if x < p.len: p.substr(x+1) else: "")
|
||||
if packages.getOrDefault(name).newVersion < version or
|
||||
(not packages.hasKey(name)):
|
||||
packages[name] = $version
|
||||
|
||||
iterator chosen(packages: StringTableRef): string =
|
||||
for key, val in pairs(packages):
|
||||
let res = if val == latest: key else: key & '-' & val
|
||||
let res = if val.len == 0: key else: key & '-' & val
|
||||
yield res
|
||||
|
||||
proc addNimblePath(p: string, info: TLineInfo) =
|
||||
if not contains(options.searchPaths, p):
|
||||
message(info, hintPath, p)
|
||||
options.lazyPaths.insert(p, 0)
|
||||
var path = p
|
||||
let nimbleLinks = toSeq(walkPattern(p / "*.nimble-link"))
|
||||
if nimbleLinks.len > 0:
|
||||
# If the user has more than one .nimble-link file then... we just ignore it.
|
||||
# Spec for these files is available in Nimble's readme:
|
||||
# https://github.com/nim-lang/nimble#nimble-link
|
||||
let nimbleLinkLines = readFile(nimbleLinks[0]).splitLines()
|
||||
path = nimbleLinkLines[1]
|
||||
if not path.isAbsolute():
|
||||
path = p / path
|
||||
|
||||
if not contains(options.searchPaths, path):
|
||||
message(info, hintPath, path)
|
||||
options.lazyPaths.insert(path, 0)
|
||||
|
||||
proc addPathRec(dir: string, info: TLineInfo) =
|
||||
var packages = newStringTable(modeStyleInsensitive)
|
||||
|
|
@ -82,7 +107,17 @@ proc nimblePath*(path: string, info: TLineInfo) =
|
|||
addNimblePath(path, info)
|
||||
|
||||
when isMainModule:
|
||||
proc v(s: string): Version = s.newVersion
|
||||
# #head is special in the sense that it's assumed to always be newest.
|
||||
doAssert v"1.0" < v"#head"
|
||||
doAssert v"1.0" < v"1.1"
|
||||
doAssert v"1.0.1" < v"1.1"
|
||||
doAssert v"1" < v"1.1"
|
||||
doAssert v"#aaaqwe" < v"1.1" # We cannot assume that a branch is newer.
|
||||
doAssert v"#a111" < v"#head"
|
||||
|
||||
var rr = newStringTable()
|
||||
addPackage rr, "irc-#a111"
|
||||
addPackage rr, "irc-#head"
|
||||
addPackage rr, "irc-0.1.0"
|
||||
addPackage rr, "irc"
|
||||
|
|
@ -93,5 +128,6 @@ when isMainModule:
|
|||
addPackage rr, "ab-0.1"
|
||||
addPackage rr, "justone"
|
||||
|
||||
for p in rr.chosen:
|
||||
echo p
|
||||
doAssert toSeq(rr.chosen) ==
|
||||
@["irc-#head", "another-0.1", "ab-0.1.3", "justone"]
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
|||
parseDirective(L, tok, config) # else: give the token to the parser
|
||||
|
||||
proc checkSymbol(L: TLexer, tok: TToken) =
|
||||
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
|
||||
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
|
||||
lexMessage(L, errIdentifierExpected, tokToStr(tok))
|
||||
|
||||
proc parseAssignment(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ type
|
|||
cmdRun # run the project via TCC backend
|
||||
TStringSeq* = seq[string]
|
||||
TGCMode* = enum # the selected GC
|
||||
gcNone, gcBoehm, gcGo, gcStack, gcMarkAndSweep, gcRefc,
|
||||
gcNone, gcBoehm, gcGo, gcRegions, gcMarkAndSweep, gcRefc,
|
||||
gcV2, gcGenerational
|
||||
|
||||
IdeCmd* = enum
|
||||
|
|
@ -291,8 +291,8 @@ proc pathSubs*(p, config: string): string =
|
|||
"projectpath", options.gProjectPath,
|
||||
"projectdir", options.gProjectPath,
|
||||
"nimcache", getNimcacheDir()])
|
||||
if '~' in result:
|
||||
result = result.replace("~", home)
|
||||
if "~/" in result:
|
||||
result = result.replace("~/", home & '/')
|
||||
|
||||
proc toGeneratedFile*(path, ext: string): string =
|
||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||
|
|
|
|||
|
|
@ -685,6 +685,11 @@ proc namedParams(p: var TParser, callee: PNode,
|
|||
# progress guaranteed
|
||||
exprColonEqExprListAux(p, endTok, result)
|
||||
|
||||
proc commandParam(p: var TParser): PNode =
|
||||
result = parseExpr(p)
|
||||
if p.tok.tokType == tkDo:
|
||||
result = postExprBlocks(p, result)
|
||||
|
||||
proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
|
||||
#| primarySuffix = '(' (exprColonEqExpr comma?)* ')' doBlocks?
|
||||
#| | doBlocks
|
||||
|
|
@ -733,7 +738,7 @@ proc primarySuffix(p: var TParser, r: PNode, baseIndent: int): PNode =
|
|||
when true:
|
||||
# progress NOT guaranteed
|
||||
p.hasProgress = false
|
||||
addSon result, parseExpr(p)
|
||||
addSon result, commandParam(p)
|
||||
if not p.hasProgress: break
|
||||
else:
|
||||
while p.tok.tokType != tkEof:
|
||||
|
|
@ -1253,14 +1258,12 @@ proc parseExprStmt(p: var TParser): PNode =
|
|||
while true:
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
var e = parseExpr(p)
|
||||
addSon(result, e)
|
||||
addSon(result, commandParam(p))
|
||||
if p.tok.tokType != tkComma: break
|
||||
elif p.tok.indent < 0 and isExprStart(p):
|
||||
result = newNode(nkCommand, a.info, @[a])
|
||||
while true:
|
||||
var e = parseExpr(p)
|
||||
addSon(result, e)
|
||||
addSon(result, commandParam(p))
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
import
|
||||
strutils, options, ast, astalgo, llstream, msgs, platform, os,
|
||||
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
|
||||
nimsets, syntaxes, times, rodread, idgen, modulegraphs
|
||||
nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder
|
||||
|
||||
type
|
||||
TPassContext* = object of RootObj # the pass's context
|
||||
|
|
@ -202,7 +202,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
if graph.stopCompile(): break
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
if sfNoForward in module.flags:
|
||||
if {sfNoForward, sfReorder} * module.flags != {}:
|
||||
# read everything, no streaming possible
|
||||
var sl = newNodeI(nkStmtList, n.info)
|
||||
sl.add n
|
||||
|
|
@ -210,6 +210,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
sl.add n
|
||||
if sfReorder in module.flags:
|
||||
sl = reorder sl
|
||||
discard processTopLevelStmt(sl, a)
|
||||
break
|
||||
elif not processTopLevelStmt(n, a): break
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ type
|
|||
# conditionals to condsyms (end of module).
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osVxworks, osGenode
|
||||
osJS, osNimrodVM, osStandalone
|
||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osAndroid, osVxworks
|
||||
osGenode, osJS, osNimrodVM, osStandalone
|
||||
|
||||
type
|
||||
TInfoOSProp* = enum
|
||||
|
|
@ -143,6 +143,10 @@ const
|
|||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
||||
(name: "Android", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
|
||||
props: {ospNeedsPIC, ospPosix}),
|
||||
(name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
|
||||
|
|
@ -171,7 +175,8 @@ type
|
|||
# alias conditionals to condsyms (end of module).
|
||||
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
|
||||
cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel,
|
||||
cpuArm, cpuArm64, cpuJS, cpuNimrodVM, cpuAVR, cpuMSP430, cpuSparc64
|
||||
cpuArm, cpuArm64, cpuJS, cpuNimrodVM, cpuAVR, cpuMSP430, cpuSparc64,
|
||||
cpuMips64, cpuMips64el
|
||||
|
||||
type
|
||||
TEndian* = enum
|
||||
|
|
@ -200,7 +205,9 @@ const
|
|||
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
|
||||
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
|
||||
(name: "msp430", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16),
|
||||
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64)]
|
||||
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
|
||||
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64)]
|
||||
|
||||
var
|
||||
targetCPU*, hostCPU*: TSystemCPU
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const
|
|||
wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
|
||||
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
|
||||
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
|
||||
wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto,
|
||||
wInjectStmt, wDeprecated, wExperimental, wThis}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
|
|
@ -210,9 +210,9 @@ proc pragmaDeadCodeElim(c: PContext, n: PNode) =
|
|||
if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
|
||||
else: excl(c.module.flags, sfDeadCodeElim)
|
||||
|
||||
proc pragmaNoForward(c: PContext, n: PNode) =
|
||||
if isTurnedOn(c, n): incl(c.module.flags, sfNoForward)
|
||||
else: excl(c.module.flags, sfNoForward)
|
||||
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
|
||||
if isTurnedOn(c, n): incl(c.module.flags, flag)
|
||||
else: excl(c.module.flags, flag)
|
||||
|
||||
proc processCallConv(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
|
|
@ -726,6 +726,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
|||
incl(sym.flags, sfThread)
|
||||
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
|
||||
of wNoForward: pragmaNoForward(c, it)
|
||||
of wReorder: pragmaNoForward(c, it, sfReorder)
|
||||
of wMagic: processMagic(c, it, sym)
|
||||
of wCompileTime:
|
||||
noVal(it)
|
||||
|
|
|
|||
|
|
@ -1327,7 +1327,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
|
||||
if n.hasExplicitParams:
|
||||
put(g, tkBracketLe, "[")
|
||||
gcomma(g, n)
|
||||
gsemicolon(g, n)
|
||||
put(g, tkBracketRi, "]")
|
||||
of nkFormalParams:
|
||||
put(g, tkParLe, "(")
|
||||
|
|
|
|||
102
compiler/reorder.nim
Normal file
102
compiler/reorder.nim
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
|
||||
import intsets, tables, ast, idents, renderer
|
||||
|
||||
const
|
||||
nfTempMark = nfTransf
|
||||
nfPermMark = nfNoRewrite
|
||||
|
||||
proc accQuoted(n: PNode): PIdent =
|
||||
var id = ""
|
||||
for i in 0 .. <n.len:
|
||||
let x = n[i]
|
||||
case x.kind
|
||||
of nkIdent: id.add(x.ident.s)
|
||||
of nkSym: id.add(x.sym.name.s)
|
||||
else: discard
|
||||
result = getIdent(id)
|
||||
|
||||
proc addDecl(n: PNode; declares: var IntSet) =
|
||||
case n.kind
|
||||
of nkPostfix: addDecl(n[1], declares)
|
||||
of nkPragmaExpr: addDecl(n[0], declares)
|
||||
of nkIdent:
|
||||
declares.incl n.ident.id
|
||||
of nkSym:
|
||||
declares.incl n.sym.name.id
|
||||
of nkAccQuoted:
|
||||
declares.incl accQuoted(n).id
|
||||
else: discard
|
||||
|
||||
proc computeDeps(n: PNode, declares, uses: var IntSet; topLevel: bool) =
|
||||
template deps(n) = computeDeps(n, declares, uses, false)
|
||||
template decl(n) =
|
||||
if topLevel: addDecl(n, declares)
|
||||
case n.kind
|
||||
of procDefs:
|
||||
decl(n[0])
|
||||
for i in 1..bodyPos: deps(n[i])
|
||||
of nkLetSection, nkVarSection, nkUsingStmt:
|
||||
for a in n:
|
||||
if a.kind in {nkIdentDefs, nkVarTuple}:
|
||||
for j in countup(0, a.len-3): decl(a[j])
|
||||
for j in a.len-2..a.len-1: deps(a[j])
|
||||
of nkConstSection, nkTypeSection:
|
||||
for a in n:
|
||||
if a.len >= 3:
|
||||
decl(a[0])
|
||||
for i in 1..<a.len: deps(a[i])
|
||||
of nkIdent: uses.incl n.ident.id
|
||||
of nkSym: uses.incl n.sym.name.id
|
||||
of nkAccQuoted: uses.incl accQuoted(n).id
|
||||
of nkOpenSymChoice, nkClosedSymChoice:
|
||||
uses.incl n.sons[0].sym.name.id
|
||||
of nkStmtList, nkStmtListExpr, nkWhenStmt, nkElifBranch, nkElse:
|
||||
for i in 0..<len(n): computeDeps(n[i], declares, uses, topLevel)
|
||||
else:
|
||||
for i in 0..<safeLen(n): deps(n[i])
|
||||
|
||||
proc visit(i: int; all, res: PNode; deps: var seq[(IntSet, IntSet)]): bool =
|
||||
let n = all[i]
|
||||
if nfTempMark in n.flags:
|
||||
# not a DAG!
|
||||
return true
|
||||
if nfPermMark notin n.flags:
|
||||
incl n.flags, nfTempMark
|
||||
var uses = deps[i][1]
|
||||
for j in 0..<all.len:
|
||||
if j != i:
|
||||
let declares = deps[j][0]
|
||||
for d in declares:
|
||||
if uses.contains(d):
|
||||
let oldLen = res.len
|
||||
if visit(j, all, res, deps):
|
||||
result = true
|
||||
# rollback what we did, it turned out to be a dependency that caused
|
||||
# trouble:
|
||||
for k in oldLen..<res.len:
|
||||
res.sons[k].flags = res.sons[k].flags - {nfPermMark, nfTempMark}
|
||||
if oldLen != res.len: res.sons.setLen oldLen
|
||||
break
|
||||
n.flags = n.flags + {nfPermMark} - {nfTempMark}
|
||||
res.add n
|
||||
|
||||
proc reorder*(n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
var deps = newSeq[(IntSet, IntSet)](n.len)
|
||||
for i in 0..<n.len:
|
||||
deps[i][0] = initIntSet()
|
||||
deps[i][1] = initIntSet()
|
||||
computeDeps(n[i], deps[i][0], deps[i][1], true)
|
||||
|
||||
for i in 0 .. n.len-1:
|
||||
discard visit(i, n, result, deps)
|
||||
for i in 0..<result.len:
|
||||
result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
|
||||
when false:
|
||||
# reverse the result:
|
||||
let L = result.len-1
|
||||
for i in 0 .. result.len div 2:
|
||||
result.sons[i].flags = result.sons[i].flags - {nfTempMark, nfPermMark}
|
||||
result.sons[L - i].flags = result.sons[L - i].flags - {nfTempMark, nfPermMark}
|
||||
swap(result.sons[i], result.sons[L - i])
|
||||
#echo result
|
||||
|
|
@ -228,6 +228,7 @@ proc prepend*(a: var Rope, b: string) = a = b & a
|
|||
var
|
||||
rnl* = tnl.newRope
|
||||
softRnl* = tnl.newRope
|
||||
noRnl* = "".newRope
|
||||
|
||||
proc `%`*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
||||
var i = 0
|
||||
|
|
|
|||
|
|
@ -47,11 +47,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
#raiseRecoverableError("")
|
||||
result = errorNode(c, n)
|
||||
if result.typ == nil or result.typ == enforceVoidContext:
|
||||
if n.kind != nkStmtList:
|
||||
# we cannot check for 'void' in macros ...
|
||||
localError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
localError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
else:
|
||||
if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
|
||||
if result.typ.kind == tyVar: result = newDeref(result)
|
||||
|
|
@ -276,41 +274,6 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
|||
n.typ = getSysType(tyInt)
|
||||
result = n
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[2])
|
||||
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||
|
||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
elif b.kind != tyObject or a.kind != tyObject:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
else:
|
||||
let diff = inheritanceDiff(a, b)
|
||||
# | returns: 0 iff `a` == `b`
|
||||
# | returns: -x iff `a` is the x'th direct superclass of `b`
|
||||
# | returns: +x iff `a` is the x'th direct subclass of `b`
|
||||
# | returns: `maxint` iff `a` and `b` are not compatible at all
|
||||
if diff <= 0:
|
||||
# optimize to true:
|
||||
message(n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
else:
|
||||
localError(n.info, errXExpectsTwoArguments, "of")
|
||||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
internalAssert n.sonsLen == 3 and
|
||||
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
|
||||
|
|
@ -1121,9 +1084,11 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
if ty.n != nil and ty.n.kind == nkRecList:
|
||||
let field = lookupInRecord(ty.n, i)
|
||||
if field != nil:
|
||||
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
|
||||
n.typ.n = copyTree(n)
|
||||
n.typ = makeTypeDesc(c, field.typ)
|
||||
return n
|
||||
#n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.typ])
|
||||
#n.typ.n = copyTree(n)
|
||||
#return n
|
||||
else:
|
||||
tryReadingGenericParam(ty)
|
||||
return
|
||||
|
|
@ -1490,6 +1455,9 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
|||
var t = skipTypes(restype, {tyGenericInst, tyAlias})
|
||||
case t.kind
|
||||
of tyVar:
|
||||
if n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
n.sons[0] = n.sons[0].sons[1]
|
||||
|
||||
n.sons[0] = takeImplicitAddr(c, n.sons[0])
|
||||
of tyTuple:
|
||||
for i in 0.. <t.sonsLen:
|
||||
|
|
@ -1829,11 +1797,11 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
|||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
#of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||
#of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
||||
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||
of mOf: result = semOf(c, setMs(n, s))
|
||||
#of mOf: result = semOf(c, setMs(n, s))
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||
of mQuoteAst: result = semQuoteAst(c, n)
|
||||
|
|
@ -2207,9 +2175,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
message(n.info, warnDeprecated, "bind")
|
||||
result = semExpr(c, n.sons[0], flags)
|
||||
of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy:
|
||||
if c.matchedConcept != nil and n.len == 1:
|
||||
let modifier = n.modifierTypeKindOfNode
|
||||
if modifier != tyNone:
|
||||
var baseType = semExpr(c, n[0]).typ.skipTypes({tyTypeDesc})
|
||||
result.typ = c.makeTypeDesc(c.newTypeWithSons(modifier, @[baseType]))
|
||||
return
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
# check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1)
|
||||
|
|
|
|||
|
|
@ -200,6 +200,41 @@ proc isStrangeArray(t: PType): bool =
|
|||
let t = t.skipTypes(abstractInst)
|
||||
result = t.kind == tyArray and t.firstOrd != 0
|
||||
|
||||
proc semOf(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efDetermineType})
|
||||
#restoreOldStyleType(n.sons[1])
|
||||
#restoreOldStyleType(n.sons[2])
|
||||
let a = skipTypes(n.sons[1].typ, abstractPtrs)
|
||||
let b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||
let x = skipTypes(n.sons[1].typ, abstractPtrs-{tyTypeDesc})
|
||||
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
|
||||
|
||||
if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
elif b.kind != tyObject or a.kind != tyObject:
|
||||
localError(n.info, errXExpectsObjectTypes, "of")
|
||||
else:
|
||||
let diff = inheritanceDiff(a, b)
|
||||
# | returns: 0 iff `a` == `b`
|
||||
# | returns: -x iff `a` is the x'th direct superclass of `b`
|
||||
# | returns: +x iff `a` is the x'th direct subclass of `b`
|
||||
# | returns: `maxint` iff `a` and `b` are not compatible at all
|
||||
if diff <= 0:
|
||||
# optimize to true:
|
||||
message(n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
else:
|
||||
localError(n.info, errXExpectsTwoArguments, "of")
|
||||
n.typ = getSysType(tyBool)
|
||||
result = n
|
||||
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
case n[0].sym.magic
|
||||
|
|
@ -219,6 +254,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
|||
result.typ = getSysType(tyString)
|
||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||
of mOrd: result = semOrd(c, n)
|
||||
of mOf: result = semOf(c, n)
|
||||
of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mNBindSym: result = semBindSym(c, n)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ proc locateFieldInInitExpr(field: PSym, initExpr: PNode): PNode =
|
|||
let fieldId = field.name.id
|
||||
for i in 1 .. <initExpr.len:
|
||||
let assignment = initExpr[i]
|
||||
internalAssert assignment.kind == nkExprColonExpr
|
||||
if assignment.kind != nkExprColonExpr:
|
||||
localError(initExpr.info, "incorrect object construction syntax")
|
||||
continue
|
||||
|
||||
if fieldId == considerQuotedIdent(assignment[0]).id:
|
||||
return assignment
|
||||
|
|
@ -278,6 +280,9 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
for i in 1.. <result.len:
|
||||
let field = result[i]
|
||||
if nfSem notin field.flags:
|
||||
if field.kind != nkExprColonExpr:
|
||||
localError(n.info, "incorrect object construction syntax")
|
||||
continue
|
||||
let id = considerQuotedIdent(field[0])
|
||||
# This node was not processed. There are two possible reasons:
|
||||
# 1) It was shadowed by a field with the same name on the left
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@
|
|||
discard """
|
||||
hygienic templates:
|
||||
|
||||
template `||` (a, b: expr): expr =
|
||||
template `||` (a, b: untyped): untyped =
|
||||
let aa = a
|
||||
if aa: aa else: b
|
||||
|
||||
var
|
||||
a, b: T
|
||||
|
||||
a || b || a
|
||||
echo a || b || a
|
||||
|
||||
Each evaluation context has to be different and we need to perform
|
||||
some form of preliminary symbol lookup in template definitions. Hygiene is
|
||||
|
|
|
|||
|
|
@ -1202,6 +1202,15 @@ proc freshType(res, prev: PType): PType {.inline.} =
|
|||
else:
|
||||
result = res
|
||||
|
||||
template modifierTypeKindOfNode(n: PNode): TTypeKind =
|
||||
case n.kind
|
||||
of nkVarTy: tyVar
|
||||
of nkRefTy: tyRef
|
||||
of nkPtrTy: tyPtr
|
||||
of nkStaticTy: tyStatic
|
||||
of nkTypeOfExpr: tyTypeDesc
|
||||
else: tyNone
|
||||
|
||||
proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
# if n.sonsLen == 0: return newConstraint(c, tyTypeClass)
|
||||
if nfBase2 in n.flags:
|
||||
|
|
@ -1227,13 +1236,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
|||
dummyName: PNode
|
||||
dummyType: PType
|
||||
|
||||
let modifier = case param.kind
|
||||
of nkVarTy: tyVar
|
||||
of nkRefTy: tyRef
|
||||
of nkPtrTy: tyPtr
|
||||
of nkStaticTy: tyStatic
|
||||
of nkTypeOfExpr: tyTypeDesc
|
||||
else: tyNone
|
||||
let modifier = param.modifierTypeKindOfNode
|
||||
|
||||
if modifier != tyNone:
|
||||
dummyName = param[0]
|
||||
|
|
@ -1509,9 +1512,26 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
dec c.inTypeContext
|
||||
|
||||
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
|
||||
# source : https://en.wikipedia.org/wiki/Data_structure_alignment#x86
|
||||
m.typ.kind = kind
|
||||
m.typ.align = size.int16
|
||||
m.typ.size = size
|
||||
# this usually works for most basic types
|
||||
# Assuming that since ARM, ARM64 don't support unaligned access
|
||||
# data is aligned to type size
|
||||
m.typ.align = size.int16
|
||||
|
||||
# FIXME: proper support for clongdouble should be added.
|
||||
# long double size can be 8, 10, 12, 16 bytes depending on platform & compiler
|
||||
if targetCPU == cpuI386 and size == 8:
|
||||
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
|
||||
if kind in {tyFloat64, tyFloat} and
|
||||
targetOS in {osLinux, osAndroid, osNetbsd, osFreebsd, osOpenbsd, osDragonfly}:
|
||||
m.typ.align = 4
|
||||
# on i386, all known compiler, 64bits ints are aligned to 4bytes (except with -malign-double)
|
||||
elif kind in {tyInt, tyUInt, tyInt64, tyUInt64}:
|
||||
m.typ.align = 4
|
||||
else:
|
||||
discard
|
||||
|
||||
proc processMagicType(c: PContext, m: PSym) =
|
||||
case m.magic
|
||||
|
|
|
|||
|
|
@ -297,7 +297,9 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
|
|||
n.sons[i].typ = arg.typ
|
||||
n.sons[i].sons[1] = arg
|
||||
else:
|
||||
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
|
||||
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
|
||||
nkOfBranch, nkElifBranch,
|
||||
nkExceptBranch}:
|
||||
arg = c.semOperand(c, n.sons[i])
|
||||
n.sons[i] = arg
|
||||
if arg.typ != nil and arg.typ.kind == tyError: return
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
template tests*(body: stmt) {.immediate.} =
|
||||
when defined(selftest):
|
||||
when not declared(unittest): import unittest
|
||||
body
|
||||
|
||||
|
|
@ -409,6 +409,28 @@ proc recSetFlagIsRef(arg: PNode) =
|
|||
for i in 0 ..< arg.safeLen:
|
||||
arg.sons[i].recSetFlagIsRef
|
||||
|
||||
proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
|
||||
# FIXME: this doesn't attempt to solve incomplete
|
||||
# support of tyPtr, tyRef in VM.
|
||||
let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
|
||||
let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
|
||||
let typeKind = case typeEntry.kind
|
||||
of tyUInt..tyUInt64: nkUIntLit
|
||||
of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
|
||||
of tyFloat..tyFloat128: nkFloatLit
|
||||
of tyString: nkStrLit
|
||||
of tyObject: nkObjConstr
|
||||
of tySequence: nkNilLit
|
||||
of tyProc, tyTuple: nkPar
|
||||
else: nkEmpty
|
||||
|
||||
let oldLen = node.len
|
||||
setLen(node.sons, newLen)
|
||||
if oldLen < newLen:
|
||||
# TODO: This is still not correct for tyPtr, tyRef default value
|
||||
for i in oldLen .. <newLen:
|
||||
node.sons[i] = newNodeI(typeKind, info)
|
||||
|
||||
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
var pc = start
|
||||
var tos = tos
|
||||
|
|
@ -1118,14 +1140,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
decodeB(rkNode)
|
||||
let newLen = regs[rb].intVal.int
|
||||
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
|
||||
else:
|
||||
let oldLen = regs[ra].node.len
|
||||
setLen(regs[ra].node.sons, newLen)
|
||||
if oldLen < newLen:
|
||||
# XXX This is still not entirely correct
|
||||
# set to default value:
|
||||
for i in oldLen .. <newLen:
|
||||
regs[ra].node.sons[i] = newNodeI(nkEmpty, c.debug[pc])
|
||||
else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
|
||||
of opcReset:
|
||||
internalError(c.debug[pc], "too implement")
|
||||
of opcNarrowS:
|
||||
|
|
@ -1307,12 +1322,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
ensureKind(rkNode)
|
||||
if c.callsite != nil: regs[ra].node = c.callsite
|
||||
else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
|
||||
of opcNLineInfo:
|
||||
of opcNGetFile:
|
||||
decodeB(rkNode)
|
||||
let n = regs[rb].node
|
||||
createStr regs[ra]
|
||||
regs[ra].node.strVal = n.info.toFileLineCol
|
||||
regs[ra].node.info = c.debug[pc]
|
||||
regs[ra].node = newStrNode(nkStrLit, n.info.toFilename)
|
||||
regs[ra].node.info = n.info
|
||||
regs[ra].node.typ = n.typ
|
||||
of opcNGetLine:
|
||||
decodeB(rkNode)
|
||||
let n = regs[rb].node
|
||||
regs[ra].node = newIntNode(nkIntLit, n.info.line)
|
||||
regs[ra].node.info = n.info
|
||||
regs[ra].node.typ = n.typ
|
||||
of opcNGetColumn:
|
||||
decodeB(rkNode)
|
||||
let n = regs[rb].node
|
||||
regs[ra].node = newIntNode(nkIntLit, n.info.col)
|
||||
regs[ra].node.info = n.info
|
||||
regs[ra].node.typ = n.typ
|
||||
of opcEqIdent:
|
||||
decodeBC(rkInt)
|
||||
if regs[rb].node.kind == nkIdent and regs[rc].node.kind == nkIdent:
|
||||
|
|
@ -1471,6 +1498,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
createStrKeepNode(regs[ra])
|
||||
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
|
||||
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode)
|
||||
of opcToNarrowInt:
|
||||
decodeBC(rkInt)
|
||||
let mask = (1'i64 shl rc) - 1 # 0xFF
|
||||
let signbit = 1'i64 shl (rc - 1) # 0x80
|
||||
let toggle = mask - signbit # 0x7F
|
||||
# algorithm: -((i8 and 0xFF) xor 0x7F) + 0x7F
|
||||
# mask off higher bits.
|
||||
# uses two's complement to sign-extend integer.
|
||||
# reajust integer into desired range.
|
||||
regs[ra].intVal = -((regs[rb].intVal and mask) xor toggle) + toggle
|
||||
|
||||
inc pc
|
||||
|
||||
proc execute(c: PCtx, start: int): PNode =
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ type
|
|||
opcNError,
|
||||
opcNWarning,
|
||||
opcNHint,
|
||||
opcNLineInfo,
|
||||
opcNGetLine, opcNGetColumn, opcNGetFile,
|
||||
opcEqIdent,
|
||||
opcStrToIdent,
|
||||
opcIdentToStr,
|
||||
|
|
@ -136,7 +136,8 @@ type
|
|||
opcNBindSym,
|
||||
opcSetType, # dest.typ = types[Bx]
|
||||
opcTypeTrait,
|
||||
opcMarshalLoad, opcMarshalStore
|
||||
opcMarshalLoad, opcMarshalStore,
|
||||
opcToNarrowInt
|
||||
|
||||
TBlock* = object
|
||||
label*: PSym
|
||||
|
|
|
|||
|
|
@ -224,12 +224,13 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
|||
result.add copyTree(c)
|
||||
of tyTuple:
|
||||
if inst:
|
||||
result = newNodeX(nkTupleTy)
|
||||
# only named tuples have a node, unnamed tuples don't
|
||||
if t.n.isNil:
|
||||
result = newNodeX(nkPar)
|
||||
for subType in t.sons:
|
||||
result.add mapTypeToAst(subType, info)
|
||||
else:
|
||||
result = newNodeX(nkTupleTy)
|
||||
for s in t.n.sons:
|
||||
result.add newIdentDefs(s)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -656,16 +656,17 @@ proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
|
|||
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
|
||||
# uint is uint64 in the VM, we we only need to mask the result for
|
||||
# other unsigned types:
|
||||
if t.kind in {tyUInt8..tyUInt32}:
|
||||
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
|
||||
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
|
||||
elif t.kind in {tyInt8..tyInt32}:
|
||||
elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8):
|
||||
c.gABC(n, opcNarrowS, dest, TRegister(t.size*8))
|
||||
|
||||
proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
|
||||
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
|
||||
# uint is uint64 in the VM, we we only need to mask the result for
|
||||
# other unsigned types:
|
||||
if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}:
|
||||
if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or
|
||||
(t.kind in {tyUInt, tyInt} and t.size < 8):
|
||||
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
|
||||
|
||||
proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||
|
|
@ -875,11 +876,25 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
|||
of mBitnotI:
|
||||
genUnaryABC(c, n, dest, opcBitnotInt)
|
||||
genNarrowU(c, n, dest)
|
||||
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64,
|
||||
mToU8, mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt,
|
||||
of mToFloat, mToBiggestFloat, mToInt,
|
||||
mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
|
||||
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
|
||||
genConv(c, n, n.sons[1], dest)
|
||||
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
|
||||
#genNarrowU modified
|
||||
let t = skipTypes(n.sons[1].typ, abstractVar-{tyTypeDesc})
|
||||
let tmp = c.genx(n.sons[1])
|
||||
c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
|
||||
# assign result to dest register
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABC(n, opcAsgnInt, dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
of mToU8, mToU16, mToU32:
|
||||
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
|
||||
var tmp = c.genx(n.sons[1])
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABC(n, opcToNarrowInt, dest, tmp, TRegister(t.size*8))
|
||||
c.freeTemp(tmp)
|
||||
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
|
||||
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
|
||||
of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
|
||||
|
|
@ -1071,7 +1086,16 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
|||
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
|
||||
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
|
||||
of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)
|
||||
of mNLineInfo: genUnaryABC(c, n, dest, opcNLineInfo)
|
||||
of mNLineInfo:
|
||||
case n[0].sym.name.s
|
||||
of "getFile":
|
||||
genUnaryABC(c, n, dest, opcNGetFile)
|
||||
of "getLine":
|
||||
genUnaryABC(c, n, dest, opcNGetLine)
|
||||
of "getColumn":
|
||||
genUnaryABC(c, n, dest, opcNGetColumn)
|
||||
else:
|
||||
internalAssert false
|
||||
of mNHint:
|
||||
unused(n, dest)
|
||||
genUnaryStmt(c, n, opcNHint)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ type
|
|||
wFloatchecks, wNanChecks, wInfChecks,
|
||||
wAssertions, wPatterns, wWarnings,
|
||||
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
|
||||
wDeadCodeElim, wSafecode, wNoForward, wNoRewrite,
|
||||
wDeadCodeElim, wSafecode, wNoForward, wReorder, wNoRewrite,
|
||||
wPragma,
|
||||
wCompileTime, wNoInit,
|
||||
wPassc, wPassl, wBorrow, wDiscardable,
|
||||
|
|
@ -143,7 +143,7 @@ const
|
|||
|
||||
"assertions", "patterns", "warnings", "hints",
|
||||
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
|
||||
"deadcodeelim", "safecode", "noforward", "norewrite",
|
||||
"deadcodeelim", "safecode", "noforward", "reorder", "norewrite",
|
||||
"pragma",
|
||||
"compiletime", "noinit",
|
||||
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue