summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/evalffi.nim34
-rw-r--r--compiler/vm.nim17
-rw-r--r--compiler/vmgen.nim10
-rw-r--r--lib/pure/os.nim50
-rw-r--r--lib/system/sysio.nim4
-rw-r--r--lib/system/widestrs.nim3
-rw-r--r--todo.txt1
-rw-r--r--tools/detect/detect.nim21
8 files changed, 80 insertions, 60 deletions
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index 92b79f9b6..f2337f7ce 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -9,7 +9,7 @@
 
 ## This file implements the FFI part of the evaluator for Nimrod code.
 
-import ast, astalgo, ropes, types, options, tables, dynlib, libffi, msgs
+import ast, astalgo, ropes, types, options, tables, dynlib, libffi, msgs, os
 
 when defined(windows):
   const libcDll = "msvcrt.dll"
@@ -20,7 +20,11 @@ type
   TDllCache = tables.TTable[string, TLibHandle]
 var
   gDllCache = initTable[string, TLibHandle]()
-  gExeHandle = LoadLib()
+
+when defined(windows):
+  var gExeHandle = loadLib(os.getAppFilename())
+else:
+  var gExeHandle = loadLib()
 
 proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
   result = cache[dll]
@@ -28,10 +32,10 @@ proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
     var libs: seq[string] = @[]
     libCandidates(dll, libs)
     for c in libs:
-      result = LoadLib(c)
+      result = loadLib(c)
       if not result.isNil: break
     if result.isNil:
-      GlobalError(info, "cannot load: " & dll)
+      globalError(info, "cannot load: " & dll)
     cache[dll] = result
 
 const
@@ -50,7 +54,7 @@ proc importcSymbol*(sym: PSym): PNode =
   else:
     let lib = sym.annex
     if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
-      GlobalError(sym.info, "dynlib needs to be a string lit for the REPL")
+      globalError(sym.info, "dynlib needs to be a string lit for the REPL")
     var theAddr: pointer
     if lib.isNil and not gExehandle.isNil:
       # first try this exe itself:
@@ -58,10 +62,12 @@ proc importcSymbol*(sym: PSym): PNode =
       # then try libc:
       if theAddr.isNil:
         let dllhandle = gDllCache.getDll(libcDll, sym.info)
-        theAddr = dllhandle.checkedSymAddr(name)
-    else:
-      let dllhandle = gDllCache.getDll(lib.path.strVal, sym.info)
-      theAddr = dllhandle.checkedSymAddr(name)
+        theAddr = dllhandle.symAddr(name)
+    elif not lib.isNil:
+      let dllhandle = gDllCache.getDll(if lib.kind == libHeader: libcDll 
+                                       else: lib.path.strVal, sym.info)
+      theAddr = dllhandle.symAddr(name)
+    if theAddr.isNil: globalError(sym.info, "cannot import: " & sym.name.s)
     result.intVal = cast[TAddress](theAddr)
 
 proc mapType(t: ast.PType): ptr libffi.TType =
@@ -139,7 +145,7 @@ proc getField(n: PNode; position: int): PSym =
       else: internalError(n.info, "getField(record case branch)")
   of nkSym:
     if n.sym.position == position: result = n.sym
-  else: nil
+  else: discard
 
 proc packObject(x: PNode, typ: PType, res: pointer) =
   InternalAssert x.kind in {nkObjConstr, nkPar}
@@ -192,7 +198,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyPointer, tyProc,  tyCString, tyString:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
-      nil
+      discard
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
     elif v.kind in {nkStrLit..nkTripleStrLit}:
@@ -202,7 +208,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyPtr, tyRef, tyVar:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
-      nil
+      discard
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
     else:
@@ -220,7 +226,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyObject, tyTuple:
     packObject(v, typ, res)
   of tyNil:
-    nil
+    discard
   of tyDistinct, tyGenericInst:
     pack(v, typ.sons[0], res)
   else:
@@ -241,7 +247,7 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
     pair.sons[1] = unpack(x +! n.sym.offset, n.sym.typ, nil)
     #echo "offset: ", n.sym.name.s, " ", n.sym.offset
     result.add pair
-  else: nil
+  else: discard
 
 proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
   # compute the field's offsets:
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 80b8abb8b..854b491fb 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -632,12 +632,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
         # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
         # 'regs' in a register:
         when hasFFI:
+          if c.globals.sons[prc.position-1].kind == nkEmpty:
+            globalError(c.debug[pc], errGenerated, "canot run " & prc.name.s)
           let newValue = callForeignFunction(c.globals.sons[prc.position-1],
                                              prc.typ, tos.slots,
                                              rb+1, rc-1, c.debug[pc])
           if newValue.kind != nkEmpty:
             assert instr.opcode == opcIndCallAsgn
-            regs[ra] = newValue
+            asgnRef(regs[ra], newValue)
         else:
           globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
       elif prc.kind != skTemplate:
@@ -796,7 +798,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       decodeB(nkBracket)
       let newLen = regs[rb].getOrdValue.int
       setLen(regs[ra].sons, newLen)
-    of opcSwap, opcCast, opcReset:
+    of opcSwap, opcReset:
       internalError(c.debug[pc], "too implement")
     of opcIsNil:
       decodeB(nkIntLit)
@@ -938,6 +940,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
         stackTrace(c, tos, pc, errGenerated,
           msgKindToString(errIllegalConvFromXtoY) % [
           "unknown type" , "unknown type"])
+    of opcCast:
+      let rb = instr.regB
+      inc pc
+      let typ = c.types[c.code[pc].regBx - wordExcess]
+      when hasFFI:
+        let dest = fficast(regs[rb], typ)
+        asgnRef(regs[ra], dest)
+      else:
+        globalError(c.debug[pc], "cannot evaluate cast")
     of opcNSetIntVal:
       decodeB(nkMetaNode)
       var dest = regs[ra].uast
@@ -1074,6 +1085,8 @@ proc myOpen(module: PSym): PPassContext =
   # XXX produce a new 'globals' environment here:
   setupGlobalCtx(module)
   result = globalCtx
+  when hasFFI:
+    globalCtx.features = {allowFFI, allowCast}
 
 var oldErrorCount: int
 
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 134b2d15a..486d24e6c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -945,7 +945,10 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
 proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
   when hasFFI:
     if allowFFI in c.features:
-      c.globals.add(importcSymbol(s))
+      if s.kind == skVar and lfNoDecl in s.loc.flags:
+        c.globals.add(copyNode(emptyNode))
+      else:
+        c.globals.add(importcSymbol(s))
       s.position = c.globals.len
     else:
       localError(info, errGenerated, "VM is not allowed to 'importc'")
@@ -1303,6 +1306,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
   of nkCurly: genSetConstr(c, n, dest)
   of nkObjConstr: genObjConstr(c, n, dest)
   of nkPar, nkClosure: genTupleConstr(c, n, dest)
+  of nkCast:
+    if allowCast in c.features:
+      genConv(c, n, n.sons[1], dest, opcCast)
+    else:
+      localError(n.info, errGenerated, "VM is not allowed to 'cast'")
   else:
     InternalError n.info, "too implement " & $n.kind
 
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 71639d821..d5c4acaec 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -341,16 +341,6 @@ when defined(windows):
     template FindNextFile(a, b: expr): expr = FindNextFileW(a, b)
     template getCommandLine(): expr = getCommandLineW()
 
-    proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
-      let 
-        nul = 0
-        dot = ord('.')
-      result = (f.cFilename[0].int == dot)
-      if result:
-        result = (f.cFilename[1].int in {dot, nul})
-        if result:
-          result = (f.cFilename[2].int == nul)
-
     template getFilename(f: expr): expr =
       $cast[WideCString](addr(f.cFilename[0]))
   else:
@@ -358,18 +348,13 @@ when defined(windows):
     template FindNextFile(a, b: expr): expr = FindNextFileA(a, b)
     template getCommandLine(): expr = getCommandLineA()
 
-    proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
-      let 
-        nul = '\0'
-        dot = '.'
-      result = (f.cFilename[0] == dot)
-      if result:
-        result = (f.cFilename[1] in {dot, nul})
-        if result:
-          result = (f.cFilename[2] == nul)
-
     template getFilename(f: expr): expr = $f.cFilename
 
+  proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} =
+    const dot = ord('.')
+    result = f.cFilename[0].int == dot and(f.cFilename[1].int == 0 or
+             f.cFilename[1].int == dot and f.cFilename[2].int == 0)
+
 proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
                                           tags: [FReadDir].} =
   ## Returns true if the file exists, false otherwise.
@@ -468,20 +453,21 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
   ## `newDir` cannot been set.
   when defined(Windows):
     when useWinUnicode:
-      if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError(OSLastError())
+      if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
+        OSError(OSLastError())
     else:
       if SetCurrentDirectoryA(newDir) == 0'i32: OSError(OSLastError())
   else:
     if chdir(newDir) != 0'i32: OSError(OSLastError())
 
-proc JoinPath*(head, tail: string): string {.
+proc joinPath*(head, tail: string): string {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Joins two directory names to one.
   ##
   ## For example on Unix:
   ##
   ## .. code-block:: nimrod
-  ##   JoinPath("usr", "lib")
+  ##   joinPath("usr", "lib")
   ##
   ## results in:
   ##
@@ -495,10 +481,10 @@ proc JoinPath*(head, tail: string): string {.
   ## examples on Unix:
   ##
   ## .. code-block:: nimrod
-  ##   assert JoinPath("usr", "") == "usr/"
-  ##   assert JoinPath("", "lib") == "lib"
-  ##   assert JoinPath("", "/lib") == "/lib"
-  ##   assert JoinPath("usr/", "/lib") == "usr/lib"
+  ##   assert joinPath("usr", "") == "usr/"
+  ##   assert joinPath("", "lib") == "lib"
+  ##   assert joinPath("", "/lib") == "/lib"
+  ##   assert joinPath("usr/", "/lib") == "usr/lib"
   if len(head) == 0:
     result = tail
   elif head[len(head)-1] in {DirSep, AltSep}:
@@ -512,14 +498,14 @@ proc JoinPath*(head, tail: string): string {.
     else:
       result = head & DirSep & tail
 
-proc JoinPath*(parts: varargs[string]): string {.noSideEffect,
+proc joinPath*(parts: varargs[string]): string {.noSideEffect,
   rtl, extern: "nos$1OpenArray".} =
-  ## The same as `JoinPath(head, tail)`, but works with any number of directory
+  ## The same as `joinPath(head, tail)`, but works with any number of directory
   ## parts. You need to pass at least one element or the proc will assert in
   ## debug builds and crash on release builds.
   result = parts[0]
   for i in 1..high(parts):
-    result = JoinPath(result, parts[i])
+    result = joinPath(result, parts[i])
 
 proc `/` * (head, tail: string): string {.noSideEffect.} =
   ## The same as ``JoinPath(head, tail)``
@@ -533,7 +519,7 @@ proc `/` * (head, tail: string): string {.noSideEffect.} =
   ##   assert "usr/" / "/lib" == "usr/lib"
   return JoinPath(head, tail)
 
-proc SplitPath*(path: string): tuple[head, tail: string] {.
+proc splitPath*(path: string): tuple[head, tail: string] {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Splits a directory into (head, tail), so that
   ## ``JoinPath(head, tail) == path``.
@@ -699,7 +685,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
     if r.isNil: OSError(OSLastError())
     setlen(result, c_strlen(result))
 
-proc ChangeFileExt*(filename, ext: string): string {.
+proc changeFileExt*(filename, ext: string): string {.
   noSideEffect, rtl, extern: "nos$1".} =
   ## Changes the file extension to `ext`.
   ##
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index a877f8b28..5af1c96d4 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -194,9 +194,9 @@ const
     # should not be translated.
 
 
-proc Open(f: var TFile, filename: string,
+proc open(f: var TFile, filename: string,
           mode: TFileMode = fmRead,
-          bufSize: int = -1): Bool =
+          bufSize: int = -1): bool =
   var p: pointer = fopen(filename, FormatOpen[mode])
   result = (p != nil)
   f = cast[TFile](p)
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index cf1f0910c..6a699274c 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -101,7 +101,8 @@ proc newWideCString*(s: cstring): WideCString =
   if s.isNil: return nil

 

   when not defined(c_strlen):

-    proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}

+    proc c_strlen(a: cstring): int {.
+      header: "<string.h>", noSideEffect, importc: "strlen".}

 

   let L = cstrlen(s)

   result = newWideCString(s, L)

diff --git a/todo.txt b/todo.txt
index 4c999226f..a6301ce0b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -3,7 +3,6 @@ version 0.9.4
 
 - new VM:
   - implement overflow checking
-  - implement the FFI
 
 - make 'bind' default for templates and introduce 'mixin'
 - special rule for ``[]=``
diff --git a/tools/detect/detect.nim b/tools/detect/detect.nim
index cf61c2823..b2beba828 100644
--- a/tools/detect/detect.nim
+++ b/tools/detect/detect.nim
@@ -10,7 +10,7 @@
 import os, strutils
 
 const
-  cc = "gcc -o $1 $1.c"
+  cc = "gcc -o $# $#.c"
 
   cfile = """
 /* Generated by detect.nim */
@@ -37,6 +37,7 @@ var
   tl = ""
 
 proc myExec(cmd: string): bool = 
+  echo "CMD ", cmd
   return execShellCmd(cmd) == 0
 
 proc header(s: string): bool = 
@@ -46,7 +47,7 @@ proc header(s: string): bool =
     f.write("#include $1\n" % s)
     f.write("int main() { return 0; }\n")
     close(f)
-    result = myExec(cc % testh)
+    result = myExec(cc % [testh.addFileExt(ExeExt), testh])
     removeFile(addFileExt(testh, "c"))
   if result:
     addf(hd, "#include $1\n", s)
@@ -60,13 +61,16 @@ proc main =
   if open(f, addFileExt(gen, "c"), fmWrite): 
     f.write(cfile % [hd, tl, system.hostOS, system.hostCPU])
     close(f)
-  if not myExec(cc % gen): quit(1)
-  if not myExec("./" & gen): quit(1)
+  if not myExec(cc % [gen.addFileExt(ExeExt), gen]): quit(1)
+  when defined(windows):
+    if not myExec(gen.addFileExt(ExeExt)): quit(1)
+  else:
+    if not myExec("./" & gen): quit(1)
   removeFile(addFileExt(gen, "c"))
   echo("Success")
 
 proc v(name: string, typ: TTypeKind=cint) = 
-  var n = if name[0] == '_': copy(name, 1) else: name
+  var n = if name[0] == '_': substr(name, 1) else: name
   var t = $typ
   case typ
   of pointer: 
@@ -369,7 +373,7 @@ if header("<pthread.h>"):
   #v("PTHREAD_MUTEX_INITIALIZER") 
   v("PTHREAD_MUTEX_NORMAL") 
   v("PTHREAD_MUTEX_RECURSIVE") #{.importc, header: "<pthread.h>".}: cint
-  v("PTHREAD_ONCE_INIT") #{.importc, header: "<pthread.h>".}: cint
+  #v("PTHREAD_ONCE_INIT") #{.importc, header: "<pthread.h>".}: cint
   v("PTHREAD_PRIO_INHERIT") #{.importc, header: "<pthread.h>".}: cint
   v("PTHREAD_PRIO_NONE") #{.importc, header: "<pthread.h>".}: cint
   v("PTHREAD_PRIO_PROTECT") #{.importc, header: "<pthread.h>".}: cint
@@ -820,5 +824,8 @@ if header("<spawn.h>"):
   v("POSIX_SPAWN_SETSIGDEF")
   v("POSIX_SPAWN_SETSIGMASK")
 
-main()
+if header("<stdio.h>"):
+  v "_IOFBF"
+  v "_IONBF"
 
+main()