summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-laptop>2010-04-02 19:34:57 +0200
committerAndreas Rumpf <andreas@andreas-laptop>2010-04-02 19:34:57 +0200
commitf530bbd6315f21469d7479991186e88302608726 (patch)
tree8b05aba5a3d407d50160c448fa2ba5b2fa952a6f
parent227b76c34259cf406131d27fb8e0cc88530e38f7 (diff)
downloadNim-f530bbd6315f21469d7479991186e88302608726.tar.gz
tiny C backend for a much faster REPL
-rwxr-xr-xlib/wrappers/gtk/gdk2.nim2
-rw-r--r--lib/wrappers/tinyc.nim118
-rwxr-xr-xrod/cgen.nim48
-rwxr-xr-xrod/commands.nim2
-rwxr-xr-xrod/evals.nim6
-rwxr-xr-xrod/extccomp.nim6
-rwxr-xr-xrod/main.nim12
-rwxr-xr-xrod/msgs.nim12
-rwxr-xr-xrod/nimrod.nim15
-rwxr-xr-xrod/options.nim6
-rwxr-xr-xrod/ropes.nim8
-rwxr-xr-xtools/nimrepl.nim26
12 files changed, 208 insertions, 53 deletions
diff --git a/lib/wrappers/gtk/gdk2.nim b/lib/wrappers/gtk/gdk2.nim
index 3be2c4027..5841aeee3 100755
--- a/lib/wrappers/gtk/gdk2.nim
+++ b/lib/wrappers/gtk/gdk2.nim
@@ -17,7 +17,7 @@ elif defined(darwin):
     lib = "gdk-x11-2.0"
 else: 
   const 
-    lib = "libgdk-x11-2.0.so"
+    lib = "libgdk-x11-2.0.so(|.0)"
 const 
   NUMPTSTOBUFFER* = 200
   MAX_TIMECOORD_AXES* = 128
diff --git a/lib/wrappers/tinyc.nim b/lib/wrappers/tinyc.nim
new file mode 100644
index 000000000..f685c714d
--- /dev/null
+++ b/lib/wrappers/tinyc.nim
@@ -0,0 +1,118 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2010 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+type
+  TccState {.pure, final.} = object
+  PccState* = ptr TccState
+  
+  TErrorFunc* = proc (opaque: pointer, msg: cstring) {.cdecl.}
+
+proc openCCState*(): PccState {.importc: "tcc_new", cdecl.}
+  ## create a new TCC compilation context
+
+proc closeCCState*(s: PccState) {.importc: "tcc_delete", cdecl.}
+  ## free a TCC compilation context
+
+proc enableDebug*(s: PccState) {.importc: "tcc_enable_debug", cdecl.}
+  ## add debug information in the generated code
+
+proc setErrorFunc*(s: PccState, errorOpaque: pointer, errorFun: TErrorFunc) {.
+  cdecl, importc: "tcc_set_error_func".}
+  ## set error/warning display callback
+
+proc setWarning*(s: PccState, warningName: cstring, value: int) {.cdecl,
+  importc: "tcc_set_warning".}
+  ## set/reset a warning
+
+# preprocessor 
+
+proc addIncludePath*(s: PccState, pathname: cstring) {.cdecl, 
+  importc: "tcc_add_include_path".}
+  ## add include path
+
+proc addSysincludePath*(s: PccState, pathname: cstring) {.cdecl, 
+  importc: "tcc_add_sysinclude_path".}
+  ## add in system include path
+
+
+proc defineSymbol*(s: PccState, sym, value: cstring) {.cdecl, 
+  importc: "tcc_define_symbol".}
+  ## define preprocessor symbol 'sym'. Can put optional value
+
+proc undefineSymbol*(s: PccState, sym: cstring) {.cdecl, 
+  importc: "tcc_undefine_symbol".}
+  ## undefine preprocess symbol 'sym'
+
+# compiling 
+
+proc addFile*(s: PccState, filename: cstring): cint {.cdecl, 
+  importc: "tcc_add_file".}
+  ## add a file (either a C file, dll, an object, a library or an ld
+  ## script). Return -1 if error.
+
+proc compileString*(s: PccState, buf: cstring): cint {.cdecl, 
+  importc: "tcc_compile_string".}
+  ## compile a string containing a C source. Return non zero if error.
+
+# linking commands
+
+
+const
+  OutputMemory*: cint = 0 ## output will be ran in memory (no
+                          ## output file) (default)
+  OutputExe*: cint = 1 ## executable file
+  OutputDll*: cint = 2 ## dynamic library
+  OutputObj*: cint = 3 ## object file
+  OutputPreprocess*: cint = 4 ## preprocessed file (used internally)
+  
+  OutputFormatElf*: cint = 0 ## default output format: ELF
+  OutputFormatBinary*: cint = 1 ## binary image output
+  OutputFormatCoff*: cint = 2 ## COFF
+
+proc setOutputType*(s: PCCState, outputType: cint): cint {.cdecl, 
+  importc: "tcc_set_output_type".}
+  ## set output type. MUST BE CALLED before any compilation
+
+proc addLibraryPath*(s: PccState, pathname: cstring): cint {.cdecl,
+  importc: "tcc_add_library_path".}
+  ## equivalent to -Lpath option
+
+proc addLibrary*(s: PCCState, libraryname: cstring): cint {.cdecl,
+  importc: "tcc_add_library".}
+  ## the library name is the same as the argument of the '-l' option
+
+proc addSymbol*(s: PccState, name: cstring, val: pointer): cint {.cdecl,
+  importc: "tcc_add_symbol".}
+  ## add a symbol to the compiled program
+
+proc outputFile*(s: PccState, filename: cstring): cint {.cdecl,
+  importc: "tcc_output_file".}
+  ## output an executable, library or object file. DO NOT call
+  ## tcc_relocate() before.
+
+proc run*(s: PccState, argc: cint, argv: cstringArray): cint {.cdecl,
+  importc: "tcc_run".}
+  ## link and run main() function and return its value. DO NOT call
+  ## tcc_relocate() before.
+
+proc relocate*(s: PccState, p: pointer): cint {.cdecl,
+  importc: "tcc_relocate".}
+  ## copy code into memory passed in by the caller and do all relocations
+  ## (needed before using tcc_get_symbol()).
+  ## returns -1 on error and required size if ptr is NULL
+
+proc getSymbol*(s: PccState, name: cstring): pointer {.cdecl,
+  importc: "tcc_get_symbol".}
+  ## return symbol value or NULL if not found
+
+proc setLibPath*(s: PccState, path: cstring) {.cdecl,
+  importc: "tcc_set_lib_path".}
+  ## set CONFIG_TCCDIR at runtime
+  
+
diff --git a/rod/cgen.nim b/rod/cgen.nim
index 989778a02..ad322a1dd 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -15,6 +15,9 @@ import
   nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, 
   times, ropes, math, passes, rodread, wordrecg, rnimsyn, treetab, cgmeth
 
+when options.hasTinyCBackend:
+  import tccgen
+
 proc cgenPass*(): TPass
 # implementation
 
@@ -518,7 +521,8 @@ proc genProcAux(m: BModule, prc: PSym) =
     if p.beforeRetNeeded: app(generatedProc, "BeforeRet: ;" & tnl)
     if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
     if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): 
-      appf(generatedProc, "profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n", 
+      appf(generatedProc, 
+          "profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n", 
            [toRope(prc.loc.a)])
     app(generatedProc, returnStmt)
     app(generatedProc, '}' & tnl)
@@ -600,13 +604,15 @@ proc genConstPrototype(m: BModule, sym: PSym) =
 proc getFileHeader(cfilenoext: string): PRope = 
   if optCompileOnly in gGlobalOptions: 
     result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
-        "/*   (c) 2009 Andreas Rumpf */$n", "; Generated by Nimrod Compiler v$1$n" &
-        ";   (c) 2009 Andreas Rumpf$n", [toRope(versionAsString)])
+        "/*   (c) 2010 Andreas Rumpf */$n", 
+        "; Generated by Nimrod Compiler v$1$n" &
+        ";   (c) 2010 Andreas Rumpf$n", [toRope(versionAsString)])
   else: 
     result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
-        "/*   (c) 2009 Andreas Rumpf */$n" & "/* Compiled for: $2, $3, $4 */$n" &
-        "/* Command for C compiler:$n   $5 */$n", "; Generated by Nimrod Compiler v$1$n" &
-        ";   (c) 2009 Andreas Rumpf$n" & "; Compiled for: $2, $3, $4$n" &
+        "/*   (c) 2010 Andreas Rumpf */$n" & "/* Compiled for: $2, $3, $4 */$n" &
+        "/* Command for C compiler:$n   $5 */$n", 
+        "; Generated by Nimrod Compiler v$1$n" &
+        ";   (c) 2010 Andreas Rumpf$n" & "; Compiled for: $2, $3, $4$n" &
         "; Command for LLVM compiler:$n   $5$n", [toRope(versionAsString), 
         toRope(platform.OS[targetOS].name), 
         toRope(platform.CPU[targetCPU].name), 
@@ -668,7 +674,8 @@ proc genMainProc(m: BModule) =
         "                    LPVOID lpvReserved) {$n" & "  NimMain();$n" &
         "  return 1;$n" & "}$n"
     WinNimDllMainLLVM = WinNimMainLLVM
-    WinCDllMainLLVM = "define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n" &
+    WinCDllMainLLVM = 
+        "define stdcall i32 @DllMain(i32 %hinstDLL, i32 %fwdreason, $n" &
         "                            i8* %lpvReserved) {$n" &
         "  call void @NimMain()$n" & "  ret i32 1$n" & "}$n"
   var nimMain, otherMain: TFormatStr
@@ -795,13 +802,13 @@ proc myOpen(module: PSym, filename: string): PPassContext =
   if gNimDat == nil: registerTypeInfoModule()
   result = newModule(module, filename)
 
-proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext = 
-  var cfile, cfilenoext, objFile: string
+proc myOpenCached(module: PSym, filename: string, 
+                  rd: PRodReader): PPassContext = 
   if gNimDat == nil: 
     registerTypeInfoModule()  
     #MessageOut('cgen.myOpenCached has been called ' + filename);
-  cfile = changeFileExt(completeCFilePath(filename), cExt)
-  cfilenoext = changeFileExt(cfile, "")
+  var cfile = changeFileExt(completeCFilePath(filename), cExt)
+  var cfilenoext = changeFileExt(cfile, "")
   addFileToLink(cfilenoext)
   registerModuleToMain(module) 
   # XXX: this cannot be right here, initalization has to be appended during
@@ -838,18 +845,21 @@ proc finishModule(m: BModule) =
   setlen(m.forwardedProcs, 0)
 
 proc writeModule(m: BModule) = 
-  var 
-    cfile, cfilenoext: string
-    code: PRope
   # generate code for the init statements of the module:
   genInitCode(m)
   finishTypeDescriptions(m)
-  cfile = completeCFilePath(m.cfilename)
-  cfilenoext = changeFileExt(cfile, "")
+  var cfile = completeCFilePath(m.cfilename)
+  var cfilenoext = changeFileExt(cfile, "")
   if sfMainModule in m.module.flags: 
     # generate main file:
     app(m.s[cfsProcHeaders], mainModProcs)
-  code = genModule(m, cfilenoext)
+  var code = genModule(m, cfilenoext)
+  
+  when hasTinyCBackend:
+    if gCmd == cmdRun:
+      tccgen.compileCCode(ropeToStr(code))
+      return
+  
   if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext): 
     addFileToCompile(cfilenoext)
   addFileToLink(cfilenoext)
@@ -867,7 +877,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
     finishModule(m)
   if sfMainModule in m.module.flags: 
     var disp = generateMethodDispatchers()
-    for i in countup(0, sonsLen(disp) - 1): genProcAux(gNimDat, disp.sons[i].sym)
+    for i in 0..sonsLen(disp)-1: genProcAux(gNimDat, disp.sons[i].sym)
     genMainProc(m) 
     # we need to process the transitive closure because recursive module
     # deps are allowed (and the system module is processed in the wrong
diff --git a/rod/commands.nim b/rod/commands.nim
index 17c946292..01b015b53 100755
--- a/rod/commands.nim
+++ b/rod/commands.nim
@@ -36,6 +36,7 @@ Usage::
 Command::
   compile, c                compile project with default code generator (C)
   compileToC, cc            compile project with C code generator
+  run                       compile the project in memory and run it
   doc                       generate the documentation for inputfile
   rst2html                  converts a reStructuredText file to HTML
   rst2tex                   converts a reStructuredText file to TeX
@@ -70,7 +71,6 @@ Options:
         
   AdvancedUsage = """
 Advanced commands::
-  pas                       convert a Pascal file to Nimrod syntax
   pretty                    pretty print the inputfile
   genDepend                 generate a DOT file containing the
                             module dependency graph
diff --git a/rod/evals.nim b/rod/evals.nim
index 79428e60f..7306f61b1 100755
--- a/rod/evals.nim
+++ b/rod/evals.nim
@@ -1014,9 +1014,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
       case result.kind
       of nkExceptBranch, nkReturnToken, nkBreakStmt: break 
       else: nil
-  of nkProcDef, nkMethodDef, nkMacroDef, nkCommentStmt, nkPragma, nkTypeSection, 
-     nkTemplateDef, nkConstSection, nkIteratorDef, nkConverterDef, 
-     nkIncludeStmt, nkImportStmt, nkFromStmt: 
+  of nkProcDef, nkMethodDef, nkMacroDef, nkCommentStmt, nkPragma,
+     nkTypeSection, nkTemplateDef, nkConstSection, nkIteratorDef,
+     nkConverterDef, nkIncludeStmt, nkImportStmt, nkFromStmt: 
     nil
   of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, 
      nkLambda, nkContinueStmt, nkIdent: 
diff --git a/rod/extccomp.nim b/rod/extccomp.nim
index 563434e0f..a565bee72 100755
--- a/rod/extccomp.nim
+++ b/rod/extccomp.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -480,8 +480,8 @@ proc genMappingFiles(list: TLinkedList): PRope =
     it = PStrEntry(it.next)
 
 proc writeMapping(gSymbolMapping: PRope) = 
-  if not (optGenMapping in gGlobalOptions): return 
-  var code = toRope("[C_Files]" & "\n")
+  if optGenMapping notin gGlobalOptions: return 
+  var code = toRope("[C_Files]\n")
   app(code, genMappingFiles(toCompile))
   app(code, genMappingFiles(externalToCompile))
   appf(code, "[Symbols]$n$1", [gSymbolMapping])
diff --git a/rod/main.nim b/rod/main.nim
index 3221f531e..2a261bfe5 100755
--- a/rod/main.nim
+++ b/rod/main.nim
@@ -118,7 +118,8 @@ proc CommandCompileToC(filename: string) =
   registerPass(rodwrite.rodwritePass())
   #registerPass(cleanupPass())
   compileProject(filename)
-  extccomp.CallCCompiler(changeFileExt(filename, ""))
+  if gCmd != cmdRun:
+    extccomp.CallCCompiler(changeFileExt(filename, ""))
 
 when has_LLVM_Backend:
   proc CommandCompileToLLVM(filename: string) = 
@@ -191,6 +192,13 @@ proc MainCommand(cmd, filename: string) =
     gCmd = cmdCompileToC
     wantFile(filename)
     CommandCompileToC(filename)
+  of wRun:
+    gCmd = cmdRun
+    wantFile(filename)
+    when hasTinyCBackend:
+      CommandCompileToC(filename)
+    else: 
+      rawMessage(errInvalidCommandX, cmd)
   of wCompileToCpp: 
     gCmd = cmdCompileToCpp
     wantFile(filename)
@@ -204,6 +212,8 @@ proc MainCommand(cmd, filename: string) =
     wantFile(filename)
     when has_LLVM_Backend:
       CommandCompileToLLVM(filename)
+    else:
+      rawMessage(errInvalidCommandX, cmd)
   of wPretty: 
     gCmd = cmdPretty
     wantFile(filename)        #CommandExportSymbols(filename);
diff --git a/rod/msgs.nim b/rod/msgs.nim
index 01852e0ba..ff42bc690 100755
--- a/rod/msgs.nim
+++ b/rod/msgs.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2009 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -298,14 +298,18 @@ const
 type 
   TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
   TNoteKinds* = set[TNoteKind]
-  TLineInfo*{.final.} = object # This is designed to be as small as possible, because it is used
-                               # in syntax nodes. We safe space here by using two int16 and an int32
-                               # on 64 bit and on 32 bit systems this is only 8 bytes.
+  TLineInfo*{.final.} = object # This is designed to be as small as possible,
+                               # because it is used
+                               # in syntax nodes. We safe space here by using 
+                               # two int16 and an int32
+                               # on 64 bit and on 32 bit systems this is 
+                               # only 8 bytes.
     line*, col*: int16
     fileIndex*: int32
 
 
 proc UnknownLineInfo*(): TLineInfo
+
 var 
   gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)}
   gErrorCounter*: int = 0     # counts the number of errors
diff --git a/rod/nimrod.nim b/rod/nimrod.nim
index a6f3365c2..26bfcde2d 100755
--- a/rod/nimrod.nim
+++ b/rod/nimrod.nim
@@ -11,6 +11,9 @@ import
   times, commands, scanner, condsyms, options, msgs, nversion, nimconf, ropes, 
   extccomp, strutils, os, platform, main, parseopt
 
+when hasTinyCBackend:
+  import tccgen
+
 var 
   arguments: string = ""      # the arguments to be passed to the program that
                               # should be run
@@ -21,8 +24,7 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
   while true: 
     parseopt.next(p)
     case p.kind
-    of cmdEnd: 
-      break 
+    of cmdEnd: break 
     of cmdLongOption, cmdShortOption: 
       # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
       # we fix this here
@@ -41,7 +43,7 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
         break 
   if pass == passCmd2: 
     arguments = cmdLineRest(p)
-    if not (optRun in gGlobalOptions) and (arguments != ""): 
+    if optRun notin gGlobalOptions and arguments != "": 
       rawMessage(errArgsNeedRunOption, [])
   
 proc HandleCmdLine() = 
@@ -63,8 +65,11 @@ proc HandleCmdLine() =
     ProcessCmdLine(passCmd2, command, filename)
     MainCommand(command, filename)
     if gVerbosity >= 2: echo(GC_getStatistics())
-    if (gCmd != cmdInterpret) and (msgs.gErrorCounter == 0): 
-      rawMessage(hintSuccessX, [$(gLinesCompiled), $(getTime() - start)])
+    when hasTinyCBackend:
+      if gCmd == cmdRun:
+        tccgen.run()
+    if gCmd notin {cmdInterpret, cmdRun} and msgs.gErrorCounter == 0: 
+      rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)])
     if optRun in gGlobalOptions: 
       when defined(unix): 
         var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
diff --git a/rod/options.nim b/rod/options.nim
index 514c3db3b..9ce54a41c 100755
--- a/rod/options.nim
+++ b/rod/options.nim
@@ -9,6 +9,9 @@
 
 import 
   os, lists, strutils, nstrtabs
+  
+const
+  hasTinyCBackend* = true
 
 type                          # please make sure we have under 32 options
                               # (improves code efficiency a lot!)
@@ -48,7 +51,8 @@ type                          # please make sure we have under 32 options
     cmdDebugTrans,            # debug a transformation pass
     cmdRst2html,              # convert a reStructuredText file to HTML
     cmdRst2tex,               # convert a reStructuredText file to TeX
-    cmdInteractive            # start interactive session
+    cmdInteractive,           # start interactive session
+    cmdRun                    # run the project via TCC backend
   TStringSeq* = seq[string]
 
 const 
diff --git a/rod/ropes.nim b/rod/ropes.nim
index 1fe5ed55e..0139daf2b 100755
--- a/rod/ropes.nim
+++ b/rod/ropes.nim
@@ -67,10 +67,12 @@ const
 
 type 
   TFormatStr* = string # later we may change it to CString for better
-                       # performance of the code generator (assignments copy the format strings
+                       # performance of the code generator (assignments 
+                       # copy the format strings
                        # though it is not necessary)
   PRope* = ref TRope
-  TRope*{.acyclic.} = object of TObject # the empty rope is represented by nil to safe space
+  TRope*{.acyclic.} = object of TObject # the empty rope is represented 
+                                        # by nil to safe space
     left*, right*: PRope
     length*: int
     data*: string             # != nil if a leaf
@@ -405,4 +407,4 @@ proc writeRopeIfNotEqual(r: PRope, filename: string): bool =
   else: 
     result = false
   
-new(N) # init dummy node for splay algorithm
\ No newline at end of file
+new(N) # init dummy node for splay algorithm
diff --git a/tools/nimrepl.nim b/tools/nimrepl.nim
index bf0578285..210ac2467 100755
--- a/tools/nimrepl.nim
+++ b/tools/nimrepl.nim
@@ -1,20 +1,22 @@
-import glib2, gtk2, gdk2, osproc, dialogs, strutils
-
-type
-  output = tuple[compiler, app: string]
+#
+#
+#              Nimrod REPL
+#        (c) Copyright 2010 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
 
-proc execCode(code: string): output =
+import glib2, gtk2, gdk2, osproc, dialogs, strutils
 
+proc execCode(code: string): string =
   var f: TFile
   if open(f, "temp.nim", fmWrite):
     f.write(code)
     f.close()
   else:
-    raise newException(EIO, "Unable to open file")
-    
-  var compilerOutput = osproc.execProcess("nimrod c temp.nim")
-  var appOutput = osproc.execProcess("temp.exe")
-  return (compilerOutput, appOutput)
+    raise newException(EIO, "Unable to open file")    
+  result = osproc.execProcess("nimrod run --verbosity:0 temp.nim")
 
 var shiftPressed = False
 var w: gtk2.PWindow
@@ -83,8 +85,8 @@ proc inputKeyReleased(widget: PWidget, event: PEventKey,
 
       try:
         var r = execCode($InputText)
-        set_text(OutputTextBuffer, r[0] & r[1], len(r[0] & r[1]))
-      except:
+        set_text(OutputTextBuffer, r, len(r))
+      except EIO:
         setError("Error: Could not open file temp.nim")