]>
Witch of Git - ivy/blob - rt/src/lib.rs
2 use core
::{sync
::atomic
::{AtomicU32
, Ordering
}, panic
::PanicInfo
, fmt
::Write
};
5 fn handle_panic(panic_info
: &PanicInfo
) -> ! {
6 if let Some(s
) = panic_info
.payload().downcast_ref
::<&str>() {
9 abort("a panic occurred\n");
13 const STDOUT
: i32 = 1;
14 const STDERR
: i32 = 2;
17 #[derive(PartialEq, Eq)]
24 pub struct ObjHeader
{
41 func
: fn(&ObjLam
) -> Obj
,
46 #[derive(Clone, Copy)]
49 header
: *mut ObjHeader
,
56 pub fn write(fd
: i32, buf
: *const u8, len
: usize) -> isize;
57 pub fn exit(code
: i32) -> !;
58 pub fn malloc(size
: usize) -> *mut u8;
59 pub fn free(ptr
: *mut u8);
64 pub unsafe extern "C" fn ivy_debug(obj
: Obj
) -> Obj
{
65 // let mut buffer = String::new();
66 // writeln!(&mut buffer, "DBUG {:016x}", obj.int);
67 const BUFFER
: &str = "DEBUG\n";
68 sys
::write(STDOUT
, BUFFER
.as_ptr(), BUFFER
.len());
73 pub unsafe extern "C" fn ivy_abort(msg
: *const u8, len
: usize) -> ! {
74 sys
::write(STDERR
, msg
, len
);
79 pub unsafe extern "C" fn ivy_check_int(obj
: Obj
) {
81 abort("Abort: ivy_check_int called with non-integer object.\n");
86 pub unsafe extern "C" fn ivy_check_lam(obj
: Obj
) {
88 abort("Abort: ivy_check_lam called with non-lambda object.\n");
92 // This should probably be a macro rather than a call?
93 // But it might be good to have it for completeness.
94 // Or maybe it's valuable if we want to support big integers.
96 pub unsafe extern "C" fn ivy_make_int(value
: i64) -> Obj
{
97 Obj
{ int
: value
<< 1 }
101 pub unsafe extern "C" fn ivy_make_lam(func
: fn(&ObjLam
) -> Obj
, params
: u16, upvars
: u16) -> Obj
{
102 let size
= ObjLam
::size_of(params
, upvars
);
103 let box_lam
= sys
::malloc(size
) as *mut ObjLam
;
104 box_lam
.write(ObjLam
{
107 rc
: AtomicU32
::new(0),
114 .write_bytes(0, (params
+ upvars
) as usize);
115 // println!("MAKE {:016x}", box_lam as usize);
120 pub unsafe extern "C" fn ivy_free(obj
: Obj
) {
124 sys
::free(obj
.header
as *mut u8)
128 pub unsafe extern "C" fn ivy_incref(obj
: Obj
) {
133 pub unsafe extern "C" fn ivy_decref(obj
: Obj
) {
138 pub unsafe extern "C" fn ivy_clone(obj
: Obj
) -> Obj
{
139 if obj
.is
_n
ull
() || !obj
.is
_box
() {
143 abort("Abort: copying boxed integers is not implemented.\n")
145 let lam
= &*obj
.box_lam
;
146 let size
= lam
.size();
147 let data
= sys
::malloc(size
);
148 core
::ptr
::copy(obj
.box_lam
as *const u8, data
, size
);
149 let box_lam
= data
as *mut ObjLam
;
150 *(*box_lam
).rc
.get_mut() = 0;
151 // println!("COPY {:016x} {:016x}", obj.int, box_lam as usize);
156 pub unsafe extern "C" fn ivy_app(mut fun
: Obj
, arg
: Obj
) -> Obj
{
157 ivy_app_mut(ivy_clone(fun
), arg
)
161 pub unsafe extern "C" fn ivy_app_mut(fun
: Obj
, arg
: Obj
) -> Obj
{
162 // println!("APP {:016x} {:016x}", fun.int, arg.int);
164 abort("Abort: ivy_app called with a non-lam as the function.\n");
166 let lam
= &mut *fun
.box_lam
;
167 if lam
.filled
< lam
.params
{
169 abort("Abort: ivy_app called with a null arg.\n");
172 let idx
= lam
.filled
as usize;
173 lam
.params_mut()[idx
] = arg
;
175 } else if lam
.params
== lam
.filled
{
177 abort("Abort: ivy_app called for a 0-arity application with a non-null arg.\n");
181 if lam
.params
== lam
.filled
{
182 // println!("RUN {:016x}", fun.int);
185 // println!("UPD8 {:016x}", fun.int);
191 fn abort(msg
: &str) -> ! {
192 unsafe { ivy_abort(msg
.as_ptr(), msg
.len()) }
196 fn is_null(self) -> bool
{
197 unsafe { self.int
== 0 }
200 fn is_box(self) -> bool
{
201 !self.is
_n
ull
() && unsafe { self.int
& 1 == 0 }
204 unsafe fn refcount(self) -> u32 {
206 (*self.header
).rc
.load(Ordering
::SeqCst
)
212 unsafe fn unique(self) -> bool
{
216 unsafe fn is_int(self) -> bool
{
217 !self.is
_n
ull
() && (!self.is
_box
() || (*self.header
).tag
== ObjTag
::Int
)
220 unsafe fn is_lam(self) -> bool
{
221 self.is
_box
() && (*self.header
).tag
== ObjTag
::Lam
224 unsafe fn incref(self) {
228 (*self.header
).rc
.fetch
_add
(1, Ordering
::SeqCst
);
231 unsafe fn decref(self) {
235 if (*self.header
).rc
.fetch
_s
ub
(1, Ordering
::SeqCst
) == 1 {
240 unsafe fn dealloc(self) {
245 let lam
= &mut *self.box_lam
;
246 for param
in lam
.params_mut() {
249 for upvar
in lam
.upvars
_m
ut
() {
253 sys
::free(self.header
as *mut u8);
258 fn size_of(params
: u16, upvars
: u16) -> usize {
259 core
::mem
::size_of
::<ObjLam
>() + params
as usize * 8 + upvars
as usize * 8
262 fn size(&self) -> usize {
263 ObjLam
::size_of(self.params
, self.upvars
)
266 unsafe fn raw_fields_mut(&mut self) -> *mut Obj
{
267 (self as *mut ObjLam
).add(1) as *mut Obj
270 unsafe fn params_mut(&mut self) -> &mut [Obj
] {
271 let ptr
= self.raw_fields_mut();
272 core
::slice
::from_raw_parts_mut(ptr
, self.params
as usize)
275 unsafe fn upvars_mut(&mut self) -> &mut [Obj
] {
276 let ptr
= self.raw_fields_mut().add(self.params
as usize);
277 core
::slice
::from_raw_parts_mut(ptr
, self.upvars
as usize)