factor/library/compiler/alien.factor

210 lines
5.7 KiB
Factor
Raw Normal View History

2005-01-23 16:47:28 -05:00
! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
2004-09-25 16:18:11 -04:00
IN: alien
USING: assembler compiler errors generic hashtables inference
2005-04-02 02:39:33 -05:00
interpreter kernel lists math namespaces parser sequences stdio
strings unparser words ;
! ! ! WARNING ! ! !
! Reloading this file into a running Factor instance on Win32
! or Unix with FFI I/O will bomb the runtime, since I/O words
! would become uncompiled, and FFI calls can only be made from
! compiled code.
! USAGE:
!
! Command line parameters given to the runtime specify libraries
! to load.
2004-12-25 15:52:08 -05:00
!
! -libraries:<foo>:name=<soname> -- define a library <foo>, to be
2004-12-25 15:52:08 -05:00
! loaded from the <soname> DLL.
!
! -libraries:<foo>:abi=stdcall -- define a library using the
2004-12-25 15:52:08 -05:00
! stdcall ABI. This ABI is usually used on Win32. Any other abi
! parameter, or a missing abi parameter indicates the cdecl ABI
! should be used, which is common on Unix.
2004-09-25 16:18:11 -04:00
2005-03-06 20:03:22 -05:00
: null? ( alien -- ? ) dup [ alien-address 0 = ] when ;
: null>f ( alien -- alien/f )
dup alien-address 0 = [ drop f ] when ;
2004-12-23 01:14:07 -05:00
M: alien hashcode ( obj -- n )
2004-12-31 02:17:45 -05:00
alien-address >fixnum ;
2004-12-23 01:14:07 -05:00
M: alien = ( obj obj -- ? )
over alien? [
over local-alien? over local-alien? or [
eq?
] [
alien-address swap alien-address =
] ifte
] [
2drop f
] ifte ;
2005-01-23 16:47:28 -05:00
M: alien unparse ( obj -- str )
[
"#<" ,
dup local-alien? "local-alien" "alien" ? ,
" @ " ,
alien-address unparse ,
">" ,
] make-string ;
2004-12-25 15:52:08 -05:00
: library ( name -- object )
dup [ "libraries" get hash ] when ;
2004-09-25 16:18:11 -04:00
2004-12-25 18:08:20 -05:00
: load-dll ( name -- dll )
#! Higher level wrapper around dlopen primitive.
library dup [
[
"dll" get dup [
drop "name" get dlopen dup "dll" set
] unless
] bind
] when ;
2004-12-23 06:51:42 -05:00
: add-library ( library name abi -- )
"libraries" get [
<namespace> [
"abi" set
"name" set
] extend put
] bind ;
2004-12-13 19:14:03 -05:00
SYMBOL: #cleanup ( unwind stack by parameter )
SYMBOL: #unbox ( move top of datastack to C stack )
SYMBOL: #box ( move EAX to datastack )
2004-12-25 15:52:08 -05:00
: library-abi ( library -- abi )
library [ [ "abi" get ] bind ] [ "cdecl" ] ifte* ;
2004-12-13 19:14:03 -05:00
2004-12-25 15:52:08 -05:00
SYMBOL: #alien-invoke
2005-03-29 19:11:10 -05:00
SYMBOL: #alien-global
2004-12-18 00:38:51 -05:00
2004-12-25 15:52:08 -05:00
! These are set in the #alien-invoke dataflow IR node.
2004-12-13 19:14:03 -05:00
SYMBOL: alien-returns
SYMBOL: alien-parameters
2004-12-25 15:52:08 -05:00
: set-alien-returns ( returns node -- )
[ dup alien-returns set ] bind
"void" = [
[ object ] produce-d 1 0 node-outputs
] unless ;
: set-alien-parameters ( parameters node -- )
[ dup alien-parameters set ] bind
[ drop object ] map dup dup ensure-d
length 0 node-inputs consume-d ;
2005-03-29 19:11:10 -05:00
: ensure-dlsym ( symbol library -- ) load-dll dlsym drop ;
: alien-invoke-node ( returns params function library -- )
#! We should fail if the library does not exist, so that
#! compilation does not keep trying to compile FFI words
#! over and over again if the library is not loaded.
2005-03-29 19:11:10 -05:00
2dup ensure-dlsym
2004-12-25 15:52:08 -05:00
cons #alien-invoke dataflow,
[ set-alien-parameters ] keep
set-alien-returns ;
2005-03-29 20:03:55 -05:00
DEFER: alien-invoke
2005-03-29 19:11:10 -05:00
: infer-alien-invoke ( -- )
\ alien-invoke "infer-effect" word-prop car ensure-d
pop-literal
pop-literal >r
pop-literal
pop-literal -rot
r> swap alien-invoke-node ;
: alien-global-node ( type name library -- )
2dup ensure-dlsym
cons #alien-global dataflow,
set-alien-returns ;
2005-03-29 20:03:55 -05:00
DEFER: alien-global
2005-03-29 19:11:10 -05:00
: infer-alien-global ( -- )
\ alien-global "infer-effect" word-prop car ensure-d
pop-literal
pop-literal
pop-literal -rot
alien-global-node ;
2004-12-13 19:14:03 -05:00
2004-12-25 15:52:08 -05:00
: box-parameter
c-type [
"width" get cell align
"unboxer" get
] bind #unbox swons , ;
2004-12-13 19:14:03 -05:00
: linearize-parameters ( params -- count )
#! Generate code for boxing a list of C types.
#! Return amount stack must be unwound by.
2004-12-16 19:57:03 -05:00
[ alien-parameters get reverse ] bind 0 swap [
2004-12-25 15:52:08 -05:00
box-parameter +
2004-12-13 19:14:03 -05:00
] each ;
: linearize-returns ( returns -- )
[ alien-returns get ] bind dup "void" = [
drop
] [
2004-12-25 15:52:08 -05:00
c-type [ "boxer" get ] bind #box swons ,
2004-12-13 19:14:03 -05:00
] ifte ;
2005-03-29 19:11:10 -05:00
: linearize-alien-invoke ( node -- )
2004-12-13 19:14:03 -05:00
dup linearize-parameters >r
2005-03-29 19:11:10 -05:00
dup [ node-param get ] bind #alien-invoke swons ,
2004-12-25 22:15:37 -05:00
dup [ node-param get cdr library-abi "stdcall" = ] bind
2004-12-25 15:52:08 -05:00
r> swap [ drop ] [ #cleanup swons , ] ifte
2004-12-13 19:14:03 -05:00
linearize-returns ;
2005-03-29 19:11:10 -05:00
#alien-invoke [ linearize-alien-invoke ] "linearizer" set-word-prop
: linearize-alien-global ( node -- )
dup [ node-param get ] bind #alien-global swons ,
linearize-returns ;
#alien-global [ linearize-alien-global ] "linearizer" set-word-prop
2004-12-13 19:14:03 -05:00
TUPLE: alien-error lib ;
C: alien-error ( lib -- ) [ set-alien-error-lib ] keep ;
M: alien-error error. ( error -- )
[
2005-03-29 19:11:10 -05:00
"C library interface words cannot be interpreted. " ,
"Either the compiler is disabled, " ,
"or the ``" , alien-error-lib ,
"'' library is missing." ,
] make-string print ;
: alien-invoke ( ... returns library function parameters -- ... )
2004-12-18 00:38:51 -05:00
#! Call a C library function.
#! 'returns' is a type spec, and 'parameters' is a list of
#! type specs. 'library' is an entry in the "libraries"
#! namespace.
rot <alien-error> throw ;
2005-03-29 19:11:10 -05:00
\ alien-invoke [ [ string string string general-list ] [ ] ]
"infer-effect" set-word-prop
\ alien-invoke [ infer-alien-invoke ] "infer" set-word-prop
: alien-global ( type library name -- value )
#! Fetch the value of C global variable.
#! 'type' is a type spec. 'library' is an entry in the
#! "libraries" namespace.
swap <alien-error> throw ;
\ alien-global [ [ string string string ] [ object ] ]
"infer-effect" set-word-prop
2005-03-29 19:11:10 -05:00
\ alien-global [ infer-alien-global ] "infer" set-word-prop
2004-12-13 19:14:03 -05:00
global [
"libraries" get [ <namespace> "libraries" set ] unless
] bind