diff --git a/compiler/ast.nim b/compiler/ast.nim
index 9055766555..69269be846 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -406,7 +406,8 @@ type
lfNoDecl, # do not declare it in C
lfDynamicLib, # link symbol to dynamic library
lfExportLib, # export symbol for dynamic library generation
- lfHeader # include header file for symbol
+ lfHeader, # include header file for symbol
+ lfImportCompilerProc # ``importc`` of a compilerproc
TStorageLoc* = enum
OnUnknown, # location is unknown (stack, heap or static)
OnStack, # location is on hardware stack
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 38cfafcfae..88284e9fbd 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1452,7 +1452,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
mInSet:
genSetOp(p, e, d, op)
- of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit, mCreateThread:
+ of mCreateThread: genCall(p, e, d)
+ of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit:
var opr = e.sons[0].sym
if lfNoDecl notin opr.loc.flags:
discard cgsym(p.module, opr.loc.r.ropeToStr)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 60c052d5d4..02fcce9800 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -666,17 +666,21 @@ proc genProcPrototype(m: BModule, sym: PSym) =
proc genProcNoForward(m: BModule, prc: PSym) =
fillProcLoc(prc)
useHeader(m, prc)
+ if lfImportCompilerProc in prc.loc.flags:
+ # dependency to a compilerproc:
+ discard cgsym(m, prc.name.s)
+ return
genProcPrototype(m, prc)
- if lfNoDecl in prc.loc.Flags: return
- if prc.typ.callConv == ccInline:
+ if lfNoDecl in prc.loc.Flags: nil
+ elif prc.typ.callConv == ccInline:
# We add inline procs to the calling module to enable C based inlining.
# This also means that a check with ``gGeneratedSyms`` is wrong, we need
# a check for ``m.declaredThings``.
if not ContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
- elif lfDynamicLib in prc.loc.flags:
+ elif lfDynamicLib in prc.loc.flags:
if not ContainsOrIncl(gGeneratedSyms, prc.id):
SymInDynamicLib(findPendingModule(m, prc), prc)
- elif not (sfImportc in prc.flags):
+ elif sfImportc notin prc.flags:
if not ContainsOrIncl(gGeneratedSyms, prc.id):
genProcAux(findPendingModule(m, prc), prc)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 7ca980dcc9..754a88fdaa 100755
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -22,7 +22,7 @@ const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wCompilerProc, wPure, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
- wBorrow, wExtern}
+ wBorrow, wExtern, wImportCompilerProc}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
@@ -80,6 +80,12 @@ proc MakeExternExport(s: PSym, extname: string) =
setExternName(s, extname)
incl(s.flags, sfExportc)
+proc processImportCompilerProc(s: PSym, extname: string) =
+ setExternName(s, extname)
+ incl(s.flags, sfImportc)
+ excl(s.flags, sfForward)
+ incl(s.loc.flags, lfImportCompilerProc)
+
proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr:
GlobalError(n.info, errStringLiteralExpected)
@@ -401,6 +407,8 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
makeExternExport(sym, getOptionalStr(c, it, sym.name.s))
incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s))
+ of wImportCompilerProc:
+ processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it))
of wAlign:
if sym.typ == nil: invalidPragma(it)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 088972e0e8..5335c2ccf1 100755
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -33,8 +33,9 @@ type
wWithout, wXor, wYield,
wColon, wColonColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus,
- wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc,
- wExtern,
+ wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks,
+ wImportCompilerProc,
+ wImportc, wExportc, wExtern,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
@@ -79,8 +80,8 @@ const
"yield",
":", "::", "=", ".", "..", "^", "*", "-",
- "magic", "typecheck", "final", "profiler", "objchecks", "importc",
- "exportc", "extern",
+ "magic", "typecheck", "final", "profiler", "objchecks",
+ "importcompilerproc", "importc", "exportc", "extern",
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
"compilerproc", "procvar", "fatal", "error", "warning", "hint", "line",
diff --git a/koch.nim b/koch.nim
index 29fa86cb3a..8faee0cc7e 100755
--- a/koch.nim
+++ b/koch.nim
@@ -178,7 +178,11 @@ proc clean(args: string) =
proc tests(args: string) =
exec("nimrod cc tests/tester")
- exec("tests/tester")
+ exec("tests/tester reject")
+ exec("tests/tester compile")
+ exec("tests/tester examples")
+ exec("tests/tester run")
+ exec("tests/tester merge")
proc showHelp() =
quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)),
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 9de3fde168..3434cd9d40 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -60,12 +60,13 @@ type
const
GenericSeqSize = (2 * sizeof(int))
-proc genericAssign(dest, src: Pointer, mt: PNimType) {.importc.}
-proc genericShallowAssign(dest, src: Pointer, mt: PNimType) {.importc.}
-proc incrSeq(seq: PGenSeq, elemSize: int): PGenSeq {.importc, nodecl.}
-proc newObj(typ: PNimType, size: int): pointer {.importc, nodecl.}
-proc newSeq(typ: PNimType, len: int): pointer {.importc.}
-proc objectInit(dest: Pointer, typ: PNimType) {.importc.}
+proc genericAssign(dest, src: Pointer, mt: PNimType) {.importCompilerProc.}
+proc genericShallowAssign(dest, src: Pointer, mt: PNimType) {.
+ importCompilerProc.}
+proc incrSeq(seq: PGenSeq, elemSize: int): PGenSeq {.importCompilerProc.}
+proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
+proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
+proc objectInit(dest: Pointer, typ: PNimType) {.importCompilerProc.}
template `+!!`(a, b: expr): expr = cast[pointer](cast[TAddress](a) + b)
@@ -228,7 +229,9 @@ iterator fields*(x: TAny): tuple[name: string, any: TAny] =
assert x.rawType.kind in {tyTuple, tyPureObject, tyObject}
var p = x.value
var t = x.rawType
- if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
+ # XXX BUG: does not work yet, however is questionable anyway
+ when false:
+ if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
var n = t.node
var ret: seq[tuple[name: cstring, any: TAny]] = @[]
fieldsAux(p, n, ret)
@@ -272,7 +275,9 @@ proc getFieldNode(p: pointer, n: ptr TNimNode,
proc `[]=`*(x: TAny, fieldName: string, value: TAny) =
## sets a field of `x`; `x` represents an object or a tuple.
var t = x.rawType
- if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
+ # XXX BUG: does not work yet, however is questionable anyway
+ when false:
+ if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
assert x.rawType.kind in {tyTuple, tyPureObject, tyObject}
var n = getFieldNode(x.value, t.node, fieldname)
if n != nil:
@@ -284,7 +289,9 @@ proc `[]=`*(x: TAny, fieldName: string, value: TAny) =
proc `[]`*(x: TAny, fieldName: string): TAny =
## gets a field of `x`; `x` represents an object or a tuple.
var t = x.rawType
- if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
+ # XXX BUG: does not work yet, however is questionable anyway
+ when false:
+ if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
assert x.rawType.kind in {tyTuple, tyPureObject, tyObject}
var n = getFieldNode(x.value, t.node, fieldname)
if n != nil:
diff --git a/tests/tester.nim b/tests/tester.nim
index 5908b8e291..3883969b94 100755
--- a/tests/tester.nim
+++ b/tests/tester.nim
@@ -10,12 +10,14 @@
## This program verifies Nimrod against the testcases.
import
- parseutils, strutils, pegs, os, osproc, streams, parsecfg, browsers, json
+ parseutils, strutils, pegs, os, osproc, streams, parsecfg, browsers, json,
+ marshal
const
cmdTemplate = r"nimrod cc --hints:on $# $#"
resultsFile = "testresults.html"
jsonFile = "testresults.json"
+ Usage = "usage: tester reject|compile|examples|run|merge [nimrod options]"
type
TTestAction = enum
@@ -141,6 +143,12 @@ proc initResults: TResults =
result.skipped = 0
result.data = ""
+proc readResults(filename: string): TResults =
+ result = marshal.to[TResults](readFile(filename))
+
+proc writeResults(filename: string, r: TResults) =
+ writeFile(filename, $$r)
+
proc `$`(x: TResults): string =
result = ("Tests passed: $1 / $3
\n" &
"Tests skipped: $2 / $3
\n") %
@@ -275,22 +283,45 @@ proc outputJSON(reject, compile, run: TResults) =
var s = pretty(doc)
writeFile(jsonFile, s)
-var options = ""
-var rejectRes = initResults()
-var compileRes = initResults()
-var runRes = initResults()
+proc main(action: string) =
+ const
+ compileJson = "compile.json"
+ runJson = "run.json"
+ rejectJson = "reject.json"
+ var options = ""
+ for i in 2.. paramCount():
+ add(options, " ")
+ add(options, paramStr(i))
-for i in 1.. paramCount():
- add(options, " ")
- add(options, paramStr(i))
+ case action
+ of "reject":
+ var rejectRes = initResults()
+ reject(rejectRes, "tests/reject", options)
+ writeResults(rejectJson, rejectRes)
+ of "compile":
+ var compileRes = initResults()
+ compile(compileRes, "tests/accept/compile/t*.nim", options)
+ writeResults(compileJson, compileRes)
+ of "examples":
+ var compileRes = readResults(compileJson)
+ compileExample(compileRes, "lib/pure/*.nim", options)
+ compileExample(compileRes, "examples/*.nim", options)
+ compileExample(compileRes, "examples/gtk/*.nim", options)
+ writeResults(compileJson, compileRes)
+ of "run":
+ var runRes = initResults()
+ run(runRes, "tests/accept/run", options)
+ writeResults(runJson, runRes)
+ of "merge":
+ var rejectRes = readResults(rejectJson)
+ var compileRes = readResults(compileJson)
+ var runRes = readResults(runJson)
+ listResults(rejectRes, compileRes, runRes)
+ outputJSON(rejectRes, compileRes, runRes)
+ else:
+ quit usage
-reject(rejectRes, "tests/reject", options)
-compile(compileRes, "tests/accept/compile/t*.nim", options)
-compileExample(compileRes, "lib/pure/*.nim", options)
-compileExample(compileRes, "examples/*.nim", options)
-compileExample(compileRes, "examples/gtk/*.nim", options)
-run(runRes, "tests/accept/run", options)
-listResults(rejectRes, compileRes, runRes)
-outputJSON(rejectRes, compileRes, runRes)
-openDefaultBrowser(resultsFile)
+if paramCount() == 0:
+ quit usage
+main(paramStr(1))
diff --git a/todo.txt b/todo.txt
index 3308309c7c..384f493ea1 100755
--- a/todo.txt
+++ b/todo.txt
@@ -3,6 +3,7 @@ High priority (version 0.8.12)
* test threads on windows; thread analysis needs to be even more restrictive!
* implement message passing built-ins: channels/queues
* bug: {:}.toTable[int, string]()
+* test tester
version 0.9.0