1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::fmt;
use std::hash::{Hash, Hasher};
use crate::boxed::refs::Gc;
use crate::boxed::*;
use crate::task;
pub type Captures = Gc<Any>;
pub type ThunkEntry = extern "C" fn(&mut task::Task, Captures, Gc<Any>) -> Gc<Any>;
#[repr(C, align(16))]
pub struct FunThunk {
header: Header,
pub(crate) captures: Captures,
entry: ThunkEntry,
}
impl Boxed for FunThunk {}
impl UniqueTagged for FunThunk {}
impl FunThunk {
pub fn new(heap: &mut impl AsHeap, captures: Captures, entry: ThunkEntry) -> Gc<FunThunk> {
heap.as_heap_mut().place_box(FunThunk {
header: Self::TYPE_TAG.to_heap_header(Self::size()),
captures,
entry,
})
}
pub fn size() -> BoxSize {
BoxSize::Size32
}
pub fn apply(&self, task: &mut task::Task, arg_list: Gc<Any>) -> Gc<Any> {
(self.entry)(task, self.captures, arg_list)
}
}
impl PartialEq for FunThunk {
fn eq(&self, _: &FunThunk) -> bool {
false
}
}
impl Eq for FunThunk {}
impl Hash for FunThunk {
fn hash<H: Hasher>(&self, state: &mut H) {
Self::TYPE_TAG.hash(state);
state.write_usize(self as *const _ as usize);
}
}
impl fmt::Debug for FunThunk {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(formatter, "FunThunk({:p})", self)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::boxed;
use crate::boxed::heap::Heap;
use std::mem;
extern "C" fn identity_entry(
_: &mut task::Task,
_captures: Captures,
rest: Gc<Any>,
) -> Gc<Any> {
rest
}
extern "C" fn return_42_entry(
task: &mut task::Task,
_captures: Captures,
_rest: Gc<Any>,
) -> Gc<Any> {
Int::new(task, 32).as_any_ref()
}
#[test]
fn sizes() {
assert_eq!(32, mem::size_of::<FunThunk>());
}
#[test]
fn equality() {
let mut heap = Heap::empty();
let nil_captures = boxed::NIL_INSTANCE.as_any_ref();
let boxed_identity1 = FunThunk::new(&mut heap, nil_captures, identity_entry);
let boxed_identity2 = FunThunk::new(&mut heap, nil_captures, identity_entry);
let boxed_return = FunThunk::new(&mut heap, nil_captures, return_42_entry);
assert_ne!(boxed_identity1, boxed_return);
assert_ne!(boxed_identity1, boxed_identity2);
}
}