diff options
-rw-r--r-- | compiler/aliases.nim | 2 | ||||
-rwxr-xr-x | compiler/astalgo.nim | 4 | ||||
-rw-r--r-- | compiler/ccgcalls.nim | 92 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 5 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 26 | ||||
-rwxr-xr-x | compiler/cgen.nim | 29 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 2 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 6 | ||||
-rw-r--r-- | compiler/semmagic.nim | 4 | ||||
-rwxr-xr-x | doc/manual.txt | 6 | ||||
-rwxr-xr-x | lib/system.nim | 14 | ||||
-rwxr-xr-x | tests/run/tpegs.nim | 74 | ||||
-rwxr-xr-x | todo.txt | 6 | ||||
-rwxr-xr-x | web/news.txt | 11 |
14 files changed, 167 insertions, 114 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim index e5f58356e..aa579feee 100644 --- a/compiler/aliases.nim +++ b/compiler/aliases.nim @@ -41,7 +41,7 @@ proc isPartOfAux(n: PNode, b: PType, marker: var TIntSet): TAnalysisResult = proc isPartOfAux(a, b: PType, marker: var TIntSet): TAnalysisResult = result = arNo - if a == nil: return + if a == nil or b == nil: return if ContainsOrIncl(marker, a.id): return if compareTypes(a, b, dcEqIgnoreDistinct): return arYes case a.kind diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index d405bd34c..94046a723 100755 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -155,9 +155,7 @@ proc SameValue*(a, b: PNode): bool = if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: if b.kind in {nkStrLit..nkTripleStrLit}: result = a.strVal == b.strVal - else: - debug a - debug b + else: InternalError(a.info, "SameValue") proc leValue*(a, b: PNode): bool = diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 1c57479ae..570c931fb 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -10,16 +10,30 @@ type TAfterCallActions = tuple[p: BProc, actions: PRope] -proc fixupCall(p: BProc, t: PNode, d: var TLoc, pl: PRope) = +proc leftAppearsOnRightSide(le, ri: PNode): bool = + if le != nil: + for i in 1 .. <ri.len: + if le.isPartOf(ri[i]) != arNo: return true + +proc hasNoInit(call: PNode): bool {.inline.} = + result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags + +proc resetLoc(p: BProc, d: var TLoc) = + zeroVar(p, d, containsGarbageCollectedRef(d.t)) + +proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) = var pl = pl - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): - if sonsLen(t) > 1: app(pl, ", ") - # beware of 'result = p(result)'. We always allocate a temporary: - if d.k in {locTemp, locNone}: - # We already got a temp. Great, special case it: + if sonsLen(ri) > 1: app(pl, ", ") + # beware of 'result = p(result)'. We may need to allocate a temporary: + if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri): + # Great, we can use 'd': if d.k == locNone: getTemp(p, typ.sons[0], d) + elif d.k notin {locExpr, locTemp} and not hasNoInit(ri): + # reset before pass as 'result' var: + resetLoc(p, d) app(pl, addrLoc(d)) app(pl, ")") app(p.s[cpsStmts], pl) @@ -117,40 +131,40 @@ proc genArgNoParam(aca: var TAfterCallActions, n: PNode): PRope = initLocExpr(aca.p, n, a) result = rdLoc(a) -proc genCall(p: BProc, t: PNode, d: var TLoc) = +proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op: TLoc var aca: TAfterCallActions aca.p = p # this is a hotspot in the compiler - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl = con(op.r, "(") - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) for i in countup(1, length - 1): assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(aca, t.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(aca, ri.sons[i], typ.n.sons[i].sym)) else: - app(pl, genArgNoParam(aca, t.sons[i])) + app(pl, genArgNoParam(aca, ri.sons[i])) if i < length - 1: app(pl, ", ") - fixupCall(p, t, d, pl) + fixupCall(p, le, ri, d, pl) emitAfterCallActions(aca) -proc genInfixCall(p: BProc, t: PNode, d: var TLoc) = +proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = var op, a: TLoc var aca: TAfterCallActions aca.p = p - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl: PRope = nil - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) assert(sonsLen(typ) == sonsLen(typ.n)) var param = typ.n.sons[1].sym - app(pl, genArg(aca, t.sons[1], param)) + app(pl, genArg(aca, ri.sons[1], param)) if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, "->") else: app(pl, ".") @@ -160,45 +174,45 @@ proc genInfixCall(p: BProc, t: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(aca, t.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(aca, ri.sons[i], typ.n.sons[i].sym)) else: - app(pl, genArgNoParam(aca, t.sons[i])) + app(pl, genArgNoParam(aca, ri.sons[i])) if i < length - 1: app(pl, ", ") - fixupCall(p, t, d, pl) + fixupCall(p, le, ri, d, pl) emitAfterCallActions(aca) -proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) = +proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = # generates a crappy ObjC call var op, a: TLoc var aca: TAfterCallActions aca.p = p - initLocExpr(p, t.sons[0], op) + initLocExpr(p, ri.sons[0], op) var pl = toRope"[" - var typ = t.sons[0].typ # getUniqueType() is too expensive here! + var typ = ri.sons[0].typ # getUniqueType() is too expensive here! assert(typ.kind == tyProc) - var length = sonsLen(t) + var length = sonsLen(ri) assert(sonsLen(typ) == sonsLen(typ.n)) if length > 1: - app(pl, genArg(aca, t.sons[1], typ.n.sons[1].sym)) + app(pl, genArg(aca, ri.sons[1], typ.n.sons[1].sym)) app(pl, " ") app(pl, op.r) if length > 2: app(pl, ": ") - app(pl, genArg(aca, t.sons[2], typ.n.sons[2].sym)) + app(pl, genArg(aca, ri.sons[2], typ.n.sons[2].sym)) for i in countup(3, length-1): assert(sonsLen(typ) == sonsLen(typ.n)) if i >= sonsLen(typ): - InternalError(t.info, "varargs for objective C method?") + InternalError(ri.info, "varargs for objective C method?") assert(typ.n.sons[i].kind == nkSym) var param = typ.n.sons[i].sym app(pl, " ") app(pl, param.name.s) app(pl, ": ") - app(pl, genArg(aca, t.sons[i], param)) + app(pl, genArg(aca, ri.sons[i], param)) if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): - if sonsLen(t) > 1: app(pl, " ") + if sonsLen(ri) > 1: app(pl, " ") # beware of 'result = p(result)'. We always allocate a temporary: if d.k in {locTemp, locNone}: # We already got a temp. Great, special case it: @@ -230,3 +244,21 @@ proc genNamedParamCall(p: BProc, t: PNode, d: var TLoc) = appf(p.s[cpsStmts], ";$n") emitAfterCallActions(aca) +proc genCall(p: BProc, e: PNode, d: var TLoc) = + if e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and + e.len >= 2: + genInfixCall(p, nil, e, d) + elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags: + genNamedParamCall(p, e, d) + else: + genPrefixCall(p, nil, e, d) + +proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) = + if ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags and + ri.len >= 2: + genInfixCall(p, le, ri, d) + elif ri.sons[0].kind == nkSym and sfNamedParamCall in ri.sons[0].sym.flags: + genNamedParamCall(p, ri, d) + else: + genPrefixCall(p, le, ri, d) + diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3a2c5965b..ddd272fba 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1628,11 +1628,6 @@ proc expr(p: BProc, e: PNode, d: var TLoc) = nkCallStrLit: if e.sons[0].kind == nkSym and e.sons[0].sym.magic != mNone: genMagicExpr(p, e, d, e.sons[0].sym.magic) - elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and - e.len >= 2: - genInfixCall(p, e, d) - elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags: - genNamedParamCall(p, e, d) else: genCall(p, e, d) of nkCurly: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a994f27f3..108d7f071 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -18,16 +18,16 @@ proc genVarTuple(p: BProc, n: PNode) = if n.kind != nkVarTuple: InternalError(n.info, "genVarTuple") var L = sonsLen(n) genLineDir(p, n) - initLocExpr(p, n.sons[L - 1], tup) + initLocExpr(p, n.sons[L-1], tup) var t = tup.t - for i in countup(0, L - 3): + for i in countup(0, L-3): var v = n.sons[i].sym if sfGlobal in v.flags: assignGlobalVar(p, v) genObjectInit(p, cpsInit, v.typ, v.loc, true) - else: + else: assignLocalVar(p, v) - initVariable(p, v) + initLocalVar(p, v, immediateAsgn=true) initLoc(field, locExpr, t.sons[i], tup.s) if t.n == nil: field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)]) @@ -37,17 +37,25 @@ proc genVarTuple(p: BProc, n: PNode) = [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) putLocIntoDest(p, v.loc, field) +proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} = + if ri.kind in nkCallKinds and (ri.sons[0].kind != nkSym or + ri.sons[0].sym.magic == mNone): + genAsgnCall(p, le, ri, a) + else: + expr(p, ri, a) + proc genSingleVar(p: BProc, a: PNode) = var v = a.sons[0].sym + var immediateAsgn = a.sons[2].kind != nkEmpty if sfGlobal in v.flags: assignGlobalVar(p, v) genObjectInit(p, cpsInit, v.typ, v.loc, true) - else: + else: assignLocalVar(p, v) - initVariable(p, v) - if a.sons[2].kind != nkEmpty: + initLocalVar(p, v, immediateAsgn) + if immediateAsgn: genLineDir(p, a) - expr(p, a.sons[2], v.loc) + loadInto(p, a.sons[0], a.sons[2], v.loc) proc genVarStmt(p: BProc, n: PNode) = for i in countup(0, sonsLen(n) - 1): @@ -658,7 +666,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) = InitLocExpr(p, e.sons[0], a) if fastAsgn: incl(a.flags, lfNoDeepCopy) assert(a.t != nil) - expr(p, e.sons[1], a) + loadInto(p, e.sons[0], e.sons[1], a) else: asgnFieldDiscriminant(p, e) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 2018d7e6d..aa07f40aa 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -14,7 +14,7 @@ import options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, - rodutils, renderer, idgen, cgendata, ccgmerge, semfold + rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases when options.hasTinyCBackend: import tccgen @@ -235,16 +235,17 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = genRefAssign(p, loc, nilLoc, {afSrcIsNil}) else: appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)]) - else: + else: if containsGcref and p.WithInLoop > 0: appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) + genObjectInit(p, cpsInit, loc.t, loc, true) appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(loc), genTypeInfo(p.module, loc.t)]) else: appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) - genObjectInit(p, cpsInit, loc.t, loc, true) + genObjectInit(p, cpsStmts, loc.t, loc, true) proc zeroTemp(p: BProc, loc: TLoc) = if skipTypes(loc.t, abstractVarRange).Kind notin @@ -259,15 +260,22 @@ proc zeroTemp(p: BProc, loc: TLoc) = else: appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", [addrLoc(loc), rdLoc(loc)]) + # XXX no object init necessary for temporaries? when false: appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", [addrLoc(loc), genTypeInfo(p.module, loc.t)]) -proc initVariable(p: BProc, v: PSym) = +proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = if sfNoInit notin v.flags: - var b = containsGarbageCollectedRef(v.typ) - if b or v.ast == nil: - zeroVar(p, v.loc, b) + # we know it is a local variable and thus on the stack! + # If ``not immediateAsgn`` it is not initialized in a binding like + # ``var v = X`` and thus we need to init it. + # If ``v`` contains a GC-ref we may pass it to ``unsureAsgnRef`` somehow + # which requires initialization. However this can really only happen if + # ``var v = X()`` gets transformed into ``X(&v)``. + # Nowadays the logic in ccgcalls deals with this case however. + if not immediateAsgn: + zeroVar(p, v.loc, containsGarbageCollectedRef(v.typ)) proc initTemp(p: BProc, tmp: var TLoc) = if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t): @@ -534,13 +542,14 @@ proc genProcAux(m: BModule, prc: PSym) = assert(prc.ast != nil) if sfPure notin prc.flags and prc.typ.sons[0] != nil: var res = prc.ast.sons[resultPos].sym # get result symbol - if not isInvalidReturnType(prc.typ.sons[0]): + if not isInvalidReturnType(prc.typ.sons[0]): + if sfNoInit in prc.flags: incl(res.flags, sfNoInit) # declare the result symbol: assignLocalVar(p, res) assert(res.loc.r != nil) returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)]) - initVariable(p, res) - else: + initLocalVar(p, res, immediateAsgn=false) + else: fillResult(res) assignParam(p, res) if skipTypes(res.typ, abstractInst).kind == tyArray: diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d4ea3226d..a291d4741 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -23,7 +23,7 @@ const wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, - wNoStackFrame, wError, wDiscardable} + wNoStackFrame, wError, wDiscardable, wNoInit} converterPragmas* = procPragmas methodPragmas* = procPragmas macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a08e9c875..a5093f567 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -983,12 +983,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = else: result = semDirectOp(c, n, flags) of mExpandToAst: result = semExpandToAst(c, n, s, flags) - of mAstToStr: - if sonsLen(n) == 2: - result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) - result.typ = getSysType(tyString) - else: - result = semDirectOp(c, n, flags) else: result = semDirectOp(c, n, flags) proc semIfExpr(c: PContext, n: PNode): PNode = diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index da1101729..696988fd3 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -31,6 +31,8 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, case n[0].sym.magic of mSlurp: result = semSlurp(c, n, flags) of mIsPartOf: result = semIsPartOf(c, n, flags) + of mAstToStr: + result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) + result.typ = getSysType(tyString) else: result = n - diff --git a/doc/manual.txt b/doc/manual.txt index 164410a68..97af7fe2a 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1584,6 +1584,11 @@ The implicit initialization can be avoided for optimization reasons with the var a {.noInit.}: array [0..1023, char] +If a proc is annotated with the ``noinit`` pragma this refers to its implicit +``result`` variable: + +.. code-block:: nimrod + proc returnUndefinedValue: int {.noinit.} = nil let statement @@ -2849,6 +2854,7 @@ exported. The algorithm for compiling modules is: - compile the whole module as usual, following import statements recursively + - if there is a cycle only import the already parsed symbols (that are exported); if an unknown identifier occurs then abort diff --git a/lib/system.nim b/lib/system.nim index c7e26230a..8a99781cc 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -2071,14 +2071,24 @@ proc astToStr*[T](x: T): string {.magic: "AstToStr", noSideEffect.} ## converts the AST of `x` into a string representation. This is very useful ## for debugging. +proc raiseAssert(msg: string) {.noinline.} = + raise newException(EAssertionFailed, msg) + template assert*(cond: expr, msg = "") = ## provides a means to implement `programming by contracts`:idx: in Nimrod. ## ``assert`` evaluates expression ``cond`` and if ``cond`` is false, it ## raises an ``EAssertionFailure`` exception. However, the compiler may ## not generate any code at all for ``assert`` if it is advised to do so. ## Use ``assert`` for debugging purposes only. + bind raiseAssert when compileOption("assertions"): if not cond: - raise newException(EAssertionFailed, astToStr(cond) & ' ' & msg) - + raiseAssert(astToStr(cond) & ' ' & msg) + +template doAssert*(cond: expr, msg = "") = + ## same as `assert' but is always turned on and not affected by the + ## ``--assertions`` command line switch. + bind raiseAssert + if not cond: + raiseAssert(astToStr(cond) & ' ' & msg) diff --git a/tests/run/tpegs.nim b/tests/run/tpegs.nim index 64c547b24..8fe302073 100755 --- a/tests/run/tpegs.nim +++ b/tests/run/tpegs.nim @@ -1669,25 +1669,25 @@ proc escapePeg*(s: string): string = if inQuote: result.add('\'') when isMainModule: - assert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27" - #assert match("(a b c)", peg"'(' @ ')'") - assert match("W_HI_Le", peg"\y 'while'") - assert(not match("W_HI_L", peg"\y 'while'")) - assert(not match("W_HI_Le", peg"\y v'while'")) - assert match("W_HI_Le", peg"y'while'") + doAssert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27" + #doAssert match("(a b c)", peg"'(' @ ')'") + doAssert match("W_HI_Le", peg"\y 'while'") + doAssert(not match("W_HI_L", peg"\y 'while'")) + doAssert(not match("W_HI_Le", peg"\y v'while'")) + doAssert match("W_HI_Le", peg"y'while'") - assert($ +digits == $peg"\d+") - assert "0158787".match(peg"\d+") - assert "ABC 0232".match(peg"\w+\s+\d+") - assert "ABC".match(peg"\d+ / \w+") + doAssert($ +digits == $peg"\d+") + doAssert "0158787".match(peg"\d+") + doAssert "ABC 0232".match(peg"\w+\s+\d+") + doAssert "ABC".match(peg"\d+ / \w+") for word in split("00232this02939is39an22example111", peg"\d+"): writeln(stdout, word) - assert matchLen("key", ident) == 3 + doAssert matchLen("key", ident) == 3 var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident) - assert matchLen("key1= cal9", pattern) == 11 + doAssert matchLen("key1= cal9", pattern) == 11 var ws = newNonTerminal("ws", 1, 1) ws.rule = *whitespace @@ -1698,24 +1698,24 @@ when isMainModule: var c: TCaptures var s = "a+b + c +d+e+f" - assert rawMatch(s, expr.rule, 0, c) == len(s) + doAssert rawMatch(s, expr.rule, 0, c) == len(s) var a = "" for i in 0..c.ml-1: a.add(substr(s, c.matches[i][0], c.matches[i][1])) - assert a == "abcdef" + doAssert a == "abcdef" #echo expr.rule #const filename = "lib/devel/peg/grammar.txt" #var grammar = parsePeg(newFileStream(filename, fmRead), filename) #echo "a <- [abc]*?".match(grammar) - assert find("_____abc_______", term("abc"), 2) == 5 - assert match("_______ana", peg"A <- 'ana' / . A") - assert match("abcs%%%", peg"A <- ..A / .A / '%'") + doAssert find("_____abc_______", term("abc"), 2) == 5 + doAssert match("_______ana", peg"A <- 'ana' / . A") + doAssert match("abcs%%%", peg"A <- ..A / .A / '%'") if "abc" =~ peg"{'a'}'bc' 'xyz' / {\ident}": - assert matches[0] == "abc" + doAssert matches[0] == "abc" else: - assert false + doAssert false var g2 = peg"""S <- A B / C D A <- 'a'+ @@ -1723,44 +1723,44 @@ when isMainModule: C <- 'c'+ D <- 'd'+ """ - assert($g2 == "((A B) / (C D))") - assert match("cccccdddddd", g2) - assert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") == + doAssert($g2 == "((A B) / (C D))") + doAssert match("cccccdddddd", g2) + doAssert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") == "var1<-keykey; var2<-key2key2") - assert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}") + doAssert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}") if "aaaaaa" =~ peg"'aa' !. / ({'a'})+": - assert matches[0] == "a" + doAssert matches[0] == "a" else: - assert false + doAssert false var matches: array[0..5, string] if match("abcdefg", peg"c {d} ef {g}", matches, 2): - assert matches[0] == "d" - assert matches[1] == "g" + doAssert matches[0] == "d" + doAssert matches[1] == "g" else: - assert false + doAssert false for x in findAll("abcdef", peg"{.}", 3): echo x if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')": - assert matches[0] == "f" - assert matches[1] == "a, b" + doAssert matches[0] == "f" + doAssert matches[1] == "a, b" else: - assert false + doAssert false - assert match("eine übersicht und außerdem", peg"(\letter \white*)+") + doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+") # ß is not a lower cased letter?! - assert match("eine übersicht und auerdem", peg"(\lower \white*)+") - assert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+") - assert(not match("456678", peg"(\letter)+")) + doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+") + doAssert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+") + doAssert(not match("456678", peg"(\letter)+")) - assert("var1 = key; var2 = key2".replacef( + doAssert("var1 = key; var2 = key2".replacef( peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") == "var1<-keykey;var2<-key2key2") - assert match("prefix/start", peg"^start$", 7) + doAssert match("prefix/start", peg"^start$", 7) # tricky test to check for false aliasing: block: diff --git a/todo.txt b/todo.txt index ba7fed751..33dc52bf9 100755 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,8 @@ version 0.8.14 ============== -- find a proper bugfix for C compilers optimizing away stack roots +- implement a proper bugfix for C compilers optimizing away stack roots + - cleanup file path handling in the compiler - warning for implicit openArray -> varargs convention - implement explicit varargs; **but** ``len(varargs)`` problem remains! @@ -37,9 +38,6 @@ version 0.9.0 Bugs ---- - bug: generic assign still buggy - - Optimization: If we use a temporary for the result anyway the code gen - should make use of this fact to generate better code... - - bug: memset() without type field initialization? - 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: diff --git a/web/news.txt b/web/news.txt index b4c76cdc3..22e0377c5 100755 --- a/web/news.txt +++ b/web/news.txt @@ -29,7 +29,7 @@ Changes affecting backwards compatibility ``os.iterOverEnvironment``, ``os.pcDirectory``, ``os.pcLinkToDirectory``, ``os.SplitPath``, ``os.extractDir``, ``os.SplitFilename``, ``os.extractFileTrunk``, ``os.extractFileExt``, ``osproc.executeProcess``, - ``osproc.executeCommand``. + ``osproc.executeCommand``. - Removed deprecated ``parseopt.init``, ``parseopt.getRestOfCommandLine``. - Moved ``strutils.validEmailAddress`` to ``matchers.validEmailAddress``. - The pointer dereference operator ``^`` has been removed, so that ``^`` @@ -53,8 +53,8 @@ Changes affecting backwards compatibility because they should not be used directly anymore. Wrapper procs have been created that should be used instead. - ``export`` is now a keyword. -- ``assert`` is now implemented in pure Nimrod; it's easy to implement your - own assertion schemes now. +- ``assert`` is now implemented in pure Nimrod as a template; it's easy + to implement your own assertion templates with ``system.astToStr``. Language Additions @@ -112,6 +112,7 @@ Compiler Additions - Added ``--import:file`` and ``--include:file`` configuration options for specifying modules that will be automatically imported/incluced. - ``nimrod i`` can now optionally be given a module to execute. +- The compiler now performs a simple aliases analysis to generate better code. Library Additions @@ -128,7 +129,7 @@ Library Additions - Added ``system.program_result``. - Added ``xmltree.innerText``. - Added ``os.isAbsolute``, ``os.dynLibFormat``, ``os.isRootDir``, - ``os.parentDirs``. + ``os.parentDirs``. - Added ``parseutils.interpolatedFragments``. - Added ``macros.treeRepr``, ``macros.lispRepr``, ``macros.dumpTree``, ``macros.dumpLisp``, ``macros.parseExpr``, ``macros.parseStmt``, @@ -142,7 +143,7 @@ Library Additions and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to the old implementation. - Added ``intsets.assign``. -- Added ``system.astToStr`` and ``system.rand``. +- Added ``system.astToStr`` and ``system.rand``, ``system.doAssert``. 2011-07-10 Version 0.8.12 released |