diff options
-rw-r--r-- | compiler/evalffi.nim | 57 | ||||
-rwxr-xr-x | compiler/evals.nim | 17 | ||||
-rwxr-xr-x | koch.nim | 2 | ||||
-rwxr-xr-x | todo.txt | 9 |
4 files changed, 53 insertions, 32 deletions
diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim index 66ed3a87e..35659ed26 100644 --- a/compiler/evalffi.nim +++ b/compiler/evalffi.nim @@ -34,19 +34,25 @@ proc getDll(cache: var TDllCache; dll: string): pointer = cache[dll] = result proc importcSymbol*(sym: PSym): PNode = - let lib = sym.annex - if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}: - InternalError("dynlib needs to be a string literal for the REPL") - - let dllpath = if lib.isNil: libcDll else: lib.path.strVal - let dllhandle = gDllCache.getDll(dllpath) let name = ropeToStr(sym.loc.r) - let theAddr = dllhandle.checkedSymAddr(name) # the AST does not support untyped pointers directly, so we use an nkIntLit # that contains the address instead: result = newNodeIT(nkIntLit, sym.info, sym.typ) - result.intVal = cast[TAddress](theAddr) + case name + of "stdin": result.intVal = cast[TAddress](system.stdin) + of "stdout": result.intVal = cast[TAddress](system.stdout) + of "stderr": result.intVal = cast[TAddress](system.stderr) + else: + let lib = sym.annex + if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}: + InternalError(sym.info, "dynlib needs to be a string literal for the REPL") + + let dllpath = if lib.isNil: libcDll else: lib.path.strVal + let dllhandle = gDllCache.getDll(dllpath) + let theAddr = dllhandle.checkedSymAddr(name) + + result.intVal = cast[TAddress](theAddr) proc mapType(t: ast.PType): ptr libffi.TType = if t == nil: return addr libffi.type_void @@ -63,8 +69,10 @@ proc mapType(t: ast.PType): ptr libffi.TType = of tyFloat, tyFloat64: result = addr libffi.type_double of tyFloat32: result = addr libffi.type_float of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, - tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr: + tyStmt, tyTypeDesc, tyProc, tyArray, tyArrayConstr, tyNil: result = addr libffi.type_pointer + of tyDistinct: + result = mapType(t.sons[0]) else: InternalError("cannot map type to FFI") # too risky: @@ -80,12 +88,12 @@ proc mapCallConv(cc: TCallingConvention): TABI = template rd(T, p: expr): expr {.immediate.} = (cast[ptr T](p))[] template wr(T, p, v: expr) {.immediate.} = (cast[ptr T](p))[] = v -proc pack(v: PNode): pointer = +proc pack(v: PNode, typ: PType): pointer = template awr(T, v: expr) {.immediate, dirty.} = result = alloc0(sizeof(T)) wr(T, result, v) - case v.typ.kind + case typ.kind of tyBool: awr(bool, v.intVal != 0) of tyChar: awr(char, v.intVal.chr) of tyInt: awr(int, v.intVal.int) @@ -120,6 +128,10 @@ proc pack(v: PNode): pointer = result = alloc0(sizeof(pointer)) else: awr(cstring, cstring(v.strVal)) + of tyNil: + result = alloc0(sizeof(pointer)) + of tyDistinct, tyGenericInst: + result = pack(v, typ.sons[0]) else: InternalError("cannot map value to FFI " & typeToString(v.typ)) @@ -168,31 +180,36 @@ proc unpack(x: pointer, typ: PType, info: TLineInfo): PNode = result = newNodeIT(nkNilLit, info, typ) else: aws(nkStrLit, $p) + of tyNil: result = newNodeIT(nkNilLit, info, typ) + of tyDistinct, tyGenericInst: + result = unpack(x, typ.sons[0], info) else: InternalError("cannot map value from FFI " & typeToString(typ)) proc callForeignFunction*(call: PNode): PNode = InternalAssert call.sons[0].kind == nkIntLit - let typ = call.sons[0].typ var cif: TCif var sig: TParamList - for i in 1..typ.len-1: sig[i-1] = mapType(typ.sons[i]) + # use the arguments' types for varargs support: + for i in 1..call.len-1: sig[i-1] = mapType(call.sons[i].typ) - if prep_cif(cif, mapCallConv(typ.callConv), cuint(typ.len-1), + let typ = call.sons[0].typ + if prep_cif(cif, mapCallConv(typ.callConv), cuint(call.len-1), mapType(typ.sons[0]), sig) != OK: InternalError(call.info, "error in FFI call") var args: TArgList let fn = cast[pointer](call.sons[0].intVal) - for i in 0 .. call.len-1: - args[i] = pack(call.sons[i+1]) - let retVal = alloc(typ.sons[0].getSize.int) + for i in 1 .. call.len-1: + args[i-1] = pack(call.sons[i], call.sons[i].typ) + let retVal = if isEmptyType(typ.sons[0]): pointer(nil) + else: alloc(typ.sons[0].getSize.int) libffi.call(cif, fn, retVal, args) - if isEmptyType(typ.sons[0]): result = emptyNode + if retVal.isNil: result = emptyNode else: result = unpack(retVal, typ.sons[0], call.info) - dealloc retVal - for i in countdown(call.len-1, 0): dealloc args[i] + if retVal != nil: dealloc retVal + for i in countdown(call.len-2, 0): dealloc args[i] diff --git a/compiler/evals.nim b/compiler/evals.nim index 535d9aebd..ab6218be0 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -339,16 +339,15 @@ proc evalGlobalVar(c: PEvalContext, s: PSym, flags: TEvalFlags): PNode = if not aliasNeeded(result, flags): result = copyTree(result) else: + when hasFFI: + if sfImportc in s.flags: + result = importcSymbol(s) + IdNodeTablePut(c.globals, s, result) + return result + result = s.ast if result == nil or result.kind == nkEmpty: - when hasFFI: - # for 'stdin' etc. we need to support 'importc' for variables: - if sfImportc in s.flags: - result = importcSymbol(s) - else: - result = getNullValue(s.typ, s.info) - else: - result = getNullValue(s.typ, s.info) + result = getNullValue(s.typ, s.info) else: result = evalAux(c, result, {}) if isSpecial(result): return @@ -392,7 +391,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode = var newCall = newNodeI(nkCall, n.info, n.len) newCall.sons[0] = evalGlobalVar(c, prc.sym, {}) for i in 1 .. <n.len: - newCall.sons[i] = d.params[i-1] + newCall.sons[i] = d.params[i] return callForeignFunction(newCall) pushStackFrame(c, d) diff --git a/koch.nim b/koch.nim index 029e8a733..b01de94cb 100755 --- a/koch.nim +++ b/koch.nim @@ -215,7 +215,7 @@ when defined(withUpdate): if errcode == 0: if output == "": # No changes - echo("No update. Exiting..") + echo("No update. Exiting...") return else: echo("Fetching updates from repo...") diff --git a/todo.txt b/todo.txt index 3d8859fc2..2a6a45370 100755 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,12 @@ version 0.9.2 ============= +- FFI: + * proper byte buffers + * support for arrays + * support for tuples/objects + * make system.nim aware of nimffi - fix closure bug finally -- test&finish first class iterators: - * nested iterators - fix marshal bug - investigate nimgame bug @@ -11,6 +14,8 @@ version 0.9.2 version 0.9.X ============= +- test&finish first class iterators: + * nested iterators - implement the missing features wrt inheritance - implement generic methods - improve the compiler as a service |