summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/astalgo.nim2
-rw-r--r--compiler/evalffi.nim69
-rwxr-xr-xcompiler/llstream.nim17
3 files changed, 60 insertions, 28 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 9a2bebab4..564f262d7 100755
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -429,7 +429,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
                    [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
       case n.kind
-      of nkCharLit..nkInt64Lit: 
+      of nkCharLit..nkUInt64Lit:
         appf(result, ",$N$1\"intVal\": $2", [istr, toRope(n.intVal)])
       of nkFloatLit, nkFloat32Lit, nkFloat64Lit: 
         appf(result, ",$N$1\"floatVal\": $2", 
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim
index b55f2baad..ba6e7ee8f 100644
--- a/compiler/evalffi.nim
+++ b/compiler/evalffi.nim
@@ -156,7 +156,10 @@ proc packObject(x: PNode, typ: PType, res: pointer) =
       pack(it, field.typ, res +! field.offset)
     else:
       GlobalError(x.info, "cannot pack unnamed tuple")
-      
+
+const maxPackDepth = 20
+var packRecCheck = 0
+
 proc pack(v: PNode, typ: PType, res: pointer) =
   template awr(T, v: expr) {.immediate, dirty.} =
     wr(T, res, v)
@@ -186,12 +189,14 @@ proc pack(v: PNode, typ: PType, res: pointer) =
   of tyFloat32: awr(float32, v.floatVal)
   of tyFloat64: awr(float64, v.floatVal)
   
-  of tyPointer, tyProc:
+  of tyPointer, tyProc,  tyCString, tyString:
     if v.kind == nkNilLit:
       # nothing to do since the memory is 0 initialized anyway
       nil
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
+    elif v.kind in {nkStrLit..nkTripleStrLit}:
+      awr(cstring, cstring(v.strVal))
     else:
       GlobalError(v.info, "cannot map pointer/proc value to FFI")
   of tyPtr, tyRef, tyVar:
@@ -201,15 +206,13 @@ proc pack(v: PNode, typ: PType, res: pointer) =
     elif v.kind == nkPtrLit:
       awr(pointer, cast[pointer](v.intVal))
     else:
+      if packRecCheck > maxPackDepth:
+        packRecCheck = 0
+        GlobalError(v.info, "cannot map value to FFI " & typeToString(v.typ))
+      inc packRecCheck
       pack(v.sons[0], typ.sons[0], res +! sizeof(pointer))
+      dec packRecCheck
       awr(pointer, res +! sizeof(pointer))
-  of tyCString, tyString:
-    if v.kind == nkNilLit:
-      nil
-    elif v.kind in {nkStrLit..nkTripleStrLit}:
-      awr(cstring, cstring(v.strVal))
-    else:
-      GlobalError(v.info, "cannot map string value to FFI")
   of tyArray, tyArrayConstr:
     let baseSize = typ.sons[1].getSize
     for i in 0 .. <v.len:
@@ -236,6 +239,8 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
     var pair = newNodeI(nkExprColonExpr, result.info, 2)
     pair.sons[0] = n
     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
 
 proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
@@ -295,8 +300,10 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
       # check we have the right field:
       result = n
       if result.kind.canonNodeKind != k.canonNodeKind:
-        echo "expected ", k, " but got ", result.kind
-        GlobalError(n.info, "cannot map value from FFI")
+        #echo "expected ", k, " but got ", result.kind
+        #debug result
+        return newNodeI(nkExceptBranch, n.info)
+        #GlobalError(n.info, "cannot map value from FFI")
     result.field = v
 
   template setNil() =
@@ -315,7 +322,7 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
   
   case typ.kind
   of tyBool: awi(nkIntLit, rd(bool, x).ord)
-  of tyChar: awi(nkIntLit, rd(char, x).ord)
+  of tyChar: awi(nkCharLit, rd(char, x).ord)
   of tyInt:  awi(nkIntLit, rd(int, x))
   of tyInt8: awi(nkInt8Lit, rd(int8, x))
   of tyInt16: awi(nkInt16Lit, rd(int16, x))
@@ -341,6 +348,10 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
     let p = rd(pointer, x)
     if p.isNil:
       setNil()
+    elif n != nil and n.kind == nkStrLit:
+      # we passed a string literal as a pointer; however strings are already
+      # in their unboxed representation so nothing it to be unpacked:
+      result = n
     else:
       awi(nkPtrLit, cast[TAddress](p))
   of tyPtr, tyRef, tyVar:
@@ -350,7 +361,9 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
     elif n == nil or n.kind == nkPtrLit:
       awi(nkPtrLit, cast[TAddress](p))
     elif n != nil and n.len == 1:
-      n.sons[0] = unpack(rd(pointer, x), typ.sons[0], n.sons[0])
+      internalAssert n.kind == nkRefTy
+      n.sons[0] = unpack(p, typ.sons[0], n.sons[0])
+      result = n
     else:
       GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
   of tyObject, tyTuple:
@@ -372,12 +385,24 @@ proc unpack(x: pointer, typ: PType, n: PNode): PNode =
     GlobalError(n.info, "cannot map value from FFI " & typeToString(typ))
 
 proc fficast*(x: PNode, destTyp: PType): PNode =
-  # we play safe here and allocate the max possible size:
-  let allocSize = max(packSize(x, x.typ), packSize(x, destTyp))
-  var a = alloc0(allocSize)
-  pack(x, x.typ, a)
-  result = unpack(a, destTyp, nil)
-  dealloc a
+  if x.kind == nkPtrLit and x.typ.kind in {tyPtr, tyRef, tyVar, tyPointer, 
+                                           tyProc, tyCString, tyString, 
+                                           tySequence}:
+    result = newNodeIT(x.kind, x.info, destTyp)
+    result.intVal = x.intVal
+  elif x.kind == nkNilLit:
+    result = newNodeIT(x.kind, x.info, destTyp)
+  else:
+    # we play safe here and allocate the max possible size:
+    let size = max(packSize(x, x.typ), packSize(x, destTyp))
+    var a = alloc0(size)
+    pack(x, x.typ, a)
+    # cast through a pointer needs a new inner object:
+    let y = if x.kind == nkRefTy: newNodeI(nkRefTy, x.info, 1)
+            else: x.copyTree
+    y.typ = x.typ
+    result = unpack(a, destTyp, y)
+    dealloc a
 
 proc callForeignFunction*(call: PNode): PNode =
   InternalAssert call.sons[0].kind == nkPtrLit
@@ -413,6 +438,6 @@ proc callForeignFunction*(call: PNode): PNode =
     result.info = call.info
 
   if retVal != nil: dealloc retVal
-  for i in countdown(call.len-2, 0):
-    call.sons[i+1] = unpack(args[i], typ.sons[i+1], call[i+1])
-    dealloc args[i]
+  for i in 1 .. call.len-1:
+    call.sons[i] = unpack(args[i-1], typ.sons[i], call[i])
+    dealloc args[i-1]
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 1d1722176..8ccf24b99 100755
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -103,17 +103,24 @@ proc continueLine(line: string, inTripleString: bool): bool {.inline.} =
       line[0] == ' ' or
       line.endsWith(LineContinuationOprs+AdditionalLineContinuationOprs)
 
-proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = 
-  var inTripleString = false
+proc countTriples(s: string): int =
+  var i = 0
+  while i < s.len:
+    if s[i] == '"' and s[i+1] == '"' and s[i+2] == '"':
+      inc result
+      inc i, 2
+    inc i
+
+proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
   s.s = ""
   s.rd = 0
   var line = newStringOfCap(120)
+  var triples = 0
   while ReadLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line): 
     add(s.s, line)
     add(s.s, "\n")
-    if line.contains("\"\"\""):
-      inTripleString = not inTripleString
-    if not continueLine(line, inTripleString): break
+    inc triples, countTriples(line)
+    if not continueLine(line, (triples and 1) == 1): break
   inc(s.lineOffset)
   result = min(bufLen, len(s.s) - s.rd)
   if result > 0: