]>
Witch of Git - ivy/blob - rt/src/lib.rs
1 use std
::sync
::atomic
::{Ordering
, AtomicU32
};
3 const _STDOUT
: i32 = 1;
7 ($fmt
:literal $
(, $arg
:expr
)* $
(,)?
) => {
8 if std
::env
::var("IVY_RT_TRACE").is
_ok
() {
9 eprintln
!($fmt
, $
($arg
),*);
15 #[derive(PartialEq, Eq)]
22 pub struct ObjHeader
{
39 func
: fn(&ObjLam
) -> Obj
,
44 #[derive(Clone, Copy)]
47 header
: *mut ObjHeader
,
53 pub fn write(fd
: i32, buf
: *const u8, len
: usize) -> isize;
54 pub fn exit(code
: i32) -> !;
55 pub fn malloc(size
: usize) -> *mut u8;
56 pub fn free(ptr
: *mut u8);
61 pub unsafe extern "C" fn ivy_debug(obj
: Obj
) -> Obj
{
62 println
!("DEBUG {:016x}", obj
.int
);
67 pub unsafe extern "C" fn ivy_abort(msg
: *const u8, len
: usize) -> ! {
68 sys
::write(STDERR
, msg
, len
);
73 pub unsafe extern "C" fn ivy_exit(code
: i32) -> ! {
78 pub unsafe extern "C" fn ivy_check_int(obj
: Obj
) {
80 panic
!("ivy_check_int called with non-integer object {:016x}.", obj
.int
);
85 pub unsafe extern "C" fn ivy_check_lam(obj
: Obj
) {
87 panic
!("ivy_check_lam called with non-lambda object {:016x}.", obj
.int
);
91 // This should probably be a macro rather than a call?
92 // But it might be good to have it for completeness.
93 // Or maybe it's valuable if we want to support big integers.
95 pub unsafe extern "C" fn ivy_make_int(value
: i64) -> Obj
{
96 Obj
{ int
: value
<< 1 }
100 pub unsafe extern "C" fn ivy_make_lam(func
: fn(&ObjLam
) -> Obj
, params
: u16, upvars
: u16) -> Obj
{
101 let size
= ObjLam
::size_of(params
, upvars
);
102 let box_lam
= sys
::malloc(size
) as *mut ObjLam
;
103 box_lam
.write(ObjLam
{
106 rc
: AtomicU32
::new(0),
113 .write_bytes(0, (params
+ upvars
) as usize);
114 trace
!("MAKE {:016x} {:016x}", box_lam
as usize, func
as usize);
119 pub unsafe extern "C" fn ivy_free(obj
: Obj
) {
123 sys
::free(obj
.header
as *mut u8)
127 pub unsafe extern "C" fn ivy_incref(obj
: Obj
) {
132 pub unsafe extern "C" fn ivy_decref(obj
: Obj
) {
137 pub unsafe extern "C" fn ivy_clone(obj
: Obj
) -> Obj
{
138 if obj
.is
_n
ull
() || !obj
.is
_box
() {
142 unimplemented
!("copying boxed integers")
144 let lam
= &*obj
.box_lam
;
145 let size
= lam
.size();
146 let data
= sys
::malloc(size
);
147 core
::ptr
::copy(obj
.box_lam
as *const u8, data
, size
);
148 let box_lam
= data
as *mut ObjLam
;
149 *(*box_lam
).rc
.get_mut() = 0;
150 trace
!("COPY {:016x} {:016x}", obj
.int
, box_lam
as usize);
155 pub unsafe extern "C" fn ivy_app(fun
: Obj
, arg
: Obj
) -> Obj
{
156 ivy_app_mut(ivy_clone(fun
), arg
)
160 pub unsafe extern "C" fn ivy_app_mut(fun
: Obj
, arg
: Obj
) -> Obj
{
161 trace
!("APP {:016x} {:016x}", fun
.int
, arg
.int
);
163 panic
!("ivy_app called with a non-lam as the function: {:016x}.", fun
.int
);
165 let lam
= &mut *fun
.box_lam
;
166 if lam
.filled
< lam
.params
{
169 "Lam @ {:016x} ({:016x}) has {} of {} arguments filled.",
170 fun
.int
, lam
.func
as usize, lam
.filled
, lam
.params
172 panic
!("ivy_app called with a null arg.");
175 let idx
= lam
.filled
as usize;
176 lam
.params_mut()[idx
] = arg
;
178 } else if lam
.params
== lam
.filled
{
180 panic
!("ivy_app called for a 0-arity application with a non-null arg.");
184 if lam
.params
== lam
.filled
{
185 trace
!("RUN {:016x}", fun
.int
);
188 trace
!("UPD8 {:016x}", fun
.int
);
195 fn is_null(self) -> bool
{
196 unsafe { self.int
== 0 }
199 fn is_box(self) -> bool
{
200 !self.is
_n
ull
() && unsafe { self.int
& 1 == 0 }
203 unsafe fn is_int(self) -> bool
{
204 !self.is
_n
ull
() && (!self.is
_box
() || (*self.header
).tag
== ObjTag
::Int
)
207 unsafe fn is_lam(self) -> bool
{
208 self.is
_box
() && (*self.header
).tag
== ObjTag
::Lam
211 unsafe fn incref(self) {
215 (*self.header
).rc
.fetch
_add
(1, Ordering
::SeqCst
);
218 unsafe fn decref(self) {
222 if (*self.header
).rc
.fetch
_s
ub
(1, Ordering
::SeqCst
) == 1 {
227 unsafe fn dealloc(self) {
232 let lam
= &mut *self.box_lam
;
233 for param
in lam
.params_mut() {
236 for upvar
in lam
.upvars
_m
ut
() {
240 sys
::free(self.header
as *mut u8);
245 fn size_of(params
: u16, upvars
: u16) -> usize {
246 core
::mem
::size_of
::<ObjLam
>() + params
as usize * 8 + upvars
as usize * 8
249 fn size(&self) -> usize {
250 ObjLam
::size_of(self.params
, self.upvars
)
253 unsafe fn raw_fields_mut(&mut self) -> *mut Obj
{
254 (self as *mut ObjLam
).add(1) as *mut Obj
257 unsafe fn params_mut(&mut self) -> &mut [Obj
] {
258 let ptr
= self.raw_fields_mut();
259 core
::slice
::from_raw_parts_mut(ptr
, self.params
as usize)
262 unsafe fn upvars_mut(&mut self) -> &mut [Obj
] {
263 let ptr
= self.raw_fields_mut().add(self.params
as usize);
264 core
::slice
::from_raw_parts_mut(ptr
, self.upvars
as usize)