diff options
52 files changed, 459 insertions, 319 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index e1d389b63..fa7880c30 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -273,7 +273,7 @@ type tfNoSideEffect, # procedure type does not allow side effects tfFinal, # is the object final? tfAcyclic, # type is acyclic (for GC optimization) - tfEnumHasWholes, # enum cannot be mapped into a range + tfEnumHasHoles, # enum cannot be mapped into a range tfShallow # type can be shallow copied on assignment TTypeFlags* = set[TTypeFlag] diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 840200444..84e1850ad 100755 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -669,37 +669,34 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) = [expr, toRope(length)]) appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp]) -proc genEnumInfo(m: BModule, typ: PType, name: PRope) = - var - nodePtrs, elemNode, enumNames, enumArray, counter, specialCases: PRope - length, firstNimNode: int - field: PSym +proc genEnumInfo(m: BModule, typ: PType, name: PRope) = # Type information for enumerations is quite heavy, so we do some # optimizations here: The ``typ`` field is never set, as it is redundant # anyway. We generate a cstring array and a loop over it. Exceptional # positions will be reset after the loop. genTypeInfoAux(m, typ, name) - nodePtrs = getTempName() - length = sonsLen(typ.n) + var nodePtrs = getTempName() + var length = sonsLen(typ.n) appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", [nodePtrs, toRope(length)]) - enumNames = nil - specialCases = nil - firstNimNode = m.typeNodes + var enumNames, specialCases: PRope + var firstNimNode = m.typeNodes + var hasHoles = false for i in countup(0, length - 1): assert(typ.n.sons[i].kind == nkSym) - field = typ.n.sons[i].sym - elemNode = getNimNode(m) + var field = typ.n.sons[i].sym + var elemNode = getNimNode(m) if field.ast == nil: # no explicit string literal for the enum field, so use field.name: app(enumNames, makeCString(field.name.s)) else: app(enumNames, makeCString(field.ast.strVal)) if i < length - 1: app(enumNames, ", " & tnl) - if field.position != i: + if field.position != i or tfEnumHasHoles in typ.flags: appf(specialCases, "$1.offset = $2;$n", [elemNode, toRope(field.position)]) - enumArray = getTempName() - counter = getTempName() + hasHoles = true + var enumArray = getTempName() + var counter = getTempName() appf(m.s[cfsTypeInit1], "NI $1;$n", [counter]) appf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n", [enumArray, toRope(length), enumNames]) @@ -711,6 +708,9 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) = appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n", [getNimNode(m), toRope(length), nodePtrs, name]) + if hasHoles: + # 1 << 2 is {ntfEnumHole} + appf(m.s[cfsTypeInit3], "$1->flags = 1<<2;$n", [name]) proc genSetInfo(m: BModule, typ: PType, name: PRope) = assert(typ.sons[0] != nil) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 74316871d..eeb40f256 100755 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -297,8 +297,11 @@ proc getName(n: PNode, splitAfter: int = - 1): string = of nkPragmaExpr: result = getName(n.sons[0], splitAfter) of nkSym: result = esc(n.sym.name.s, splitAfter) of nkIdent: result = esc(n.ident.s, splitAfter) - of nkAccQuoted: result = esc("`") & getName(n.sons[0], splitAfter) & esc("`") - else: + of nkAccQuoted: + result = esc("`") + for i in 0.. <n.len: result.add(getName(n[i], splitAfter)) + result.add esc("`") + else: internalError(n.info, "getName()") result = "" @@ -308,8 +311,10 @@ proc getRstName(n: PNode): PRstNode = of nkPragmaExpr: result = getRstName(n.sons[0]) of nkSym: result = newRstNode(rnLeaf, n.sym.name.s) of nkIdent: result = newRstNode(rnLeaf, n.ident.s) - of nkAccQuoted: result = getRstName(n.sons[0]) - else: + of nkAccQuoted: + result = getRstName(n.sons[0]) + for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text) + else: internalError(n.info, "getRstName()") result = nil diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index a673c5ca0..8fa52b5d2 100755 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -69,7 +69,8 @@ const linkerExe: "llvm-gcc", linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", includeCmd: " -I", - debug: "", pic: "-fPIC", + debug: "", + pic: "-fPIC", asmStmtFrmt: "asm($1);$n", props: {hasSwitchRange, hasComputedGoto, hasCpp}), (name: "clang", @@ -83,7 +84,8 @@ const linkerExe: "clang", linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", includeCmd: " -I", - debug: "", pic: "-fPIC", + debug: "", + pic: "-fPIC", asmStmtFrmt: "asm($1);$n", props: {hasSwitchRange, hasComputedGoto, hasCpp}), (name: "lcc", diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 80a6cd17e..0aaff6bc5 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -12,6 +12,24 @@ import ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer +proc considerAcc*(n: PNode): PIdent = + case n.kind + of nkIdent: result = n.ident + of nkSym: result = n.sym.name + of nkAccQuoted: + case n.len + of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n)) + of 1: result = considerAcc(n.sons[0]) + else: + var id = "" + for i in 0.. <n.len: + if n.sons[i].kind != nkIdent: + GlobalError(n.info, errIdentifierExpected, renderTree(n)) + id.add(n.sons[i].ident.s) + result = getIdent(id) + else: + GlobalError(n.info, errIdentifierExpected, renderTree(n)) + type TOverloadIterMode* = enum oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice, @@ -87,13 +105,15 @@ proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int) = proc lookUp*(c: PContext, n: PNode): PSym = # Looks up a symbol. Generates an error in case of nil. case n.kind - of nkAccQuoted: - result = lookup(c, n.sons[0]) - of nkSym: - result = n.sym - of nkIdent: + of nkIdent: result = SymtabGet(c.Tab, n.ident) if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s) + of nkSym: + result = n.sym + of nkAccQuoted: + var ident = considerAcc(n) + result = SymtabGet(c.Tab, ident) + if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s) else: InternalError(n.info, "lookUp") if IntSetContains(c.AmbiguousSymbols, result.id): LocalError(n.info, errUseQualifier, result.name.s) @@ -102,16 +122,17 @@ proc lookUp*(c: PContext, n: PNode): PSym = type TLookupFlag* = enum checkAmbiguity, checkUndeclared - + proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = case n.kind - of nkIdent: - result = SymtabGet(c.Tab, n.ident) + of nkIdent, nkAccQuoted: + var ident = considerAcc(n) + result = SymtabGet(c.Tab, ident) if result == nil and checkUndeclared in flags: - GlobalError(n.info, errUndeclaredIdentifier, n.ident.s) + GlobalError(n.info, errUndeclaredIdentifier, ident.s) elif checkAmbiguity in flags and result != nil and IntSetContains(c.AmbiguousSymbols, result.id): - LocalError(n.info, errUseQualifier, n.ident.s) + LocalError(n.info, errUseQualifier, ident.s) of nkSym: result = n.sym if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, @@ -122,11 +143,10 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) if (m != nil) and (m.kind == skModule): var ident: PIdent = nil - if (n.sons[1].kind == nkIdent): + if n.sons[1].kind == nkIdent: ident = n.sons[1].ident - elif (n.sons[1].kind == nkAccQuoted) and - (n.sons[1].sons[0].kind == nkIdent): - ident = n.sons[1].sons[0].ident + elif n.sons[1].kind == nkAccQuoted: + ident = considerAcc(n.sons[1]) if ident != nil: if m == c.module: result = StrTableGet(c.tab.stack[ModuleTablePos], ident) @@ -137,21 +157,20 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = elif checkUndeclared in flags: GlobalError(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1])) - of nkAccQuoted: - result = QualifiedLookup(c, n.sons[0], flags) - else: + else: result = nil - if (result != nil) and (result.kind == skStub): loadStub(result) + if result != nil and result.kind == skStub: loadStub(result) proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = case n.kind - of nkIdent: + of nkIdent, nkAccQuoted: + var ident = considerAcc(n) o.stackPtr = c.tab.tos o.mode = oimNoQualifier - while result == nil: + while result == nil: dec(o.stackPtr) - if o.stackPtr < 0: break - result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident) + if o.stackPtr < 0: break + result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], ident) of nkSym: result = n.sym o.mode = oimDone @@ -162,9 +181,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = var ident: PIdent = nil if n.sons[1].kind == nkIdent: ident = n.sons[1].ident - elif n.sons[1].kind == nkAccQuoted and - n.sons[1].sons[0].kind == nkIdent: - ident = n.sons[1].sons[0].ident + elif n.sons[1].kind == nkAccQuoted: + ident = considerAcc(n.sons[1]) if ident != nil: if o.m == c.module: # a module may access its private members: @@ -175,8 +193,6 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = else: GlobalError(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1])) - of nkAccQuoted: - result = InitOverloadIter(o, c, n.sons[0]) of nkSymChoice: o.mode = oimSymChoice result = n.sons[0].sym @@ -191,9 +207,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = of oimDone: result = nil of oimNoQualifier: - if n.kind == nkAccQuoted: - result = nextOverloadIter(o, c, n.sons[0]) - elif o.stackPtr >= 0: + if o.stackPtr >= 0: result = nextIdentIter(o.it, c.tab.stack[o.stackPtr]) while result == nil: dec(o.stackPtr) diff --git a/compiler/nimrod.ini b/compiler/nimrod.ini index 3a88fd521..3cca80b51 100755 --- a/compiler/nimrod.ini +++ b/compiler/nimrod.ini @@ -73,33 +73,11 @@ Files: "lib/wrappers/x11/*.nim" Files: "lib/wrappers/zip/*.nim" Files: "lib/wrappers/zip/libzip_all.c" -Files: "lib/oldwrappers/*.nim" - -Files: "lib/oldwrappers/cairo/*.nim" -Files: "lib/oldwrappers/gtk/*.nim" -Files: "lib/oldwrappers/lua/*.nim" -Files: "lib/oldwrappers/opengl/*.nim" -Files: "lib/oldwrappers/pcre/*.nim" -Files: "lib/oldwrappers/pcre/pcre_all.c" -Files: "lib/oldwrappers/sdl/*.nim" -Files: "lib/oldwrappers/x11/*.nim" -Files: "lib/oldwrappers/zip/*.nim" -Files: "lib/oldwrappers/zip/libzip_all.c" - Files: "lib/windows/*.nim" Files: "lib/posix/*.nim" Files: "lib/ecmas/*.nim" [Other] -Files: "tests/*.nim" -Files: "tests/*.html" -Files: "tests/*.txt" -Files: "tests/*.cfg" -Files: "tests/*.tmpl" -Files: "tests/accept/run/*.nim" -Files: "tests/accept/compile/*.nim" -Files: "tests/reject/*.nim" - Files: "examples/*.nim" Files: "examples/*.html" Files: "examples/*.txt" diff --git a/compiler/parser.nim b/compiler/parser.nim index 1b8f2f259..181ae19a7 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -52,7 +52,6 @@ proc optInd*(p: var TParser, n: PNode) proc indAndComment*(p: var TParser, n: PNode) proc setBaseFlags*(n: PNode, base: TNumericalBase) proc parseSymbol*(p: var TParser): PNode -proc accExpr*(p: var TParser): PNode # implementation proc initParser(p: var TParser) = @@ -173,60 +172,33 @@ proc parseSymbol(p: var TParser): PNode = of tkAccent: result = newNodeP(nkAccQuoted, p) getTok(p) - var id = "" while true: case p.tok.tokType of tkBracketLe: - id.add("[]") + add(result, newIdentNodeP(getIdent"[]", p)) getTok(p) eat(p, tkBracketRi) of tkEquals: - id.add('=') + add(result, newIdentNodeP(getIdent"=", p)) getTok(p) - of tkParLe: - id.add("()") + of tkParLe: + add(result, newIdentNodeP(getIdent"()", p)) getTok(p) eat(p, tkParRi) of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot: - id.add(p.tok.ident.s) + add(result, newIdentNodeP(p.tok.ident, p)) getTok(p) of tkIntLit..tkCharLit: - id.add(tokToStr(p.tok)) + add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p)) getTok(p) else: - if id.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok)) + if result.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok)) break - add(result, newIdentNodeP(getIdent(id), p)) eat(p, tkAccent) else: parMessage(p, errIdentifierExpected, tokToStr(p.tok)) result = ast.emptyNode -proc accExpr(p: var TParser): PNode = - result = newNodeP(nkAccQuoted, p) - getTok(p) # skip ` - var x = ast.emptyNode - var y = ast.emptyNode - case p.tok.tokType - of tkSymbol, tkOpr, tokKeywordLow..tokKeywordHigh: - x = newIdentNodeP(p.tok.ident, p) - getTok(p) - else: - parMessage(p, errIdentifierExpected, tokToStr(p.tok)) - if p.tok.tokType == tkDot: - getTok(p) - case p.tok.tokType - of tkSymbol, tkOpr, tokKeywordLow..tokKeywordHigh: - y = newNodeP(nkDotExpr, p) - addSon(y, x) - addSon(y, newIdentNodeP(p.tok.ident, p)) - getTok(p) - x = y - else: - parMessage(p, errIdentifierExpected, tokToStr(p.tok)) - addSon(result, x) - eat(p, tkAccent) - proc indexExpr(p: var TParser): PNode = result = parseExpr(p) @@ -379,7 +351,7 @@ proc identOrLiteral(p: var TParser): PNode = getTok(p) result = parseGStrLit(p, result) of tkAccent: - result = accExpr(p) # literals + result = parseSymbol(p) # literals of tkIntLit: result = newIntNodeP(nkIntLit, p.tok.iNumber, p) setBaseFlags(result, p.tok.base) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 476709f8d..2167c8e5d 100755 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -369,7 +369,7 @@ proc lsub(n: PNode): int = of nkPragmaExpr: result = lsub(n.sons[0]) + lcomma(n, 1) of nkRange: result = lsons(n) + 2 of nkDerefExpr: result = lsub(n.sons[0]) + 2 - of nkAccQuoted: result = lsub(n.sons[0]) + 2 + of nkAccQuoted: result = lsons(n) + 2 of nkIfExpr: result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) + len("if_:_") @@ -823,9 +823,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = gsub(g, n.sons[0]) putWithSpace(g, tkHat, "^") # unfortunately this requires a space, because ^. would be only one operator - of nkAccQuoted: + of nkAccQuoted: put(g, tkAccent, "`") - gsub(g, n.sons[0]) + if n.len > 0: gsub(g, n.sons[0]) + for i in 0 .. <n.len: + put(g, tkSpaces, Space) + gsub(g, n.sons[i]) put(g, tkAccent, "`") of nkIfExpr: putWithSpace(g, tkIf, "if") diff --git a/compiler/sem.nim b/compiler/sem.nim index 2b2d9506b..2e63ea2ef 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -18,16 +18,6 @@ import proc semPass*(): TPass # implementation -proc considerAcc(n: PNode): PIdent = - var x = n - if x.kind == nkAccQuoted: x = x.sons[0] - case x.kind - of nkIdent: result = x.ident - of nkSym: result = x.sym.name - else: - GlobalError(n.info, errIdentifierExpected, renderTree(n)) - result = nil - proc isTopLevel(c: PContext): bool {.inline.} = result = c.tab.tos <= 2 @@ -35,7 +25,8 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerAcc(n), getCurrOwner()) result.info = n.info -proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym +proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, + allowed: TSymFlags): PSym # identifier with visability proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym @@ -120,20 +111,13 @@ proc typeMismatch(n: PNode, formal, actual: PType) = proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = result = IndexTypesMatch(c, formal, arg.typ, arg) - if result == nil: + if result == nil: #debug(arg) typeMismatch(arg, formal, arg.typ) proc forceBool(c: PContext, n: PNode): PNode = result = fitNode(c, getSysType(tyBool), n) if result == nil: result = n - when false: - result = t - if (t.Typ == nil) or - (skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool): - var a = ConvertTo(c, getSysType(tyBool), t) - if a != nil: result = a - else: LocalError(t.Info, errExprMustBeBool) proc semConstBoolExpr(c: PContext, n: PNode): PNode = result = fitNode(c, getSysType(tyBool), semExprWithType(c, n)) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 35fb793c4..a7b35f08b 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -501,14 +501,17 @@ proc semEcho(c: PContext, n: PNode): PNode = n.sons[i] = semExpr(c, buildStringify(c, arg)) result = n +proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym = + if onlyCurrentScope: + result = SymtabLocalGet(c.tab, i) + else: + result = SymtabGet(c.Tab, i) # no need for stub loading + proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = case n.kind of nkIdent: - if onlyCurrentScope: - result = SymtabLocalGet(c.tab, n.ident) - else: - result = SymtabGet(c.Tab, n.ident) # no need for stub loading - of nkDotExpr: + result = LookupForDefined(c, n.ident, onlyCurrentScope) + of nkDotExpr: result = nil if onlyCurrentScope: return checkSonsLen(n, 2) @@ -522,9 +525,8 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = result = StrTableGet(m.tab, ident) else: GlobalError(n.sons[1].info, errIdentifierExpected, "") - of nkAccQuoted: - checkSonsLen(n, 1) - result = lookupForDefined(c, n.sons[0], onlyCurrentScope) + of nkAccQuoted: + result = lookupForDefined(c, considerAcc(n), onlyCurrentScope) else: GlobalError(n.info, errIdentifierExpected, renderTree(n)) result = nil @@ -955,17 +957,16 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = else: GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments})) - + proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = n - if gCmd == cmdIdeTools: - suggestExpr(c, n) + if gCmd == cmdIdeTools: suggestExpr(c, n) if nfSem in n.flags: return - case n.kind # atoms: - of nkIdent: + case n.kind + of nkIdent, nkAccQuoted: var s = lookUp(c, n) result = semSym(c, n, s, flags) - of nkSym: + of nkSym: # because of the changed symbol binding, this does not mean that we # don't have to check the symbol for semantics here again! result = semSym(c, n, n.sym, flags) @@ -1062,9 +1063,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = checkSonsLen(n, 1) n.sons[0] = semExpr(c, n.sons[0], flags) of nkCast: result = semCast(c, n) - of nkAccQuoted: - checkSonsLen(n, 1) - result = semExpr(c, n.sons[0]) of nkIfExpr: result = semIfExpr(c, n) of nkStmtListExpr: result = semStmtListExpr(c, n) of nkBlockExpr: result = semBlockExpr(c, n) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 4894843f8..463fd72ca 100755 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -53,17 +53,12 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode = proc getIdentNode(n: PNode): PNode = case n.kind of nkPostfix: result = getIdentNode(n.sons[1]) - of nkPragmaExpr, nkAccQuoted: result = getIdentNode(n.sons[0]) - of nkIdent: result = n + of nkPragmaExpr: result = getIdentNode(n.sons[0]) + of nkIdent, nkAccQuoted: result = n else: illFormedAst(n) result = n -# of nkAccQuoted: -# s = lookUp(c, n) -# if withinBind in flags: result = symChoice(c, n, s) -# else: result = semGenericStmtSymbol(c, n, s) - proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode = result = n diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 624b8f196..341434275 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -127,7 +127,7 @@ proc semWhile(c: PContext, n: PNode): PNode = proc toCover(t: PType): biggestInt = var t2 = skipTypes(t, abstractVarRange) - if t2.kind == tyEnum and enumHasWholes(t2): + if t2.kind == tyEnum and enumHasHoles(t2): result = sonsLen(t2.n) else: result = lengthOrd(skipTypes(t, abstractVar)) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index ed9b9f4d5..91a00de11 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -51,7 +51,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = else: x = getOrdValue(v) if i != 1: - if (x != counter): incl(result.flags, tfEnumHasWholes) + if (x != counter): incl(result.flags, tfEnumHasHoles) if x < counter: GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) e.ast = strVal # might be nil @@ -128,7 +128,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = if not (a.typ.kind in {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): GlobalError(n.info, errOrdinalTypeExpected) - if enumHasWholes(a.typ): + if enumHasHoles(a.typ): GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty) addSon(result.n, a) @@ -155,7 +155,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = if indx.kind != tyGenericParam: if not isOrdinalType(indx): GlobalError(n.sons[1].info, errOrdinalTypeExpected) - if enumHasWholes(indx): + if enumHasHoles(indx): GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s) base = semTypeNode(c, n.sons[2], nil) addSon(result, base) diff --git a/compiler/types.nim b/compiler/types.nim index dcabbd3ee..953366deb 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -48,7 +48,7 @@ type proc equalParams*(a, b: PNode): TParamsEquality # returns whether the parameter lists of the procs a, b are exactly the same proc isOrdinalType*(t: PType): bool -proc enumHasWholes*(t: PType): bool +proc enumHasHoles*(t: PType): bool const abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal} abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal} @@ -193,10 +193,10 @@ proc isOrdinalType(t: PType): bool = result = (t.Kind in {tyChar, tyInt..tyInt64, tyBool, tyEnum}) or (t.Kind in {tyRange, tyOrdinal}) and isOrdinalType(t.sons[0]) -proc enumHasWholes(t: PType): bool = +proc enumHasHoles(t: PType): bool = var b = t while b.kind == tyRange: b = b.sons[0] - result = (b.Kind == tyEnum) and (tfEnumHasWholes in b.flags) + result = b.Kind == tyEnum and tfEnumHasHoles in b.flags proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter, closure: PObject): bool diff --git a/doc/manual.txt b/doc/manual.txt index 9067946ac..a284c6a0b 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -346,10 +346,10 @@ notation: ``0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64`` is approximately 1.72826e35 according to the IEEE floating point standard. - -Operators ---------- - + +Operators +--------- + In Nimrod one can define his own operators. An `operator`:idx: is any combination of the following characters:: @@ -358,14 +358,14 @@ combination of the following characters:: ! ? ^ . : \ These keywords are also operators: -``and or not xor shl shr div mod in notin is isnot``. - -`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they -are used for other notational purposes. - -``*:`` is as a special case the two tokens `*`:tok: and `:`:tok: +``and or not xor shl shr div mod in notin is isnot``. + +`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they +are used for other notational purposes. + +``*:`` is as a special case the two tokens `*`:tok: and `:`:tok: (to support ``var v*: T``). - + Other tokens ------------ @@ -373,10 +373,10 @@ Other tokens The following strings denote other tokens:: ` ( ) { } [ ] , ; [. .] {. .} (. .) - - -The `slice`:idx: operator `..`:tok: takes precedence over other tokens that -contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: + + +The `slice`:idx: operator `..`:tok: takes precedence over other tokens that +contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: and not the two tokens `{.`:tok:, `.}`:tok:. @@ -398,7 +398,7 @@ Precedence level Operators First characte 9 (highest) ``$ ^`` OP9 8 ``* / div mod shl shr %`` ``* % \ /`` OP8 7 ``+ -`` ``+ ~ |`` OP7 - 6 ``&`` ``&`` OP6 + 6 ``&`` ``&`` OP6 5 ``..`` ``.`` OP5 4 ``== <= < >= > != in not_in is isnot not`` ``= < > !`` OP4 3 ``and`` OP3 @@ -1815,34 +1815,34 @@ Example: An if expression always results in a value, so the ``else`` part is required. ``Elif`` parts are also allowed (but unlikely to be good style). - - -Table constructor + + +Table constructor ~~~~~~~~~~~~~~~~~ - -A `table constructor`:idx: is syntactic sugar for an array constructor: - -.. code-block:: nimrod - {"key1": "value1", "key2": "value2"} - - # is the same as: - [("key1", "value1"), ("key2", "value2")] - - -The empty table can be written ``{:}`` (in contrast to the empty set -which is ``{}``) which is thus another way to write as the empty array -constructor ``[]``. This slightly unusal way of supporting tables + +A `table constructor`:idx: is syntactic sugar for an array constructor: + +.. code-block:: nimrod + {"key1": "value1", "key2": "value2"} + + # is the same as: + [("key1", "value1"), ("key2", "value2")] + + +The empty table can be written ``{:}`` (in contrast to the empty set +which is ``{}``) which is thus another way to write as the empty array +constructor ``[]``. This slightly unusal way of supporting tables has lots of advantages: - -* The order of the (key,value)-pairs is preserved, thus it is easy to - support ordered dicts with for example ``{key: val}.newOrderedTable``. -* A table literal can be put into a ``const`` section and the compiler - can easily put it into the executable's data section just like it can - for arrays and the generated data section requires a minimal amount - of memory. -* Every table implementation is treated equal syntactically. -* Apart from the minimal syntactic sugar the language core does not need to - know about tables. + +* The order of the (key,value)-pairs is preserved, thus it is easy to + support ordered dicts with for example ``{key: val}.newOrderedTable``. +* A table literal can be put into a ``const`` section and the compiler + can easily put it into the executable's data section just like it can + for arrays and the generated data section requires a minimal amount + of memory. +* Every table implementation is treated equal syntactically. +* Apart from the minimal syntactic sugar the language core does not need to + know about tables. Type conversions @@ -2248,7 +2248,7 @@ introduce type parameters or to instantiate a generic proc, iterator or type. Templates -~~~~~~~~~ +--------- A `template`:idx: is a simple form of a macro: It is a simple substitution mechanism that operates on Nimrod's abstract syntax trees. It is processed in @@ -2372,6 +2372,24 @@ powerful programming construct that still suffices. So the "check list" is: (3) Else: Use a template, if possible. (4) Else: Use a macro. +Identifier construction +~~~~~~~~~~~~~~~~~~~~~~~ + +In templates identifiers can be constructed with the backticks notation: + +.. code-block:: nimrod + + template typedef(name: expr, typ: typeDesc) = + type + `T name`* = typ + `P name`* = ref `T name` + + typedef(myint, int) + var x: PMyInt + +In the example ``name`` is instantiated with ``myint``, so \`T name\` becomes +``Tmyint``. + Macros ------ @@ -2986,10 +3004,10 @@ string expressions in general: proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} **Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant -strings, because they are precompiled. - -**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime -because of order of initialization problems. +strings, because they are precompiled. + +**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime +because of order of initialization problems. Dynlib pragma for export diff --git a/koch.nim b/koch.nim index 4c4f107da..2200578ad 100755 --- a/koch.nim +++ b/koch.nim @@ -32,7 +32,8 @@ Possible Commands: web generates the website csource [options] builds the C sources for installation zip builds the installation ZIP package - inno [options] builds the Inno Setup installer + inno [options] builds the Inno Setup installer (for Windows) + tests run the testsuite Boot options: -d:release produce a release version of the compiler -d:tinyc include the Tiny C backend (not supported on Windows) @@ -52,11 +53,11 @@ proc tryExec(cmd: string): bool = result = execShellCmd(cmd) == 0 proc csource(args: string) = - exec("nimrod cc $1 -r tools/niminst --var:version=$2 csource compiler/nimrod $1" % + exec("nimrod cc $1 -r tools/niminst --var:version=$2 csource compiler/nimrod.ini $1" % [args, NimrodVersion]) proc zip(args: string) = - exec("nimrod cc -r tools/niminst --var:version=$# zip compiler/nimrod" % + exec("nimrod cc -r tools/niminst --var:version=$# zip compiler/nimrod.ini" % NimrodVersion) proc buildTool(toolname, args: string) = @@ -172,6 +173,12 @@ proc clean(args: string) = removePattern("web/*.html") removePattern("doc/*.html") cleanAux(getCurrentDir()) + for kind, path in walkDir(getCurrentDir() / "build"): + if kind == pcDir: RemoveDir(path) + +proc tests(args: string) = + exec("nimrod cc tests/tester") + exec("tests/tester") proc showHelp() = quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)), @@ -190,6 +197,7 @@ of cmdArgument: of "zip": zip(op.cmdLineRest) of "inno": inno(op.cmdLineRest) of "install": install(op.cmdLineRest) + of "test", "tests": tests(op.cmdLineRest) else: showHelp() of cmdEnd: showHelp() diff --git a/lib/pure/collections/hashtables.nim b/lib/pure/collections/hashtables.nim index 9562d3a6a..29ba6bf6f 100644 --- a/lib/pure/collections/hashtables.nim +++ b/lib/pure/collections/hashtables.nim @@ -23,21 +23,21 @@ type PHashTable*[A, B] = ref THashTable[A, B] ## use this type to declare tables -proc len*[A, B](t: PHashTable[A, B]): int = +proc len*[A, B](t: THashTable[A, B]): int = ## returns the number of keys in `t`. result = t.counter -iterator pairs*[A, B](t: PHashTable[A, B]): tuple[key: A, val: B] = +iterator pairs*[A, B](t: THashTable[A, B]): tuple[key: A, val: B] = ## iterates over any (key, value) pair in the table `t`. for h in 0..high(t.data): if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val) -iterator keys*[A, B](t: PHashTable[A, B]): A = +iterator keys*[A, B](t: THashTable[A, B]): A = ## iterates over any key in the table `t`. for h in 0..high(t.data): if t.data[h].slot == seFilled: yield t.data[h].key -iterator values*[A, B](t: PHashTable[A, B]): B = +iterator values*[A, B](t: THashTable[A, B]): B = ## iterates over any value in the table `t`. for h in 0..high(t.data): if t.data[h].slot == seFilled: yield t.data[h].val @@ -52,7 +52,7 @@ proc mustRehash(length, counter: int): bool {.inline.} = proc nextTry(h, maxHash: THash): THash {.inline.} = result = ((5 * h) + 1) and maxHash -proc RawGet[A, B](t: PHashTable[A, B], key: A): int = +template rawGetImpl() = var h: THash = hash(key) and high(t.data) # start with real hash value while t.data[h].slot != seEmpty: if t.data[h].key == key and t.data[h].slot == seFilled: @@ -60,7 +60,18 @@ proc RawGet[A, B](t: PHashTable[A, B], key: A): int = h = nextTry(h, high(t.data)) result = -1 -proc `[]`*[A, B](t: PHashTable[A, B], key: A): B = +template rawInsertImpl() = + var h: THash = hash(key) and high(data) + while data[h].slot == seFilled: + h = nextTry(h, high(data)) + data[h].key = key + data[h].val = val + data[h].slot = seFilled + +proc RawGet[A, B](t: THashTable[A, B], key: A): int = + rawGetImpl() + +proc `[]`*[A, B](t: THashTable[A, B], key: A): B = ## retrieves the value at ``t[key]``. If `key` is not in `t`, ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key @@ -68,28 +79,22 @@ proc `[]`*[A, B](t: PHashTable[A, B], key: A): B = var index = RawGet(t, key) if index >= 0: result = t.data[index].val -proc hasKey*[A, B](t: PHashTable[A, B], key: A): bool = +proc hasKey*[A, B](t: THashTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc RawInsert[A, B](t: PHashTable[A, B], data: var TKeyValuePairSeq[A, B], +proc RawInsert[A, B](t: var THashTable[A, B], data: var TKeyValuePairSeq[A, B], key: A, val: B) = - var h: THash = hash(key) and high(data) - while data[h].slot == seFilled: - h = nextTry(h, high(data)) - data[h].key = key - data[h].val = val - data[h].slot = seFilled + rawInsertImpl() -proc Enlarge[A, B](t: PHashTable[A, B]) = +proc Enlarge[A, B](t: var THashTable[A, B]) = var n: TKeyValuePairSeq[A, B] newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) -proc `[]=`*[A, B](t: PHashTable[A, B], key: A, val: B) = - ## puts a (key, value)-pair into `t`. +template PutImpl() = var index = RawGet(t, key) if index >= 0: t.data[index].val = val @@ -98,23 +103,25 @@ proc `[]=`*[A, B](t: PHashTable[A, B], key: A, val: B) = RawInsert(t, t.data, key, val) inc(t.counter) -proc del*[A, B](t: PHashTable[A, B], key: A) = +proc `[]=`*[A, B](t: var THashTable[A, B], key: A, val: B) = + ## puts a (key, value)-pair into `t`. + putImpl() + +proc del*[A, B](t: var THashTable[A, B], key: A) = ## deletes `key` from hash table `t`. var index = RawGet(t, key) if index >= 0: t.data[index].slot = seDeleted dec(t.counter) -proc newHashTable*[A, B](initialSize = 64): PHashTable[A, B] = +proc initHashTable*[A, B](initialSize = 64): THashTable[A, B] = ## creates a new string table that is empty. `initialSize` needs to be ## a power of two. assert isPowerOfTwo(initialSize) - new(result) result.counter = 0 newSeq(result.data, initialSize) -proc `$`*[A, B](t: PHashTable[A, B]): string = - ## The `$` operator for string tables. +template dollarImpl(): stmt = if t.len == 0: result = "{:}" else: @@ -126,6 +133,108 @@ proc `$`*[A, B](t: PHashTable[A, B]): string = result.add($val) result.add("}") +proc `$`*[A, B](t: THashTable[A, B]): string = + ## The `$` operator for string tables. + dollarImpl() + +# ------------------------------ ordered table ------------------------------ + +type + TOrderedKeyValuePair[A, B] = tuple[ + slot: TSlotEnum, next: int, key: A, val: B] + TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]] + TOrderedHashTable*[A, B] {.final.} = object + data: TOrderedKeyValuePairSeq[A, B] + counter, first, last: int + +proc len*[A, B](t: TOrderedHashTable[A, B]): int {.inline.} = + ## returns the number of keys in `t`. + result = t.counter + +template forAllOrderedPairs(yieldStmt: stmt) = + var i = t.first + while i >= 0: + var nxt = t.data[i].next + if t.data[h].slot == seFilled: yieldStmt + i = nxt + +iterator pairs*[A, B](t: TOrderedHashTable[A, B]): tuple[key: A, val: B] = + ## iterates over any (key, value) pair in the table `t` in insertion + ## order. + forAllOrderedPairs: + yield (t.data[h].key, t.data[h].val) + +iterator keys*[A, B](t: TOrderedHashTable[A, B]): A = + ## iterates over any key in the table `t` in insertion order. + forAllOrderedPairs: + yield t.data[h].key + +iterator values*[A, B](t: TOrderedHashTable[A, B]): B = + ## iterates over any value in the table `t` in insertion order. + forAllOrderedPairs: + yield t.data[h].val + +proc RawGet[A, B](t: TOrderedHashTable[A, B], key: A): int = + rawGetImpl() + +proc `[]`*[A, B](t: TOrderedHashTable[A, B], key: A): B = + ## retrieves the value at ``t[key]``. If `key` is not in `t`, + ## default empty value for the type `B` is returned + ## and no exception is raised. One can check with ``hasKey`` whether the key + ## exists. + var index = RawGet(t, key) + if index >= 0: result = t.data[index].val + +proc hasKey*[A, B](t: TOrderedHashTable[A, B], key: A): bool = + ## returns true iff `key` is in the table `t`. + result = rawGet(t, key) >= 0 + +proc RawInsert[A, B](t: TOrderedHashTable[A, B], + data: var TOrderedKeyValuePairSeq[A, B], + key: A, val: B) = + rawInsertImpl() + data[h].next = -1 + if first < 0: first = h + if last >= 0: data[last].next = h + lastEntry = h + +proc Enlarge[A, B](t: TOrderedHashTable[A, B]) = + var n: TOrderedKeyValuePairSeq[A, B] + newSeq(n, len(t.data) * growthFactor) + forAllOrderedPairs: + RawInsert(t, n, t.data[h].key, t.data[h].val) + swap(t.data, n) + +proc `[]=`*[A, B](t: TOrderedHashTable[A, B], key: A, val: B) = + ## puts a (key, value)-pair into `t`. + var index = RawGet(t, key) + if index >= 0: + t.data[index].val = val + else: + if mustRehash(len(t.data), t.counter): Enlarge(t) + RawInsert(t, t.data, key, val) + inc(t.counter) + +proc del*[A, B](t: TOrderedHashTable[A, B], key: A) = + ## deletes `key` from hash table `t`. + var index = RawGet(t, key) + if index >= 0: + t.data[index].slot = seDeleted + dec(t.counter) + +proc initHashTable*[A, B](initialSize = 64): TOrderedHashTable[A, B] = + ## creates a new string table that is empty. `initialSize` needs to be + ## a power of two. + assert isPowerOfTwo(initialSize) + result.counter = 0 + result.first = -1 + result.last = -1 + newSeq(result.data, initialSize) + +proc `$`*[A, B](t: TOrderedHashTable[A, B]): string = + ## The `$` operator for hash tables. + dollarImpl() + # ------------------------------ count tables ------------------------------- const diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index f88560304..78f489615 100755 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -142,19 +142,18 @@ proc newStringTable*(mode: TStringTableMode): PStringTable {. result.counter = 0 newSeq(result.data, startSize) -when false: - proc newStringTable(keyValuePairs: openarray[string], - mode = modeCaseSensitive): PStringTable {. - rtl, extern: "nst$1WithPairs".} = - ## creates a new string table with given key value pairs. - ## Example:: - ## var mytab = newStringTable("key1", "val1", "key2", "val2", - ## modeCaseInsensitive) - result = newStringTable(mode) - var i = 0 - while i < high(keyValuePairs): - result[keyValuePairs[i]] = keyValuePairs[i + 1] - inc(i, 2) +proc newStringTable*(keyValuePairs: openarray[string], + mode: TStringTableMode): PStringTable {. + rtl, extern: "nst$1WithPairs".} = + ## creates a new string table with given key value pairs. + ## Example:: + ## var mytab = newStringTable("key1", "val1", "key2", "val2", + ## modeCaseInsensitive) + result = newStringTable(mode) + var i = 0 + while i < high(keyValuePairs): + result[keyValuePairs[i]] = keyValuePairs[i + 1] + inc(i, 2) proc newStringTable*(keyValuePairs: openarray[tuple[key, val: string]], mode: TStringTableMode = modeCaseSensitive): PStringTable {. diff --git a/lib/system.nim b/lib/system.nim index 815d14fa4..bacb4325a 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -1349,7 +1349,7 @@ template accumulateResult*(iter: expr) = # we have to compute this here before turning it off in except.nim anyway ... const nimrodStackTrace = compileOption("stacktrace") -{.push checks: off, line_dir: off, debugger: off.} +{.push checks: off, line_dir: off, debugger: off.} # obviously we cannot generate checking operations here :-) # because it would yield into an endless recursion # however, stack-traces are available for most parts diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 3343000ae..d22109061 100755 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -45,7 +45,9 @@ type # This should be he same as ast.TTypeKind TNimTypeFlag = enum ntfNoRefs = 0, # type contains no tyRef, tySequence, tyString - ntfAcyclic = 1 # type cannot form a cycle + ntfAcyclic = 1, # type cannot form a cycle + ntfEnumHole = 2 # enum has holes and thus `$` for them needs the slow + # version TNimType {.compilerproc, final.} = object size: int kind: TNimKind diff --git a/lib/system/repr.nim b/lib/system/repr.nim index a70989cad..87588421f 100755 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -53,10 +53,16 @@ proc reprChar(x: char): string {.compilerRtl.} = add result, "\'" proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} = - if e <% typ.node.len: # BUGFIX - result = $typ.node.sons[e].name + if ntfEnumHole notin typ.flags: + if e <% typ.node.len: + return $typ.node.sons[e].name else: - result = $e & " (invalid data!)" + # ugh we need a slow linear search: + var n = typ.node + var s = n.sons + for i in 0 .. n.len-1: + if s[i].offset == e: return $s[i].name + result = $e & " (invalid data!)" type pbyteArray = ptr array[0.. 0xffff, byte] diff --git a/tests/accept/compile/tcan_alias_specialised_generic.nim b/tests/accept/compile/tcan_alias_specialised_generic.nim index 9e93e7266..a8f1972c8 100644 --- a/tests/accept/compile/tcan_alias_specialised_generic.nim +++ b/tests/accept/compile/tcan_alias_specialised_generic.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + ## ## can_alias_specialised_generic Nimrod Module ## diff --git a/tests/accept/compile/tconsteval.nim b/tests/accept/compile/tconsteval.nim index ce90d7c27..10af9ad35 100755 --- a/tests/accept/compile/tconsteval.nim +++ b/tests/accept/compile/tconsteval.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + import strutils const diff --git a/tests/accept/compile/tdictdestruct.nim b/tests/accept/compile/tdictdestruct.nim index 8d828aaf7..9c1f27ed8 100755 --- a/tests/accept/compile/tdictdestruct.nim +++ b/tests/accept/compile/tdictdestruct.nim @@ -1,3 +1,6 @@ +discard """ + disabled: true +""" type TDict[TK, TV] = object diff --git a/tests/accept/compile/tgenericmatcher.nim b/tests/accept/compile/tgenericmatcher.nim index eaf3da67c..6ff0dd505 100644 --- a/tests/accept/compile/tgenericmatcher.nim +++ b/tests/accept/compile/tgenericmatcher.nim @@ -1,3 +1,6 @@ +discard """ + disabled: true +""" type TMatcherKind = enum diff --git a/tests/accept/compile/tgenericrefs.nim b/tests/accept/compile/tgenericrefs.nim index b0e77cef5..2a3de7edd 100644 --- a/tests/accept/compile/tgenericrefs.nim +++ b/tests/accept/compile/tgenericrefs.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + # Compiles: type diff --git a/tests/accept/compile/tlexer.nim b/tests/accept/compile/tlexer.nim index 968a10bdf..10a8ab51d 100755 --- a/tests/accept/compile/tlexer.nim +++ b/tests/accept/compile/tlexer.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + # We start with a comment # This is the same comment diff --git a/tests/accept/compile/tmodulealias.nim b/tests/accept/compile/tmodulealias.nim index 1154cb99d..a7d155e51 100755 --- a/tests/accept/compile/tmodulealias.nim +++ b/tests/accept/compile/tmodulealias.nim @@ -1,4 +1,6 @@ - +discard """ + disabled: true +""" when defined(windows): import winlean diff --git a/tests/accept/compile/toop.nim b/tests/accept/compile/toop.nim index d103c6304..db6d9e595 100755 --- a/tests/accept/compile/toop.nim +++ b/tests/accept/compile/toop.nim @@ -1,3 +1,6 @@ +discard """ + disabled: true +""" type TA = object diff --git a/tests/accept/compile/trectuple.nim b/tests/accept/compile/trectuple.nim index c9ac45797..f60fe2841 100755 --- a/tests/accept/compile/trectuple.nim +++ b/tests/accept/compile/trectuple.nim @@ -1,3 +1,7 @@ +discard """ + disabled: true +""" + type PNode = ref TNode TNode = tuple[self: PNode] diff --git a/tests/accept/compile/tsortdev.nim b/tests/accept/compile/tsortdev.nim index 1246d7581..c4e63fab4 100755 --- a/tests/accept/compile/tsortdev.nim +++ b/tests/accept/compile/tsortdev.nim @@ -1,3 +1,6 @@ +discard """ + disabled: true +""" import math, algorithm diff --git a/tests/accept/compile/tstrtabs.nim b/tests/accept/compile/tstrtabs.nim index 299db609d..251ec77ef 100755 --- a/tests/accept/compile/tstrtabs.nim +++ b/tests/accept/compile/tstrtabs.nim @@ -1,6 +1,6 @@ import strtabs -var tab = newStringTable(["key1", "val1", "key2", "val2"], +var tab = newStringTable({"key1": "val1", "key2": "val2"}, modeStyleInsensitive) for i in 0..80: tab["key_" & $i] = "value" & $i diff --git a/tests/accept/compile/ttempl3.nim b/tests/accept/compile/ttempl3.nim index 0c8fa9a94..7b2c70f79 100755 --- a/tests/accept/compile/ttempl3.nim +++ b/tests/accept/compile/ttempl3.nim @@ -24,3 +24,19 @@ var ha = 1 echo(ha) + +# Test identifier generation: +template prefix(name: expr): expr = `"hu" name` + +var `hu "XYZ"` = "yay" + +echo prefix(XYZ) + +template typedef(name: expr, typ: typeDesc) = + type + `T name`* = typ + `P name`* = ref `T name` + +typedef(myint, int) +var x: PMyInt + diff --git a/tests/accept/run/tassert.nim b/tests/accept/run/tassert.nim index e32ee0a84..50793c3d6 100755 --- a/tests/accept/run/tassert.nim +++ b/tests/accept/run/tassert.nim @@ -1,22 +1,22 @@ discard """ file: "tassert.nim" - output: "assertion failure!this shall be always written" + outputsub: "assertion failure!this shall be always written" """ -# test assert and exception handling - -proc callB() = assert(False) -proc callA() = callB() -proc callC() = callA() - -try: - callC() -except EAssertionFailed: - write(stdout, "assertion failure!") -except: - write(stdout, "unknown exception!") -finally: - system.write(stdout, "this shall be always written") - -assert(false) #OUT assertion failure!this shall be always written +# test assert and exception handling + +proc callB() = assert(False) +proc callA() = callB() +proc callC() = callA() + +try: + callC() +except EAssertionFailed: + write(stdout, "assertion failure!") +except: + write(stdout, "unknown exception!") +finally: + system.write(stdout, "this shall be always written") + +assert(false) #OUT assertion failure!this shall be always written diff --git a/tests/accept/run/tcgbug.nim b/tests/accept/run/tcgbug.nim index aa0f0fa6b..417b909ae 100755 --- a/tests/accept/run/tcgbug.nim +++ b/tests/accept/run/tcgbug.nim @@ -1,6 +1,6 @@ discard """ file: "tcgbug.nim" - output: "" + output: "success" """ type @@ -19,5 +19,5 @@ var new(a) q(a) - +echo "success" diff --git a/tests/accept/run/tclosure.nim b/tests/accept/run/tclosure.nim index 28a51e1ac..d7c0ec0e3 100755 --- a/tests/accept/run/tclosure.nim +++ b/tests/accept/run/tclosure.nim @@ -1,6 +1,7 @@ discard """ file: "tclosure.nim" output: "2 4 6 8 10" + disabled: true """ # Test the closure implementation diff --git a/tests/accept/run/tcontinuexc.nim b/tests/accept/run/tcontinuexc.nim index c43e68c93..82cce923e 100755 --- a/tests/accept/run/tcontinuexc.nim +++ b/tests/accept/run/tcontinuexc.nim @@ -1,6 +1,6 @@ discard """ file: "tcontinuexc.nim" - output: "ECcaught" + outputsub: "ECcaught" """ type ESomething = object of E_Base diff --git a/tests/accept/run/texcsub.nim b/tests/accept/run/texcsub.nim index 3dba357f9..e78da8df6 100755 --- a/tests/accept/run/texcsub.nim +++ b/tests/accept/run/texcsub.nim @@ -1,6 +1,7 @@ discard """ file: "texcsub.nim" output: "caught!" + disabled: true """ # Test inheritance for exception matching: diff --git a/tests/accept/run/texplicitgeneric2.nim b/tests/accept/run/texplicitgeneric2.nim index f2e628223..95461d023 100755 --- a/tests/accept/run/texplicitgeneric2.nim +++ b/tests/accept/run/texplicitgeneric2.nim @@ -1,5 +1,6 @@ discard """ output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13" + disabled: true """ # test explicit type instantiation diff --git a/tests/accept/run/tfloat1.nim b/tests/accept/run/tfloat1.nim index 3826bf1f5..7d6e0c6a3 100755 --- a/tests/accept/run/tfloat1.nim +++ b/tests/accept/run/tfloat1.nim @@ -1,6 +1,6 @@ discard """ file: "tfloat1.nim" - output: "Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]" + outputsub: "Error: unhandled exception: FPU operation caused an overflow [EFloatOverflow]" """ # Test new floating point exceptions diff --git a/tests/accept/run/tfloat2.nim b/tests/accept/run/tfloat2.nim index e7a9ce76f..b0df1e8b7 100755 --- a/tests/accept/run/tfloat2.nim +++ b/tests/accept/run/tfloat2.nim @@ -1,6 +1,6 @@ discard """ file: "tfloat2.nim" - output: "Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]" + outputsub: "Error: unhandled exception: FPU operation caused a NaN result [EFloatInvalidOp]" """ # Test new floating point exceptions diff --git a/tests/accept/run/tgenerics1.nim b/tests/accept/run/tgenerics1.nim index cb310f552..5d20a864b 100755 --- a/tests/accept/run/tgenerics1.nim +++ b/tests/accept/run/tgenerics1.nim @@ -41,7 +41,7 @@ proc add*[T](heap: PBinHeap[T], priority: int, data: T) = proc print*[T](heap: PBinHeap[T]) = for i in countup(0, heap.last): - echo heap.heap[i].data + stdout.write($heap.heap[i].data, " ") var heap: PBinHeap[int] diff --git a/tests/accept/run/tmatrix.nim b/tests/accept/run/tmatrix.nim index 1dd09291b..90dfde959 100755 --- a/tests/accept/run/tmatrix.nim +++ b/tests/accept/run/tmatrix.nim @@ -19,30 +19,12 @@ proc createMatrix*(width, height: int): TMatrix = proc width*(m: TMatrix): int {.inline.} = return m.fWidth proc height*(m: TMatrix): int {.inline.} = return m.fHeight -proc `[,]`*(m: TMatrix, x, y: int): float {.inline.} = +proc `[]`*(m: TMatrix, x, y: int): float {.inline.} = result = m.data[x|y] -proc `[,]=`*(m: var TMatrix, x, y: int, val: float) {.inline.} = +proc `[]=`*(m: var TMatrix, x, y: int, val: float) {.inline.} = m.data[x|y] = val -proc `[$ .. $, $ .. $]`*(m: TMatrix, a, b, c, d: int): TMatrix = - result = createMatrix(b-a+1, d-c+1) - for x in a..b: - for y in c..d: - result[x-a, y-c] = m[x, y] - -proc `[$ .. $, $ .. $]=`*(m: var TMatrix, a, b, c, d: int, val: float) = - for x in a..b: - for y in c..d: - m[x, y] = val - -proc `[$ .. $, $ .. $]=`*(m: var TMatrix, a, b, c, d: int, val: TMatrix) = - assert val.width == b-a+1 - assert val.height == d-c+1 - for x in a..b: - for y in c..d: - m[x, y] = val[x-a, y-c] - proc `-|`*(m: TMatrix): TMatrix = ## transposes a matrix result = createMatrix(m.height, m.width) diff --git a/tests/accept/run/toverflw2.nim b/tests/accept/run/toverflw2.nim index 14a77ebad..075eae9e9 100755 --- a/tests/accept/run/toverflw2.nim +++ b/tests/accept/run/toverflw2.nim @@ -1,6 +1,6 @@ discard """ file: "toverflw2.nim" - output: "Error: unhandled exception: over- or underflow [EOverflow]" + outputsub: "Error: unhandled exception: over- or underflow [EOverflow]" """ var a : int32 = 2147483647 var b : int32 = 2147483647 diff --git a/tests/accept/run/treraise.nim b/tests/accept/run/treraise.nim index 7e147c336..71736b512 100755 --- a/tests/accept/run/treraise.nim +++ b/tests/accept/run/treraise.nim @@ -1,6 +1,6 @@ discard """ file: "treraise.nim" - output: "Error: unhandled exception: bla [ESomeOtherErr]" + outputsub: "Error: unhandled exception: bla [ESomeOtherErr]" """ type ESomething = object of E_Base diff --git a/tests/accept/run/tunhandledexc.nim b/tests/accept/run/tunhandledexc.nim index c60de2234..ae62b4ee5 100755 --- a/tests/accept/run/tunhandledexc.nim +++ b/tests/accept/run/tunhandledexc.nim @@ -1,6 +1,6 @@ discard """ file: "tunhandledexc.nim" - output: "Error: unhandled exception: bla [ESomeOtherErr]" + outputsub: "Error: unhandled exception: bla [ESomeOtherErr]" """ type ESomething = object of E_Base diff --git a/tests/accept/run/twrongexc.nim b/tests/accept/run/twrongexc.nim index 592693769..81f4d5595 100755 --- a/tests/accept/run/twrongexc.nim +++ b/tests/accept/run/twrongexc.nim @@ -1,6 +1,6 @@ discard """ file: "twrongexc.nim" - output: "Error: unhandled exception [EInvalidValue]" + outputsub: "Error: unhandled exception [EInvalidValue]" """ try: raise newException(EInvalidValue, "") diff --git a/tests/reject/tnot.nim b/tests/reject/tnot.nim index 8075a4768..1985ef666 100755 --- a/tests/reject/tnot.nim +++ b/tests/reject/tnot.nim @@ -1,6 +1,5 @@ discard """ file: "system.nim" - line: 599 errormsg: "type mismatch" """ # BUG: following compiles, but should not: diff --git a/tests/reject/trectype.nim b/tests/reject/trectype.nim index b8b23a806..7bb12a3b6 100755 --- a/tests/reject/trectype.nim +++ b/tests/reject/trectype.nim @@ -1,6 +1,4 @@ discard """ - file: "trectype.nim" - line: 25 errormsg: "internal error: cannot generate C type for: PA" """ # Test recursive type descriptions diff --git a/tests/reject/ttypelessemptyset.nim b/tests/reject/ttypelessemptyset.nim index 68bfb0249..3e171387b 100755 --- a/tests/reject/ttypelessemptyset.nim +++ b/tests/reject/ttypelessemptyset.nim @@ -1,11 +1,6 @@ discard """ - file: "ttypelessemptyset.nim" - line: 5 errormsg: "internal error: invalid kind for last(tyEmpty)" """ var q = false discard (if q: {} else: {}) - - - diff --git a/tests/tester.nim b/tests/tester.nim index 00fe7909a..9e5028567 100755 --- a/tests/tester.nim +++ b/tests/tester.nim @@ -27,6 +27,7 @@ type msg: string err: bool disabled: bool + substr: bool TResults {.pure.} = object total, passed, skipped: int data: string @@ -53,7 +54,7 @@ proc extractSpec(filename: string): string = if a >= 0 and b > a: result = x.copy(a+3, b-1).replace("'''", tripleQuote) else: - echo "warning: file does not contain spec: " & filename + #echo "warning: file does not contain spec: " & filename result = "" template parseSpecAux(fillResult: stmt) = @@ -87,6 +88,9 @@ proc parseSpec(filename: string): TSpec = of "file": result.file = e.value of "line": discard parseInt(e.value, result.line) of "output": result.outp = e.value + of "outputsub": + result.outp = e.value + result.substr = true of "errormsg", "msg": result.msg = e.value of "disabled": result.disabled = parseCfgBool(e.value) of "cmd": result.cmd = e.value @@ -184,9 +188,10 @@ proc listResults(reject, compile, run: TResults) = proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) = if strip(expected.msg) notin strip(given.msg): r.addResult(test, expected.msg, given.msg, reFailure) - elif extractFilename(expected.file) != extractFilename(given.file): + elif extractFilename(expected.file) != extractFilename(given.file) and + "internal error:" notin expected.msg: r.addResult(test, expected.file, given.file, reFailure) - elif expected.line != given.line: + elif expected.line != given.line and expected.line != 0: r.addResult(test, $expected.line, $given.line, reFailure) else: r.addResult(test, expected.msg, given.msg, reSuccess) @@ -206,7 +211,21 @@ proc reject(r: var TResults, dir, options: string) = var given = callCompiler(expected.cmd, test, options) cmpMsgs(r, expected, given, t) -proc compile(r: var TResults, pattern, options: string) = +proc compile(r: var TResults, pattern, options: string) = + for test in os.walkFiles(pattern): + var t = extractFilename(test) + echo t + inc(r.total) + var expected = parseSpec(test) + if expected.disabled: + r.addResult(t, "", reIgnored) + inc(r.skipped) + else: + var given = callCompiler(expected.cmd, test, options) + r.addResult(t, given.msg, if given.err: reFailure else: reSuccess) + if not given.err: inc(r.passed) + +proc compileExample(r: var TResults, pattern, options: string) = for test in os.walkFiles(pattern): var t = extractFilename(test) inc(r.total) @@ -233,6 +252,7 @@ proc run(r: var TResults, dir, options: string) = if existsFile(exeFile): var buf = myExec(exeFile) var success = strip(buf) == strip(expected.outp) + if expected.substr: success = expected.outp in buf if success: inc(r.passed) r.addResult(t, expected.outp, buf, if success: reSuccess else: reFailure) @@ -250,8 +270,8 @@ for i in 1.. paramCount(): reject(rejectRes, "tests/reject", options) compile(compileRes, "tests/accept/compile/t*.nim", options) -compile(compileRes, "examples/*.nim", options) -compile(compileRes, "examples/gtk/*.nim", options) +compileExample(compileRes, "examples/*.nim", options) +compileExample(compileRes, "examples/gtk/*.nim", options) run(runRes, "tests/accept/run", options) listResults(rejectRes, compileRes, runRes) openDefaultBrowser(resultsFile) diff --git a/todo.txt b/todo.txt index f673f4118..2d4ce4c60 100755 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,3 @@ -- clean up the tests! - implicit ref/ptr->var conversion - warning for implicit openArray -> varargs convention - implement explicit varargs @@ -7,6 +6,8 @@ High priority (version 0.9.0) ============================= +- tests: run modules that contain "when isMainModule", compile the other + modules; run the GC tests - fix implicit generic routines - fix the streams implementation so that it uses methods - fix overloading resolution @@ -50,7 +51,6 @@ Low priority is hard because of partial evaluation --> symbol files will fix this as a side effect - floating point checks for EcmaScript -- enhance `` notation for identifier concatenation: `concat` a `these` - prefer proc in current module over other procs with same overloading result? - real types for template results - generalized case statement (requires better transf) |