anachro_forth_core/
builtins.rs

1use crate::*;
2use core::fmt::Write;
3
4pub fn bi_emit<BuiltinTok, SeqTok, Sdata, Sexec, O>(
5    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
6) -> Result<(), Error>
7where
8    Sdata: Stack<Item = i32>,
9    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
10    SeqTok: Clone,
11    BuiltinTok: Clone,
12    O: Write,
13{
14    let word = ctxt.data_stk.pop()? as u32;
15    let symbol = core::char::from_u32(word).unwrap_or('‽');
16    write!(&mut ctxt.cur_output, "{}", symbol).map_err(|_| Error::OutputFormat)
17}
18
19pub fn bi_pop<BuiltinTok, SeqTok, Sdata, Sexec, O>(
20    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
21) -> Result<(), Error>
22where
23    Sdata: Stack<Item = i32>,
24    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
25    SeqTok: Clone,
26    BuiltinTok: Clone,
27    O: Write,
28{
29    writeln!(&mut ctxt.cur_output, "{}", ctxt.data_stk.pop()?)?;
30    Ok(())
31}
32
33pub fn bi_cr<BuiltinTok, SeqTok, Sdata, Sexec, O>(
34    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
35) -> Result<(), Error>
36where
37    Sdata: Stack<Item = i32>,
38    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
39    SeqTok: Clone,
40    BuiltinTok: Clone,
41    O: Write,
42{
43    writeln!(&mut ctxt.cur_output)?;
44    Ok(())
45}
46
47pub fn bi_lt<BuiltinTok, SeqTok, Sdata, Sexec, O>(
48    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
49) -> Result<(), Error>
50where
51    Sdata: Stack<Item = i32>,
52    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
53    SeqTok: Clone,
54    BuiltinTok: Clone,
55    O: Write,
56{
57    let val2 = ctxt.data_stk.pop()?;
58    let val1 = ctxt.data_stk.pop()?;
59    ctxt.data_stk.push(if val1 < val2 { -1 } else { 0 });
60    Ok(())
61}
62
63pub fn bi_gt<BuiltinTok, SeqTok, Sdata, Sexec, O>(
64    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
65) -> Result<(), Error>
66where
67    Sdata: Stack<Item = i32>,
68    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
69    SeqTok: Clone,
70    BuiltinTok: Clone,
71    O: Write,
72{
73    let val2 = ctxt.data_stk.pop()?;
74    let val1 = ctxt.data_stk.pop()?;
75    ctxt.data_stk.push(if val1 > val2 { -1 } else { 0 });
76    Ok(())
77}
78
79pub fn bi_retstk_push<BuiltinTok, SeqTok, Sdata, Sexec, O>(
80    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
81) -> Result<(), Error>
82where
83    Sdata: Stack<Item = i32>,
84    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
85    SeqTok: Clone,
86    BuiltinTok: Clone,
87    O: Write,
88{
89    let val = ctxt.data_stk.pop()?;
90    ctxt.ret_stk.push(val);
91    Ok(())
92}
93
94pub fn bi_retstk_pop<BuiltinTok, SeqTok, Sdata, Sexec, O>(
95    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
96) -> Result<(), Error>
97where
98    Sdata: Stack<Item = i32>,
99    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
100    SeqTok: Clone,
101    BuiltinTok: Clone,
102    O: Write,
103{
104    let val = ctxt.ret_stk.pop()?;
105    ctxt.data_stk.push(val);
106    Ok(())
107}
108
109pub fn bi_eq<BuiltinTok, SeqTok, Sdata, Sexec, O>(
110    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
111) -> Result<(), Error>
112where
113    Sdata: Stack<Item = i32>,
114    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
115    SeqTok: Clone,
116    BuiltinTok: Clone,
117    O: Write,
118{
119    let val1 = ctxt.data_stk.pop()?;
120    let val2 = ctxt.data_stk.pop()?;
121    ctxt.data_stk.push(if val1 == val2 { -1 } else { 0 });
122    Ok(())
123}
124
125pub fn bi_add<BuiltinTok, SeqTok, Sdata, Sexec, O>(
126    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
127) -> Result<(), Error>
128where
129    Sdata: Stack<Item = i32>,
130    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
131    SeqTok: Clone,
132    BuiltinTok: Clone,
133    O: Write,
134{
135    let val1 = ctxt.data_stk.pop()?;
136    let val2 = ctxt.data_stk.pop()?;
137    ctxt.data_stk.push(val1.wrapping_add(val2));
138    Ok(())
139}
140
141pub fn bi_dup<BuiltinTok, SeqTok, Sdata, Sexec, O>(
142    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
143) -> Result<(), Error>
144where
145    Sdata: Stack<Item = i32>,
146    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
147    SeqTok: Clone,
148    BuiltinTok: Clone,
149    O: Write,
150{
151    let val1 = *ctxt.data_stk.last()?;
152    ctxt.data_stk.push(val1);
153    Ok(())
154}
155
156pub fn bi_retstk_dup<BuiltinTok, SeqTok, Sdata, Sexec, O>(
157    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
158) -> Result<(), Error>
159where
160    Sdata: Stack<Item = i32>,
161    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
162    SeqTok: Clone,
163    BuiltinTok: Clone,
164    O: Write,
165{
166    let val1 = *ctxt.ret_stk.last()?;
167    ctxt.ret_stk.push(val1);
168    Ok(())
169}
170
171pub fn bi_retstk_swap<BuiltinTok, SeqTok, Sdata, Sexec, O>(
172    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
173) -> Result<(), Error>
174where
175    Sdata: Stack<Item = i32>,
176    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
177    SeqTok: Clone,
178    BuiltinTok: Clone,
179    O: Write,
180{
181    let top = ctxt.ret_stk.pop()?;
182    let bot = ctxt.ret_stk.pop()?;
183    ctxt.ret_stk.push(top);
184    ctxt.ret_stk.push(bot);
185
186    Ok(())
187}
188
189pub fn bi_priv_loop<BuiltinTok, SeqTok, Sdata, Sexec, O>(
190    ctxt: &mut Runtime<BuiltinTok, SeqTok, Sdata, Sexec, O>,
191) -> Result<(), Error>
192where
193    Sdata: Stack<Item = i32>,
194    Sexec: ExecutionStack<BuiltinTok, SeqTok>,
195    SeqTok: Clone,
196    BuiltinTok: Clone,
197    O: Write,
198{
199    let lmt = ctxt.ret_stk.pop()?;
200    let mut idx = ctxt.ret_stk.pop()?;
201
202    idx = idx.checked_add(1).ok_or(Error::BadMath)?;
203
204    if idx == lmt {
205        ctxt.data_stk.push(-1);
206    } else {
207        ctxt.data_stk.push(0);
208        ctxt.ret_stk.push(idx);
209        ctxt.ret_stk.push(lmt);
210    }
211
212    Ok(())
213}