mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 13:33:22 +00:00
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
112
doc/manual.txt
112
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
|
||||
|
||||
14
koch.nim
14
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()
|
||||
|
||||
|
||||
@@ -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,20 +60,7 @@ 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 =
|
||||
## 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) =
|
||||
template rawInsertImpl() =
|
||||
var h: THash = hash(key) and high(data)
|
||||
while data[h].slot == seFilled:
|
||||
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].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]
|
||||
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
|
||||
|
||||
@@ -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 {.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
##
|
||||
## can_alias_specialised_generic Nimrod Module
|
||||
##
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
import strutils
|
||||
|
||||
const
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
type
|
||||
TDict[TK, TV] = object
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
type
|
||||
TMatcherKind = enum
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
# Compiles:
|
||||
|
||||
type
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
# We start with a comment
|
||||
# This is the same comment
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
when defined(windows):
|
||||
import winlean
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
type
|
||||
TA = object
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
type
|
||||
PNode = ref TNode
|
||||
TNode = tuple[self: PNode]
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
import math, algorithm
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
file: "tcgbug.nim"
|
||||
output: ""
|
||||
output: "success"
|
||||
"""
|
||||
|
||||
type
|
||||
@@ -19,5 +19,5 @@ var
|
||||
new(a)
|
||||
q(a)
|
||||
|
||||
|
||||
echo "success"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
discard """
|
||||
file: "tclosure.nim"
|
||||
output: "2 4 6 8 10"
|
||||
disabled: true
|
||||
"""
|
||||
# Test the closure implementation
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
file: "tcontinuexc.nim"
|
||||
output: "ECcaught"
|
||||
outputsub: "ECcaught"
|
||||
"""
|
||||
type
|
||||
ESomething = object of E_Base
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
discard """
|
||||
file: "texcsub.nim"
|
||||
output: "caught!"
|
||||
disabled: true
|
||||
"""
|
||||
# Test inheritance for exception matching:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
file: "twrongexc.nim"
|
||||
output: "Error: unhandled exception [EInvalidValue]"
|
||||
outputsub: "Error: unhandled exception [EInvalidValue]"
|
||||
"""
|
||||
try:
|
||||
raise newException(EInvalidValue, "")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
discard """
|
||||
file: "system.nim"
|
||||
line: 599
|
||||
errormsg: "type mismatch"
|
||||
"""
|
||||
# BUG: following compiles, but should not:
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
discard """
|
||||
file: "trectype.nim"
|
||||
line: 25
|
||||
errormsg: "internal error: cannot generate C type for: PA"
|
||||
"""
|
||||
# Test recursive type descriptions
|
||||
|
||||
@@ -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: {})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
4
todo.txt
4
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)
|
||||
|
||||
Reference in New Issue
Block a user