Merge remote-tracking branch 'nim-lang/devel' into emscripten-support
This commit is contained in:
commit
c16c1b47b8
26 changed files with 282 additions and 118 deletions
|
|
@ -709,6 +709,7 @@ type
|
||||||
lfSingleUse # no location yet and will only be used once
|
lfSingleUse # no location yet and will only be used once
|
||||||
TStorageLoc* = enum
|
TStorageLoc* = enum
|
||||||
OnUnknown, # location is unknown (stack, heap or static)
|
OnUnknown, # location is unknown (stack, heap or static)
|
||||||
|
OnStatic, # in a static section
|
||||||
OnStack, # location is on hardware stack
|
OnStack, # location is on hardware stack
|
||||||
OnHeap # location is on heap or global
|
OnHeap # location is on heap or global
|
||||||
# (reference counting needed)
|
# (reference counting needed)
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ proc optAsgnLoc(a: TLoc, t: PType, field: Rope): TLoc =
|
||||||
|
|
||||||
proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
let newflags =
|
let newflags =
|
||||||
if src.k == locData:
|
if src.s == OnStatic:
|
||||||
flags + {needToCopy}
|
flags + {needToCopy}
|
||||||
elif tfShallow in dest.t.flags:
|
elif tfShallow in dest.t.flags:
|
||||||
flags - {needToCopy}
|
flags - {needToCopy}
|
||||||
|
|
@ -238,7 +238,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||||
t: PNode) =
|
t: PNode) =
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
let newflags =
|
let newflags =
|
||||||
if src.k == locData:
|
if src.s == OnStatic:
|
||||||
flags + {needToCopy}
|
flags + {needToCopy}
|
||||||
elif tfShallow in dest.t.flags:
|
elif tfShallow in dest.t.flags:
|
||||||
flags - {needToCopy}
|
flags - {needToCopy}
|
||||||
|
|
@ -287,13 +287,13 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
of tyRef:
|
of tyRef:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if needToCopy notin flags and src.k != locData:
|
if needToCopy notin flags and src.s != OnStatic:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
of tyString:
|
of tyString:
|
||||||
if needToCopy notin flags and src.k != locData:
|
if needToCopy notin flags and src.s != OnStatic:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if dest.s == OnStack or not usesNativeGC():
|
if dest.s == OnStack or not usesNativeGC():
|
||||||
|
|
@ -413,7 +413,7 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if d.k != locNone:
|
if d.k != locNone:
|
||||||
# need to generate an assignment here
|
# need to generate an assignment here
|
||||||
initLoc(a, locData, t, OnUnknown)
|
initLoc(a, locData, t, OnStatic)
|
||||||
a.r = r
|
a.r = r
|
||||||
if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
|
if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
|
||||||
else: genAssignment(p, d, a, {needToCopy})
|
else: genAssignment(p, d, a, {needToCopy})
|
||||||
|
|
@ -424,11 +424,11 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
|
||||||
d.t = t
|
d.t = t
|
||||||
d.r = r
|
d.r = r
|
||||||
|
|
||||||
proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope) =
|
proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: Rope; s=OnUnknown) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if d.k != locNone:
|
if d.k != locNone:
|
||||||
# need to generate an assignment here
|
# need to generate an assignment here
|
||||||
initLoc(a, locExpr, t, OnUnknown)
|
initLoc(a, locExpr, t, s)
|
||||||
a.r = r
|
a.r = r
|
||||||
if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
|
if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {})
|
||||||
else: genAssignment(p, d, a, {needToCopy})
|
else: genAssignment(p, d, a, {needToCopy})
|
||||||
|
|
@ -685,7 +685,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
||||||
d.s = OnUnknown
|
d.s = OnUnknown
|
||||||
if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
|
if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
|
||||||
e.kind == nkHiddenDeref:
|
e.kind == nkHiddenDeref:
|
||||||
putIntoDest(p, d, e.typ, rdLoc(a))
|
putIntoDest(p, d, e.typ, rdLoc(a), a.s)
|
||||||
return
|
return
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
d.s = OnUnknown # BUGFIX!
|
d.s = OnUnknown # BUGFIX!
|
||||||
|
|
@ -694,7 +694,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
||||||
let typ = skipTypes(a.t, abstractInst)
|
let typ = skipTypes(a.t, abstractInst)
|
||||||
if typ.kind == tyVar and tfVarIsPtr notin typ.flags and
|
if typ.kind == tyVar and tfVarIsPtr notin typ.flags and
|
||||||
e.kind == nkHiddenDeref:
|
e.kind == nkHiddenDeref:
|
||||||
putIntoDest(p, d, e.typ, rdLoc(a))
|
putIntoDest(p, d, e.typ, rdLoc(a), a.s)
|
||||||
return
|
return
|
||||||
if enforceDeref and mt == ctPtrToArray:
|
if enforceDeref and mt == ctPtrToArray:
|
||||||
# we lie about the type for better C interop: 'ptr array[3,T]' is
|
# we lie about the type for better C interop: 'ptr array[3,T]' is
|
||||||
|
|
@ -702,23 +702,23 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
|
||||||
# See tmissingderef. So we get rid of the deref instead. The codegen
|
# See tmissingderef. So we get rid of the deref instead. The codegen
|
||||||
# ends up using 'memcpy' for the array assignment,
|
# ends up using 'memcpy' for the array assignment,
|
||||||
# so the '&' and '*' cancel out:
|
# so the '&' and '*' cancel out:
|
||||||
putIntoDest(p, d, a.t.sons[0], rdLoc(a))
|
putIntoDest(p, d, a.t.sons[0], rdLoc(a), a.s)
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)])
|
putIntoDest(p, d, e.typ, "(*$1)" % [rdLoc(a)], a.s)
|
||||||
|
|
||||||
proc genAddr(p: BProc, e: PNode, d: var TLoc) =
|
proc genAddr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# careful 'addr(myptrToArray)' needs to get the ampersand:
|
# careful 'addr(myptrToArray)' needs to get the ampersand:
|
||||||
if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
|
if e.sons[0].typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
putIntoDest(p, d, e.typ, "&" & a.r)
|
putIntoDest(p, d, e.typ, "&" & a.r, a.s)
|
||||||
#Message(e.info, warnUser, "HERE NEW &")
|
#Message(e.info, warnUser, "HERE NEW &")
|
||||||
elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ):
|
elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ):
|
||||||
expr(p, e.sons[0], d)
|
expr(p, e.sons[0], d)
|
||||||
else:
|
else:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
putIntoDest(p, d, e.typ, addrLoc(a))
|
putIntoDest(p, d, e.typ, addrLoc(a), a.s)
|
||||||
|
|
||||||
template inheritLocation(d: var TLoc, a: TLoc) =
|
template inheritLocation(d: var TLoc, a: TLoc) =
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
|
|
@ -745,7 +745,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal)
|
||||||
else: internalError(e.info, "genTupleElem")
|
else: internalError(e.info, "genTupleElem")
|
||||||
addf(r, ".Field$1", [rope(i)])
|
addf(r, ".Field$1", [rope(i)])
|
||||||
putIntoDest(p, d, ty.sons[i], r)
|
putIntoDest(p, d, ty.sons[i], r, a.s)
|
||||||
|
|
||||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
|
|
@ -756,7 +756,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# we found a unique tuple type which lacks field information
|
# we found a unique tuple type which lacks field information
|
||||||
# so we use Field$i
|
# so we use Field$i
|
||||||
addf(r, ".Field$1", [rope(f.position)])
|
addf(r, ".Field$1", [rope(f.position)])
|
||||||
putIntoDest(p, d, f.typ, r)
|
putIntoDest(p, d, f.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
var field: PSym = nil
|
var field: PSym = nil
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
|
|
@ -769,7 +769,7 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if field == nil: internalError(e.info, "genRecordField 2 ")
|
if field == nil: internalError(e.info, "genRecordField 2 ")
|
||||||
if field.loc.r == nil: internalError(e.info, "genRecordField 3")
|
if field.loc.r == nil: internalError(e.info, "genRecordField 3")
|
||||||
addf(r, ".$1", [field.loc.r])
|
addf(r, ".$1", [field.loc.r])
|
||||||
putIntoDest(p, d, field.typ, r)
|
putIntoDest(p, d, field.typ, r, a.s)
|
||||||
#d.s = a.s
|
#d.s = a.s
|
||||||
|
|
||||||
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||||
|
|
@ -824,7 +824,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
internalError(e.info, "genCheckedRecordField") # generate the checks:
|
internalError(e.info, "genCheckedRecordField") # generate the checks:
|
||||||
genFieldCheck(p, e, r, field)
|
genFieldCheck(p, e, r, field)
|
||||||
add(r, rfmt(nil, ".$1", field.loc.r))
|
add(r, rfmt(nil, ".$1", field.loc.r))
|
||||||
putIntoDest(p, d, field.typ, r)
|
putIntoDest(p, d, field.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
genRecordField(p, e.sons[0], d)
|
genRecordField(p, e.sons[0], d)
|
||||||
|
|
||||||
|
|
@ -851,7 +851,7 @@ proc genArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
localError(x.info, errIndexOutOfBounds)
|
localError(x.info, errIndexOutOfBounds)
|
||||||
d.inheritLocation(a)
|
d.inheritLocation(a)
|
||||||
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
||||||
rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first))
|
rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.s)
|
||||||
|
|
||||||
proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
|
proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
|
|
@ -860,7 +860,7 @@ proc genCStringElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
var ty = skipTypes(a.t, abstractVarRange)
|
var ty = skipTypes(a.t, abstractVarRange)
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
||||||
rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)))
|
rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
|
||||||
|
|
||||||
proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
|
proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
|
|
@ -871,7 +871,7 @@ proc genOpenArrayElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
|
rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
||||||
rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)))
|
rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.s)
|
||||||
|
|
||||||
proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
|
proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
var a, b: TLoc
|
var a, b: TLoc
|
||||||
|
|
@ -894,7 +894,7 @@ proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
a.r = rfmt(nil, "(*$1)", a.r)
|
a.r = rfmt(nil, "(*$1)", a.r)
|
||||||
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
||||||
rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)))
|
rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.s)
|
||||||
|
|
||||||
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
|
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
|
||||||
var ty = skipTypes(n.sons[0].typ, abstractVarRange)
|
var ty = skipTypes(n.sons[0].typ, abstractVarRange)
|
||||||
|
|
@ -1272,7 +1272,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
|
r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
|
||||||
else:
|
else:
|
||||||
r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
|
r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
|
||||||
putIntoDest(p, d, getSysType(tyBool), r)
|
putIntoDest(p, d, getSysType(tyBool), r, a.s)
|
||||||
|
|
||||||
proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
||||||
genOf(p, n.sons[1], n.sons[2].typ, d)
|
genOf(p, n.sons[1], n.sons[2].typ, d)
|
||||||
|
|
@ -1284,47 +1284,47 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||||
putIntoDest(p, d, e.typ,
|
putIntoDest(p, d, e.typ,
|
||||||
ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]))
|
ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]), a.s)
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]), a.s)
|
||||||
of tyBool:
|
of tyBool:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]))
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprBool($1)", [rdLoc(a)]), a.s)
|
||||||
of tyChar:
|
of tyChar:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]))
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprChar($1)", [rdLoc(a)]), a.s)
|
||||||
of tyEnum, tyOrdinal:
|
of tyEnum, tyOrdinal:
|
||||||
putIntoDest(p, d, e.typ,
|
putIntoDest(p, d, e.typ,
|
||||||
ropecg(p.module, "#reprEnum($1, $2)", [
|
ropecg(p.module, "#reprEnum($1, $2)", [
|
||||||
rdLoc(a), genTypeInfo(p.module, t)]))
|
rdLoc(a), genTypeInfo(p.module, t)]), a.s)
|
||||||
of tyString:
|
of tyString:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]))
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprStr($1)", [rdLoc(a)]), a.s)
|
||||||
of tySet:
|
of tySet:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprSet($1, $2)", [
|
||||||
addrLoc(a), genTypeInfo(p.module, t)]))
|
addrLoc(a), genTypeInfo(p.module, t)]), a.s)
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
var b: TLoc
|
var b: TLoc
|
||||||
case a.t.kind
|
case a.t.kind
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
putIntoDest(p, b, e.typ, "$1, $1Len0" % [rdLoc(a)])
|
putIntoDest(p, b, e.typ, "$1, $1Len0" % [rdLoc(a)], a.s)
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
putIntoDest(p, b, e.typ,
|
putIntoDest(p, b, e.typ,
|
||||||
"$1->data, $1->$2" % [rdLoc(a), lenField(p)])
|
"$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.s)
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
putIntoDest(p, b, e.typ,
|
putIntoDest(p, b, e.typ,
|
||||||
"$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))])
|
"$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.s)
|
||||||
else: internalError(e.sons[0].info, "genRepr()")
|
else: internalError(e.sons[0].info, "genRepr()")
|
||||||
putIntoDest(p, d, e.typ,
|
putIntoDest(p, d, e.typ,
|
||||||
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
|
ropecg(p.module, "#reprOpenArray($1, $2)", [rdLoc(b),
|
||||||
genTypeInfo(p.module, elemType(t))]))
|
genTypeInfo(p.module, elemType(t))]), a.s)
|
||||||
of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
|
of tyCString, tyArray, tyArrayConstr, tyRef, tyPtr, tyPointer, tyNil,
|
||||||
tySequence:
|
tySequence:
|
||||||
putIntoDest(p, d, e.typ,
|
putIntoDest(p, d, e.typ,
|
||||||
ropecg(p.module, "#reprAny($1, $2)", [
|
ropecg(p.module, "#reprAny($1, $2)", [
|
||||||
rdLoc(a), genTypeInfo(p.module, t)]))
|
rdLoc(a), genTypeInfo(p.module, t)]), a.s)
|
||||||
of tyEmpty:
|
of tyEmpty:
|
||||||
localError(e.info, "'repr' doesn't support 'void' type")
|
localError(e.info, "'repr' doesn't support 'void' type")
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
|
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprAny($1, $2)",
|
||||||
[addrLoc(a), genTypeInfo(p.module, t)]))
|
[addrLoc(a), genTypeInfo(p.module, t)]), a.s)
|
||||||
gcUsage(e)
|
gcUsage(e)
|
||||||
|
|
||||||
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
@ -1549,13 +1549,13 @@ proc genSomeCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let etyp = skipTypes(e.typ, abstractRange)
|
let etyp = skipTypes(e.typ, abstractRange)
|
||||||
if etyp.kind in ValueTypes and lfIndirect notin a.flags:
|
if etyp.kind in ValueTypes and lfIndirect notin a.flags:
|
||||||
putIntoDest(p, d, e.typ, "(*($1*) ($2))" %
|
putIntoDest(p, d, e.typ, "(*($1*) ($2))" %
|
||||||
[getTypeDesc(p.module, e.typ), addrLoc(a)])
|
[getTypeDesc(p.module, e.typ), addrLoc(a)], a.s)
|
||||||
elif etyp.kind == tyProc and etyp.callConv == ccClosure:
|
elif etyp.kind == tyProc and etyp.callConv == ccClosure:
|
||||||
putIntoDest(p, d, e.typ, "(($1) ($2))" %
|
putIntoDest(p, d, e.typ, "(($1) ($2))" %
|
||||||
[getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)])
|
[getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)], a.s)
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, e.typ, "(($1) ($2))" %
|
putIntoDest(p, d, e.typ, "(($1) ($2))" %
|
||||||
[getTypeDesc(p.module, e.typ), rdCharLoc(a)])
|
[getTypeDesc(p.module, e.typ), rdCharLoc(a)], a.s)
|
||||||
|
|
||||||
proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
const floatTypes = {tyFloat..tyFloat128}
|
const floatTypes = {tyFloat..tyFloat128}
|
||||||
|
|
@ -1575,7 +1575,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
tmp.s = OnStack
|
tmp.s = OnStack
|
||||||
tmp.flags = {}
|
tmp.flags = {}
|
||||||
expr(p, e.sons[1], tmp)
|
expr(p, e.sons[1], tmp)
|
||||||
putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl])
|
putIntoDest(p, d, e.typ, "LOC$#.dest" % [lbl], tmp.s)
|
||||||
else:
|
else:
|
||||||
# I prefer the shorter cast version for pointer types -> generate less
|
# I prefer the shorter cast version for pointer types -> generate less
|
||||||
# C code; plus it's the right thing to do for closures:
|
# C code; plus it's the right thing to do for closures:
|
||||||
|
|
@ -1589,13 +1589,13 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) =
|
||||||
{tyUInt..tyUInt64}:
|
{tyUInt..tyUInt64}:
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, n.typ, "(($1) ($2))" %
|
putIntoDest(p, d, n.typ, "(($1) ($2))" %
|
||||||
[getTypeDesc(p.module, dest), rdCharLoc(a)])
|
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.s)
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
|
putIntoDest(p, d, dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [
|
||||||
getTypeDesc(p.module, dest), rdCharLoc(a),
|
getTypeDesc(p.module, dest), rdCharLoc(a),
|
||||||
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
|
genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest),
|
||||||
rope(magic)]))
|
rope(magic)]), a.s)
|
||||||
|
|
||||||
proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let destType = e.typ.skipTypes({tyVar, tyGenericInst})
|
let destType = e.typ.skipTypes({tyVar, tyGenericInst})
|
||||||
|
|
@ -1607,13 +1607,13 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
||||||
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)])
|
putIntoDest(p, d, skipTypes(n.typ, abstractVar), "$1->data" % [rdLoc(a)], a.s)
|
||||||
|
|
||||||
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, skipTypes(n.typ, abstractVar),
|
putIntoDest(p, d, skipTypes(n.typ, abstractVar),
|
||||||
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]))
|
ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]), a.s)
|
||||||
gcUsage(n)
|
gcUsage(n)
|
||||||
|
|
||||||
proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
@ -1763,7 +1763,7 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
|
||||||
var t = getUniqueType(n.typ)
|
var t = getUniqueType(n.typ)
|
||||||
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
discard getTypeDesc(p.module, t) # so that any fields are initialized
|
||||||
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
|
||||||
fillLoc(d, locData, t, "TMP" & rope(id), OnHeap)
|
fillLoc(d, locData, t, "TMP" & rope(id), OnStatic)
|
||||||
if id == gBackendId:
|
if id == gBackendId:
|
||||||
# expression not found in the cache:
|
# expression not found in the cache:
|
||||||
inc(gBackendId)
|
inc(gBackendId)
|
||||||
|
|
@ -1849,7 +1849,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var tmp = "LOC" & rope(p.labels)
|
var tmp = "LOC" & rope(p.labels)
|
||||||
addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n",
|
||||||
[getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)])
|
[getTypeDesc(p.module, n.typ), tmp, genConstExpr(p, n)])
|
||||||
putIntoDest(p, d, n.typ, tmp)
|
putIntoDest(p, d, n.typ, tmp, OnStatic)
|
||||||
else:
|
else:
|
||||||
var tmp, a, b: TLoc
|
var tmp, a, b: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
|
|
@ -1903,10 +1903,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
r, genTypeInfo(p.module, dest))
|
r, genTypeInfo(p.module, dest))
|
||||||
if n.sons[0].typ.kind != tyObject:
|
if n.sons[0].typ.kind != tyObject:
|
||||||
putIntoDest(p, d, n.typ,
|
putIntoDest(p, d, n.typ,
|
||||||
"(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)])
|
"(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.s)
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, n.typ, "(*($1*) ($2))" %
|
putIntoDest(p, d, n.typ, "(*($1*) ($2))" %
|
||||||
[getTypeDesc(p.module, dest), addrLoc(a)])
|
[getTypeDesc(p.module, dest), addrLoc(a)], a.s)
|
||||||
|
|
||||||
proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
if p.module.compileToCpp:
|
if p.module.compileToCpp:
|
||||||
|
|
@ -1938,9 +1938,9 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
|
linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r)
|
||||||
else:
|
else:
|
||||||
r = "&" & r
|
r = "&" & r
|
||||||
putIntoDest(p, d, n.typ, r)
|
putIntoDest(p, d, n.typ, r, a.s)
|
||||||
else:
|
else:
|
||||||
putIntoDest(p, d, n.typ, r)
|
putIntoDest(p, d, n.typ, r, a.s)
|
||||||
|
|
||||||
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var t = getUniqueType(n.typ)
|
var t = getUniqueType(n.typ)
|
||||||
|
|
@ -1955,7 +1955,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
|
||||||
[getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
|
[getTypeDesc(p.module, t), tmp, genConstExpr(p, n)])
|
||||||
|
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
fillLoc(d, locData, t, tmp, OnHeap)
|
fillLoc(d, locData, t, tmp, OnStatic)
|
||||||
else:
|
else:
|
||||||
putDataIntoDest(p, d, t, tmp)
|
putDataIntoDest(p, d, t, tmp)
|
||||||
|
|
||||||
|
|
@ -1982,7 +1982,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
|
if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
elif isSimpleConst(sym.typ):
|
elif isSimpleConst(sym.typ):
|
||||||
putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ))
|
putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ), OnStatic)
|
||||||
else:
|
else:
|
||||||
genComplexConst(p, sym, d)
|
genComplexConst(p, sym, d)
|
||||||
of skEnumField:
|
of skEnumField:
|
||||||
|
|
|
||||||
|
|
@ -760,7 +760,7 @@ proc requestConstImpl(p: BProc, sym: PSym) =
|
||||||
var m = p.module
|
var m = p.module
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
if sym.loc.k == locNone:
|
if sym.loc.k == locNone:
|
||||||
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
|
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnStatic)
|
||||||
if lfNoDecl in sym.loc.flags: return
|
if lfNoDecl in sym.loc.flags: return
|
||||||
# declare implementation:
|
# declare implementation:
|
||||||
var q = findPendingModule(m, sym)
|
var q = findPendingModule(m, sym)
|
||||||
|
|
|
||||||
|
|
@ -645,11 +645,18 @@ proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
|
||||||
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
proc processArgument*(pass: TCmdLinePass; p: OptParser;
|
||||||
argsCount: var int): bool =
|
argsCount: var int): bool =
|
||||||
if argsCount == 0:
|
if argsCount == 0:
|
||||||
if pass != passCmd2: options.command = p.key
|
# nim filename.nims is the same as "nim e filename.nims":
|
||||||
|
if p.key.endswith(".nims"):
|
||||||
|
options.command = "e"
|
||||||
|
options.gProjectName = unixToNativePath(p.key)
|
||||||
|
arguments = cmdLineRest(p)
|
||||||
|
result = true
|
||||||
|
elif pass != passCmd2:
|
||||||
|
options.command = p.key
|
||||||
else:
|
else:
|
||||||
if pass == passCmd1: options.commandArgs.add p.key
|
if pass == passCmd1: options.commandArgs.add p.key
|
||||||
if argsCount == 1:
|
if argsCount == 1:
|
||||||
# support UNIX style filenames anywhere for portable build scripts:
|
# support UNIX style filenames everywhere for portable build scripts:
|
||||||
options.gProjectName = unixToNativePath(p.key)
|
options.gProjectName = unixToNativePath(p.key)
|
||||||
arguments = cmdLineRest(p)
|
arguments = cmdLineRest(p)
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -91,3 +91,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimnomagic64")
|
defineSymbol("nimnomagic64")
|
||||||
defineSymbol("nimvarargstyped")
|
defineSymbol("nimvarargstyped")
|
||||||
defineSymbol("nimtypedescfixed")
|
defineSymbol("nimtypedescfixed")
|
||||||
|
defineSymbol("nimKnowsNimvm")
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,9 @@ proc parseLine(p: var TTmplParser) =
|
||||||
keyw: string
|
keyw: string
|
||||||
j = 0
|
j = 0
|
||||||
while p.x[j] == ' ': inc(j)
|
while p.x[j] == ' ': inc(j)
|
||||||
if (p.x[0] == p.nimDirective) and (p.x[0 + 1] == '!'):
|
if p.x[0] == p.nimDirective and p.x[1] in {'?', '!'}:
|
||||||
newLine(p)
|
newLine(p)
|
||||||
elif (p.x[j] == p.nimDirective):
|
elif p.x[j] == p.nimDirective:
|
||||||
newLine(p)
|
newLine(p)
|
||||||
inc(j)
|
inc(j)
|
||||||
while p.x[j] == ' ': inc(j)
|
while p.x[j] == ' ': inc(j)
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||||
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
|
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
|
||||||
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
|
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
|
||||||
mParallel, mPlugin, mGetTypeInfo:
|
mParallel, mPlugin, mGetTypeInfo, mTypeOf:
|
||||||
discard
|
discard
|
||||||
of mEqProc:
|
of mEqProc:
|
||||||
result = newIntNodeT(ord(
|
result = newIntNodeT(ord(
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,15 @@ proc parsePipe(filename: string, inputStream: PLLStream): PNode =
|
||||||
var line = newStringOfCap(80)
|
var line = newStringOfCap(80)
|
||||||
discard llStreamReadLine(s, line)
|
discard llStreamReadLine(s, line)
|
||||||
var i = utf8Bom(line)
|
var i = utf8Bom(line)
|
||||||
|
var linenumber = 1
|
||||||
if containsShebang(line, i):
|
if containsShebang(line, i):
|
||||||
discard llStreamReadLine(s, line)
|
discard llStreamReadLine(s, line)
|
||||||
i = 0
|
i = 0
|
||||||
if line[i] == '#' and line[i+1] == '!':
|
inc linenumber
|
||||||
|
if line[i] == '#' and line[i+1] in {'?', '!'}:
|
||||||
|
if line[i+1] == '!':
|
||||||
|
message(newLineInfo(filename, linenumber, 1),
|
||||||
|
warnDeprecated, "use '#?' instead; '#!'")
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
while line[i] in Whitespace: inc(i)
|
while line[i] in Whitespace: inc(i)
|
||||||
var q: TParser
|
var q: TParser
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ proc deps(w: var W; n: PNode) =
|
||||||
|
|
||||||
proc possibleAliases(w: var W; result: var seq[ptr TSym]) =
|
proc possibleAliases(w: var W; result: var seq[ptr TSym]) =
|
||||||
# this is an expensive fixpoint iteration. We could speed up this analysis
|
# this is an expensive fixpoint iteration. We could speed up this analysis
|
||||||
# by a smarter data-structure but we wait until prolifing shows us it's
|
# by a smarter data-structure but we wait until profiling shows us it's
|
||||||
# expensive. Usually 'w.assignments' is small enough.
|
# expensive. Usually 'w.assignments' is small enough.
|
||||||
var alreadySeen = initIntSet()
|
var alreadySeen = initIntSet()
|
||||||
template addNoDup(x) =
|
template addNoDup(x) =
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Comex
|
Comex
|
||||||
Eric Doughty-Papassideris
|
Eric Doughty-Papassideris
|
||||||
Simon Hafner
|
Simon Hafner
|
||||||
Keita Haga
|
Keita Haga
|
||||||
|
|
@ -6,7 +6,7 @@ Grzegorz Adam Hankiewicz
|
||||||
Philippe Lhoste
|
Philippe Lhoste
|
||||||
Zahary Karadjov
|
Zahary Karadjov
|
||||||
Mario Ray Mahardhika
|
Mario Ray Mahardhika
|
||||||
Alex Mitchell
|
Alexander Mitchell-Robinson (Amrykid)
|
||||||
Dominik Picheta
|
Dominik Picheta
|
||||||
Jonathan Plona
|
Jonathan Plona
|
||||||
Alexander Rødseth
|
Alexander Rødseth
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ Short description of Nim's modules
|
||||||
============== ==========================================================
|
============== ==========================================================
|
||||||
Module Description
|
Module Description
|
||||||
============== ==========================================================
|
============== ==========================================================
|
||||||
nim main module: parses the command line and calls
|
nim main module: parses the command line and calls
|
||||||
``main.MainCommand``
|
``main.MainCommand``
|
||||||
main implements the top-level command dispatching
|
main implements the top-level command dispatching
|
||||||
nimconf implements the config file reader
|
nimconf implements the config file reader
|
||||||
syntaxes dispatcher for the different parsers and filters
|
syntaxes dispatcher for the different parsers and filters
|
||||||
filter_tmpl standard template filter (``#! stdtempl``)
|
filter_tmpl standard template filter (``#? stdtempl``)
|
||||||
lexbase buffer handling of the lexical analyser
|
lexbase buffer handling of the lexical analyser
|
||||||
lexer lexical analyser
|
lexer lexical analyser
|
||||||
parser Nim's parser
|
parser Nim's parser
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ A `Source Code Filter` transforms the input character stream to an in-memory
|
||||||
output stream before parsing. A filter can be used to provide templating
|
output stream before parsing. A filter can be used to provide templating
|
||||||
systems or preprocessors.
|
systems or preprocessors.
|
||||||
|
|
||||||
To use a filter for a source file the *shebang* notation is used::
|
To use a filter for a source file the ``#?`` notation is used::
|
||||||
|
|
||||||
#! stdtmpl(subsChar = '$', metaChar = '#')
|
#? stdtmpl(subsChar = '$', metaChar = '#')
|
||||||
#proc generateXML(name, age: string): string =
|
#proc generateXML(name, age: string): string =
|
||||||
# result = ""
|
# result = ""
|
||||||
<xml>
|
<xml>
|
||||||
|
|
@ -20,7 +20,8 @@ To use a filter for a source file the *shebang* notation is used::
|
||||||
|
|
||||||
As the example shows, passing arguments to a filter can be done
|
As the example shows, passing arguments to a filter can be done
|
||||||
just like an ordinary procedure call with named or positional arguments. The
|
just like an ordinary procedure call with named or positional arguments. The
|
||||||
available parameters depend on the invoked filter.
|
available parameters depend on the invoked filter. Before version 0.12.0 of
|
||||||
|
the language ``#!`` was used instead of ``#?``.
|
||||||
|
|
||||||
|
|
||||||
Pipe operator
|
Pipe operator
|
||||||
|
|
@ -28,7 +29,7 @@ Pipe operator
|
||||||
|
|
||||||
Filters can be combined with the ``|`` pipe operator::
|
Filters can be combined with the ``|`` pipe operator::
|
||||||
|
|
||||||
#! strip(startswith="<") | stdtmpl
|
#? strip(startswith="<") | stdtmpl
|
||||||
#proc generateXML(name, age: string): string =
|
#proc generateXML(name, age: string): string =
|
||||||
# result = ""
|
# result = ""
|
||||||
<xml>
|
<xml>
|
||||||
|
|
@ -104,7 +105,7 @@ Parameters and their defaults:
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
#! stdtmpl | standard
|
#? stdtmpl | standard
|
||||||
#proc generateHTMLPage(title, currentTab, content: string,
|
#proc generateHTMLPage(title, currentTab, content: string,
|
||||||
# tabs: openArray[string]): string =
|
# tabs: openArray[string]): string =
|
||||||
# result = ""
|
# result = ""
|
||||||
|
|
@ -172,7 +173,7 @@ produces ``$``.
|
||||||
The template engine is quite flexible. It is easy to produce a procedure that
|
The template engine is quite flexible. It is easy to produce a procedure that
|
||||||
writes the template code directly to a file::
|
writes the template code directly to a file::
|
||||||
|
|
||||||
#! stdtmpl(emit="f.write") | standard
|
#? stdtmpl(emit="f.write") | standard
|
||||||
#proc writeHTMLPage(f: File, title, currentTab, content: string,
|
#proc writeHTMLPage(f: File, title, currentTab, content: string,
|
||||||
# tabs: openArray[string]) =
|
# tabs: openArray[string]) =
|
||||||
<head><title>$title</title></head>
|
<head><title>$title</title></head>
|
||||||
|
|
|
||||||
|
|
@ -329,8 +329,10 @@ The ``when`` statement enables conditional compilation techniques. As
|
||||||
a special syntactic extension, the ``when`` construct is also available
|
a special syntactic extension, the ``when`` construct is also available
|
||||||
within ``object`` definitions.
|
within ``object`` definitions.
|
||||||
|
|
||||||
|
|
||||||
When nimvm statement
|
When nimvm statement
|
||||||
---------------------
|
--------------------
|
||||||
|
|
||||||
``nimvm`` is a special symbol, that may be used as expression of ``when nimvm``
|
``nimvm`` is a special symbol, that may be used as expression of ``when nimvm``
|
||||||
statement to differentiate execution path between runtime and compile time.
|
statement to differentiate execution path between runtime and compile time.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,13 @@ Strong spaces
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The number of spaces preceding a non-keyword operator affects precedence
|
The number of spaces preceding a non-keyword operator affects precedence
|
||||||
if the experimental parser directive ``#!strongSpaces`` is used. Indentation
|
if the experimental parser directive ``#?strongSpaces`` is used. Indentation
|
||||||
is not used to determine the number of spaces. If 2 or more operators have the
|
is not used to determine the number of spaces. If 2 or more operators have the
|
||||||
same number of preceding spaces the precedence table applies, so ``1 + 3 * 4``
|
same number of preceding spaces the precedence table applies, so ``1 + 3 * 4``
|
||||||
is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``:
|
is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
#! strongSpaces
|
#? strongSpaces
|
||||||
if foo+4 * 4 == 8 and b&c | 9 ++
|
if foo+4 * 4 == 8 and b&c | 9 ++
|
||||||
bar:
|
bar:
|
||||||
echo ""
|
echo ""
|
||||||
|
|
@ -86,7 +86,7 @@ Furthermore whether an operator is used a prefix operator is affected by the
|
||||||
number of spaces:
|
number of spaces:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
#! strongSpaces
|
#? strongSpaces
|
||||||
echo $foo
|
echo $foo
|
||||||
# is parsed as
|
# is parsed as
|
||||||
echo($foo)
|
echo($foo)
|
||||||
|
|
@ -95,7 +95,7 @@ This also affects whether ``[]``, ``{}``, ``()`` are parsed as constructors
|
||||||
or as accessors:
|
or as accessors:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
#! strongSpaces
|
#? strongSpaces
|
||||||
echo (1,2)
|
echo (1,2)
|
||||||
# is parsed as
|
# is parsed as
|
||||||
echo((1,2))
|
echo((1,2))
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ a ``myproject.nims`` file that simply contains Nim code controlling the
|
||||||
compilation process.
|
compilation process.
|
||||||
|
|
||||||
The VM cannot deal with ``importc``, the FFI is not available, so there are not
|
The VM cannot deal with ``importc``, the FFI is not available, so there are not
|
||||||
many stdlib modules that you can use with Nim's VM. However, the following
|
many stdlib modules that you can use with Nim's VM. However, at least the
|
||||||
modules are available:
|
following modules are available:
|
||||||
|
|
||||||
* `strutils <strutils.html>`_
|
* `strutils <strutils.html>`_
|
||||||
* `ospaths <ospaths.html>`_
|
* `ospaths <ospaths.html>`_
|
||||||
|
|
@ -40,7 +40,7 @@ NimScript as a build tool
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
The ``task`` template that the ``system`` module defines allows a NimScript
|
The ``task`` template that the ``system`` module defines allows a NimScript
|
||||||
file to be used as a build tool. The following exampled defines a
|
file to be used as a build tool. The following example defines a
|
||||||
task ``build`` that is an alias for the ``c`` command:
|
task ``build`` that is an alias for the ``c`` command:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nim's Runtime Library
|
# Nim's Runtime Library
|
||||||
# (c) Copyright 2011 Alex Mitchell
|
# (c) Copyright 2011 Alexander Mitchell-Robinson
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## :Author: Alex Mitchell
|
## :Author: Alexander Mitchell-Robinson (Amrykid)
|
||||||
##
|
##
|
||||||
## This module implements operations for the built-in `seq`:idx: type which
|
## This module implements operations for the built-in `seq`:idx: type which
|
||||||
## were inspired by functional programming languages. If you are looking for
|
## were inspired by functional programming languages. If you are looking for
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nim's Runtime Library
|
# Nim's Runtime Library
|
||||||
# (c) Copyright 2011 Alex Mitchell
|
# (c) Copyright 2011 Alexander Mitchell-Robinson
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## :Author: Alex Mitchell
|
## :Author: Alexander Mitchell-Robinson (Amrykid)
|
||||||
##
|
##
|
||||||
## This module implements an event system that is not dependent on external
|
## This module implements an event system that is not dependent on external
|
||||||
## graphical toolkits. It was originally called ``NimEE`` because
|
## graphical toolkits. It was originally called ``NimEE`` because
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ type
|
||||||
|
|
||||||
{.deprecated: [Toid: Oid].}
|
{.deprecated: [Toid: Oid].}
|
||||||
|
|
||||||
|
proc `==`*(oid1: Oid, oid2: Oid): bool =
|
||||||
|
## Compare two Mongo Object IDs for equality
|
||||||
|
return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and (oid1.count == oid2.count)
|
||||||
|
|
||||||
proc hexbyte*(hex: char): int =
|
proc hexbyte*(hex: char): int =
|
||||||
case hex
|
case hex
|
||||||
of '0'..'9': result = (ord(hex) - ord('0'))
|
of '0'..'9': result = (ord(hex) - ord('0'))
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,26 @@
|
||||||
## This module contains routines and types for dealing with time.
|
## This module contains routines and types for dealing with time.
|
||||||
## This module is available for the `JavaScript target
|
## This module is available for the `JavaScript target
|
||||||
## <backends.html#the-javascript-target>`_.
|
## <backends.html#the-javascript-target>`_.
|
||||||
|
##
|
||||||
|
## Examples:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
##
|
||||||
|
## import times, os
|
||||||
|
## var
|
||||||
|
## t = cpuTime()
|
||||||
|
##
|
||||||
|
## sleep(100) # replace this with something to be timed
|
||||||
|
## echo "Time taken: ",cpuTime() - t
|
||||||
|
##
|
||||||
|
## echo "My formatted time: ", format(getLocalTime(getTime()), "d MMMM yyyy HH:mm")
|
||||||
|
## echo "Using predefined formats: ", getClockStr(), " ", getDateStr()
|
||||||
|
##
|
||||||
|
## echo "epochTime() float value: ", epochTime()
|
||||||
|
## echo "getTime() float value: ", toSeconds(getTime())
|
||||||
|
## echo "cpuTime() float value: ", cpuTime()
|
||||||
|
## echo "An hour from now : ", getLocalTime(getTime()) + initInterval(0,0,0,1)
|
||||||
|
## echo "An hour from (UTC) now: ", getGmTime(getTime()) + initInterval(0,0,0,1)
|
||||||
|
|
||||||
{.push debugger:off.} # the user does not want to trace a part
|
{.push debugger:off.} # the user does not want to trace a part
|
||||||
# of the standard library!
|
# of the standard library!
|
||||||
|
|
@ -288,10 +308,10 @@ proc `+`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
|
||||||
## very accurate.
|
## very accurate.
|
||||||
let t = toSeconds(timeInfoToTime(a))
|
let t = toSeconds(timeInfoToTime(a))
|
||||||
let secs = toSeconds(a, interval)
|
let secs = toSeconds(a, interval)
|
||||||
if a.tzname == "UTC":
|
#if a.tzname == "UTC":
|
||||||
result = getGMTime(fromSeconds(t + secs))
|
# result = getGMTime(fromSeconds(t + secs))
|
||||||
else:
|
#else:
|
||||||
result = getLocalTime(fromSeconds(t + secs))
|
result = getLocalTime(fromSeconds(t + secs))
|
||||||
|
|
||||||
proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
|
proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
|
||||||
## subtracts ``interval`` time.
|
## subtracts ``interval`` time.
|
||||||
|
|
@ -300,10 +320,10 @@ proc `-`*(a: TimeInfo, interval: TimeInterval): TimeInfo =
|
||||||
## when you subtract so much that you reach the Julian calendar.
|
## when you subtract so much that you reach the Julian calendar.
|
||||||
let t = toSeconds(timeInfoToTime(a))
|
let t = toSeconds(timeInfoToTime(a))
|
||||||
let secs = toSeconds(a, interval)
|
let secs = toSeconds(a, interval)
|
||||||
if a.tzname == "UTC":
|
#if a.tzname == "UTC":
|
||||||
result = getGMTime(fromSeconds(t - secs))
|
# result = getGMTime(fromSeconds(t - secs))
|
||||||
else:
|
#else:
|
||||||
result = getLocalTime(fromSeconds(t - secs))
|
result = getLocalTime(fromSeconds(t - secs))
|
||||||
|
|
||||||
when not defined(JS):
|
when not defined(JS):
|
||||||
proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
|
proc epochTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].}
|
||||||
|
|
@ -1269,3 +1289,28 @@ when isMainModule:
|
||||||
assert getDayOfWeekJulian(21, 9, 1970) == dMon
|
assert getDayOfWeekJulian(21, 9, 1970) == dMon
|
||||||
assert getDayOfWeekJulian(1, 1, 2000) == dSat
|
assert getDayOfWeekJulian(1, 1, 2000) == dSat
|
||||||
assert getDayOfWeekJulian(1, 1, 2021) == dFri
|
assert getDayOfWeekJulian(1, 1, 2021) == dFri
|
||||||
|
|
||||||
|
# toSeconds tests with GM and Local timezones
|
||||||
|
#var t4 = getGMTime(fromSeconds(876124714)) # Mon 6 Oct 08:58:34 BST 1997
|
||||||
|
var t4L = getLocalTime(fromSeconds(876124714))
|
||||||
|
assert toSeconds(timeInfoToTime(t4L)) == 876124714 # fromSeconds is effectively "localTime"
|
||||||
|
assert toSeconds(timeInfoToTime(t4L)) + t4L.timezone.float == toSeconds(timeInfoToTime(t4))
|
||||||
|
|
||||||
|
assert toSeconds(t4, initInterval(seconds=0)) == 0.0
|
||||||
|
assert toSeconds(t4L, initInterval(milliseconds=1)) == toSeconds(t4, initInterval(milliseconds=1))
|
||||||
|
assert toSeconds(t4L, initInterval(seconds=1)) == toSeconds(t4, initInterval(seconds=1))
|
||||||
|
assert toSeconds(t4L, initInterval(minutes=1)) == toSeconds(t4, initInterval(minutes=1))
|
||||||
|
assert toSeconds(t4L, initInterval(hours=1)) == toSeconds(t4, initInterval(hours=1))
|
||||||
|
assert toSeconds(t4L, initInterval(days=1)) == toSeconds(t4, initInterval(days=1))
|
||||||
|
assert toSeconds(t4L, initInterval(months=1)) == toSeconds(t4, initInterval(months=1))
|
||||||
|
assert toSeconds(t4L, initInterval(years=1)) == toSeconds(t4, initInterval(years=1))
|
||||||
|
|
||||||
|
# adding intervals
|
||||||
|
var
|
||||||
|
a1L = toSeconds(timeInfoToTime(t4L + initInterval(hours = 1))) + t4L.timezone.float
|
||||||
|
a1G = toSeconds(timeInfoToTime(t4)) + 60.0 * 60.0
|
||||||
|
assert a1L == a1G
|
||||||
|
# subtracting intervals
|
||||||
|
a1L = toSeconds(timeInfoToTime(t4L - initInterval(hours = 1))) + t4L.timezone.float
|
||||||
|
a1G = toSeconds(timeInfoToTime(t4)) - (60.0 * 60.0)
|
||||||
|
assert a1L == a1G
|
||||||
|
|
|
||||||
|
|
@ -1175,9 +1175,12 @@ const
|
||||||
|
|
||||||
seqShallowFlag = low(int)
|
seqShallowFlag = low(int)
|
||||||
|
|
||||||
let nimvm* {.magic: "Nimvm".}: bool = false
|
when defined(nimKnowsNimvm):
|
||||||
|
let nimvm* {.magic: "Nimvm".}: bool = false
|
||||||
## may be used only in "when" expression.
|
## may be used only in "when" expression.
|
||||||
## It is true in Nim VM context and false otherwise
|
## It is true in Nim VM context and false otherwise
|
||||||
|
else:
|
||||||
|
const nimvm*: bool = false
|
||||||
|
|
||||||
proc compileOption*(option: string): bool {.
|
proc compileOption*(option: string): bool {.
|
||||||
magic: "CompileOption", noSideEffect.}
|
magic: "CompileOption", noSideEffect.}
|
||||||
|
|
@ -1293,25 +1296,42 @@ proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
|
||||||
proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
||||||
## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
|
## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`.
|
||||||
## This is an O(1) operation.
|
## This is an O(1) operation.
|
||||||
let xl = x.len
|
let xl = x.len - 1
|
||||||
shallowCopy(x[i], x[xl-1])
|
shallowCopy(x[i], x[xl])
|
||||||
setLen(x, xl-1)
|
setLen(x, xl)
|
||||||
|
|
||||||
proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
|
||||||
## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
|
## deletes the item at index `i` by moving ``x[i+1..]`` by one position.
|
||||||
## This is an O(n) operation.
|
## This is an O(n) operation.
|
||||||
let xl = x.len
|
template defaultImpl =
|
||||||
for j in i..xl-2: shallowCopy(x[j], x[j+1])
|
let xl = x.len
|
||||||
setLen(x, xl-1)
|
for j in i..xl-2: shallowCopy(x[j], x[j+1])
|
||||||
|
setLen(x, xl-1)
|
||||||
|
|
||||||
|
when nimvm:
|
||||||
|
defaultImpl()
|
||||||
|
else:
|
||||||
|
when defined(js):
|
||||||
|
{.emit: "`x`[`x`_Idx].splice(`i`, 1);".}
|
||||||
|
else:
|
||||||
|
defaultImpl()
|
||||||
|
|
||||||
proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
|
proc insert*[T](x: var seq[T], item: T, i = 0.Natural) {.noSideEffect.} =
|
||||||
## inserts `item` into `x` at position `i`.
|
## inserts `item` into `x` at position `i`.
|
||||||
let xl = x.len
|
template defaultImpl =
|
||||||
setLen(x, xl+1)
|
let xl = x.len
|
||||||
var j = xl-1
|
setLen(x, xl+1)
|
||||||
while j >= i:
|
var j = xl-1
|
||||||
shallowCopy(x[j+1], x[j])
|
while j >= i:
|
||||||
dec(j)
|
shallowCopy(x[j+1], x[j])
|
||||||
|
dec(j)
|
||||||
|
when nimvm:
|
||||||
|
defaultImpl()
|
||||||
|
else:
|
||||||
|
when defined(js):
|
||||||
|
{.emit: "`x`[`x`_Idx].splice(`i`, 0, null);".}
|
||||||
|
else:
|
||||||
|
defaultImpl()
|
||||||
x[i] = item
|
x[i] = item
|
||||||
|
|
||||||
proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.}
|
proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.}
|
||||||
|
|
@ -3042,7 +3062,7 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} =
|
||||||
# fill the hole:
|
# fill the hole:
|
||||||
for i in 0 .. <b.len: s[i+a] = b[i]
|
for i in 0 .. <b.len: s[i+a] = b[i]
|
||||||
|
|
||||||
when hasAlloc:
|
when hasAlloc or defined(nimscript):
|
||||||
proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
|
proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
|
||||||
## slice operation for strings.
|
## slice operation for strings.
|
||||||
result = s.substr(x.a, x.b)
|
result = s.substr(x.a, x.b)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
template builtin = discard
|
template builtin = discard
|
||||||
|
|
||||||
|
# We know the effects better than the compiler:
|
||||||
|
{.push hint[XDeclaredButNotUsed]: off.}
|
||||||
|
|
||||||
proc listDirs*(dir: string): seq[string] =
|
proc listDirs*(dir: string): seq[string] =
|
||||||
## Lists all the subdirectories (non-recursively) in the directory `dir`.
|
## Lists all the subdirectories (non-recursively) in the directory `dir`.
|
||||||
builtin
|
builtin
|
||||||
|
|
@ -61,10 +64,17 @@ proc setCommand*(cmd: string) =
|
||||||
proc cmpIgnoreStyle(a, b: string): int = builtin
|
proc cmpIgnoreStyle(a, b: string): int = builtin
|
||||||
proc cmpIgnoreCase(a, b: string): int = builtin
|
proc cmpIgnoreCase(a, b: string): int = builtin
|
||||||
|
|
||||||
proc cmpic*(a, b: string): int = cmpIgnoreCase(a, b)
|
proc cmpic*(a, b: string): int =
|
||||||
|
## Compares `a` and `b` ignoring case.
|
||||||
|
cmpIgnoreCase(a, b)
|
||||||
|
|
||||||
proc getEnv*(key: string): string = builtin
|
proc getEnv*(key: string): string {.tags: [ReadIOEffect].} =
|
||||||
proc existsEnv*(key: string): bool = builtin
|
## Retrieves the environment variable of name `key`.
|
||||||
|
builtin
|
||||||
|
|
||||||
|
proc existsEnv*(key: string): bool {.tags: [ReadIOEffect].} =
|
||||||
|
## Checks for the existance of an environment variable named `key`.
|
||||||
|
builtin
|
||||||
|
|
||||||
proc fileExists*(filename: string): bool {.tags: [ReadIOEffect].} =
|
proc fileExists*(filename: string): bool {.tags: [ReadIOEffect].} =
|
||||||
## Checks if the file exists.
|
## Checks if the file exists.
|
||||||
|
|
@ -96,8 +106,13 @@ proc strip(s: string): string =
|
||||||
while s[i] in {' ', '\c', '\L'}: inc i
|
while s[i] in {' ', '\c', '\L'}: inc i
|
||||||
result = s.substr(i)
|
result = s.substr(i)
|
||||||
|
|
||||||
template `--`*(key, val: untyped) = switch(astToStr(key), strip astToStr(val))
|
template `--`*(key, val: untyped) =
|
||||||
template `--`*(key: untyped) = switch(astToStr(key), "")
|
## A shortcut for ``switch(astToStr(key), astToStr(val))``.
|
||||||
|
switch(astToStr(key), strip astToStr(val))
|
||||||
|
|
||||||
|
template `--`*(key: untyped) =
|
||||||
|
## A shortcut for ``switch(astToStr(key)``.
|
||||||
|
switch(astToStr(key), "")
|
||||||
|
|
||||||
type
|
type
|
||||||
ScriptMode* {.pure.} = enum ## Controls the behaviour of the script.
|
ScriptMode* {.pure.} = enum ## Controls the behaviour of the script.
|
||||||
|
|
@ -158,7 +173,8 @@ proc exec*(command: string) =
|
||||||
raise newException(OSError, "FAILED: " & command)
|
raise newException(OSError, "FAILED: " & command)
|
||||||
checkOsError()
|
checkOsError()
|
||||||
|
|
||||||
proc exec*(command: string, input: string, cache = "") =
|
proc exec*(command: string, input: string, cache = "") {.
|
||||||
|
raises: [OSError], tags: [ExecIOEffect].} =
|
||||||
## Executes an external process.
|
## Executes an external process.
|
||||||
log "exec: " & command:
|
log "exec: " & command:
|
||||||
echo staticExec(command, input, cache)
|
echo staticExec(command, input, cache)
|
||||||
|
|
@ -256,3 +272,5 @@ proc requires*(deps: varargs[string]) =
|
||||||
## Nimble support: Call this to set the list of requirements of your Nimble
|
## Nimble support: Call this to set the list of requirements of your Nimble
|
||||||
## package.
|
## package.
|
||||||
for d in deps: requiresData.add(d)
|
for d in deps: requiresData.add(d)
|
||||||
|
|
||||||
|
{.pop.}
|
||||||
|
|
|
||||||
19
tests/ccgbugs/twrong_string_asgn.nim
Normal file
19
tests/ccgbugs/twrong_string_asgn.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
discard """
|
||||||
|
output: "adf"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncdispatch
|
||||||
|
const
|
||||||
|
test = ["adf"]
|
||||||
|
|
||||||
|
proc foo() {.async.} =
|
||||||
|
for i in test:
|
||||||
|
echo(i)
|
||||||
|
|
||||||
|
var finished = false
|
||||||
|
let x = foo()
|
||||||
|
x.callback =
|
||||||
|
proc () =
|
||||||
|
finished = true
|
||||||
|
|
||||||
|
while not finished: discard
|
||||||
16
tests/typerel/typeof_in_template.nim
Normal file
16
tests/typerel/typeof_in_template.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
discard """
|
||||||
|
output: '''@[a, c]'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# bug #3230
|
||||||
|
|
||||||
|
import sequtils
|
||||||
|
|
||||||
|
const
|
||||||
|
test_strings = ["a", "b", "c"]
|
||||||
|
|
||||||
|
proc is_doc(x: string): bool = x == "b"
|
||||||
|
|
||||||
|
let
|
||||||
|
tests = @test_strings.filter_it(not it.is_doc)
|
||||||
|
echo tests
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''(name: hello)'''
|
output: '''(name: hello)
|
||||||
|
(-1, 0)'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# bug #2774
|
# bug #2774, bug #3195
|
||||||
|
|
||||||
type Foo = object
|
type Foo = object
|
||||||
name: string
|
name: string
|
||||||
|
|
@ -12,3 +13,24 @@ const fooArray = [
|
||||||
]
|
]
|
||||||
|
|
||||||
echo fooArray[0]
|
echo fooArray[0]
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
Position = object
|
||||||
|
x, y: int
|
||||||
|
|
||||||
|
proc `$`(pos: Position): string =
|
||||||
|
result = "(" & $pos.x & ", " & $pos.y & ")"
|
||||||
|
|
||||||
|
proc newPos(x, y: int): Position =
|
||||||
|
result = Position(x: x, y: y)
|
||||||
|
|
||||||
|
const
|
||||||
|
offset: array[1..4, Position] = [
|
||||||
|
newPos(-1, 0),
|
||||||
|
newPos(1, 0),
|
||||||
|
newPos(0, -1),
|
||||||
|
newPos(0, 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
echo offset[1]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#! stdtmpl | standard
|
#? stdtmpl | standard
|
||||||
#proc generateHTMLPage(c: var TConfigData, currentTab, content, rss: string): string =
|
#proc generateHTMLPage(c: var TConfigData, currentTab, content, rss: string): string =
|
||||||
# result = ""
|
# result = ""
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
# if t != "index" and t != "community" and t != "news":
|
# if t != "index" and t != "community" and t != "news":
|
||||||
# let name = c.tabs[i].key
|
# let name = c.tabs[i].key
|
||||||
# if currentTab == t:
|
# if currentTab == t:
|
||||||
<a class="active"
|
<a class="active"
|
||||||
# else:
|
# else:
|
||||||
<a
|
<a
|
||||||
# end if
|
# end if
|
||||||
|
|
@ -104,7 +104,7 @@ p.greet() <span class="cmt"># or greet(p)</span>
|
||||||
<span class="cmt"># declare a C procedure..</span>
|
<span class="cmt"># declare a C procedure..</span>
|
||||||
<span class="kwd">proc</span> <span class="def">unsafeScanf</span>(f: <span class="typ">File</span>, s: <span class="typ">cstring</span>)
|
<span class="kwd">proc</span> <span class="def">unsafeScanf</span>(f: <span class="typ">File</span>, s: <span class="typ">cstring</span>)
|
||||||
<span class="tab"> </span>{.varargs,
|
<span class="tab"> </span>{.varargs,
|
||||||
<span class="tab"> </span>importc: <span class="val">"fscanf"</span>,
|
<span class="tab"> </span>importc: <span class="val">"fscanf"</span>,
|
||||||
<span class="tab end"> </span>header: <span class="val">"<stdio.h>"</span>.}
|
<span class="tab end"> </span>header: <span class="val">"<stdio.h>"</span>.}
|
||||||
|
|
||||||
<span class="cmt"># ..and use it...</span>
|
<span class="cmt"># ..and use it...</span>
|
||||||
|
|
@ -191,7 +191,7 @@ runForever()
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
# if currentTab == "index":
|
# if currentTab == "index":
|
||||||
<script src="assets/index.js"></script>
|
<script src="assets/index.js"></script>
|
||||||
# end if
|
# end if
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,8 @@ News
|
||||||
are likely to break as well.
|
are likely to break as well.
|
||||||
- Base methods now need to be annotated with the ``base`` pragma. This makes
|
- Base methods now need to be annotated with the ``base`` pragma. This makes
|
||||||
multi methods less error-prone to use with the effect system.
|
multi methods less error-prone to use with the effect system.
|
||||||
|
- Nim's parser directive ``#!`` is now ``#?`` in order to produce no conflicts
|
||||||
|
with Unix's ``#!``.
|
||||||
|
|
||||||
|
|
||||||
Library Additions
|
Library Additions
|
||||||
|
|
@ -89,7 +91,8 @@ News
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- The compiler now supports a new configuration system based on ``NimScript``.
|
- The compiler now supports a new configuration system based on
|
||||||
|
`NimScript <docs/nims.html>`_.
|
||||||
|
|
||||||
|
|
||||||
Language Additions
|
Language Additions
|
||||||
|
|
@ -106,7 +109,7 @@ News
|
||||||
is allowed. Note that this doesn't declare ``x`` and ``y`` variables, for
|
is allowed. Note that this doesn't declare ``x`` and ``y`` variables, for
|
||||||
this ``let (x, y) == f()`` still needs to be used.
|
this ``let (x, y) == f()`` still needs to be used.
|
||||||
- ``when nimvm`` can now be used for compiletime versions of some code
|
- ``when nimvm`` can now be used for compiletime versions of some code
|
||||||
sections. See (XXX) for details.
|
sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue