new VM: some progress for the FFI support
This commit is contained in:
parent
e2a4d591e5
commit
9145bcfbb6
8 changed files with 80 additions and 60 deletions
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
## This file implements the FFI part of the evaluator for Nimrod code.
|
## 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):
|
when defined(windows):
|
||||||
const libcDll = "msvcrt.dll"
|
const libcDll = "msvcrt.dll"
|
||||||
|
|
@ -20,7 +20,11 @@ type
|
||||||
TDllCache = tables.TTable[string, TLibHandle]
|
TDllCache = tables.TTable[string, TLibHandle]
|
||||||
var
|
var
|
||||||
gDllCache = initTable[string, TLibHandle]()
|
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 =
|
proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
|
||||||
result = cache[dll]
|
result = cache[dll]
|
||||||
|
|
@ -28,10 +32,10 @@ proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
|
||||||
var libs: seq[string] = @[]
|
var libs: seq[string] = @[]
|
||||||
libCandidates(dll, libs)
|
libCandidates(dll, libs)
|
||||||
for c in libs:
|
for c in libs:
|
||||||
result = LoadLib(c)
|
result = loadLib(c)
|
||||||
if not result.isNil: break
|
if not result.isNil: break
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
GlobalError(info, "cannot load: " & dll)
|
globalError(info, "cannot load: " & dll)
|
||||||
cache[dll] = result
|
cache[dll] = result
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -50,7 +54,7 @@ proc importcSymbol*(sym: PSym): PNode =
|
||||||
else:
|
else:
|
||||||
let lib = sym.annex
|
let lib = sym.annex
|
||||||
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
|
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
|
var theAddr: pointer
|
||||||
if lib.isNil and not gExehandle.isNil:
|
if lib.isNil and not gExehandle.isNil:
|
||||||
# first try this exe itself:
|
# first try this exe itself:
|
||||||
|
|
@ -58,10 +62,12 @@ proc importcSymbol*(sym: PSym): PNode =
|
||||||
# then try libc:
|
# then try libc:
|
||||||
if theAddr.isNil:
|
if theAddr.isNil:
|
||||||
let dllhandle = gDllCache.getDll(libcDll, sym.info)
|
let dllhandle = gDllCache.getDll(libcDll, sym.info)
|
||||||
theAddr = dllhandle.checkedSymAddr(name)
|
theAddr = dllhandle.symAddr(name)
|
||||||
else:
|
elif not lib.isNil:
|
||||||
let dllhandle = gDllCache.getDll(lib.path.strVal, sym.info)
|
let dllhandle = gDllCache.getDll(if lib.kind == libHeader: libcDll
|
||||||
theAddr = dllhandle.checkedSymAddr(name)
|
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)
|
result.intVal = cast[TAddress](theAddr)
|
||||||
|
|
||||||
proc mapType(t: ast.PType): ptr libffi.TType =
|
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)")
|
else: internalError(n.info, "getField(record case branch)")
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if n.sym.position == position: result = n.sym
|
if n.sym.position == position: result = n.sym
|
||||||
else: nil
|
else: discard
|
||||||
|
|
||||||
proc packObject(x: PNode, typ: PType, res: pointer) =
|
proc packObject(x: PNode, typ: PType, res: pointer) =
|
||||||
InternalAssert x.kind in {nkObjConstr, nkPar}
|
InternalAssert x.kind in {nkObjConstr, nkPar}
|
||||||
|
|
@ -192,7 +198,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
|
||||||
of tyPointer, tyProc, tyCString, tyString:
|
of tyPointer, tyProc, tyCString, tyString:
|
||||||
if v.kind == nkNilLit:
|
if v.kind == nkNilLit:
|
||||||
# nothing to do since the memory is 0 initialized anyway
|
# nothing to do since the memory is 0 initialized anyway
|
||||||
nil
|
discard
|
||||||
elif v.kind == nkPtrLit:
|
elif v.kind == nkPtrLit:
|
||||||
awr(pointer, cast[pointer](v.intVal))
|
awr(pointer, cast[pointer](v.intVal))
|
||||||
elif v.kind in {nkStrLit..nkTripleStrLit}:
|
elif v.kind in {nkStrLit..nkTripleStrLit}:
|
||||||
|
|
@ -202,7 +208,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
|
||||||
of tyPtr, tyRef, tyVar:
|
of tyPtr, tyRef, tyVar:
|
||||||
if v.kind == nkNilLit:
|
if v.kind == nkNilLit:
|
||||||
# nothing to do since the memory is 0 initialized anyway
|
# nothing to do since the memory is 0 initialized anyway
|
||||||
nil
|
discard
|
||||||
elif v.kind == nkPtrLit:
|
elif v.kind == nkPtrLit:
|
||||||
awr(pointer, cast[pointer](v.intVal))
|
awr(pointer, cast[pointer](v.intVal))
|
||||||
else:
|
else:
|
||||||
|
|
@ -220,7 +226,7 @@ proc pack(v: PNode, typ: PType, res: pointer) =
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
packObject(v, typ, res)
|
packObject(v, typ, res)
|
||||||
of tyNil:
|
of tyNil:
|
||||||
nil
|
discard
|
||||||
of tyDistinct, tyGenericInst:
|
of tyDistinct, tyGenericInst:
|
||||||
pack(v, typ.sons[0], res)
|
pack(v, typ.sons[0], res)
|
||||||
else:
|
else:
|
||||||
|
|
@ -241,7 +247,7 @@ proc unpackObjectAdd(x: pointer, n, result: PNode) =
|
||||||
pair.sons[1] = unpack(x +! n.sym.offset, n.sym.typ, nil)
|
pair.sons[1] = unpack(x +! n.sym.offset, n.sym.typ, nil)
|
||||||
#echo "offset: ", n.sym.name.s, " ", n.sym.offset
|
#echo "offset: ", n.sym.name.s, " ", n.sym.offset
|
||||||
result.add pair
|
result.add pair
|
||||||
else: nil
|
else: discard
|
||||||
|
|
||||||
proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
|
proc unpackObject(x: pointer, typ: PType, n: PNode): PNode =
|
||||||
# compute the field's offsets:
|
# compute the field's offsets:
|
||||||
|
|
|
||||||
|
|
@ -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
|
# we pass 'tos.slots' instead of 'regs' so that the compiler can keep
|
||||||
# 'regs' in a register:
|
# 'regs' in a register:
|
||||||
when hasFFI:
|
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],
|
let newValue = callForeignFunction(c.globals.sons[prc.position-1],
|
||||||
prc.typ, tos.slots,
|
prc.typ, tos.slots,
|
||||||
rb+1, rc-1, c.debug[pc])
|
rb+1, rc-1, c.debug[pc])
|
||||||
if newValue.kind != nkEmpty:
|
if newValue.kind != nkEmpty:
|
||||||
assert instr.opcode == opcIndCallAsgn
|
assert instr.opcode == opcIndCallAsgn
|
||||||
regs[ra] = newValue
|
asgnRef(regs[ra], newValue)
|
||||||
else:
|
else:
|
||||||
globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
|
globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
|
||||||
elif prc.kind != skTemplate:
|
elif prc.kind != skTemplate:
|
||||||
|
|
@ -796,7 +798,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||||
decodeB(nkBracket)
|
decodeB(nkBracket)
|
||||||
let newLen = regs[rb].getOrdValue.int
|
let newLen = regs[rb].getOrdValue.int
|
||||||
setLen(regs[ra].sons, newLen)
|
setLen(regs[ra].sons, newLen)
|
||||||
of opcSwap, opcCast, opcReset:
|
of opcSwap, opcReset:
|
||||||
internalError(c.debug[pc], "too implement")
|
internalError(c.debug[pc], "too implement")
|
||||||
of opcIsNil:
|
of opcIsNil:
|
||||||
decodeB(nkIntLit)
|
decodeB(nkIntLit)
|
||||||
|
|
@ -938,6 +940,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||||
stackTrace(c, tos, pc, errGenerated,
|
stackTrace(c, tos, pc, errGenerated,
|
||||||
msgKindToString(errIllegalConvFromXtoY) % [
|
msgKindToString(errIllegalConvFromXtoY) % [
|
||||||
"unknown type" , "unknown type"])
|
"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:
|
of opcNSetIntVal:
|
||||||
decodeB(nkMetaNode)
|
decodeB(nkMetaNode)
|
||||||
var dest = regs[ra].uast
|
var dest = regs[ra].uast
|
||||||
|
|
@ -1074,6 +1085,8 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
# XXX produce a new 'globals' environment here:
|
# XXX produce a new 'globals' environment here:
|
||||||
setupGlobalCtx(module)
|
setupGlobalCtx(module)
|
||||||
result = globalCtx
|
result = globalCtx
|
||||||
|
when hasFFI:
|
||||||
|
globalCtx.features = {allowFFI, allowCast}
|
||||||
|
|
||||||
var oldErrorCount: int
|
var oldErrorCount: int
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -945,7 +945,10 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
|
||||||
proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
||||||
when hasFFI:
|
when hasFFI:
|
||||||
if allowFFI in c.features:
|
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
|
s.position = c.globals.len
|
||||||
else:
|
else:
|
||||||
localError(info, errGenerated, "VM is not allowed to 'importc'")
|
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 nkCurly: genSetConstr(c, n, dest)
|
||||||
of nkObjConstr: genObjConstr(c, n, dest)
|
of nkObjConstr: genObjConstr(c, n, dest)
|
||||||
of nkPar, nkClosure: genTupleConstr(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:
|
else:
|
||||||
InternalError n.info, "too implement " & $n.kind
|
InternalError n.info, "too implement " & $n.kind
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -341,16 +341,6 @@ when defined(windows):
|
||||||
template FindNextFile(a, b: expr): expr = FindNextFileW(a, b)
|
template FindNextFile(a, b: expr): expr = FindNextFileW(a, b)
|
||||||
template getCommandLine(): expr = getCommandLineW()
|
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 =
|
template getFilename(f: expr): expr =
|
||||||
$cast[WideCString](addr(f.cFilename[0]))
|
$cast[WideCString](addr(f.cFilename[0]))
|
||||||
else:
|
else:
|
||||||
|
|
@ -358,18 +348,13 @@ when defined(windows):
|
||||||
template FindNextFile(a, b: expr): expr = FindNextFileA(a, b)
|
template FindNextFile(a, b: expr): expr = FindNextFileA(a, b)
|
||||||
template getCommandLine(): expr = getCommandLineA()
|
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
|
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",
|
proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
|
||||||
tags: [FReadDir].} =
|
tags: [FReadDir].} =
|
||||||
## Returns true if the file exists, false otherwise.
|
## Returns true if the file exists, false otherwise.
|
||||||
|
|
@ -468,20 +453,21 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
|
||||||
## `newDir` cannot been set.
|
## `newDir` cannot been set.
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError(OSLastError())
|
if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
|
||||||
|
OSError(OSLastError())
|
||||||
else:
|
else:
|
||||||
if SetCurrentDirectoryA(newDir) == 0'i32: OSError(OSLastError())
|
if SetCurrentDirectoryA(newDir) == 0'i32: OSError(OSLastError())
|
||||||
else:
|
else:
|
||||||
if chdir(newDir) != 0'i32: OSError(OSLastError())
|
if chdir(newDir) != 0'i32: OSError(OSLastError())
|
||||||
|
|
||||||
proc JoinPath*(head, tail: string): string {.
|
proc joinPath*(head, tail: string): string {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Joins two directory names to one.
|
## Joins two directory names to one.
|
||||||
##
|
##
|
||||||
## For example on Unix:
|
## For example on Unix:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## JoinPath("usr", "lib")
|
## joinPath("usr", "lib")
|
||||||
##
|
##
|
||||||
## results in:
|
## results in:
|
||||||
##
|
##
|
||||||
|
|
@ -495,10 +481,10 @@ proc JoinPath*(head, tail: string): string {.
|
||||||
## examples on Unix:
|
## examples on Unix:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## assert JoinPath("usr", "") == "usr/"
|
## assert joinPath("usr", "") == "usr/"
|
||||||
## assert JoinPath("", "lib") == "lib"
|
## assert joinPath("", "lib") == "lib"
|
||||||
## assert JoinPath("", "/lib") == "/lib"
|
## assert joinPath("", "/lib") == "/lib"
|
||||||
## assert JoinPath("usr/", "/lib") == "usr/lib"
|
## assert joinPath("usr/", "/lib") == "usr/lib"
|
||||||
if len(head) == 0:
|
if len(head) == 0:
|
||||||
result = tail
|
result = tail
|
||||||
elif head[len(head)-1] in {DirSep, AltSep}:
|
elif head[len(head)-1] in {DirSep, AltSep}:
|
||||||
|
|
@ -512,14 +498,14 @@ proc JoinPath*(head, tail: string): string {.
|
||||||
else:
|
else:
|
||||||
result = head & DirSep & tail
|
result = head & DirSep & tail
|
||||||
|
|
||||||
proc JoinPath*(parts: varargs[string]): string {.noSideEffect,
|
proc joinPath*(parts: varargs[string]): string {.noSideEffect,
|
||||||
rtl, extern: "nos$1OpenArray".} =
|
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
|
## parts. You need to pass at least one element or the proc will assert in
|
||||||
## debug builds and crash on release builds.
|
## debug builds and crash on release builds.
|
||||||
result = parts[0]
|
result = parts[0]
|
||||||
for i in 1..high(parts):
|
for i in 1..high(parts):
|
||||||
result = JoinPath(result, parts[i])
|
result = joinPath(result, parts[i])
|
||||||
|
|
||||||
proc `/` * (head, tail: string): string {.noSideEffect.} =
|
proc `/` * (head, tail: string): string {.noSideEffect.} =
|
||||||
## The same as ``JoinPath(head, tail)``
|
## The same as ``JoinPath(head, tail)``
|
||||||
|
|
@ -533,7 +519,7 @@ proc `/` * (head, tail: string): string {.noSideEffect.} =
|
||||||
## assert "usr/" / "/lib" == "usr/lib"
|
## assert "usr/" / "/lib" == "usr/lib"
|
||||||
return JoinPath(head, tail)
|
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".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Splits a directory into (head, tail), so that
|
## Splits a directory into (head, tail), so that
|
||||||
## ``JoinPath(head, tail) == path``.
|
## ``JoinPath(head, tail) == path``.
|
||||||
|
|
@ -699,7 +685,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
|
||||||
if r.isNil: OSError(OSLastError())
|
if r.isNil: OSError(OSLastError())
|
||||||
setlen(result, c_strlen(result))
|
setlen(result, c_strlen(result))
|
||||||
|
|
||||||
proc ChangeFileExt*(filename, ext: string): string {.
|
proc changeFileExt*(filename, ext: string): string {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Changes the file extension to `ext`.
|
## Changes the file extension to `ext`.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -194,9 +194,9 @@ const
|
||||||
# should not be translated.
|
# should not be translated.
|
||||||
|
|
||||||
|
|
||||||
proc Open(f: var TFile, filename: string,
|
proc open(f: var TFile, filename: string,
|
||||||
mode: TFileMode = fmRead,
|
mode: TFileMode = fmRead,
|
||||||
bufSize: int = -1): Bool =
|
bufSize: int = -1): bool =
|
||||||
var p: pointer = fopen(filename, FormatOpen[mode])
|
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||||
result = (p != nil)
|
result = (p != nil)
|
||||||
f = cast[TFile](p)
|
f = cast[TFile](p)
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,8 @@ proc newWideCString*(s: cstring): WideCString =
|
||||||
if s.isNil: return nil
|
if s.isNil: return nil
|
||||||
|
|
||||||
when not defined(c_strlen):
|
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)
|
let L = cstrlen(s)
|
||||||
result = newWideCString(s, L)
|
result = newWideCString(s, L)
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -3,7 +3,6 @@ version 0.9.4
|
||||||
|
|
||||||
- new VM:
|
- new VM:
|
||||||
- implement overflow checking
|
- implement overflow checking
|
||||||
- implement the FFI
|
|
||||||
|
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
- special rule for ``[]=``
|
- special rule for ``[]=``
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
import os, strutils
|
import os, strutils
|
||||||
|
|
||||||
const
|
const
|
||||||
cc = "gcc -o $1 $1.c"
|
cc = "gcc -o $# $#.c"
|
||||||
|
|
||||||
cfile = """
|
cfile = """
|
||||||
/* Generated by detect.nim */
|
/* Generated by detect.nim */
|
||||||
|
|
@ -37,6 +37,7 @@ var
|
||||||
tl = ""
|
tl = ""
|
||||||
|
|
||||||
proc myExec(cmd: string): bool =
|
proc myExec(cmd: string): bool =
|
||||||
|
echo "CMD ", cmd
|
||||||
return execShellCmd(cmd) == 0
|
return execShellCmd(cmd) == 0
|
||||||
|
|
||||||
proc header(s: string): bool =
|
proc header(s: string): bool =
|
||||||
|
|
@ -46,7 +47,7 @@ proc header(s: string): bool =
|
||||||
f.write("#include $1\n" % s)
|
f.write("#include $1\n" % s)
|
||||||
f.write("int main() { return 0; }\n")
|
f.write("int main() { return 0; }\n")
|
||||||
close(f)
|
close(f)
|
||||||
result = myExec(cc % testh)
|
result = myExec(cc % [testh.addFileExt(ExeExt), testh])
|
||||||
removeFile(addFileExt(testh, "c"))
|
removeFile(addFileExt(testh, "c"))
|
||||||
if result:
|
if result:
|
||||||
addf(hd, "#include $1\n", s)
|
addf(hd, "#include $1\n", s)
|
||||||
|
|
@ -60,13 +61,16 @@ proc main =
|
||||||
if open(f, addFileExt(gen, "c"), fmWrite):
|
if open(f, addFileExt(gen, "c"), fmWrite):
|
||||||
f.write(cfile % [hd, tl, system.hostOS, system.hostCPU])
|
f.write(cfile % [hd, tl, system.hostOS, system.hostCPU])
|
||||||
close(f)
|
close(f)
|
||||||
if not myExec(cc % gen): quit(1)
|
if not myExec(cc % [gen.addFileExt(ExeExt), gen]): quit(1)
|
||||||
if not myExec("./" & 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"))
|
removeFile(addFileExt(gen, "c"))
|
||||||
echo("Success")
|
echo("Success")
|
||||||
|
|
||||||
proc v(name: string, typ: TTypeKind=cint) =
|
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
|
var t = $typ
|
||||||
case typ
|
case typ
|
||||||
of pointer:
|
of pointer:
|
||||||
|
|
@ -369,7 +373,7 @@ if header("<pthread.h>"):
|
||||||
#v("PTHREAD_MUTEX_INITIALIZER")
|
#v("PTHREAD_MUTEX_INITIALIZER")
|
||||||
v("PTHREAD_MUTEX_NORMAL")
|
v("PTHREAD_MUTEX_NORMAL")
|
||||||
v("PTHREAD_MUTEX_RECURSIVE") #{.importc, header: "<pthread.h>".}: cint
|
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_INHERIT") #{.importc, header: "<pthread.h>".}: cint
|
||||||
v("PTHREAD_PRIO_NONE") #{.importc, header: "<pthread.h>".}: cint
|
v("PTHREAD_PRIO_NONE") #{.importc, header: "<pthread.h>".}: cint
|
||||||
v("PTHREAD_PRIO_PROTECT") #{.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_SETSIGDEF")
|
||||||
v("POSIX_SPAWN_SETSIGMASK")
|
v("POSIX_SPAWN_SETSIGMASK")
|
||||||
|
|
||||||
main()
|
if header("<stdio.h>"):
|
||||||
|
v "_IOFBF"
|
||||||
|
v "_IONBF"
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue