parent
0d75723f91
commit
6ff8752be5
52 changed files with 464 additions and 324 deletions
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -670,36 +670,33 @@ proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,10 @@ 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:
|
||||||
|
result = esc("`")
|
||||||
|
for i in 0.. <n.len: result.add(getName(n[i], splitAfter))
|
||||||
|
result.add esc("`")
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "getName()")
|
internalError(n.info, "getName()")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
@ -308,7 +311,9 @@ 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:
|
||||||
|
result = getRstName(n.sons[0])
|
||||||
|
for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text)
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "getRstName()")
|
internalError(n.info, "getRstName()")
|
||||||
result = nil
|
result = nil
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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:
|
|
||||||
result = lookup(c, n.sons[0])
|
|
||||||
of nkSym:
|
|
||||||
result = n.sym
|
|
||||||
of nkIdent:
|
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)
|
||||||
|
|
@ -105,13 +125,14 @@ type
|
||||||
|
|
||||||
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:
|
|
||||||
result = QualifiedLookup(c, n.sons[0], flags)
|
|
||||||
else:
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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_:_")
|
||||||
|
|
@ -825,7 +825,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
# 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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -127,13 +118,6 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
||||||
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))
|
||||||
|
|
|
||||||
|
|
@ -501,13 +501,16 @@ 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)
|
|
||||||
else:
|
|
||||||
result = SymtabGet(c.Tab, n.ident) # no need for stub loading
|
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
result = nil
|
result = nil
|
||||||
if onlyCurrentScope: return
|
if onlyCurrentScope: return
|
||||||
|
|
@ -523,8 +526,7 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
|
||||||
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
|
||||||
|
|
@ -958,11 +960,10 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
|
|
||||||
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:
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
------
|
------
|
||||||
|
|
|
||||||
14
koch.nim
14
koch.nim
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -142,9 +142,8 @@ 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::
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,9 +53,15 @@ 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:
|
||||||
|
# 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!)"
|
result = $e & " (invalid data!)"
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
##
|
##
|
||||||
## can_alias_specialised_generic Nimrod Module
|
## can_alias_specialised_generic Nimrod Module
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
TDict[TK, TV] = object
|
TDict[TK, TV] = object
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
TMatcherKind = enum
|
TMatcherKind = enum
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
# Compiles:
|
# Compiles:
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
import winlean
|
import winlean
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
TA = object
|
TA = object
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
PNode = ref TNode
|
PNode = ref TNode
|
||||||
TNode = tuple[self: PNode]
|
TNode = tuple[self: PNode]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
discard """
|
||||||
|
disabled: true
|
||||||
|
"""
|
||||||
|
|
||||||
import math, algorithm
|
import math, algorithm
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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, "")
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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: {})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -207,6 +212,20 @@ proc reject(r: var TResults, dir, options: string) =
|
||||||
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)
|
||||||
|
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue