1use crate::cell;
11use crate::machine::{ContFn, Machine};
12
13#[inline]
14fn mref<'a>(m: *mut Machine) -> &'a mut Machine {
15 unsafe { &mut *m }
16}
17
18#[unsafe(no_mangle)]
21pub extern "C" fn plg_rt_step(m: *mut Machine) -> i32 {
22 mref(m).step() as i32
23}
24
25#[unsafe(no_mangle)]
27pub extern "C" fn plg_rt_new_var(m: *mut Machine) -> u64 {
28 mref(m).new_var()
29}
30
31#[unsafe(no_mangle)]
33pub extern "C" fn plg_rt_frame_alloc(m: *mut Machine, n: u32) -> u64 {
34 mref(m).frame_alloc(n as usize) as u64
35}
36
37#[unsafe(no_mangle)]
38pub extern "C" fn plg_rt_frame_set(m: *mut Machine, base: u64, i: u32, w: u64) {
39 mref(m).heap[base as usize + i as usize] = w;
40}
41
42#[unsafe(no_mangle)]
43pub extern "C" fn plg_rt_frame_get(m: *mut Machine, base: u64, i: u32) -> u64 {
44 mref(m).heap[base as usize + i as usize]
45}
46
47#[unsafe(no_mangle)]
48pub extern "C" fn plg_rt_areg_get(m: *mut Machine, i: u32) -> u64 {
49 mref(m).areg[i as usize]
50}
51
52#[unsafe(no_mangle)]
53pub extern "C" fn plg_rt_areg_set(m: *mut Machine, i: u32, w: u64) {
54 mref(m).areg[i as usize] = w;
55}
56
57#[unsafe(no_mangle)]
58pub extern "C" fn plg_rt_breg_set(m: *mut Machine, i: u32, w: u64) {
59 mref(m).breg[i as usize] = w;
60}
61
62#[unsafe(no_mangle)]
64pub extern "C" fn plg_rt_put_struct(m: *mut Machine, functor: u32, arity: u32) -> u64 {
65 let m = mref(m);
66 let idx = m.heap.len();
67 m.heap.push(cell::pack_functor(functor, arity));
68 for i in 0..arity as usize {
69 let w = m.breg[i];
70 m.heap.push(w);
71 }
72 cell::make(cell::TAG_STR, idx as u64)
73}
74
75#[unsafe(no_mangle)]
76pub extern "C" fn plg_rt_put_list(m: *mut Machine, head: u64, tail: u64) -> u64 {
77 let m = mref(m);
78 let idx = m.heap.len();
79 m.heap.push(head);
80 m.heap.push(tail);
81 cell::make(cell::TAG_LST, idx as u64)
82}
83
84#[unsafe(no_mangle)]
85pub extern "C" fn plg_rt_put_float(m: *mut Machine, bits: u64) -> u64 {
86 let m = mref(m);
87 let idx = m.heap.len();
88 m.heap.push(bits);
89 cell::make(cell::TAG_FLT, idx as u64)
90}
91
92#[unsafe(no_mangle)]
94pub extern "C" fn plg_rt_put_big(m: *mut Machine, value: i64) -> u64 {
95 let m = mref(m);
96 let idx = m.heap.len();
97 m.heap.push(value as u64);
98 cell::make(cell::TAG_BIG, idx as u64)
99}
100
101#[unsafe(no_mangle)]
103pub extern "C" fn plg_rt_unify(m: *mut Machine, a: u64, b: u64) -> i32 {
104 crate::unify::unify(mref(m), a, b) as i32
105}
106
107#[unsafe(no_mangle)]
110pub extern "C" fn plg_rt_set_k(m: *mut Machine, k_fn: u64, k_env: u64) {
111 let m = mref(m);
112 m.k_fn = unsafe { std::mem::transmute::<usize, ContFn>(k_fn as usize) };
113 m.k_env = k_env;
114}
115
116#[unsafe(no_mangle)]
117pub extern "C" fn plg_rt_k_fn(m: *mut Machine) -> u64 {
118 mref(m).k_fn as usize as u64
119}
120
121#[unsafe(no_mangle)]
122pub extern "C" fn plg_rt_k_env(m: *mut Machine) -> u64 {
123 mref(m).k_env
124}
125
126#[unsafe(no_mangle)]
128pub extern "C" fn plg_rt_push_cp(m: *mut Machine, retry: u64, env: u64) {
129 let m = mref(m);
130 let retry = unsafe { std::mem::transmute::<usize, ContFn>(retry as usize) };
131 m.push_cp(retry, env);
132}
133
134#[unsafe(no_mangle)]
137pub extern "C" fn plg_rt_pred_fail(_m: *mut Machine, _env: u64) -> i32 {
138 0
139}
140
141#[unsafe(no_mangle)]
145pub extern "C" fn plg_rt_existence_error(
146 m: *mut Machine,
147 functor: u32,
148 arity: u32,
149 site_id: u32,
150) -> i32 {
151 let _site = crate::machine::ErrorSiteGuard::enter(m, site_id);
152 let m = mref(m);
153 let name = m.atoms.resolve(functor).to_string();
154 crate::errors::existence_procedure(m, &name, arity);
155 0
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use plg_shared::StringInterner;
162
163 #[test]
164 fn put_struct_consumes_breg() {
165 let mut m = Machine::new(StringInterner::new(), Vec::new());
166 let mp = &mut *m as *mut Machine;
167 plg_rt_breg_set(mp, 0, cell::make_atom(1));
168 plg_rt_breg_set(mp, 1, cell::make_int(7));
169 let w = plg_rt_put_struct(mp, 9, 2);
170 assert_eq!(cell::tag_of(w), cell::TAG_STR);
171 let idx = cell::payload(w) as usize;
172 assert_eq!(cell::unpack_functor(m.heap[idx]), (9, 2));
173 assert_eq!(m.heap[idx + 1], cell::make_atom(1));
174 assert_eq!(m.heap[idx + 2], cell::make_int(7));
175 }
176
177 #[test]
178 fn frames_roundtrip() {
179 let mut m = Machine::new(StringInterner::new(), Vec::new());
180 let mp = &mut *m as *mut Machine;
181 let f = plg_rt_frame_alloc(mp, 3);
182 plg_rt_frame_set(mp, f, 2, 99);
183 assert_eq!(plg_rt_frame_get(mp, f, 2), 99);
184 }
185
186 #[test]
187 fn k_roundtrips_through_u64() {
188 let mut m = Machine::new(StringInterner::new(), Vec::new());
189 let mp = &mut *m as *mut Machine;
190 let k = plg_rt_pred_fail as *const () as usize as u64;
191 plg_rt_set_k(mp, k, 42);
192 assert_eq!(plg_rt_k_fn(mp), k);
193 assert_eq!(plg_rt_k_env(mp), 42);
194 }
195}