Merge branch 'master' of github.com:Araq/Nimrod into upstream
This commit is contained in:
commit
88f7b7bc50
31 changed files with 459 additions and 114 deletions
|
|
@ -145,6 +145,7 @@ type
|
||||||
nkIfStmt, # an if statement
|
nkIfStmt, # an if statement
|
||||||
nkWhenStmt, # a when expression or statement
|
nkWhenStmt, # a when expression or statement
|
||||||
nkForStmt, # a for statement
|
nkForStmt, # a for statement
|
||||||
|
nkParForStmt, # a parallel for statement
|
||||||
nkWhileStmt, # a while statement
|
nkWhileStmt, # a while statement
|
||||||
nkCaseStmt, # a case statement
|
nkCaseStmt, # a case statement
|
||||||
nkTypeSection, # a type section (consists of type definitions)
|
nkTypeSection, # a type section (consists of type definitions)
|
||||||
|
|
@ -396,7 +397,7 @@ type
|
||||||
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
mAnd, mOr, mEqStr, mLeStr, mLtStr, mEqSet, mLeSet, mLtSet, mMulSet,
|
||||||
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
mPlusSet, mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT,
|
||||||
mConTArr, mConTT, mSlice,
|
mConTArr, mConTT, mSlice,
|
||||||
mFields, mFieldPairs,
|
mFields, mFieldPairs, mOmpParFor,
|
||||||
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq,
|
||||||
mIsPartOf, mAstToStr, mRand,
|
mIsPartOf, mAstToStr, mRand,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ proc hasNoInit(call: PNode): bool {.inline.} =
|
||||||
|
|
||||||
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
|
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
|
||||||
var pl = pl
|
var pl = pl
|
||||||
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
# getUniqueType() is too expensive here:
|
||||||
|
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
if isInvalidReturnType(typ.sons[0]):
|
if isInvalidReturnType(typ.sons[0]):
|
||||||
if sonsLen(ri) > 1: app(pl, ", ")
|
if sonsLen(ri) > 1: app(pl, ", ")
|
||||||
|
|
@ -124,7 +125,8 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
# this is a hotspot in the compiler
|
# this is a hotspot in the compiler
|
||||||
initLocExpr(p, ri.sons[0], op)
|
initLocExpr(p, ri.sons[0], op)
|
||||||
var pl = con(op.r, "(")
|
var pl = con(op.r, "(")
|
||||||
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
# getUniqueType() is too expensive here:
|
||||||
|
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
var length = sonsLen(ri)
|
var length = sonsLen(ri)
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
|
|
@ -150,7 +152,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
var op: TLoc
|
var op: TLoc
|
||||||
initLocExpr(p, ri.sons[0], op)
|
initLocExpr(p, ri.sons[0], op)
|
||||||
var pl: PRope
|
var pl: PRope
|
||||||
var typ = ri.sons[0].typ
|
|
||||||
|
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
var length = sonsLen(ri)
|
var length = sonsLen(ri)
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
|
|
@ -201,7 +204,8 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
var op, a: TLoc
|
var op, a: TLoc
|
||||||
initLocExpr(p, ri.sons[0], op)
|
initLocExpr(p, ri.sons[0], op)
|
||||||
var pl: PRope = nil
|
var pl: PRope = nil
|
||||||
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
# getUniqueType() is too expensive here:
|
||||||
|
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
var length = sonsLen(ri)
|
var length = sonsLen(ri)
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
|
|
@ -228,7 +232,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
var op, a: TLoc
|
var op, a: TLoc
|
||||||
initLocExpr(p, ri.sons[0], op)
|
initLocExpr(p, ri.sons[0], op)
|
||||||
var pl = toRope"["
|
var pl = toRope"["
|
||||||
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
|
# getUniqueType() is too expensive here:
|
||||||
|
var typ = skipTypes(ri.sons[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
var length = sonsLen(ri)
|
var length = sonsLen(ri)
|
||||||
assert(sonsLen(typ) == sonsLen(typ.n))
|
assert(sonsLen(typ) == sonsLen(typ.n))
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
|
|
||||||
proc expr(p: BProc, e: PNode, d: var TLoc)
|
proc expr(p: BProc, e: PNode, d: var TLoc)
|
||||||
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
||||||
initLoc(result, locNone, getUniqueType(e.typ), OnUnknown)
|
initLoc(result, locNone, e.typ, OnUnknown)
|
||||||
expr(p, e, result)
|
expr(p, e, result)
|
||||||
|
|
||||||
proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
|
proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
|
||||||
|
|
@ -543,17 +543,17 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
||||||
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
if (e.sons[1].kind != nkSym): InternalError(e.info, "genRecordFieldAux")
|
if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
result = getUniqueType(a.t)
|
result = a.t
|
||||||
|
|
||||||
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
var ty = genRecordFieldAux(p, e, d, a)
|
var ty = genRecordFieldAux(p, e, d, a)
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
var f = e.sons[1].sym
|
var f = e.sons[1].sym
|
||||||
if ty.n == nil:
|
if ty.kind == tyTuple:
|
||||||
# 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
|
||||||
appf(r, ".Field$1", [toRope(f.position)])
|
appf(r, ".Field$1", [toRope(f.position)])
|
||||||
|
|
@ -561,14 +561,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
var field: PSym = nil
|
var field: PSym = nil
|
||||||
while ty != nil:
|
while ty != nil:
|
||||||
if not (ty.kind in {tyTuple, tyObject}):
|
if ty.kind notin {tyTuple, tyObject}:
|
||||||
InternalError(e.info, "genRecordField")
|
InternalError(e.info, "genRecordField")
|
||||||
field = lookupInRecord(ty.n, f.name)
|
field = lookupInRecord(ty.n, f.name)
|
||||||
if field != nil: break
|
if field != nil: break
|
||||||
if gCmd != cmdCompileToCpp: app(r, ".Sup")
|
if gCmd != cmdCompileToCpp: app(r, ".Sup")
|
||||||
ty = GetUniqueType(ty.sons[0])
|
ty = GetUniqueType(ty.sons[0])
|
||||||
if field == nil: InternalError(e.info, "genRecordField")
|
if field == nil: InternalError(e.info, "genRecordField 2 ")
|
||||||
if field.loc.r == nil: InternalError(e.info, "genRecordField")
|
if field.loc.r == nil: InternalError(e.info, "genRecordField 3")
|
||||||
appf(r, ".$1", [field.loc.r])
|
appf(r, ".$1", [field.loc.r])
|
||||||
putIntoDest(p, d, field.typ, r)
|
putIntoDest(p, d, field.typ, r)
|
||||||
|
|
||||||
|
|
@ -579,16 +579,17 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
if d.k == locNone: d.s = a.s
|
if d.k == locNone: d.s = a.s
|
||||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
var ty = getUniqueType(a.t)
|
var ty = a.t
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
case e.sons[1].kind
|
case e.sons[1].kind
|
||||||
of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
|
of nkIntLit..nkInt64Lit: i = int(e.sons[1].intVal)
|
||||||
else: internalError(e.info, "genTupleElem")
|
else: internalError(e.info, "genTupleElem")
|
||||||
if ty.n != nil:
|
when false:
|
||||||
var field = ty.n.sons[i].sym
|
if ty.n != nil:
|
||||||
if field == nil: InternalError(e.info, "genTupleElem")
|
var field = ty.n.sons[i].sym
|
||||||
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
if field == nil: InternalError(e.info, "genTupleElem")
|
||||||
appf(r, ".$1", [field.loc.r])
|
if field.loc.r == nil: InternalError(e.info, "genTupleElem")
|
||||||
|
appf(r, ".$1", [field.loc.r])
|
||||||
else:
|
else:
|
||||||
appf(r, ".Field$1", [toRope(i)])
|
appf(r, ".Field$1", [toRope(i)])
|
||||||
putIntoDest(p, d, ty.sons[i], r)
|
putIntoDest(p, d, ty.sons[i], r)
|
||||||
|
|
@ -1510,11 +1511,10 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr: it = it.sons[1]
|
if it.kind == nkExprColonExpr: it = it.sons[1]
|
||||||
if t.n == nil:
|
initLoc(rec, locExpr, it.typ, d.s)
|
||||||
initLoc(rec, locExpr, it.typ, d.s)
|
rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
|
||||||
rec.r = ropef("$1.Field$2", [rdLoc(d), toRope(i)])
|
expr(p, it, rec)
|
||||||
expr(p, it, rec)
|
when false:
|
||||||
else:
|
|
||||||
initLoc(rec, locExpr, it.typ, d.s)
|
initLoc(rec, locExpr, it.typ, d.s)
|
||||||
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
|
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genTupleConstr")
|
||||||
rec.r = ropef("$1.$2",
|
rec.r = ropef("$1.$2",
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
assignLocalVar(p, v)
|
assignLocalVar(p, v)
|
||||||
initLocalVar(p, v, immediateAsgn=true)
|
initLocalVar(p, v, immediateAsgn=true)
|
||||||
initLoc(field, locExpr, t.sons[i], tup.s)
|
initLoc(field, locExpr, t.sons[i], tup.s)
|
||||||
if t.n == nil:
|
if t.kind == tyTuple:
|
||||||
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
||||||
else:
|
else:
|
||||||
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
|
if (t.n.sons[i].kind != nkSym): InternalError(n.info, "genVarTuple")
|
||||||
|
|
@ -258,6 +258,34 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
|
||||||
else: genStmts(p, t.sons[1])
|
else: genStmts(p, t.sons[1])
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
|
proc genParForStmt(p: BProc, t: PNode) =
|
||||||
|
assert(sonsLen(t) == 3)
|
||||||
|
inc(p.withinLoop)
|
||||||
|
genLineDir(p, t)
|
||||||
|
|
||||||
|
preserveBreakIdx:
|
||||||
|
let forLoopVar = t.sons[0].sym
|
||||||
|
var rangeA, rangeB: TLoc
|
||||||
|
assignLocalVar(P, forLoopVar)
|
||||||
|
#initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
|
||||||
|
#discard mangleName(forLoopVar)
|
||||||
|
let call = t.sons[1]
|
||||||
|
initLocExpr(p, call.sons[1], rangeA)
|
||||||
|
initLocExpr(p, call.sons[2], rangeB)
|
||||||
|
|
||||||
|
appf(p.s(cpsStmts), "#pragma omp parallel for $4$n" &
|
||||||
|
"for ($1 = $2; $1 <= $3; ++$1)",
|
||||||
|
forLoopVar.loc.rdLoc,
|
||||||
|
rangeA.rdLoc, rangeB.rdLoc,
|
||||||
|
call.sons[3].getStr.toRope)
|
||||||
|
|
||||||
|
p.breakIdx = startBlock(p)
|
||||||
|
p.blocks[p.breakIdx].isLoop = true
|
||||||
|
genStmts(p, t.sons[2])
|
||||||
|
endBlock(p)
|
||||||
|
|
||||||
|
dec(p.withinLoop)
|
||||||
|
|
||||||
proc genBreakStmt(p: BProc, t: PNode) =
|
proc genBreakStmt(p: BProc, t: PNode) =
|
||||||
var idx = p.breakIdx
|
var idx = p.breakIdx
|
||||||
if t.sons[0].kind != nkEmpty:
|
if t.sons[0].kind != nkEmpty:
|
||||||
|
|
@ -815,5 +843,6 @@ proc genStmts(p: BProc, t: PNode) =
|
||||||
# we have not only the header:
|
# we have not only the header:
|
||||||
if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags:
|
if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags:
|
||||||
genProc(p.module, prc)
|
genProc(p.module, prc)
|
||||||
|
of nkParForStmt: genParForStmt(p, t)
|
||||||
else: internalError(t.info, "genStmts(" & $t.kind & ')')
|
else: internalError(t.info, "genStmts(" & $t.kind & ')')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ proc mapSetType(typ: PType): TCTypeKind =
|
||||||
|
|
||||||
proc mapType(typ: PType): TCTypeKind =
|
proc mapType(typ: PType): TCTypeKind =
|
||||||
case typ.kind
|
case typ.kind
|
||||||
of tyNone: result = ctVoid
|
of tyNone, tyStmt: result = ctVoid
|
||||||
of tyBool: result = ctBool
|
of tyBool: result = ctBool
|
||||||
of tyChar: result = ctChar
|
of tyChar: result = ctChar
|
||||||
of tySet: result = mapSetType(typ)
|
of tySet: result = mapSetType(typ)
|
||||||
|
|
@ -561,7 +561,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
||||||
appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
|
appf(m.s[cfsForwardTypes], getForwardStructFormat(), [result])
|
||||||
IdTablePut(m.forwTypeCache, t, result)
|
IdTablePut(m.forwTypeCache, t, result)
|
||||||
IdTablePut(m.typeCache, t, result) # always call for sideeffects:
|
IdTablePut(m.typeCache, t, result) # always call for sideeffects:
|
||||||
if t.n != nil: recdesc = getRecordDesc(m, t, result, check)
|
if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check)
|
||||||
else: recdesc = getTupleDesc(m, t, result, check)
|
else: recdesc = getTupleDesc(m, t, result, check)
|
||||||
if not isImportedType(t): app(m.s[cfsTypes], recdesc)
|
if not isImportedType(t): app(m.s[cfsTypes], recdesc)
|
||||||
of tySet:
|
of tySet:
|
||||||
|
|
@ -889,8 +889,11 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||||
of tyEnum: genEnumInfo(gNimDat, t, result)
|
of tyEnum: genEnumInfo(gNimDat, t, result)
|
||||||
of tyObject: genObjectInfo(gNimDat, t, result)
|
of tyObject: genObjectInfo(gNimDat, t, result)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if t.n != nil: genObjectInfo(gNimDat, t, result)
|
# if t.n != nil: genObjectInfo(gNimDat, t, result)
|
||||||
else: genTupleInfo(gNimDat, t, result)
|
# else:
|
||||||
|
# BUGFIX: use consistently RTTI without proper field names; otherwise
|
||||||
|
# results are not deterministic!
|
||||||
|
genTupleInfo(gNimDat, t, result)
|
||||||
else: InternalError("genTypeInfo(" & $t.kind & ')')
|
else: InternalError("genTypeInfo(" & $t.kind & ')')
|
||||||
|
|
||||||
proc genTypeSection(m: BModule, n: PNode) =
|
proc genTypeSection(m: BModule, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -87,14 +87,19 @@ proc GetUniqueType*(key: PType): PType =
|
||||||
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
of tyGenericInst, tyDistinct, tyOrdinal, tyMutable, tyConst, tyIter:
|
||||||
result = GetUniqueType(lastSon(key))
|
result = GetUniqueType(lastSon(key))
|
||||||
of tyArrayConstr, tyGenericInvokation, tyGenericBody,
|
of tyArrayConstr, tyGenericInvokation, tyGenericBody,
|
||||||
tyOpenArray, tyArray, tyTuple, tySet, tyRange,
|
tyOpenArray, tyArray, tySet, tyRange, tyTuple,
|
||||||
tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
|
tyPtr, tyRef, tySequence, tyForward, tyVarargs, tyProxy, tyVar:
|
||||||
|
# tuples are quite horrible as C does not support them directly and
|
||||||
|
# tuple[string, string] is a (strange) subtype of
|
||||||
|
# tuple[nameA, nameB: string]. This bites us here, so we
|
||||||
|
# use 'sameBackendType' instead of 'sameType'.
|
||||||
|
|
||||||
# we have to do a slow linear search because types may need
|
# we have to do a slow linear search because types may need
|
||||||
# to be compared by their structure:
|
# to be compared by their structure:
|
||||||
if IdTableHasObjectAsKey(gTypeTable[k], key): return key
|
if IdTableHasObjectAsKey(gTypeTable[k], key): return key
|
||||||
for h in countup(0, high(gTypeTable[k].data)):
|
for h in countup(0, high(gTypeTable[k].data)):
|
||||||
var t = PType(gTypeTable[k].data[h].key)
|
var t = PType(gTypeTable[k].data[h].key)
|
||||||
if t != nil and sameType(t, key):
|
if t != nil and sameBackendType(t, key):
|
||||||
return t
|
return t
|
||||||
IdTablePut(gTypeTable[k], key, key)
|
IdTablePut(gTypeTable[k], key, key)
|
||||||
result = key
|
result = key
|
||||||
|
|
|
||||||
|
|
@ -1343,7 +1343,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||||
of nkWhileStmt: genWhileStmt(p, n, r)
|
of nkWhileStmt: genWhileStmt(p, n, r)
|
||||||
of nkVarSection, nkLetSection: genVarStmt(p, n, r)
|
of nkVarSection, nkLetSection: genVarStmt(p, n, r)
|
||||||
of nkConstSection: genConstStmt(p, n, r)
|
of nkConstSection: genConstStmt(p, n, r)
|
||||||
of nkForStmt: internalError(n.info, "for statement not eliminated")
|
of nkForStmt, nkParForStmt:
|
||||||
|
internalError(n.info, "for statement not eliminated")
|
||||||
of nkCaseStmt: genCaseStmt(p, n, r)
|
of nkCaseStmt: genCaseStmt(p, n, r)
|
||||||
of nkReturnStmt: genReturnStmt(p, n, r)
|
of nkReturnStmt: genReturnStmt(p, n, r)
|
||||||
of nkBreakStmt: genBreakStmt(p, n, r)
|
of nkBreakStmt: genBreakStmt(p, n, r)
|
||||||
|
|
|
||||||
|
|
@ -1331,7 +1331,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||||
of nkPragmaBlock:
|
of nkPragmaBlock:
|
||||||
result = evalAux(c, n.sons[1], flags)
|
result = evalAux(c, n.sons[1], flags)
|
||||||
of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr,
|
of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr,
|
||||||
nkLambdaKinds, nkContinueStmt, nkIdent:
|
nkLambdaKinds, nkContinueStmt, nkIdent, nkParForStmt:
|
||||||
result = raiseCannotEval(c, n.info)
|
result = raiseCannotEval(c, n.info)
|
||||||
of nkRefTy:
|
of nkRefTy:
|
||||||
result = evalAux(c, n.sons[0], flags)
|
result = evalAux(c, n.sons[0], flags)
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,19 @@ proc considerAcc*(n: PNode): PIdent =
|
||||||
case n.len
|
case n.len
|
||||||
of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
of 1: result = considerAcc(n.sons[0])
|
of 1: result = considerAcc(n.sons[0])
|
||||||
of 2:
|
else:
|
||||||
if n[0].ident.id == ord(wStar):
|
if n.len == 2 and n[0].kind == nkIdent and n[0].ident.id == ord(wStar):
|
||||||
|
# XXX find a better way instead of `*x` for 'genSym'
|
||||||
result = genSym(n[1].ident.s)
|
result = genSym(n[1].ident.s)
|
||||||
else:
|
else:
|
||||||
result = getIdent(n[0].ident.s & n[1].ident.s)
|
var id = ""
|
||||||
else:
|
for i in 0.. <n.len:
|
||||||
var id = ""
|
let x = n.sons[i]
|
||||||
for i in 0.. <n.len:
|
case x.kind
|
||||||
if n.sons[i].kind != nkIdent:
|
of nkIdent: id.add(x.ident.s)
|
||||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
of nkSym: id.add(x.sym.name.s)
|
||||||
id.add(n.sons[i].ident.s)
|
else: GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
result = getIdent(id)
|
result = getIdent(id)
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -984,7 +984,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
of nkCaseStmt, nkRecCase: gcase(g, n)
|
of nkCaseStmt, nkRecCase: gcase(g, n)
|
||||||
of nkMacroStmt: gmacro(g, n)
|
of nkMacroStmt: gmacro(g, n)
|
||||||
of nkTryStmt: gtry(g, n)
|
of nkTryStmt: gtry(g, n)
|
||||||
of nkForStmt: gfor(g, n)
|
of nkForStmt, nkParForStmt: gfor(g, n)
|
||||||
of nkBlockStmt, nkBlockExpr: gblock(g, n)
|
of nkBlockStmt, nkBlockExpr: gblock(g, n)
|
||||||
of nkStaticStmt: gstaticStmt(g, n)
|
of nkStaticStmt: gstaticStmt(g, n)
|
||||||
of nkAsmStmt: gasm(g, n)
|
of nkAsmStmt: gasm(g, n)
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
a.sons[j] = semGenericStmt(c, a.sons[j], flags, toBind)
|
a.sons[j] = semGenericStmt(c, a.sons[j], flags, toBind)
|
||||||
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind)
|
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, toBind)
|
||||||
closeScope(c.tab)
|
closeScope(c.tab)
|
||||||
of nkForStmt:
|
of nkForStmt, nkParForStmt:
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
openScope(c.tab)
|
openScope(c.tab)
|
||||||
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, toBind)
|
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, toBind)
|
||||||
|
|
|
||||||
|
|
@ -465,7 +465,11 @@ proc semFor(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
GlobalError(n.sons[length - 2].info, errIteratorExpected)
|
GlobalError(n.sons[length - 2].info, errIteratorExpected)
|
||||||
elif call.sons[0].sym.magic != mNone:
|
elif call.sons[0].sym.magic != mNone:
|
||||||
result = semForFields(c, n, call.sons[0].sym.magic)
|
if call.sons[0].sym.magic == mOmpParFor:
|
||||||
|
result = semForVars(c, n)
|
||||||
|
result.kind = nkParForStmt
|
||||||
|
else:
|
||||||
|
result = semForFields(c, n, call.sons[0].sym.magic)
|
||||||
else:
|
else:
|
||||||
result = semForVars(c, n)
|
result = semForVars(c, n)
|
||||||
closeScope(c.tab)
|
closeScope(c.tab)
|
||||||
|
|
@ -979,7 +983,7 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||||
of nkWhileStmt: result = semWhile(c, n)
|
of nkWhileStmt: result = semWhile(c, n)
|
||||||
of nkTryStmt: result = semTry(c, n)
|
of nkTryStmt: result = semTry(c, n)
|
||||||
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
of nkBreakStmt, nkContinueStmt: result = semBreakOrContinue(c, n)
|
||||||
of nkForStmt: result = semFor(c, n)
|
of nkForStmt, nkParForStmt: result = semFor(c, n)
|
||||||
of nkCaseStmt: result = semCase(c, n)
|
of nkCaseStmt: result = semCase(c, n)
|
||||||
of nkReturnStmt: result = semReturn(c, n)
|
of nkReturnStmt: result = semReturn(c, n)
|
||||||
of nkAsmStmt: result = semAsm(c, n)
|
of nkAsmStmt: result = semAsm(c, n)
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
|
||||||
|
|
||||||
proc hasContinue(n: PNode): bool =
|
proc hasContinue(n: PNode): bool =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
|
of nkEmpty..nkNilLit, nkForStmt, nkParForStmt, nkWhileStmt: nil
|
||||||
of nkContinueStmt: result = true
|
of nkContinueStmt: result = true
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
|
@ -659,6 +659,10 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||||
inc c.inLoop
|
inc c.inLoop
|
||||||
result = transformFor(c, n)
|
result = transformFor(c, n)
|
||||||
dec c.inLoop
|
dec c.inLoop
|
||||||
|
of nkParForStmt:
|
||||||
|
inc c.inLoop
|
||||||
|
result = transformSons(c, n)
|
||||||
|
dec c.inLoop
|
||||||
of nkCaseStmt: result = transformCase(c, n)
|
of nkCaseStmt: result = transformCase(c, n)
|
||||||
of nkContinueStmt:
|
of nkContinueStmt:
|
||||||
result = PTransNode(newNode(nkBreakStmt))
|
result = PTransNode(newNode(nkBreakStmt))
|
||||||
|
|
|
||||||
|
|
@ -550,6 +550,7 @@ type
|
||||||
|
|
||||||
TSameTypeClosure = object {.pure.}
|
TSameTypeClosure = object {.pure.}
|
||||||
cmp: TDistinctCompare
|
cmp: TDistinctCompare
|
||||||
|
ignoreTupleFields: bool
|
||||||
recCheck: int
|
recCheck: int
|
||||||
s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
|
s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
|
||||||
# (few elements expected)
|
# (few elements expected)
|
||||||
|
|
@ -645,7 +646,7 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
|
||||||
for i in countup(0, sonsLen(a) - 1):
|
for i in countup(0, sonsLen(a) - 1):
|
||||||
result = SameTypeAux(a.sons[i], b.sons[i], c)
|
result = SameTypeAux(a.sons[i], b.sons[i], c)
|
||||||
if not result: return
|
if not result: return
|
||||||
if a.n != nil and b.n != nil:
|
if a.n != nil and b.n != nil and not c.ignoreTupleFields:
|
||||||
for i in countup(0, sonsLen(a.n) - 1):
|
for i in countup(0, sonsLen(a.n) - 1):
|
||||||
# check field names:
|
# check field names:
|
||||||
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
|
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
|
||||||
|
|
@ -787,6 +788,11 @@ proc SameType*(x, y: PType): bool =
|
||||||
var c = initSameTypeClosure()
|
var c = initSameTypeClosure()
|
||||||
result = sameTypeAux(x, y, c)
|
result = sameTypeAux(x, y, c)
|
||||||
|
|
||||||
|
proc sameBackendType*(x, y: PType): bool =
|
||||||
|
var c = initSameTypeClosure()
|
||||||
|
c.ignoreTupleFields = true
|
||||||
|
result = sameTypeAux(x, y, c)
|
||||||
|
|
||||||
proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
|
proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool =
|
||||||
## compares two type for equality (modulo type distinction)
|
## compares two type for equality (modulo type distinction)
|
||||||
var c = initSameTypeClosure()
|
var c = initSameTypeClosure()
|
||||||
|
|
@ -863,8 +869,9 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
result = typeAllowedAux(marker, t.sons[0], skResult)
|
result = typeAllowedAux(marker, t.sons[0], skResult)
|
||||||
of tyExpr, tyStmt, tyTypeDesc:
|
of tyExpr, tyStmt, tyTypeDesc:
|
||||||
result = true
|
result = true
|
||||||
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation, tyTypeClass:
|
of tyGenericBody, tyGenericParam, tyForward, tyNone, tyGenericInvokation,
|
||||||
result = false #InternalError('shit found');
|
tyTypeClass:
|
||||||
|
result = false
|
||||||
of tyEmpty, tyNil:
|
of tyEmpty, tyNil:
|
||||||
result = kind == skConst
|
result = kind == skConst
|
||||||
of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer:
|
of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer:
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ hint[LineTooLong]=off
|
||||||
|
|
||||||
@if unix:
|
@if unix:
|
||||||
@if not bsd:
|
@if not bsd:
|
||||||
|
# -fopenmp
|
||||||
gcc.options.linker = "-ldl"
|
gcc.options.linker = "-ldl"
|
||||||
clang.options.linker = "-ldl"
|
clang.options.linker = "-ldl"
|
||||||
tcc.options.linker = "-ldl"
|
tcc.options.linker = "-ldl"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ type
|
||||||
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
|
||||||
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
|
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
|
||||||
nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt,
|
nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt,
|
||||||
nnkForStmt, nnkWhileStmt, nnkCaseStmt,
|
nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkCaseStmt,
|
||||||
nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection,
|
nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection,
|
||||||
nnkConstDef, nnkTypeDef,
|
nnkConstDef, nnkTypeDef,
|
||||||
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
|
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
|
||||||
|
|
@ -217,10 +217,19 @@ template emit*(s: expr): stmt =
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||||
##
|
##
|
||||||
block:
|
block:
|
||||||
const evaluated = s
|
const evaluated = s
|
||||||
eval: result = evaluated.parseStmt
|
eval: result = evaluated.parseStmt
|
||||||
|
when false:
|
||||||
|
template once(x: expr): expr =
|
||||||
|
block:
|
||||||
|
const y = x
|
||||||
|
y
|
||||||
|
|
||||||
|
macro `payload`(x: stmt): stmt = result = once(s).parseStmt
|
||||||
|
`payload`()
|
||||||
|
|
||||||
|
|
||||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||||
## checks that `n` is of kind `k`. If this is not the case,
|
## checks that `n` is of kind `k`. If this is not the case,
|
||||||
|
|
@ -323,7 +332,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||||
|
|
||||||
macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
||||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||||
## tree using the `toTree` function.
|
## tree using the `toTree` function. Printing is done *at compile time*.
|
||||||
##
|
##
|
||||||
## You can use this as a tool to explore the Nimrod's abstract syntax
|
## You can use this as a tool to explore the Nimrod's abstract syntax
|
||||||
## tree and to discover what kind of nodes must be created to represent
|
## tree and to discover what kind of nodes must be created to represent
|
||||||
|
|
@ -331,7 +340,7 @@ macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
||||||
|
|
||||||
macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr
|
macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr
|
||||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||||
## tree using the `toLisp` function.
|
## tree using the `toLisp` function. Printing is done *at compile time*.
|
||||||
##
|
##
|
||||||
## See `dumpTree`.
|
## See `dumpTree`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,8 @@ proc setBiggestFloat*(x: TAny, y: biggestFloat) =
|
||||||
proc getString*(x: TAny): string =
|
proc getString*(x: TAny): string =
|
||||||
## retrieve the string value out of `x`. `x` needs to represent a string.
|
## retrieve the string value out of `x`. `x` needs to represent a string.
|
||||||
assert x.rawtype.kind == tyString
|
assert x.rawtype.kind == tyString
|
||||||
result = cast[ptr string](x.value)[]
|
if not isNil(cast[ptr pointer](x.value)[]):
|
||||||
|
result = cast[ptr string](x.value)[]
|
||||||
|
|
||||||
proc setString*(x: TAny, y: string) =
|
proc setString*(x: TAny, y: string) =
|
||||||
## sets the string value of `x`. `x` needs to represent a string.
|
## sets the string value of `x`. `x` needs to represent a string.
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,11 @@ type
|
||||||
mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
|
mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
|
||||||
TWeekDay* = enum ## represents a weekday
|
TWeekDay* = enum ## represents a weekday
|
||||||
dMon, dTue, dWed, dThu, dFri, dSat, dSun
|
dMon, dTue, dWed, dThu, dFri, dSat, dSun
|
||||||
|
|
||||||
|
var
|
||||||
|
timezone {.importc, header: "<time.h>".}: int
|
||||||
|
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
|
||||||
|
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
type
|
type
|
||||||
TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
|
TTimeImpl {.importc: "time_t", header: "<sys/time.h>".} = int
|
||||||
|
|
@ -112,6 +116,20 @@ type
|
||||||
yearday*: range[0..365] ## The number of days since January 1,
|
yearday*: range[0..365] ## The number of days since January 1,
|
||||||
## in the range 0 to 365.
|
## in the range 0 to 365.
|
||||||
## Always 0 if the target is ECMAScript.
|
## Always 0 if the target is ECMAScript.
|
||||||
|
isDST*: bool ## Determines whether DST is in effect. Always
|
||||||
|
## ``False`` if time is UTC.
|
||||||
|
tzname*: string ## The timezone this time is in. E.g. GMT
|
||||||
|
timezone*: int ## The offset of the (non-DST) timezone in seconds
|
||||||
|
## west of UTC.
|
||||||
|
|
||||||
|
TTimeInterval* = object
|
||||||
|
miliseconds*: int ## The number of miliseconds
|
||||||
|
seconds*: int ## The number of seconds
|
||||||
|
minutes*: int ## The number of minutes
|
||||||
|
hours*: int ## The number of hours
|
||||||
|
days*: int ## The number of days
|
||||||
|
months*: int ## The number of months
|
||||||
|
years*: int ## The number of years
|
||||||
|
|
||||||
proc getTime*(): TTime ## gets the current calendar time
|
proc getTime*(): TTime ## gets the current calendar time
|
||||||
proc getLocalTime*(t: TTime): TTimeInfo
|
proc getLocalTime*(t: TTime): TTimeInfo
|
||||||
|
|
@ -122,7 +140,7 @@ proc getGMTime*(t: TTime): TTimeInfo
|
||||||
## expressed in Coordinated Universal Time (UTC).
|
## expressed in Coordinated Universal Time (UTC).
|
||||||
|
|
||||||
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
|
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
|
||||||
## converts a broken-down time structure, expressed as local time, to
|
## converts a broken-down time structure to
|
||||||
## calendar time representation. The function ignores the specified
|
## calendar time representation. The function ignores the specified
|
||||||
## contents of the structure members `weekday` and `yearday` and recomputes
|
## contents of the structure members `weekday` and `yearday` and recomputes
|
||||||
## them from the other information in the broken-down time structure.
|
## them from the other information in the broken-down time structure.
|
||||||
|
|
@ -146,10 +164,90 @@ proc `<=` * (a, b: TTime): bool {.
|
||||||
## returns true iff ``a <= b``.
|
## returns true iff ``a <= b``.
|
||||||
result = a - b <= 0
|
result = a - b <= 0
|
||||||
|
|
||||||
|
proc getTzname*(): tuple[nonDST, DST: string]
|
||||||
|
## returns the local timezone; ``nonDST`` is the name of the local non-DST
|
||||||
|
## timezone, ``DST`` is the name of the local DST timezone.
|
||||||
|
|
||||||
|
proc getTimezone*(): int
|
||||||
|
## returns the offset of the local (non-DST) timezone in seconds west of UTC.
|
||||||
|
|
||||||
proc getStartMilsecs*(): int {.deprecated.}
|
proc getStartMilsecs*(): int {.deprecated.}
|
||||||
## get the miliseconds from the start of the program. **Deprecated since
|
## get the miliseconds from the start of the program. **Deprecated since
|
||||||
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
|
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
|
||||||
|
|
||||||
|
proc newInterval*(miliseconds, seconds, minutes, hours, days, months,
|
||||||
|
years: int = 0): TTimeInterval =
|
||||||
|
## creates a new ``TTimeInterval``.
|
||||||
|
result.miliseconds = miliseconds
|
||||||
|
result.seconds = seconds
|
||||||
|
result.minutes = minutes
|
||||||
|
result.hours = hours
|
||||||
|
result.days = days
|
||||||
|
result.months = months
|
||||||
|
result.years = years
|
||||||
|
|
||||||
|
proc isLeapYear(year: int): bool =
|
||||||
|
if year mod 400 == 0:
|
||||||
|
return true
|
||||||
|
elif year mod 100 == 0:
|
||||||
|
return false
|
||||||
|
elif year mod 4 == 0:
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc getDaysInMonth(month: TMonth, year: int): int =
|
||||||
|
# http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
|
||||||
|
if month == mFeb: # Feb
|
||||||
|
if isLeapYear(year):
|
||||||
|
result = 29
|
||||||
|
else:
|
||||||
|
result = 28
|
||||||
|
elif month in [mApr, mJun, mSep, mNov]: result = 30
|
||||||
|
else: result = 31
|
||||||
|
|
||||||
|
proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
|
||||||
|
var anew = a
|
||||||
|
var newinterv = interval
|
||||||
|
result = 0.0
|
||||||
|
|
||||||
|
newinterv.months += interval.years * 12
|
||||||
|
var curMonth = anew.month
|
||||||
|
for mth in 1 .. newinterv.months:
|
||||||
|
result += float(getDaysInMonth(curMonth, anew.year) * 24 * 60 * 60)
|
||||||
|
if curMonth == mDec:
|
||||||
|
curMonth = mJan
|
||||||
|
anew.year.inc()
|
||||||
|
else:
|
||||||
|
curMonth.inc()
|
||||||
|
result += float(newinterv.days * 24 * 60 * 60)
|
||||||
|
result += float(newinterv.minutes * 60 * 60)
|
||||||
|
result += newinterv.seconds.float
|
||||||
|
result += newinterv.miliseconds / 1000
|
||||||
|
|
||||||
|
proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
||||||
|
## adds ``interval`` time.
|
||||||
|
##
|
||||||
|
## **Note:** This has been only briefly tested and it may not be very accurate.
|
||||||
|
let t = timeInfoToTime(a)
|
||||||
|
var secs = calculateSeconds(a, interval)
|
||||||
|
if a.tzname == "UTC":
|
||||||
|
result = getGMTime(TTime(float(t) + secs))
|
||||||
|
else:
|
||||||
|
result = getLocalTime(TTime(float(t) + secs))
|
||||||
|
|
||||||
|
proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
||||||
|
## subtracts ``interval`` time.
|
||||||
|
##
|
||||||
|
## **Note:** This has been only briefly tested, it is inaccurate especially
|
||||||
|
## when you subtract so much that you reach the Julian calendar.
|
||||||
|
let t = timeInfoToTime(a)
|
||||||
|
var secs = calculateSeconds(a, interval)
|
||||||
|
if a.tzname == "UTC":
|
||||||
|
result = getGMTime(TTime(float(t) - secs))
|
||||||
|
else:
|
||||||
|
result = getLocalTime(TTime(float(t) - secs))
|
||||||
|
|
||||||
when not defined(ECMAScript):
|
when not defined(ECMAScript):
|
||||||
proc epochTime*(): float {.rtl, extern: "nt$1".}
|
proc epochTime*(): float {.rtl, extern: "nt$1".}
|
||||||
## gets time after the UNIX epoch (1970) in seconds. It is a float
|
## gets time after the UNIX epoch (1970) in seconds. It is a float
|
||||||
|
|
@ -169,7 +267,8 @@ when not defined(ECMAScript):
|
||||||
## doWork()
|
## doWork()
|
||||||
## echo "CPU time [s] ", cpuTime() - t0
|
## echo "CPU time [s] ", cpuTime() - t0
|
||||||
|
|
||||||
when not defined(ECMAScript):
|
when not defined(ECMAScript):
|
||||||
|
|
||||||
# C wrapper:
|
# C wrapper:
|
||||||
type
|
type
|
||||||
structTM {.importc: "struct tm", final.} = object
|
structTM {.importc: "struct tm", final.} = object
|
||||||
|
|
@ -205,7 +304,7 @@ when not defined(ECMAScript):
|
||||||
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
||||||
|
|
||||||
# our own procs on top of that:
|
# our own procs on top of that:
|
||||||
proc tmToTimeInfo(tm: structTM): TTimeInfo =
|
proc tmToTimeInfo(tm: structTM, local: bool): TTimeInfo =
|
||||||
const
|
const
|
||||||
weekDays: array [0..6, TWeekDay] = [
|
weekDays: array [0..6, TWeekDay] = [
|
||||||
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
||||||
|
|
@ -217,6 +316,18 @@ when not defined(ECMAScript):
|
||||||
result.year = tm.year + 1900'i32
|
result.year = tm.year + 1900'i32
|
||||||
result.weekday = weekDays[int(tm.weekDay)]
|
result.weekday = weekDays[int(tm.weekDay)]
|
||||||
result.yearday = int(tm.yearday)
|
result.yearday = int(tm.yearday)
|
||||||
|
result.isDST = tm.isDST > 0
|
||||||
|
#result.tzname = if local: getTzname()[if result.isDST: 0 else: 1] else: "UTC"
|
||||||
|
# TODO: ^^^ Crashes the compiler.
|
||||||
|
if local:
|
||||||
|
if result.isDST:
|
||||||
|
result.tzname = getTzname()[0]
|
||||||
|
if not result.isDST:
|
||||||
|
result.tzname = getTzname()[1]
|
||||||
|
else:
|
||||||
|
result.tzname = "UTC"
|
||||||
|
|
||||||
|
result.timezone = if local: getTimezone() else: 0
|
||||||
|
|
||||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||||
const
|
const
|
||||||
|
|
@ -229,7 +340,7 @@ when not defined(ECMAScript):
|
||||||
result.year = t.year - 1900
|
result.year = t.year - 1900
|
||||||
result.weekday = weekDays[t.weekDay]
|
result.weekday = weekDays[t.weekDay]
|
||||||
result.yearday = t.yearday
|
result.yearday = t.yearday
|
||||||
result.isdst = -1
|
result.isdst = if t.isDST: 1 else: 0
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
proc `-` (a, b: TTime): int64 =
|
proc `-` (a, b: TTime): int64 =
|
||||||
|
|
@ -251,13 +362,13 @@ when not defined(ECMAScript):
|
||||||
proc getTime(): TTime = return timec(nil)
|
proc getTime(): TTime = return timec(nil)
|
||||||
proc getLocalTime(t: TTime): TTimeInfo =
|
proc getLocalTime(t: TTime): TTimeInfo =
|
||||||
var a = t
|
var a = t
|
||||||
result = tmToTimeInfo(localtime(addr(a))[])
|
result = tmToTimeInfo(localtime(addr(a))[], true)
|
||||||
# copying is needed anyway to provide reentrancity; thus
|
# copying is needed anyway to provide reentrancity; thus
|
||||||
# the convertion is not expensive
|
# the convertion is not expensive
|
||||||
|
|
||||||
proc getGMTime(t: TTime): TTimeInfo =
|
proc getGMTime(t: TTime): TTimeInfo =
|
||||||
var a = t
|
var a = t
|
||||||
result = tmToTimeInfo(gmtime(addr(a))[])
|
result = tmToTimeInfo(gmtime(addr(a))[], false)
|
||||||
# copying is needed anyway to provide reentrancity; thus
|
# copying is needed anyway to provide reentrancity; thus
|
||||||
# the convertion is not expensive
|
# the convertion is not expensive
|
||||||
|
|
||||||
|
|
@ -294,7 +405,13 @@ when not defined(ECMAScript):
|
||||||
proc winTimeToUnixTime*(t: int64): TTime =
|
proc winTimeToUnixTime*(t: int64): TTime =
|
||||||
## converts a Windows time to a UNIX `TTime` (``time_t``)
|
## converts a Windows time to a UNIX `TTime` (``time_t``)
|
||||||
result = TTime((t - epochDiff) div rateDiff)
|
result = TTime((t - epochDiff) div rateDiff)
|
||||||
|
|
||||||
|
proc getTzname(): tuple[nonDST, DST: string] =
|
||||||
|
return ($tzname[0], $tzname[1])
|
||||||
|
|
||||||
|
proc getTimezone(): int =
|
||||||
|
return timezone
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
proc epochTime(): float =
|
proc epochTime(): float =
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
|
|
@ -417,18 +534,21 @@ proc format*(info: TTimeInfo, f: string): string =
|
||||||
## tt Same as above, but ``AM`` and ``PM`` instead of ``A`` and ``P`` respectively.
|
## tt Same as above, but ``AM`` and ``PM`` instead of ``A`` and ``P`` respectively.
|
||||||
## y(yyyy) This displays the year to different digits. You most likely only want 2 or 4 'y's
|
## y(yyyy) This displays the year to different digits. You most likely only want 2 or 4 'y's
|
||||||
## yy Displays the year to two digits. ``2012 -> 12``
|
## yy Displays the year to two digits. ``2012 -> 12``
|
||||||
## yyyy Displays the year to four digits. ``2012 -> 2012``
|
## yyyy Displays the year to four digits. ``2012 -> 2012``
|
||||||
|
## z Displays the timezone offset from UTC. ``GMT+7 -> +7``, ``GMT-5 -> -5``
|
||||||
|
## zz Same as above but with leading 0. ``GMT+7 -> +07``, ``GMT-5 -> -05``
|
||||||
|
## zzz Same as above but with ``:00``. ``GMT+7 -> +07:00``, ``GMT-5 -> -05:00``
|
||||||
|
## ZZZ Displays the name of the timezone. ``GMT -> GMT``, ``EST -> EST``
|
||||||
## ========== ================================================================================= ================================================
|
## ========== ================================================================================= ================================================
|
||||||
|
##
|
||||||
|
## Other strings can be inserted by putting them in ``''``. For example ``hh'->'mm`` will give ``01->56``.
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
var i = 0
|
var i = 0
|
||||||
var currentF = ""
|
var currentF = ""
|
||||||
while True:
|
while True:
|
||||||
case f[i]
|
case f[i]
|
||||||
of '\0':
|
of ' ', '-', '/', ':', '\'', '\0':
|
||||||
break
|
|
||||||
of ' ', '-', '/', ':', '\'':
|
|
||||||
case currentF
|
case currentF
|
||||||
of "d":
|
of "d":
|
||||||
result.add($info.monthday)
|
result.add($info.monthday)
|
||||||
|
|
@ -437,9 +557,9 @@ proc format*(info: TTimeInfo, f: string): string =
|
||||||
result.add("0")
|
result.add("0")
|
||||||
result.add($info.monthday)
|
result.add($info.monthday)
|
||||||
of "ddd":
|
of "ddd":
|
||||||
result.add(($info.month)[0 .. 2])
|
result.add(($info.monthday)[0 .. 2])
|
||||||
of "dddd":
|
of "dddd":
|
||||||
result.add($info.month)
|
result.add($info.monthday)
|
||||||
of "h":
|
of "h":
|
||||||
result.add($(info.hour - 12))
|
result.add($(info.hour - 12))
|
||||||
of "hh":
|
of "hh":
|
||||||
|
|
@ -460,11 +580,11 @@ proc format*(info: TTimeInfo, f: string): string =
|
||||||
result.add('0')
|
result.add('0')
|
||||||
result.add($info.minute)
|
result.add($info.minute)
|
||||||
of "M":
|
of "M":
|
||||||
result.add($(int(info.month)))
|
result.add($(int(info.month)+1))
|
||||||
of "MM":
|
of "MM":
|
||||||
if int(info.month) < 10:
|
if int(info.month) < 10:
|
||||||
result.add('0')
|
result.add('0')
|
||||||
result.add($(int(info.month)))
|
result.add($(int(info.month)+1))
|
||||||
of "MMM":
|
of "MMM":
|
||||||
result.add(($info.month)[0..2])
|
result.add(($info.month)[0..2])
|
||||||
of "MMMM":
|
of "MMMM":
|
||||||
|
|
@ -500,12 +620,32 @@ proc format*(info: TTimeInfo, f: string): string =
|
||||||
of "yyyyy":
|
of "yyyyy":
|
||||||
result.add('0')
|
result.add('0')
|
||||||
result.add($info.year)
|
result.add($info.year)
|
||||||
|
of "z":
|
||||||
|
let hrs = (info.timezone div 60) div 60
|
||||||
|
result.add($hrs)
|
||||||
|
of "zz":
|
||||||
|
let hrs = (info.timezone div 60) div 60
|
||||||
|
|
||||||
|
result.add($hrs)
|
||||||
|
if hrs.abs < 10:
|
||||||
|
var atIndex = result.len-(($hrs).len-(if hrs < 0: 1 else: 0))
|
||||||
|
result.insert("0", atIndex)
|
||||||
|
of "zzz":
|
||||||
|
let hrs = (info.timezone div 60) div 60
|
||||||
|
|
||||||
|
result.add($hrs & ":00")
|
||||||
|
if hrs.abs < 10:
|
||||||
|
var atIndex = result.len-(($hrs & ":00").len-(if hrs < 0: 1 else: 0))
|
||||||
|
result.insert("0", atIndex)
|
||||||
|
of "ZZZ":
|
||||||
|
result.add(info.tzname)
|
||||||
of "":
|
of "":
|
||||||
nil # Do nothing.
|
nil # Do nothing.
|
||||||
else:
|
else:
|
||||||
raise newException(EInvalidValue, "Invalid format string: " & currentF)
|
raise newException(EInvalidValue, "Invalid format string: " & currentF)
|
||||||
|
|
||||||
currentF = ""
|
currentF = ""
|
||||||
|
if f[i] == '\0': break
|
||||||
|
|
||||||
if f[i] == '\'':
|
if f[i] == '\'':
|
||||||
inc(i) # Skip '
|
inc(i) # Skip '
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,13 @@ type
|
||||||
## a type description (for templates)
|
## a type description (for templates)
|
||||||
void* {.magic: "VoidType".} ## meta type to denote the absense of any type
|
void* {.magic: "VoidType".} ## meta type to denote the absense of any type
|
||||||
|
|
||||||
TInteger* = int|char|int8|int16|int32|int64|bool|enum
|
TInteger* = int|int8|int16|int32|int64
|
||||||
## type class matching all integer types
|
## type class matching all integer types
|
||||||
|
|
||||||
|
TOrdinal* = TInteger|bool|enum
|
||||||
|
## type class matching all ordinal types; however this includes enums with
|
||||||
|
## holes.
|
||||||
|
|
||||||
TNumber* = TInteger|float|float32|float64
|
TNumber* = TInteger|float|float32|float64
|
||||||
## type class matching all number types
|
## type class matching all number types
|
||||||
|
|
||||||
|
|
@ -190,6 +194,7 @@ type
|
||||||
msg* {.exportc: "message".}: string ## the exception's message. Not
|
msg* {.exportc: "message".}: string ## the exception's message. Not
|
||||||
## providing an exception message
|
## providing an exception message
|
||||||
## is bad style.
|
## is bad style.
|
||||||
|
trace: string
|
||||||
|
|
||||||
EAsynch* = object of E_Base ## Abstract exception class for
|
EAsynch* = object of E_Base ## Abstract exception class for
|
||||||
## *asynchronous exceptions* (interrupts).
|
## *asynchronous exceptions* (interrupts).
|
||||||
|
|
@ -1195,6 +1200,15 @@ iterator `..`*[S, T](a: S, b: T): T {.inline.} =
|
||||||
yield res
|
yield res
|
||||||
inc res
|
inc res
|
||||||
|
|
||||||
|
iterator `||`*[S, T](a: S, b: T, annotation=""): T {.
|
||||||
|
inline, magic: "OmpParFor", sideEffect.} =
|
||||||
|
## parallel loop iterator. Same as `..` but the loop may run in parallel.
|
||||||
|
## `annotation` is an additional annotation for the code generator to use.
|
||||||
|
## Note that the compiler maps that to
|
||||||
|
## the ``#pragma omp parallel for`` construct of `OpenMP`:idx: and as
|
||||||
|
## such isn't aware of the parallelism in your code. Be careful.
|
||||||
|
nil
|
||||||
|
|
||||||
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
|
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
|
||||||
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
|
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
|
||||||
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
|
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
|
||||||
|
|
@ -1900,6 +1914,10 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
when hostOS != "standalone":
|
when hostOS != "standalone":
|
||||||
proc getStackTrace*(): string
|
proc getStackTrace*(): string
|
||||||
## gets the current stack trace. This is only works for debug builds.
|
## gets the current stack trace. This is only works for debug builds.
|
||||||
|
|
||||||
|
proc getStackTrace*(e: ref E_Base): string
|
||||||
|
## gets the stack trace associated with `e`, which is the stack that
|
||||||
|
## lead to the ``raise`` statement. This is only works for debug builds.
|
||||||
|
|
||||||
{.push stack_trace: off.}
|
{.push stack_trace: off.}
|
||||||
when hostOS == "standalone":
|
when hostOS == "standalone":
|
||||||
|
|
@ -2177,19 +2195,19 @@ proc `*=`*[T](x: var ordinal[T], y: ordinal[T]) {.inline, noSideEffect.} =
|
||||||
## Binary `*=` operator for ordinals
|
## Binary `*=` operator for ordinals
|
||||||
x = x * y
|
x = x * y
|
||||||
|
|
||||||
proc `+=` *(x: var float, y:float) {.inline, noSideEffect.} =
|
proc `+=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
|
||||||
## Increments in placee a floating point number
|
## Increments in placee a floating point number
|
||||||
x = x + y
|
x = x + y
|
||||||
|
|
||||||
proc `-=` *(x: var float, y:float) {.inline, noSideEffect.} =
|
proc `-=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
|
||||||
## Decrements in place a floating point number
|
## Decrements in place a floating point number
|
||||||
x = x - y
|
x = x - y
|
||||||
|
|
||||||
proc `*=` *(x: var float, y:float) {.inline, noSideEffect.} =
|
proc `*=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
|
||||||
## Multiplies in place a floating point number
|
## Multiplies in place a floating point number
|
||||||
x = x * y
|
x = x * y
|
||||||
|
|
||||||
proc `/=` *(x: var float, y:float) {.inline, noSideEffect.} =
|
proc `/=`*[T: float|float32|float64] (x: var T, y: T) {.inline, noSideEffect.} =
|
||||||
## Divides in place a floating point number
|
## Divides in place a floating point number
|
||||||
x = x / y
|
x = x / y
|
||||||
|
|
||||||
|
|
@ -2283,5 +2301,18 @@ template eval*(blk: stmt): stmt =
|
||||||
macro payload(x: stmt): stmt = blk
|
macro payload(x: stmt): stmt = blk
|
||||||
payload()
|
payload()
|
||||||
|
|
||||||
|
proc insert*(x: var string, item: string, i = 0) {.noSideEffect.} =
|
||||||
|
## inserts `item` into `x` at position `i`.
|
||||||
|
var xl = x.len
|
||||||
|
setLen(x, xl+item.len)
|
||||||
|
var j = xl-1
|
||||||
|
while j >= i:
|
||||||
|
shallowCopy(x[j+item.len], x[j])
|
||||||
|
dec(j)
|
||||||
|
j = 0
|
||||||
|
while j < item.len:
|
||||||
|
x[j+i] = item[j]
|
||||||
|
inc(j)
|
||||||
|
|
||||||
when defined(initDebugger):
|
when defined(initDebugger):
|
||||||
initDebugger()
|
initDebugger()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
proc genericResetAux(dest: Pointer, n: ptr TNimNode)
|
||||||
|
|
||||||
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
|
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
|
||||||
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
||||||
var
|
var
|
||||||
|
|
@ -20,10 +22,16 @@ proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
||||||
for i in 0..n.len-1:
|
for i in 0..n.len-1:
|
||||||
genericAssignAux(dest, src, n.sons[i], shallow)
|
genericAssignAux(dest, src, n.sons[i], shallow)
|
||||||
of nkCase:
|
of nkCase:
|
||||||
|
var dd = selectBranch(dest, n)
|
||||||
|
var m = selectBranch(src, n)
|
||||||
|
# reset if different branches are in use; note different branches also
|
||||||
|
# imply that's not self-assignment (``x = x``)!
|
||||||
|
if m != dd and dd != nil:
|
||||||
|
genericResetAux(dest, dd)
|
||||||
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
||||||
n.typ.size)
|
n.typ.size)
|
||||||
var m = selectBranch(src, n)
|
if m != nil:
|
||||||
if m != nil: genericAssignAux(dest, src, m, shallow)
|
genericAssignAux(dest, src, m, shallow)
|
||||||
of nkNone: sysAssert(false, "genericAssignAux")
|
of nkNone: sysAssert(false, "genericAssignAux")
|
||||||
#else:
|
#else:
|
||||||
# echo "ugh memory corruption! ", n.kind
|
# echo "ugh memory corruption! ", n.kind
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,9 @@ proc quitOrDebug() {.inline.} =
|
||||||
|
|
||||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
e.name = ename
|
e.name = ename
|
||||||
|
when hasSomeStackTrace:
|
||||||
|
e.trace = ""
|
||||||
|
rawWriteStackTrace(e.trace)
|
||||||
if localRaiseHook != nil:
|
if localRaiseHook != nil:
|
||||||
if not localRaiseHook(e): return
|
if not localRaiseHook(e): return
|
||||||
if globalRaiseHook != nil:
|
if globalRaiseHook != nil:
|
||||||
|
|
@ -253,6 +256,12 @@ proc getStackTrace(): string =
|
||||||
else:
|
else:
|
||||||
result = "No stack traceback available\n"
|
result = "No stack traceback available\n"
|
||||||
|
|
||||||
|
proc getStackTrace(e: ref E_Base): string =
|
||||||
|
if not isNil(e) and not isNil(e.trace):
|
||||||
|
result = e.trace
|
||||||
|
else:
|
||||||
|
result = ""
|
||||||
|
|
||||||
when defined(endb):
|
when defined(endb):
|
||||||
var
|
var
|
||||||
dbgAborting: bool # whether the debugger wants to abort
|
dbgAborting: bool # whether the debugger wants to abort
|
||||||
|
|
|
||||||
|
|
@ -608,9 +608,16 @@ proc parseSmiley(p: var TRstParser): PRstNode =
|
||||||
result.text = val
|
result.text = val
|
||||||
return
|
return
|
||||||
|
|
||||||
|
when false:
|
||||||
|
const
|
||||||
|
urlChars = {'A'..'Z', 'a'..'z', '0'..'9', ':', '#', '@', '%', '/', ';',
|
||||||
|
'$', '(', ')', '~', '_', '?', '+', '-', '=', '\\', '.', '&',
|
||||||
|
'\128'..'\255'}
|
||||||
|
|
||||||
proc isURL(p: TRstParser, i: int): bool =
|
proc isURL(p: TRstParser, i: int): bool =
|
||||||
result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
|
result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
|
||||||
(p.tok[i+3].kind == tkWord) and (p.tok[i+4].symbol == ".")
|
(p.tok[i+3].kind == tkWord) and
|
||||||
|
(p.tok[i].symbol in ["http", "ftp", "gopher", "telnet", "file"])
|
||||||
|
|
||||||
proc parseURL(p: var TRstParser, father: PRstNode) =
|
proc parseURL(p: var TRstParser, father: PRstNode) =
|
||||||
#if p.tok[p.idx].symbol[strStart] == '<':
|
#if p.tok[p.idx].symbol[strStart] == '<':
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,18 @@ template typedef(name: expr, typ: typeDesc) {.immediate.} =
|
||||||
typedef(myint, int)
|
typedef(myint, int)
|
||||||
var x: PMyInt
|
var x: PMyInt
|
||||||
|
|
||||||
|
|
||||||
|
# Test UFCS
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo = object
|
||||||
|
arg: int
|
||||||
|
|
||||||
|
proc initFoo(arg: int): Foo =
|
||||||
|
result.arg = arg
|
||||||
|
|
||||||
|
template create(typ: typeDesc, arg: expr): expr = `init typ`(arg)
|
||||||
|
|
||||||
|
var ff = Foo.create(12)
|
||||||
|
|
||||||
|
echo ff.arg
|
||||||
|
|
|
||||||
11
tests/reject/tenummix.nim
Normal file
11
tests/reject/tenummix.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
file: "system.nim"
|
||||||
|
line: 640
|
||||||
|
errormsg: "type mismatch"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
TE1 = enum eA, eB
|
||||||
|
TE2 = enum eC, eD
|
||||||
|
|
||||||
|
assert eA != eC
|
||||||
27
tests/run/tdumptree.nim
Normal file
27
tests/run/tdumptree.nim
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
output: '''StmtList
|
||||||
|
VarSection
|
||||||
|
IdentDefs
|
||||||
|
Ident !"x"
|
||||||
|
nil
|
||||||
|
Call
|
||||||
|
DotExpr
|
||||||
|
Ident !"foo"
|
||||||
|
Ident !"create"
|
||||||
|
IntLit 56'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# disabled; can't work as the output is done by the compiler
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
#emit("type\n TFoo = object\n bar: int")
|
||||||
|
|
||||||
|
#var f: TFoo
|
||||||
|
#f.bar = 5
|
||||||
|
#echo(f.bar)
|
||||||
|
|
||||||
|
dumpTree:
|
||||||
|
var x = foo.create(56)
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
output: "0false"
|
output: "0false12"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Test multiple generic instantiation of generic proc vars:
|
# Test multiple generic instantiation of generic proc vars:
|
||||||
|
|
@ -17,3 +17,20 @@ proc threadProcWrapper[TMsg]() =
|
||||||
threadProcWrapper[int]()
|
threadProcWrapper[int]()
|
||||||
threadProcWrapper[bool]()
|
threadProcWrapper[bool]()
|
||||||
|
|
||||||
|
type
|
||||||
|
TFilterProc[T,D] = proc (item: T, env:D): bool
|
||||||
|
|
||||||
|
proc filter[T,D](data: seq[T], env:D, pred: TFilterProc[T,D]): seq[T] =
|
||||||
|
result = @[]
|
||||||
|
for e in data:
|
||||||
|
if pred(e, env): result.add(e)
|
||||||
|
|
||||||
|
proc predTest(item: int, value: int): Bool =
|
||||||
|
return item <= value
|
||||||
|
|
||||||
|
proc test(data: seq[int], value: int): seq[int] =
|
||||||
|
return filter(data, value, predTest)
|
||||||
|
|
||||||
|
for x in items(test(@[1,2,3], 2)):
|
||||||
|
stdout.write(x)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "tsequtils.nim"
|
file: "tsequtils.nim"
|
||||||
output: '''Zip: [{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6}]
|
output: '''Zip: [{"Field0": 1, "Field1": 2}, {"Field0": 3, "Field1": 4}, {"Field0": 5, "Field1": 6}]
|
||||||
Filter Iterator: 3
|
Filter Iterator: 3
|
||||||
Filter Iterator: 5
|
Filter Iterator: 5
|
||||||
Filter Iterator: 7
|
Filter Iterator: 7
|
||||||
|
|
|
||||||
17
todo.txt
17
todo.txt
|
|
@ -1,8 +1,10 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- make stack traces part of the exception in debug builds
|
- implement 'gorge'
|
||||||
- make templates hygienic by default
|
- implement a warning message for shadowed 'result' variable
|
||||||
|
- make templates hygienic by default: try to gensym() everything in the 'block'
|
||||||
|
of a template
|
||||||
- ``bind`` for overloaded symbols does not work apparently
|
- ``bind`` for overloaded symbols does not work apparently
|
||||||
- ``=`` should be overloadable; requires specialization for ``=``
|
- ``=`` should be overloadable; requires specialization for ``=``
|
||||||
- fix remaining generics bugs
|
- fix remaining generics bugs
|
||||||
|
|
@ -24,6 +26,7 @@ version 0.9.0
|
||||||
- we need to support iteration of 2 different data structures in parallel
|
- we need to support iteration of 2 different data structures in parallel
|
||||||
- make exceptions compatible with C++ exceptions
|
- make exceptions compatible with C++ exceptions
|
||||||
- change how comments are part of the AST
|
- change how comments are part of the AST
|
||||||
|
- find a better solution for gensym instead of `*ident`
|
||||||
- extract nimdoc properly and document it finally
|
- extract nimdoc properly and document it finally
|
||||||
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
||||||
indentation handling is quite complex too; problem with exception handling
|
indentation handling is quite complex too; problem with exception handling
|
||||||
|
|
@ -32,17 +35,9 @@ version 0.9.0
|
||||||
error handling more light-weight
|
error handling more light-weight
|
||||||
people also want ``inc a; inc b``
|
people also want ``inc a; inc b``
|
||||||
|
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
----
|
----
|
||||||
- bug: generic assign still buggy
|
|
||||||
- special case the generic assign that needs to care about case objects
|
|
||||||
|
|
||||||
- bug: returning a tyVar does not mean it is save to return it:
|
|
||||||
proc forward[T](x: var T): var T = result = x
|
|
||||||
proc p(): var int =
|
|
||||||
var x: int
|
|
||||||
# reject this call via alias analysis:
|
|
||||||
result = forward(x)
|
|
||||||
|
|
||||||
- bug: stress testing basic method example (eval example)
|
- bug: stress testing basic method example (eval example)
|
||||||
without ``-d:release`` leaks memory?
|
without ``-d:release`` leaks memory?
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@
|
||||||
# result = "#! /bin/sh\n# Generated from niminst\n" &
|
# result = "#! /bin/sh\n# Generated from niminst\n" &
|
||||||
# "# Template is in tools/buildsh.tmpl\n" &
|
# "# Template is in tools/buildsh.tmpl\n" &
|
||||||
# "# To regenerate run ``niminst csource`` or ``koch csource``\n"
|
# "# To regenerate run ``niminst csource`` or ``koch csource``\n"
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
while :
|
while :
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
@ -108,11 +111,11 @@ case $myos in
|
||||||
# var linkCmd = ""
|
# var linkCmd = ""
|
||||||
# for f in items(c.cfiles[osA][cpuA]):
|
# for f in items(c.cfiles[osA][cpuA]):
|
||||||
echo "$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}"
|
echo "$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}"
|
||||||
$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")} || exit 1
|
$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}
|
||||||
# add(linkCmd, " \\\n" & changeFileExt(f, "o"))
|
# add(linkCmd, " \\\n" & changeFileExt(f, "o"))
|
||||||
# end for
|
# end for
|
||||||
echo "$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd"
|
echo "$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd"
|
||||||
$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd || exit 1
|
$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd
|
||||||
;;
|
;;
|
||||||
# end for
|
# end for
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
# result = "#! /bin/sh\n# Generated by niminst\n"
|
# result = "#! /bin/sh\n# Generated by niminst\n"
|
||||||
# var proj = c.name.toLower
|
# var proj = c.name.toLower
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
if [ $# -eq 1 ] ; then
|
if [ $# -eq 1 ] ; then
|
||||||
# if c.cat[fcUnixBin].len > 0:
|
# if c.cat[fcUnixBin].len > 0:
|
||||||
if test -f ?{c.cat[fcUnixBin][0]}
|
if test -f ?{c.cat[fcUnixBin][0]}
|
||||||
|
|
@ -47,13 +49,13 @@ if [ $# -eq 1 ] ; then
|
||||||
docdir="$1/?proj/doc"
|
docdir="$1/?proj/doc"
|
||||||
datadir="$1/?proj/data"
|
datadir="$1/?proj/data"
|
||||||
|
|
||||||
mkdir -p $1/?proj || exit 1
|
mkdir -p $1/?proj
|
||||||
mkdir -p $bindir || exit 1
|
mkdir -p $bindir
|
||||||
mkdir -p $configdir || exit 1
|
mkdir -p $configdir
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
mkdir -p $libdir || exit 1
|
mkdir -p $libdir
|
||||||
mkdir -p $docdir || exit 1
|
mkdir -p $docdir
|
||||||
echo "copying files..."
|
echo "copying files..."
|
||||||
#var createdDirs = newStringTable()
|
#var createdDirs = newStringTable()
|
||||||
#for cat in fcConfig..fcLib:
|
#for cat in fcConfig..fcLib:
|
||||||
|
|
@ -63,30 +65,34 @@ if [ $# -eq 1 ] ; then
|
||||||
# mk = unixDirVars[cat] & "/" & mk
|
# mk = unixDirVars[cat] & "/" & mk
|
||||||
# if not createdDirs.hasKey(mk):
|
# if not createdDirs.hasKey(mk):
|
||||||
# createdDirs[mk] = "true"
|
# createdDirs[mk] = "true"
|
||||||
mkdir -p ?mk || exit 1
|
mkdir -p ?mk
|
||||||
# end if
|
# end if
|
||||||
# end if
|
# end if
|
||||||
# end for
|
# end for
|
||||||
#end for
|
#end for
|
||||||
|
|
||||||
#for f in items(c.cat[fcUnixBin]):
|
#for f in items(c.cat[fcUnixBin]):
|
||||||
cp ?f $bindir/?f.skipRoot || exit 1
|
cp ?f $bindir/?f.skipRoot
|
||||||
chmod 755 $bindir/?f.skipRoot
|
chmod 755 $bindir/?f.skipRoot
|
||||||
#end for
|
#end for
|
||||||
#for f in items(c.cat[fcConfig]):
|
#for f in items(c.cat[fcConfig]):
|
||||||
cp ?f $configdir/?f.skipRoot || exit 1
|
cp ?f $configdir/?f.skipRoot
|
||||||
chmod 644 $configdir/?f.skipRoot
|
chmod 644 $configdir/?f.skipRoot
|
||||||
#end for
|
#end for
|
||||||
#for f in items(c.cat[fcData]):
|
#for f in items(c.cat[fcData]):
|
||||||
cp ?f $datadir/?f.skipRoot || exit 1
|
if [ -f ?f ]; then
|
||||||
chmod 644 $datadir/?f.skipRoot
|
cp ?f $datadir/?f.skipRoot
|
||||||
|
chmod 644 $datadir/?f.skipRoot
|
||||||
|
fi
|
||||||
#end for
|
#end for
|
||||||
#for f in items(c.cat[fcDoc]):
|
#for f in items(c.cat[fcDoc]):
|
||||||
cp ?f $docdir/?f.skipRoot || exit 1
|
if [ -f ?f ]; then
|
||||||
chmod 644 $docdir/?f.skipRoot
|
cp ?f $docdir/?f.skipRoot
|
||||||
|
chmod 644 $docdir/?f.skipRoot
|
||||||
|
fi
|
||||||
#end for
|
#end for
|
||||||
#for f in items(c.cat[fcLib]):
|
#for f in items(c.cat[fcLib]):
|
||||||
cp ?f $libdir/?f.skipRoot || exit 1
|
cp ?f $libdir/?f.skipRoot
|
||||||
chmod 644 $libdir/?f.skipRoot
|
chmod 644 $libdir/?f.skipRoot
|
||||||
#end for
|
#end for
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ Library Additions
|
||||||
- Added ``system.clamp`` to limit a value within an interval ``[a, b]``.
|
- Added ``system.clamp`` to limit a value within an interval ``[a, b]``.
|
||||||
- Added ``strutils.continuesWith``.
|
- Added ``strutils.continuesWith``.
|
||||||
- Added ``system.getStackTrace``.
|
- Added ``system.getStackTrace``.
|
||||||
|
- Added ``system.||`` for parallel for loop support.
|
||||||
- The GC supports (soft) realtime systems via ``GC_setMaxPause``
|
- The GC supports (soft) realtime systems via ``GC_setMaxPause``
|
||||||
and ``GC_step`` procs.
|
and ``GC_step`` procs.
|
||||||
|
|
||||||
|
|
@ -73,6 +74,9 @@ Changes affecting backwards compatibility
|
||||||
- Deprecated ``system.GC_setStrategy``.
|
- Deprecated ``system.GC_setStrategy``.
|
||||||
- ``re.findAll`` and ``pegs.findAll`` don't return *captures* anymore but
|
- ``re.findAll`` and ``pegs.findAll`` don't return *captures* anymore but
|
||||||
matching *substrings*.
|
matching *substrings*.
|
||||||
|
- RTTI and thus the ``marshall`` module don't contain the proper field names
|
||||||
|
of tuples anymore. This had to be changed as the old behaviour never
|
||||||
|
produced consistent results.
|
||||||
|
|
||||||
|
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
|
|
@ -86,6 +90,7 @@ Compiler Additions
|
||||||
option or pragma.
|
option or pragma.
|
||||||
- The compiler now generates marker procs that the GC can use instead of RTTI.
|
- The compiler now generates marker procs that the GC can use instead of RTTI.
|
||||||
This speeds up the GC quite a bit.
|
This speeds up the GC quite a bit.
|
||||||
|
- The compiler now supports OpenMP's parallel for loop.
|
||||||
|
|
||||||
|
|
||||||
Language Additions
|
Language Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue