foolang
foolang copied to clipboard
FFI / shared object interface
FFI code is always accessed through the System object.
foo --extension=foo/ext/network
loads foo/ext/network.foo
, initializes it by Extension load: system
,
and makes it available as system network
.
Sketch:
-- TimeVal new
-- TimeVal sec: <Integer> usec: <Integer>
define TimeVal
Alien struct: { sec: Alien time_t,
usec: Alien suseconds_t }
end
-- TimeZone new
-- TimeZone minuteswest: <Integer> dsttime: <Integer>
define TimeZone
Alien struct: { minuteswest: Alien int,
dsttime: Alien int }
end
class Stuff { library }
method sin: x
let sin = Alien
name: "sin"
type: [Alien double] -> Alien double
library: library.
sin value: x
method gettimeofday
let gettimeofday = Alien
name: "gettimeofday"
type: [*TimeVal, *TimeZone] -> Alien int
library: library.
let tv = TimeVal new.
let tz = TimeZone new.
gettimeofday value: tv value: tz.
[tv, tz]
end
class Extension {}
class method load: system
Stuff library: (system libraries libc)
This should do for now: I'm hesitant to introduce methods that require more syntax or allow circumventing System.
Complication
- Rust's libffi crate on Windows needs a built-from source LLVM, as http://llvm.org's installer doesn't bundle llvm-config.
- Cranelift doesn't support fastcall yet. (Or maybe it does? Looking at this again.)
Both mean the same thing: need to find another backend for doing FFI in the evaluator.
Alternatives:
- https://crates.io/crates/dynasm
- https://crates.io/crates/lua-jit-sys
- https://crates.io/crates/lightning-sys
- https://github.com/TomBebbington/jit.rs
- https://github.com/lemonrock/predicator
- https://crates.io/crates/gccjit
- https://crates.io/crates/libtcc
- https://crates.io/crates/assembler
Finally, one option is to support a sufficiently impoverished number of foreign types that I can just write the glue code by hand.
Need to rewrite this for self-hosting.
Could I require that extensions are compiled first? That would work, but it would be irritating to develop with.