cleaned up the tests; fixes #30; fixes #26

This commit is contained in:
Araq 2011-05-01 20:11:55 +02:00
commit 6ff8752be5
52 changed files with 464 additions and 324 deletions

View file

@ -273,7 +273,7 @@ type
tfNoSideEffect, # procedure type does not allow side effects tfNoSideEffect, # procedure type does not allow side effects
tfFinal, # is the object final? tfFinal, # is the object final?
tfAcyclic, # type is acyclic (for GC optimization) 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 tfShallow # type can be shallow copied on assignment
TTypeFlags* = set[TTypeFlag] TTypeFlags* = set[TTypeFlag]

View file

@ -669,37 +669,34 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
[expr, toRope(length)]) [expr, toRope(length)])
appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp]) appf(m.s[cfsTypeInit3], "$1->node = &$2;$n", [name, tmp])
proc genEnumInfo(m: BModule, typ: PType, name: PRope) = proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
var
nodePtrs, elemNode, enumNames, enumArray, counter, specialCases: PRope
length, firstNimNode: int
field: PSym
# Type information for enumerations is quite heavy, so we do some # Type information for enumerations is quite heavy, so we do some
# optimizations here: The ``typ`` field is never set, as it is redundant # optimizations here: The ``typ`` field is never set, as it is redundant
# anyway. We generate a cstring array and a loop over it. Exceptional # anyway. We generate a cstring array and a loop over it. Exceptional
# positions will be reset after the loop. # positions will be reset after the loop.
genTypeInfoAux(m, typ, name) genTypeInfoAux(m, typ, name)
nodePtrs = getTempName() var nodePtrs = getTempName()
length = sonsLen(typ.n) var length = sonsLen(typ.n)
appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n",
[nodePtrs, toRope(length)]) [nodePtrs, toRope(length)])
enumNames = nil var enumNames, specialCases: PRope
specialCases = nil var firstNimNode = m.typeNodes
firstNimNode = m.typeNodes var hasHoles = false
for i in countup(0, length - 1): for i in countup(0, length - 1):
assert(typ.n.sons[i].kind == nkSym) assert(typ.n.sons[i].kind == nkSym)
field = typ.n.sons[i].sym var field = typ.n.sons[i].sym
elemNode = getNimNode(m) var elemNode = getNimNode(m)
if field.ast == nil: if field.ast == nil:
# no explicit string literal for the enum field, so use field.name: # no explicit string literal for the enum field, so use field.name:
app(enumNames, makeCString(field.name.s)) app(enumNames, makeCString(field.name.s))
else: else:
app(enumNames, makeCString(field.ast.strVal)) app(enumNames, makeCString(field.ast.strVal))
if i < length - 1: app(enumNames, ", " & tnl) 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)]) appf(specialCases, "$1.offset = $2;$n", [elemNode, toRope(field.position)])
enumArray = getTempName() hasHoles = true
counter = getTempName() var enumArray = getTempName()
var counter = getTempName()
appf(m.s[cfsTypeInit1], "NI $1;$n", [counter]) appf(m.s[cfsTypeInit1], "NI $1;$n", [counter])
appf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n", appf(m.s[cfsTypeInit1], "static char* NIM_CONST $1[$2] = {$n$3};$n",
[enumArray, toRope(length), enumNames]) [enumArray, toRope(length), enumNames])
@ -711,6 +708,9 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) =
appf(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
"$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n", "$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n",
[getNimNode(m), toRope(length), nodePtrs, name]) [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) = proc genSetInfo(m: BModule, typ: PType, name: PRope) =
assert(typ.sons[0] != nil) assert(typ.sons[0] != nil)

View file

@ -297,8 +297,11 @@ proc getName(n: PNode, splitAfter: int = - 1): string =
of nkPragmaExpr: result = getName(n.sons[0], splitAfter) of nkPragmaExpr: result = getName(n.sons[0], splitAfter)
of nkSym: result = esc(n.sym.name.s, splitAfter) of nkSym: result = esc(n.sym.name.s, splitAfter)
of nkIdent: result = esc(n.ident.s, splitAfter) of nkIdent: result = esc(n.ident.s, splitAfter)
of nkAccQuoted: result = esc("`") & getName(n.sons[0], splitAfter) & esc("`") of nkAccQuoted:
else: result = esc("`")
for i in 0.. <n.len: result.add(getName(n[i], splitAfter))
result.add esc("`")
else:
internalError(n.info, "getName()") internalError(n.info, "getName()")
result = "" result = ""
@ -308,8 +311,10 @@ proc getRstName(n: PNode): PRstNode =
of nkPragmaExpr: result = getRstName(n.sons[0]) of nkPragmaExpr: result = getRstName(n.sons[0])
of nkSym: result = newRstNode(rnLeaf, n.sym.name.s) of nkSym: result = newRstNode(rnLeaf, n.sym.name.s)
of nkIdent: result = newRstNode(rnLeaf, n.ident.s) of nkIdent: result = newRstNode(rnLeaf, n.ident.s)
of nkAccQuoted: result = getRstName(n.sons[0]) of nkAccQuoted:
else: result = getRstName(n.sons[0])
for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text)
else:
internalError(n.info, "getRstName()") internalError(n.info, "getRstName()")
result = nil result = nil

View file

