]>
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_exit(code
: i32) -> ! {
84 pub unsafe extern "C" fn ivy_check_int(obj
: Obj
) {
86 abort("Abort: ivy_check_int called with non-integer object.\n");
91 pub unsafe extern "C" fn ivy_check_lam(obj
: Obj
) {
93 abort("Abort: ivy_check_lam called with non-lambda object.\n");
97 // This should probably be a macro rather than a call?
98 // But it might be good to have it for completeness.
99 // Or maybe it's valuable if we want to support big integers.
101 pub unsafe extern "C" fn ivy_make_int(value
: i64) -> Obj
{
102 Obj
{ int
: value
<< 1 }
106 pub unsafe extern "C" fn ivy_make_lam(func
: fn(&ObjLam
) -> Obj
, params
: u16, upvars
: u16) -> Obj
{
107 let size
= ObjLam
::size_of(params
, upvars
);
108 let box_lam
= sys
::malloc(size
) as *mut ObjLam
;
109 box_lam
.write(ObjLam
{
112 rc
: AtomicU32
::new(0),
119 .write_bytes(0, (params
+ upvars
) as usize);
120 // println!("MAKE {:016x}", box_lam as usize);
125 pub unsafe extern "C" fn ivy_free(obj
: Obj
) {
129 sys
::free(obj
.header
as *mut u8)
133 pub unsafe extern "C" fn ivy_incref(obj
: Obj
) {
138 pub unsafe extern "C" fn ivy_decref(obj
: Obj
) {
143 pub unsafe extern "C" fn ivy_clone(obj
: Obj
) -> Obj
{
144 if obj
.is
_n
ull
() || !obj
.is
_box
() {
148 abort("Abort: copying boxed integers is not implemented.\n")
150 let lam
= &*obj
.box_lam
;
151 let size
= lam
.size();
152 let data
= sys
::malloc(size
);
153 core
::ptr
::copy(obj
.box_lam
as *const u8, data
, size
);
154 let box_lam
= data
as *mut ObjLam
;
155 *(*box_lam
).rc
.get_mut() = 0;
156 // println!("COPY {:016x} {:016x}", obj.int, box_lam as usize);
161 pub unsafe extern "C" fn ivy_app(mut fun
: Obj
, arg
: Obj
) -> Obj
{
162 ivy_app_mut(ivy_clone(fun
), arg
)
166 pub unsafe extern "C" fn ivy_app_mut(fun
: Obj
, arg
: Obj
) -> Obj
{
167 // println!("APP {:016x} {:016x}", fun.int, arg.int);
169 abort("Abort: ivy_app called with a non-lam as the function.\n");
171 let lam
= &mut *fun
.box_lam
;
172 if lam
.filled
< lam
.params
{
174 abort("Abort: ivy_app called with a null arg.\n");
177 let idx
= lam
.filled
as usize;
178 lam
.params_mut()[idx
] = arg
;
180 } else if lam
.params
== lam
.filled
{
182 abort("Abort: ivy_app called for a 0-arity application with a non-null arg.\n");
186 if lam
.params
== lam
.filled
{
187 // println!("RUN {:016x}", fun.int);
190 // println!("UPD8 {:016x}", fun.int);
196 fn abort(msg
: &str) -> ! {
197 unsafe { ivy_abort(msg
.as_ptr(), msg
.len()) }
201 fn is_null(self) -> bool
{
202 unsafe { self.int
== 0 }
205 fn is_box(self) -> bool
{
206 !self.is
_n
ull
() && unsafe { self.int
& 1 == 0 }
209 unsafe fn refcount(self) -> u32 {
211 (*self.header
).rc
.load(Ordering
::SeqCst
)
217 unsafe fn unique(self) -> bool
{
221 unsafe fn is_int(self) -> bool
{
222 !self.is
_n
ull
() && (!self.is
_box
() || (*self.header
).tag
== ObjTag
::Int
)
225 unsafe fn is_lam(self) -> bool
{
226 self.is
_box
() && (*self.header
).tag
== ObjTag
::Lam
229 unsafe fn incref(self) {
233 (*self.header
).rc
.fetch
_add
(1, Ordering
::SeqCst
);
236 unsafe fn decref(self) {
240 if (*self.header
).rc
.fetch
_s
ub
(1, Ordering
::SeqCst
) == 1 {
245 unsafe fn dealloc(self) {
250 let lam
= &mut *self.box_lam
;
251 for param
in lam
.params_mut() {
254 for upvar
in lam
.upvars
_m
ut
() {
258 sys
::free(self.header
as *mut u8);
263 fn size_of(params
: u16, upvars
: u16) -> usize {
264 core
::mem
::size_of
::<ObjLam
>() + params
as usize * 8 + upvars
as usize * 8
267 fn size(&self) -> usize {
268 ObjLam
::size_of(self.params
, self.upvars
)
271 unsafe fn raw_fields_mut(&mut self) -> *mut Obj
{
272 (self as *mut ObjLam
).add(1) as *mut Obj
275 unsafe fn params_mut(&mut self) -> &mut [Obj
] {
276 let ptr
= self.raw_fields_mut();
277 core
::slice
::from_raw_parts_mut(ptr
, self.params
as usize)
280 unsafe fn upvars_mut(&mut self) -> &mut [Obj
] {
281 let ptr
= self.raw_fields_mut().add(self.params
as usize);
282 core
::slice
::from_raw_parts_mut(ptr
, self.upvars
as usize)