@ -69,7 +69,8 @@ const
linkerExe: "llvm-gcc", linkerExe: "llvm-gcc",
linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles",
includeCmd: " -I", includeCmd: " -I",
debug: "", pic: "-fPIC", debug: "",
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n", asmStmtFrmt: "asm($1);$n",
props: {hasSwitchRange, hasComputedGoto, hasCpp}), props: {hasSwitchRange, hasComputedGoto, hasCpp}),
(name: "clang", (name: "clang",
@ -83,7 +84,8 @@ const
linkerExe: "clang", linkerExe: "clang",
linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles",
includeCmd: " -I", includeCmd: " -I",
debug: "", pic: "-fPIC", debug: "",
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n", asmStmtFrmt: "asm($1);$n",
props: {hasSwitchRange, hasComputedGoto, hasCpp}), props: {hasSwitchRange, hasComputedGoto, hasCpp}),
(name: "lcc", (name: "lcc",

View file

@ -12,6 +12,24 @@
import import
ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer 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 type
TOverloadIterMode* = enum TOverloadIterMode* = enum
oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice, oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
@ -87,13 +105,15 @@ proc addInterfaceOverloadableSymAt*(c: PContext, sym: PSym, at: int) =
proc lookUp*(c: PContext, n: PNode): PSym = proc lookUp*(c: PContext, n: PNode): PSym =
# Looks up a symbol. Generates an error in case of nil. # Looks up a symbol. Generates an error in case of nil.
case n.kind case n.kind
of nkAccQuoted: of nkIdent:
result = lookup(c, n.sons[0])
of nkSym:
result = n.sym
of nkIdent:
result = SymtabGet(c.Tab, n.ident) result = SymtabGet(c.Tab, n.ident)
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s) 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") else: InternalError(n.info, "lookUp")
if IntSetContains(c.AmbiguousSymbols, result.id): if IntSetContains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, result.name.s) LocalError(n.info, errUseQualifier, result.name.s)
@ -102,16 +122,17 @@ proc lookUp*(c: PContext, n: PNode): PSym =
type type
TLookupFlag* = enum TLookupFlag* = enum
checkAmbiguity, checkUndeclared checkAmbiguity, checkUndeclared
proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
case n.kind case n.kind
of nkIdent: of nkIdent, nkAccQuoted:
result = SymtabGet(c.Tab, n.ident) var ident = considerAcc(n)
result = SymtabGet(c.Tab, ident)
if result == nil and checkUndeclared in flags: 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 elif checkAmbiguity in flags and result != nil and
IntSetContains(c.AmbiguousSymbols, result.id): IntSetContains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, n.ident.s) LocalError(n.info, errUseQualifier, ident.s)
of nkSym: of nkSym:
result = n.sym result = n.sym
if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols, 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}) var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
if (m != nil) and (m.kind == skModule): if (m != nil) and (m.kind == skModule):
var ident: PIdent = nil var ident: PIdent = nil
if (n.sons[1].kind == nkIdent): if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident ident = n.sons[1].ident
elif (n.sons[1].kind == nkAccQuoted) and elif n.sons[1].kind == nkAccQuoted:
(n.sons[1].sons[0].kind == nkIdent): ident = considerAcc(n.sons[1])
ident = n.sons[1].sons[0].ident
if ident != nil: if ident != nil:
if m == c.module: if m == c.module:
result = StrTableGet(c.tab.stack[ModuleTablePos], ident) result = StrTableGet(c.tab.stack[ModuleTablePos], ident)
@ -137,21 +157,20 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
elif checkUndeclared in flags: elif checkUndeclared in flags:
GlobalError(n.sons[1].info, errIdentifierExpected, GlobalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1])) renderTree(n.sons[1]))
of nkAccQuoted: else:
result = QualifiedLookup(c, n.sons[0], flags)
else:
result = nil 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 = proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
case n.kind case n.kind
of nkIdent: of nkIdent, nkAccQuoted:
var ident = considerAcc(n)
o.stackPtr = c.tab.tos o.stackPtr = c.tab.tos
o.mode = oimNoQualifier o.mode = oimNoQualifier
while result == nil: while result == nil:
dec(o.stackPtr) dec(o.stackPtr)
if o.stackPtr < 0: break if o.stackPtr < 0: break
result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident) result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], ident)
of nkSym: of nkSym:
result = n.sym result = n.sym
o.mode = oimDone o.mode = oimDone
@ -162,9 +181,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
var ident: PIdent = nil var ident: PIdent = nil
if n.sons[1].kind == nkIdent: if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted and elif n.sons[1].kind == nkAccQuoted:
n.sons[1].sons[0].kind == nkIdent: ident = considerAcc(n.sons[1])
ident = n.sons[1].sons[0].ident
if ident != nil: if ident != nil:
if o.m == c.module: if o.m == c.module:
# a module may access its private members: # a module may access its private members:
@ -175,8 +193,6 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else: else:
GlobalError(n.sons[1].info, errIdentifierExpected, GlobalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1])) renderTree(n.sons[1]))
of nkAccQuoted:
result = InitOverloadIter(o, c, n.sons[0])
of nkSymChoice: of nkSymChoice:
o.mode = oimSymChoice o.mode = oimSymChoice
result = n.sons[0].sym result = n.sons[0].sym
@ -191,9 +207,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimDone: of oimDone:
result = nil result = nil
of oimNoQualifier: of oimNoQualifier:
if n.kind == nkAccQuoted: if o.stackPtr >= 0:
result = nextOverloadIter(o, c, n.sons[0])
elif o.stackPtr >= 0:
result = nextIdentIter(o.it, c.tab.stack[o.stackPtr]) result = nextIdentIter(o.it, c.tab.stack[o.stackPtr])
while result == nil: while result == nil:
dec(o.stackPtr) dec(o.stackPtr)

View file

@ -73,33 +73,11 @@ Files: "lib/wrappers/x11/*.nim"
Files: "lib/wrappers/zip/*.nim" Files: "lib/wrappers/zip/*.nim"
Files: "lib/wrappers/zip/libzip_all.c" 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/windows/*.nim"
Files: "lib/posix/*.nim" Files: "lib/posix/*.nim"
Files: "lib/ecmas/*.nim" Files: "lib/ecmas/*.nim"
[Other] [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/*.nim"
Files: "examples/*.html" Files: "examples/*.html"
Files: "examples/*.txt" Files: "examples/*.txt"

View file

@ -52,7 +52,6 @@ proc optInd*(p: var TParser, n: PNode)
proc indAndComment*(p: var TParser, n: PNode) proc indAndComment*(p: var TParser, n: PNode)
proc setBaseFlags*(n: PNode, base: TNumericalBase) proc setBaseFlags*(n: PNode, base: TNumericalBase)
proc parseSymbol*(p: var TParser): PNode proc parseSymbol*(p: var TParser): PNode
proc accExpr*(p: var TParser): PNode
# implementation # implementation
proc initParser(p: var TParser) = proc initParser(p: var TParser) =
@ -173,60 +172,33 @@ proc parseSymbol(p: var TParser): PNode =
of tkAccent: of tkAccent:
result = newNodeP(nkAccQuoted, p) result = newNodeP(nkAccQuoted, p)
getTok(p) getTok(p)
var id = ""
while true: while true:
case p.tok.tokType case p.tok.tokType
of tkBracketLe: of tkBracketLe:
id.add("[]") add(result, newIdentNodeP(getIdent"[]", p))
getTok(p) getTok(p)
eat(p, tkBracketRi) eat(p, tkBracketRi)
of tkEquals: of tkEquals:
id.add('=') add(result, newIdentNodeP(getIdent"=", p))
getTok(p) getTok(p)
of tkParLe: of tkParLe:
id.add("()") add(result, newIdentNodeP(getIdent"()", p))
getTok(p) getTok(p)
eat(p, tkParRi) eat(p, tkParRi)
of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot: of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot:
id.add(p.tok.ident.s) add(result, newIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
of tkIntLit..tkCharLit: of tkIntLit..tkCharLit:
id.add(tokToStr(p.tok)) add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p))
getTok(p) getTok(p)
else: else:
if id.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok)) if result.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok))
break break
add(result, newIdentNodeP(getIdent(id), p))
eat(p, tkAccent) eat(p, tkAccent)
else: else:
parMessage(p, errIdentifierExpected, tokToStr(p.tok)) parMessage(p, errIdentifierExpected, tokToStr(p.tok))
result = ast.emptyNode 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 = proc indexExpr(p: var TParser): PNode =
result = parseExpr(p) result = parseExpr(p)
@ -379,7 +351,7 @@ proc identOrLiteral(p: var TParser): PNode =
getTok(p) getTok(p)
result = parseGStrLit(p, result) result = parseGStrLit(p, result)
of tkAccent: of tkAccent:
result = accExpr(p) # literals result = parseSymbol(p) # literals
of tkIntLit: of tkIntLit:
result = newIntNodeP(nkIntLit, p.tok.iNumber, p) result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base) setBaseFlags(result, p.tok.base)

View file

@ -369,7 +369,7 @@ proc lsub(n: PNode): int =
of nkPragmaExpr: result = lsub(n.sons[0]) + lcomma(n, 1) of nkPragmaExpr: result = lsub(n.sons[0]) + lcomma(n, 1)
of nkRange: result = lsons(n) + 2 of nkRange: result = lsons(n) + 2
of nkDerefExpr: result = lsub(n.sons[0]) + 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: of nkIfExpr:
result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) + result = lsub(n.sons[0].sons[0]) + lsub(n.sons[0].sons[1]) + lsons(n, 1) +
len("if_:_") len("if_:_")
@ -823,9 +823,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0]) gsub(g, n.sons[0])
putWithSpace(g, tkHat, "^") putWithSpace(g, tkHat, "^")
# unfortunately this requires a space, because ^. would be only one operator # unfortunately this requires a space, because ^. would be only one operator
of nkAccQuoted: of nkAccQuoted:
put(g, tkAccent, "`") 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, "`") put(g, tkAccent, "`")
of nkIfExpr: of nkIfExpr:
putWithSpace(g, tkIf, "if") putWithSpace(g, tkIf, "if")

View file

@ -18,16 +18,6 @@ import
proc semPass*(): TPass proc semPass*(): TPass
# implementation # 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.} = proc isTopLevel(c: PContext): bool {.inline.} =
result = c.tab.tos <= 2 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 = newSym(kind, considerAcc(n), getCurrOwner())
result.info = n.info 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 # identifier with visability
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym allowed: TSymFlags): PSym
@ -120,20 +111,13 @@ proc typeMismatch(n: PNode, formal, actual: PType) =
proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
result = IndexTypesMatch(c, formal, arg.typ, arg) result = IndexTypesMatch(c, formal, arg.typ, arg)
if result == nil: if result == nil:
#debug(arg) #debug(arg)
typeMismatch(arg, formal, arg.typ) typeMismatch(arg, formal, arg.typ)
proc forceBool(c: PContext, n: PNode): PNode = proc forceBool(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(tyBool), n) result = fitNode(c, getSysType(tyBool), n)
if result == nil: result = 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 = proc semConstBoolExpr(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(tyBool), semExprWithType(c, n)) result = fitNode(c, getSysType(tyBool), semExprWithType(c, n))

View file

@ -501,14 +501,17 @@ proc semEcho(c: PContext, n: PNode): PNode =
n.sons[i] = semExpr(c, buildStringify(c, arg)) n.sons[i] = semExpr(c, buildStringify(c, arg))
result = n 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 = proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
case n.kind case n.kind
of nkIdent: of nkIdent:
if onlyCurrentScope: result = LookupForDefined(c, n.ident, onlyCurrentScope)
result = SymtabLocalGet(c.tab, n.ident) of nkDotExpr:
else:
result = SymtabGet(c.Tab, n.ident) # no need for stub loading
of nkDotExpr:
result = nil result = nil
if onlyCurrentScope: return if onlyCurrentScope: return
checkSonsLen(n, 2) checkSonsLen(n, 2)
@ -522,9 +525,8 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
result = StrTableGet(m.tab, ident) result = StrTableGet(m.tab, ident)
else: else:
GlobalError(n.sons[1].info, errIdentifierExpected, "") GlobalError(n.sons[1].info, errIdentifierExpected, "")
of nkAccQuoted: of nkAccQuoted:
checkSonsLen(n, 1) result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
result = lookupForDefined(c, n.sons[0], onlyCurrentScope)
else: else:
GlobalError(n.info, errIdentifierExpected, renderTree(n)) GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil result = nil
@ -955,17 +957,16 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
else: else:
GlobalError(n.info, errInvalidExpressionX, GlobalError(n.info, errInvalidExpressionX,
renderTree(a, {renderNoComments})) renderTree(a, {renderNoComments}))
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n result = n
if gCmd == cmdIdeTools: if gCmd == cmdIdeTools: suggestExpr(c, n)
suggestExpr(c, n)
if nfSem in n.flags: return if nfSem in n.flags: return
case n.kind # atoms: case n.kind
of nkIdent: of nkIdent, nkAccQuoted:
var s = lookUp(c, n) var s = lookUp(c, n)
result = semSym(c, n, s, flags) result = semSym(c, n, s, flags)
of nkSym: of nkSym:
# because of the changed symbol binding, this does not mean that we # because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again! # don't have to check the symbol for semantics here again!
result = semSym(c, n, n.sym, flags) result = semSym(c, n, n.sym, flags)
@ -1062,9 +1063,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
checkSonsLen(n, 1) checkSonsLen(n, 1)
n.sons[0] = semExpr(c, n.sons[0], flags) n.sons[0] = semExpr(c, n.sons[0], flags)
of nkCast: result = semCast(c, n) of nkCast: result = semCast(c, n)
of nkAccQuoted:
checkSonsLen(n, 1)
result = semExpr(c, n.sons[0])
of nkIfExpr: result = semIfExpr(c, n) of nkIfExpr: result = semIfExpr(c, n)
of nkStmtListExpr: result = semStmtListExpr(c, n) of nkStmtListExpr: result = semStmtListExpr(c, n)
of nkBlockExpr: result = semBlockExpr(c, n) of nkBlockExpr: result = semBlockExpr(c, n)

View file

@ -53,17 +53,12 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
proc getIdentNode(n: PNode): PNode = proc getIdentNode(n: PNode): PNode =
case n.kind case n.kind
of nkPostfix: result = getIdentNode(n.sons[1]) of nkPostfix: result = getIdentNode(n.sons[1])
of nkPragmaExpr, nkAccQuoted: result = getIdentNode(n.sons[0]) of nkPragmaExpr: result = getIdentNode(n.sons[0])
of nkIdent: result = n of nkIdent, nkAccQuoted: result = n
else: else:
illFormedAst(n) illFormedAst(n)
result = 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, proc semGenericStmt(c: PContext, n: PNode,
flags: TSemGenericFlags = {}): PNode = flags: TSemGenericFlags = {}): PNode =
result = n result = n

View file

@ -127,7 +127,7 @@ proc semWhile(c: PContext, n: PNode): PNode =
proc toCover(t: PType): biggestInt = proc toCover(t: PType): biggestInt =
var t2 = skipTypes(t, abstractVarRange) var t2 = skipTypes(t, abstractVarRange)
if t2.kind == tyEnum and enumHasWholes(t2): if t2.kind == tyEnum and enumHasHoles(t2):
result = sonsLen(t2.n) result = sonsLen(t2.n)
else: else:
result = lengthOrd(skipTypes(t, abstractVar)) result = lengthOrd(skipTypes(t, abstractVar))

View file

@ -51,7 +51,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
else: else:
x = getOrdValue(v) x = getOrdValue(v)
if i != 1: if i != 1:
if (x != counter): incl(result.flags, tfEnumHasWholes) if (x != counter): incl(result.flags, tfEnumHasHoles)
if x < counter: if x < counter:
GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
e.ast = strVal # might be nil 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 if not (a.typ.kind in
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
GlobalError(n.info, errOrdinalTypeExpected) GlobalError(n.info, errOrdinalTypeExpected)
if enumHasWholes(a.typ): if enumHasHoles(a.typ):
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty) if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
addSon(result.n, a) addSon(result.n, a)
@ -155,7 +155,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
if indx.kind != tyGenericParam: if indx.kind != tyGenericParam:
if not isOrdinalType(indx): if not isOrdinalType(indx):
GlobalError(n.sons[1].info, errOrdinalTypeExpected) GlobalError(n.sons[1].info, errOrdinalTypeExpected)
if enumHasWholes(indx): if enumHasHoles(indx):
GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s) GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
base = semTypeNode(c, n.sons[2], nil) base = semTypeNode(c, n.sons[2], nil)
addSon(result, base) addSon(result, base)

View file

@ -48,7 +48,7 @@ type
proc equalParams*(a, b: PNode): TParamsEquality proc equalParams*(a, b: PNode): TParamsEquality
# returns whether the parameter lists of the procs a, b are exactly the same # returns whether the parameter lists of the procs a, b are exactly the same
proc isOrdinalType*(t: PType): bool proc isOrdinalType*(t: PType): bool
proc enumHasWholes*(t: PType): bool proc enumHasHoles*(t: PType): bool
const const
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal} abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal}
abstractVar* = {tyVar, 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 result = (t.Kind in {tyChar, tyInt..tyInt64, tyBool, tyEnum}) or
(t.Kind in {tyRange, tyOrdinal}) and isOrdinalType(t.sons[0]) (t.Kind in {tyRange, tyOrdinal}) and isOrdinalType(t.sons[0])
proc enumHasWholes(t: PType): bool = proc enumHasHoles(t: PType): bool =
var b = t var b = t
while b.kind == tyRange: b = b.sons[0] 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, proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
closure: PObject): bool closure: PObject): bool

View file

@ -346,10 +346,10 @@ notation:
``0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64`` ``0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64``
is approximately 1.72826e35 according to the IEEE floating point standard. 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 In Nimrod one can define his own operators. An `operator`:idx: is any
combination of the following characters:: combination of the following characters::
@ -358,14 +358,14 @@ combination of the following characters::
! ? ^ . : \ ! ? ^ . : \
These keywords are also operators: These keywords are also operators:
``and or not xor shl shr div mod in notin is isnot``. ``and or not xor shl shr div mod in notin is isnot``.
`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they `=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they
are used for other notational purposes. are used for other notational purposes.
``*:`` is as a special case the two tokens `*`:tok: and `:`:tok: ``*:`` is as a special case the two tokens `*`:tok: and `:`:tok:
(to support ``var v*: T``). (to support ``var v*: T``).
Other tokens Other tokens
------------ ------------
@ -373,10 +373,10 @@ Other tokens
The following strings denote other tokens:: The following strings denote other tokens::
` ( ) { } [ ] , ; [. .] {. .} (. .) ` ( ) { } [ ] , ; [. .] {. .} (. .)
The `slice`:idx: operator `..`:tok: takes precedence over other tokens that The `slice`:idx: operator `..`:tok: takes precedence over other tokens that
contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok:
and not the two tokens `{.`:tok:, `.}`:tok:. and not the two tokens `{.`:tok:, `.}`:tok:.
@ -398,7 +398,7 @@ Precedence level Operators First characte
9 (highest) ``$ ^`` OP9 9 (highest) ``$ ^`` OP9
8 ``* / div mod shl shr %`` ``* % \ /`` OP8 8 ``* / div mod shl shr %`` ``* % \ /`` OP8
7 ``+ -`` ``+ ~ |`` OP7 7 ``+ -`` ``+ ~ |`` OP7
6 ``&`` ``&`` OP6 6 ``&`` ``&`` OP6
5 ``..`` ``.`` OP5 5 ``..`` ``.`` OP5
4 ``== <= < >= > != in not_in is isnot not`` ``= < > !`` OP4 4 ``== <= < >= > != in not_in is isnot not`` ``= < > !`` OP4
3 ``and`` OP3 3 ``and`` OP3
@ -1815,34 +1815,34 @@ Example:
An if expression always results in a value, so the ``else`` part is An if expression always results in a value, so the ``else`` part is
required. ``Elif`` parts are also allowed (but unlikely to be good required. ``Elif`` parts are also allowed (but unlikely to be good
style). style).
Table constructor Table constructor
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
A `table constructor`:idx: is syntactic sugar for an array constructor: A `table constructor`:idx: is syntactic sugar for an array constructor:
.. code-block:: nimrod .. code-block:: nimrod
{"key1": "value1", "key2": "value2"} {"key1": "value1", "key2": "value2"}
# is the same as: # is the same as:
[("key1", "value1"), ("key2", "value2")] [("key1", "value1"), ("key2", "value2")]
The empty table can be written ``{:}`` (in contrast to the empty set 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 which is ``{}``) which is thus another way to write as the empty array
constructor ``[]``. This slightly unusal way of supporting tables constructor ``[]``. This slightly unusal way of supporting tables
has lots of advantages: has lots of advantages:
* The order of the (key,value)-pairs is preserved, thus it is easy to * The order of the (key,value)-pairs is preserved, thus it is easy to
support ordered dicts with for example ``{key: val}.newOrderedTable``. support ordered dicts with for example ``{key: val}.newOrderedTable``.
* A table literal can be put into a ``const`` section and the compiler * 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 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 for arrays and the generated data section requires a minimal amount
of memory. of memory.
* Every table implementation is treated equal syntactically. * Every table implementation is treated equal syntactically.
* Apart from the minimal syntactic sugar the language core does not need to * Apart from the minimal syntactic sugar the language core does not need to
know about tables. know about tables.
Type conversions Type conversions
@ -2248,7 +2248,7 @@ introduce type parameters or to instantiate a generic proc, iterator or type.
Templates Templates
~~~~~~~~~ ---------
A `template`:idx: is a simple form of a macro: It is a simple substitution 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 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. (3) Else: Use a template, if possible.
(4) Else: Use a macro. (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 Macros
------ ------
@ -2986,10 +3004,10 @@ string expressions in general:
proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().}
**Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant **Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant
strings, because they are precompiled. strings, because they are precompiled.
**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime **Note**: Passing variables to the ``dynlib`` pragma will fail at runtime
because of order of initialization problems. because of order of initialization problems.
Dynlib pragma for export Dynlib pragma for export

View file

@ -32,7 +32,8 @@ Possible Commands:
web generates the website web generates the website
csource [options] builds the C sources for installation csource [options] builds the C sources for installation
zip builds the installation ZIP package 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: Boot options:
-d:release produce a release version of the compiler -d:release produce a release version of the compiler
-d:tinyc include the Tiny C backend (not supported on Windows) -d:tinyc include the Tiny C backend (not supported on Windows)
@ -52,11 +53,11 @@ proc tryExec(cmd: string): bool =
result = execShellCmd(cmd) == 0 result = execShellCmd(cmd) == 0
proc csource(args: string) = 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]) [args, NimrodVersion])
proc zip(args: string) = 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) NimrodVersion)
proc buildTool(toolname, args: string) = proc buildTool(toolname, args: string) =
@ -172,6 +173,12 @@ proc clean(args: string) =
removePattern("web/*.html") removePattern("web/*.html")
removePattern("doc/*.html") removePattern("doc/*.html")
cleanAux(getCurrentDir()) 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() = proc showHelp() =
quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)), quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)),
@ -190,6 +197,7 @@ of cmdArgument:
of "zip": zip(op.cmdLineRest) of "zip": zip(op.cmdLineRest)
of "inno": inno(op.cmdLineRest) of "inno": inno(op.cmdLineRest)
of "install": install(op.cmdLineRest) of "install": install(op.cmdLineRest)
of "test", "tests": tests(op.cmdLineRest)
else: showHelp() else: showHelp()
of cmdEnd: showHelp() of cmdEnd: showHelp()

View file

@ -23,21 +23,21 @@ type
PHashTable*[A, B] = ref THashTable[A, B] ## use this type to declare tables 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`. ## returns the number of keys in `t`.
result = t.counter 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`. ## iterates over any (key, value) pair in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield (t.data[h].key, t.data[h].val) 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`. ## iterates over any key in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield t.data[h].key 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`. ## iterates over any value in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if t.data[h].slot == seFilled: yield t.data[h].val 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.} = proc nextTry(h, maxHash: THash): THash {.inline.} =
result = ((5 * h) + 1) and maxHash 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 var h: THash = hash(key) and high(t.data) # start with real hash value
while t.data[h].slot != seEmpty: while t.data[h].slot != seEmpty:
if t.data[h].key == key and t.data[h].slot == seFilled: if t.data[h].key == key and t.data[h].slot == seFilled:
@ -60,20 +60,7 @@ proc RawGet[A, B](t: PHashTable[A, B], key: A): int =
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
result = -1 result = -1
proc `[]`*[A, B](t: PHashTable[A, B], key: A): B = template rawInsertImpl() =
## 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: PHashTable[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],
key: A, val: B) =
var h: THash = hash(key) and high(data) var h: THash = hash(key) and high(data)
while data[h].slot == seFilled: while data[h].slot == seFilled:
h = nextTry(h, high(data)) h = nextTry(h, high(data))
@ -81,15 +68,33 @@ proc RawInsert[A, B](t: PHashTable[A, B], data: var TKeyValuePairSeq[A, B],
data[h].val = val data[h].val = val
data[h].slot = seFilled data[h].slot = seFilled
proc Enlarge[A, B](t: PHashTable[A, B]) = 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
## exists.
var index = RawGet(t, key)
if index >= 0: result = t.data[index].val
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: var THashTable[A, B], data: var TKeyValuePairSeq[A, B],
key: A, val: B) =
rawInsertImpl()
proc Enlarge[A, B](t: var THashTable[A, B]) =
var n: TKeyValuePairSeq[A, B] var n: TKeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor) newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)): 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) if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n) swap(t.data, n)
proc `[]=`*[A, B](t: PHashTable[A, B], key: A, val: B) = template PutImpl() =
## puts a (key, value)-pair into `t`.
var index = RawGet(t, key) var index = RawGet(t, key)
if index >= 0: if index >= 0:
t.data[index].val = val 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) RawInsert(t, t.data, key, val)
inc(t.counter) 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`. ## deletes `key` from hash table `t`.
var index = RawGet(t, key) var index = RawGet(t, key)
if index >= 0: if index >= 0:
t.data[index].slot = seDeleted t.data[index].slot = seDeleted
dec(t.counter) 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 ## creates a new string table that is empty. `initialSize` needs to be
## a power of two. ## a power of two.
assert isPowerOfTwo(initialSize) assert isPowerOfTwo(initialSize)
new(result)
result.counter = 0 result.counter = 0
newSeq(result.data, initialSize) newSeq(result.data, initialSize)
proc `$`*[A, B](t: PHashTable[A, B]): string = template dollarImpl(): stmt =
## The `$` operator for string tables.
if t.len == 0: if t.len == 0:
result = "{:}" result = "{:}"
else: else:
@ -126,6 +133,108 @@ proc `$`*[A, B](t: PHashTable[A, B]): string =
result.add($val) result.add($val)
result.add("}") 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 ------------------------------- # ------------------------------ count tables -------------------------------
const const

View file

@ -142,19 +142,18 @@ proc newStringTable*(mode: TStringTableMode): PStringTable {.
result.counter = 0 result.counter = 0
newSeq(result.data, startSize) newSeq(result.data, startSize)
when false: proc newStringTable*(keyValuePairs: openarray[string],
proc newStringTable(keyValuePairs: openarray[string], mode: TStringTableMode): PStringTable {.
mode = modeCaseSensitive): PStringTable {. rtl, extern: "nst$1WithPairs".} =
rtl, extern: "nst$1WithPairs".} = ## creates a new string table with given key value pairs.
## creates a new string table with given key value pairs. ## Example::
## Example:: ## var mytab = newStringTable("key1", "val1", "key2", "val2",
## var mytab = newStringTable("key1", "val1", "key2", "val2", ## modeCaseInsensitive)
## modeCaseInsensitive) result = newStringTable(mode)
result = newStringTable(mode) var i = 0
var i = 0 while i < high(keyValuePairs):
while i < high(keyValuePairs): result[keyValuePairs[i]] = keyValuePairs[i + 1]
result[keyValuePairs[i]] = keyValuePairs[i + 1] inc(i, 2)
inc(i, 2)
proc newStringTable*(keyValuePairs: openarray[tuple[key, val: string]], proc newStringTable*(keyValuePairs: openarray[tuple[key, val: string]],
mode: TStringTableMode = modeCaseSensitive): PStringTable {. mode: TStringTableMode = modeCaseSensitive): PStringTable {.

View file

@ -1349,7 +1349,7 @@ template accumulateResult*(iter: expr) =
# we have to compute this here before turning it off in except.nim anyway ... # we have to compute this here before turning it off in except.nim anyway ...
const nimrodStackTrace = compileOption("stacktrace") 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 :-) # obviously we cannot generate checking operations here :-)
# because it would yield into an endless recursion # because it would yield into an endless recursion
# however, stack-traces are available for most parts # however, stack-traces are available for most parts

View file

@ -45,7 +45,9 @@ type # This should be he same as ast.TTypeKind
TNimTypeFlag = enum TNimTypeFlag = enum
ntfNoRefs = 0, # type contains no tyRef, tySequence, tyString 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 TNimType {.compilerproc, final.} = object
size: int size: int
kind: TNimKind kind: TNimKind

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -53,10 +53,16 @@ proc reprChar(x: char): string {.compilerRtl.} =
add result, "\'" add result, "\'"
proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} = proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
if e <% typ.node.len: # BUGFIX if ntfEnumHole notin typ.flags:
result = $typ.node.sons[e].name if e <% typ.node.len:
return $typ.node.sons[e].name
else: 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 type
pbyteArray = ptr array[0.. 0xffff, byte] pbyteArray = ptr array[0.. 0xffff, byte]

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
## ##
## can_alias_specialised_generic Nimrod Module ## can_alias_specialised_generic Nimrod Module
## ##

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
import strutils import strutils
const const

View file

@ -1,3 +1,6 @@
discard """
disabled: true
"""
type type
TDict[TK, TV] = object TDict[TK, TV] = object

View file

@ -1,3 +1,6 @@
discard """
disabled: true
"""
type type
TMatcherKind = enum TMatcherKind = enum

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
# Compiles: # Compiles:
type type

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
# We start with a comment # We start with a comment
# This is the same comment # This is the same comment

View file

@ -1,4 +1,6 @@
discard """
disabled: true
"""
when defined(windows): when defined(windows):
import winlean import winlean

View file

@ -1,3 +1,6 @@
discard """
disabled: true
"""
type type
TA = object TA = object

View file

@ -1,3 +1,7 @@
discard """
disabled: true
"""
type type
PNode = ref TNode PNode = ref TNode
TNode = tuple[self: PNode] TNode = tuple[self: PNode]

View file

@ -1,3 +1,6 @@
discard """
disabled: true
"""
import math, algorithm import math, algorithm

View file

@ -1,6 +1,6 @@
import strtabs import strtabs
var tab = newStringTable(["key1", "val1", "key2", "val2"], var tab = newStringTable({"key1": "val1", "key2": "val2"},
modeStyleInsensitive) modeStyleInsensitive)
for i in 0..80: for i in 0..80:
tab["key_" & $i] = "value" & $i tab["key_" & $i] = "value" & $i

View file

@ -24,3 +24,19 @@ var
ha = 1 ha = 1
echo(ha) 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

View file

@ -1,22 +1,22 @@
discard """ discard """
file: "tassert.nim" file: "tassert.nim"
output: "assertion failure!this shall be always written" outputsub: "assertion failure!this shall be always written"
""" """
# test assert and exception handling # test assert and exception handling
proc callB() = assert(False) proc callB() = assert(False)
proc callA() = callB() proc callA() = callB()
proc callC() = callA() proc callC() = callA()
try: try:
callC() callC()
except EAssertionFailed: except EAssertionFailed:
write(stdout, "assertion failure!") write(stdout, "assertion failure!")
except: except:
write(stdout, "unknown exception!") write(stdout, "unknown exception!")
finally: finally:
system.write(stdout, "this shall be always written") system.write(stdout, "this shall be always written")
assert(false) #OUT assertion failure!this shall be always written assert(false) #OUT assertion failure!this shall be always written

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tcgbug.nim" file: "tcgbug.nim"
output: "" output: "success"
""" """
type type
@ -19,5 +19,5 @@ var
new(a) new(a)
q(a) q(a)
echo "success"

View file

@ -1,6 +1,7 @@
discard """ discard """
file: "tclosure.nim" file: "tclosure.nim"
output: "2 4 6 8 10" output: "2 4 6 8 10"
disabled: true
""" """
# Test the closure implementation # Test the closure implementation

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tcontinuexc.nim" file: "tcontinuexc.nim"
output: "ECcaught" outputsub: "ECcaught"
""" """
type type
ESomething = object of E_Base ESomething = object of E_Base

View file

@ -1,6 +1,7 @@
discard """ discard """
file: "texcsub.nim" file: "texcsub.nim"
output: "caught!" output: "caught!"
disabled: true
""" """
# Test inheritance for exception matching: # Test inheritance for exception matching:

View file

@ -1,5 +1,6 @@
discard """ discard """
output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13" output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13"
disabled: true
""" """
# test explicit type instantiation # test explicit type instantiation

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tfloat1.nim" 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 # Test new floating point exceptions

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tfloat2.nim" 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 # Test new floating point exceptions

View file

@ -41,7 +41,7 @@ proc add*[T](heap: PBinHeap[T], priority: int, data: T) =
proc print*[T](heap: PBinHeap[T]) = proc print*[T](heap: PBinHeap[T]) =
for i in countup(0, heap.last): for i in countup(0, heap.last):
echo heap.heap[i].data stdout.write($heap.heap[i].data, " ")
var var
heap: PBinHeap[int] heap: PBinHeap[int]

View file

@ -19,30 +19,12 @@ proc createMatrix*(width, height: int): TMatrix =
proc width*(m: TMatrix): int {.inline.} = return m.fWidth proc width*(m: TMatrix): int {.inline.} = return m.fWidth
proc height*(m: TMatrix): int {.inline.} = return m.fHeight 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] 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 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 = proc `-|`*(m: TMatrix): TMatrix =
## transposes a matrix ## transposes a matrix
result = createMatrix(m.height, m.width) result = createMatrix(m.height, m.width)

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "toverflw2.nim" file: "toverflw2.nim"
output: "Error: unhandled exception: over- or underflow [EOverflow]" outputsub: "Error: unhandled exception: over- or underflow [EOverflow]"
""" """
var a : int32 = 2147483647 var a : int32 = 2147483647
var b : int32 = 2147483647 var b : int32 = 2147483647

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "treraise.nim" file: "treraise.nim"
output: "Error: unhandled exception: bla [ESomeOtherErr]" outputsub: "Error: unhandled exception: bla [ESomeOtherErr]"
""" """
type type
ESomething = object of E_Base ESomething = object of E_Base

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "tunhandledexc.nim" file: "tunhandledexc.nim"
output: "Error: unhandled exception: bla [ESomeOtherErr]" outputsub: "Error: unhandled exception: bla [ESomeOtherErr]"
""" """
type type
ESomething = object of E_Base ESomething = object of E_Base

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "twrongexc.nim" file: "twrongexc.nim"
output: "Error: unhandled exception [EInvalidValue]" outputsub: "Error: unhandled exception [EInvalidValue]"
""" """
try: try:
raise newException(EInvalidValue, "") raise newException(EInvalidValue, "")

View file

@ -1,6 +1,5 @@
discard """ discard """
file: "system.nim" file: "system.nim"
line: 599
errormsg: "type mismatch" errormsg: "type mismatch"
""" """
# BUG: following compiles, but should not: # BUG: following compiles, but should not:

View file

@ -1,6 +1,4 @@
discard """ discard """
file: "trectype.nim"
line: 25
errormsg: "internal error: cannot generate C type for: PA" errormsg: "internal error: cannot generate C type for: PA"
""" """
# Test recursive type descriptions # Test recursive type descriptions

View file

@ -1,11 +1,6 @@
discard """ discard """
file: "ttypelessemptyset.nim"
line: 5
errormsg: "internal error: invalid kind for last(tyEmpty)" errormsg: "internal error: invalid kind for last(tyEmpty)"
""" """
var q = false var q = false
discard (if q: {} else: {}) discard (if q: {} else: {})

View file

@ -27,6 +27,7 @@ type
msg: string msg: string
err: bool err: bool
disabled: bool disabled: bool
substr: bool
TResults {.pure.} = object TResults {.pure.} = object
total, passed, skipped: int total, passed, skipped: int
data: string data: string
@ -53,7 +54,7 @@ proc extractSpec(filename: string): string =
if a >= 0 and b > a: if a >= 0 and b > a:
result = x.copy(a+3, b-1).replace("'''", tripleQuote) result = x.copy(a+3, b-1).replace("'''", tripleQuote)
else: else:
echo "warning: file does not contain spec: " & filename #echo "warning: file does not contain spec: " & filename
result = "" result = ""
template parseSpecAux(fillResult: stmt) = template parseSpecAux(fillResult: stmt) =
@ -87,6 +88,9 @@ proc parseSpec(filename: string): TSpec =
of "file": result.file = e.value of "file": result.file = e.value
of "line": discard parseInt(e.value, result.line) of "line": discard parseInt(e.value, result.line)
of "output": result.outp = e.value of "output": result.outp = e.value
of "outputsub":
result.outp = e.value
result.substr = true
of "errormsg", "msg": result.msg = e.value of "errormsg", "msg": result.msg = e.value
of "disabled": result.disabled = parseCfgBool(e.value) of "disabled": result.disabled = parseCfgBool(e.value)
of "cmd": result.cmd = 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) = proc cmpMsgs(r: var TResults, expected, given: TSpec, test: string) =
if strip(expected.msg) notin strip(given.msg): if strip(expected.msg) notin strip(given.msg):
r.addResult(test, expected.msg, given.msg, reFailure) 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) 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) r.addResult(test, $expected.line, $given.line, reFailure)
else: else:
r.addResult(test, expected.msg, given.msg, reSuccess) 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) var given = callCompiler(expected.cmd, test, options)
cmpMsgs(r, expected, given, t) 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): for test in os.walkFiles(pattern):
var t = extractFilename(test) var t = extractFilename(test)
inc(r.total) inc(r.total)
@ -233,6 +252,7 @@ proc run(r: var TResults, dir, options: string) =
if existsFile(exeFile): if existsFile(exeFile):
var buf = myExec(exeFile) var buf = myExec(exeFile)
var success = strip(buf) == strip(expected.outp) var success = strip(buf) == strip(expected.outp)
if expected.substr: success = expected.outp in buf
if success: inc(r.passed) if success: inc(r.passed)
r.addResult(t, expected.outp, r.addResult(t, expected.outp,
buf, if success: reSuccess else: reFailure) buf, if success: reSuccess else: reFailure)
@ -250,8 +270,8 @@ for i in 1.. paramCount():
reject(rejectRes, "tests/reject", options) reject(rejectRes, "tests/reject", options)
compile(compileRes, "tests/accept/compile/t*.nim", options) compile(compileRes, "tests/accept/compile/t*.nim", options)
compile(compileRes, "examples/*.nim", options) compileExample(compileRes, "examples/*.nim", options)
compile(compileRes, "examples/gtk/*.nim", options) compileExample(compileRes, "examples/gtk/*.nim", options)
run(runRes, "tests/accept/run", options) run(runRes, "tests/accept/run", options)
listResults(rejectRes, compileRes, runRes) listResults(rejectRes, compileRes, runRes)
openDefaultBrowser(resultsFile) openDefaultBrowser(resultsFile)

View file

@ -1,4 +1,3 @@
- clean up the tests!
- implicit ref/ptr->var conversion - implicit ref/ptr->var conversion
- warning for implicit openArray -> varargs convention - warning for implicit openArray -> varargs convention
- implement explicit varargs - implement explicit varargs
@ -7,6 +6,8 @@
High priority (version 0.9.0) 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 implicit generic routines
- fix the streams implementation so that it uses methods - fix the streams implementation so that it uses methods
- fix overloading resolution - fix overloading resolution
@ -50,7 +51,6 @@ Low priority
is hard because of partial evaluation --> symbol files will fix this as is hard because of partial evaluation --> symbol files will fix this as
a side effect a side effect
- floating point checks for EcmaScript - 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? - prefer proc in current module over other procs with same overloading result?
- real types for template results - real types for template results
- generalized case statement (requires better transf) - generalized case statement (requires better transf)