xref: /freebsd/contrib/bc/include/lang.h (revision 44d4804d1945435745518cd09eb8ae6ab22ecef4)
1252884aeSStefan Eßer /*
2252884aeSStefan Eßer  * *****************************************************************************
3252884aeSStefan Eßer  *
43aa99676SStefan Eßer  * SPDX-License-Identifier: BSD-2-Clause
5252884aeSStefan Eßer  *
610328f8bSStefan Eßer  * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
7252884aeSStefan Eßer  *
8252884aeSStefan Eßer  * Redistribution and use in source and binary forms, with or without
9252884aeSStefan Eßer  * modification, are permitted provided that the following conditions are met:
10252884aeSStefan Eßer  *
11252884aeSStefan Eßer  * * Redistributions of source code must retain the above copyright notice, this
12252884aeSStefan Eßer  *   list of conditions and the following disclaimer.
13252884aeSStefan Eßer  *
14252884aeSStefan Eßer  * * Redistributions in binary form must reproduce the above copyright notice,
15252884aeSStefan Eßer  *   this list of conditions and the following disclaimer in the documentation
16252884aeSStefan Eßer  *   and/or other materials provided with the distribution.
17252884aeSStefan Eßer  *
18252884aeSStefan Eßer  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19252884aeSStefan Eßer  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20252884aeSStefan Eßer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21252884aeSStefan Eßer  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22252884aeSStefan Eßer  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23252884aeSStefan Eßer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24252884aeSStefan Eßer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25252884aeSStefan Eßer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26252884aeSStefan Eßer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27252884aeSStefan Eßer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28252884aeSStefan Eßer  * POSSIBILITY OF SUCH DAMAGE.
29252884aeSStefan Eßer  *
30252884aeSStefan Eßer  * *****************************************************************************
31252884aeSStefan Eßer  *
32252884aeSStefan Eßer  * Definitions for program data.
33252884aeSStefan Eßer  *
34252884aeSStefan Eßer  */
35252884aeSStefan Eßer 
36252884aeSStefan Eßer #ifndef BC_LANG_H
37252884aeSStefan Eßer #define BC_LANG_H
38252884aeSStefan Eßer 
39252884aeSStefan Eßer #include <stdbool.h>
40252884aeSStefan Eßer 
41252884aeSStefan Eßer #include <status.h>
42252884aeSStefan Eßer #include <vector.h>
43252884aeSStefan Eßer #include <num.h>
44252884aeSStefan Eßer 
45*44d4804dSStefan Eßer /// The instructions for bytecode.
46252884aeSStefan Eßer typedef enum BcInst {
47252884aeSStefan Eßer 
48252884aeSStefan Eßer #if BC_ENABLED
49*44d4804dSStefan Eßer 
50*44d4804dSStefan Eßer 	/// Postfix increment and decrement. Prefix are translated into
51*44d4804dSStefan Eßer 	/// BC_INST_ONE with either BC_INST_ASSIGN_PLUS or BC_INST_ASSIGN_MINUS.
52252884aeSStefan Eßer 	BC_INST_INC = 0,
53252884aeSStefan Eßer 	BC_INST_DEC,
54252884aeSStefan Eßer #endif // BC_ENABLED
55252884aeSStefan Eßer 
56*44d4804dSStefan Eßer 	/// Unary negation.
57252884aeSStefan Eßer 	BC_INST_NEG,
58*44d4804dSStefan Eßer 
59*44d4804dSStefan Eßer 	/// Boolean not.
60252884aeSStefan Eßer 	BC_INST_BOOL_NOT,
61252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
62*44d4804dSStefan Eßer 	/// Truncation operator.
63252884aeSStefan Eßer 	BC_INST_TRUNC,
64252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
65252884aeSStefan Eßer 
66*44d4804dSStefan Eßer 	/// These should be self-explanatory.
67252884aeSStefan Eßer 	BC_INST_POWER,
68252884aeSStefan Eßer 	BC_INST_MULTIPLY,
69252884aeSStefan Eßer 	BC_INST_DIVIDE,
70252884aeSStefan Eßer 	BC_INST_MODULUS,
71252884aeSStefan Eßer 	BC_INST_PLUS,
72252884aeSStefan Eßer 	BC_INST_MINUS,
73252884aeSStefan Eßer 
74252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
75*44d4804dSStefan Eßer 
76*44d4804dSStefan Eßer 	/// Places operator.
77252884aeSStefan Eßer 	BC_INST_PLACES,
78252884aeSStefan Eßer 
79*44d4804dSStefan Eßer 	/// Shift operators.
80252884aeSStefan Eßer 	BC_INST_LSHIFT,
81252884aeSStefan Eßer 	BC_INST_RSHIFT,
82252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
83252884aeSStefan Eßer 
84*44d4804dSStefan Eßer 	/// Comparison operators.
85252884aeSStefan Eßer 	BC_INST_REL_EQ,
86252884aeSStefan Eßer 	BC_INST_REL_LE,
87252884aeSStefan Eßer 	BC_INST_REL_GE,
88252884aeSStefan Eßer 	BC_INST_REL_NE,
89252884aeSStefan Eßer 	BC_INST_REL_LT,
90252884aeSStefan Eßer 	BC_INST_REL_GT,
91252884aeSStefan Eßer 
92*44d4804dSStefan Eßer 	/// Boolean or and and.
93252884aeSStefan Eßer 	BC_INST_BOOL_OR,
94252884aeSStefan Eßer 	BC_INST_BOOL_AND,
95252884aeSStefan Eßer 
96252884aeSStefan Eßer #if BC_ENABLED
97*44d4804dSStefan Eßer 	/// Same as the normal operators, but assigment. So ^=, *=, /=, etc.
98252884aeSStefan Eßer 	BC_INST_ASSIGN_POWER,
99252884aeSStefan Eßer 	BC_INST_ASSIGN_MULTIPLY,
100252884aeSStefan Eßer 	BC_INST_ASSIGN_DIVIDE,
101252884aeSStefan Eßer 	BC_INST_ASSIGN_MODULUS,
102252884aeSStefan Eßer 	BC_INST_ASSIGN_PLUS,
103252884aeSStefan Eßer 	BC_INST_ASSIGN_MINUS,
104252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
105*44d4804dSStefan Eßer 	/// Places and shift assignment operators.
106252884aeSStefan Eßer 	BC_INST_ASSIGN_PLACES,
107252884aeSStefan Eßer 	BC_INST_ASSIGN_LSHIFT,
108252884aeSStefan Eßer 	BC_INST_ASSIGN_RSHIFT,
109252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
110*44d4804dSStefan Eßer 
111*44d4804dSStefan Eßer 	/// Normal assignment.
112252884aeSStefan Eßer 	BC_INST_ASSIGN,
113252884aeSStefan Eßer 
114*44d4804dSStefan Eßer 	/// bc and dc detect when the value from an assignment is not necessary.
115*44d4804dSStefan Eßer 	/// For example, a plain assignment statement means the value is never used.
116*44d4804dSStefan Eßer 	/// In those cases, we can get lots of performance back by not even creating
117*44d4804dSStefan Eßer 	/// a copy at all. In fact, it saves a copy, a push onto the results stack,
118*44d4804dSStefan Eßer 	/// a pop from the results stack, and a free. Definitely worth it to detect.
119252884aeSStefan Eßer 	BC_INST_ASSIGN_POWER_NO_VAL,
120252884aeSStefan Eßer 	BC_INST_ASSIGN_MULTIPLY_NO_VAL,
121252884aeSStefan Eßer 	BC_INST_ASSIGN_DIVIDE_NO_VAL,
122252884aeSStefan Eßer 	BC_INST_ASSIGN_MODULUS_NO_VAL,
123252884aeSStefan Eßer 	BC_INST_ASSIGN_PLUS_NO_VAL,
124252884aeSStefan Eßer 	BC_INST_ASSIGN_MINUS_NO_VAL,
125252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
126*44d4804dSStefan Eßer 	/// Same as above.
127252884aeSStefan Eßer 	BC_INST_ASSIGN_PLACES_NO_VAL,
128252884aeSStefan Eßer 	BC_INST_ASSIGN_LSHIFT_NO_VAL,
129252884aeSStefan Eßer 	BC_INST_ASSIGN_RSHIFT_NO_VAL,
130252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
131252884aeSStefan Eßer #endif // BC_ENABLED
132*44d4804dSStefan Eßer 
133*44d4804dSStefan Eßer 	/// Normal assignment that pushes no value on the stack.
134252884aeSStefan Eßer 	BC_INST_ASSIGN_NO_VAL,
135252884aeSStefan Eßer 
136*44d4804dSStefan Eßer 	/// Push a constant onto the results stack.
137252884aeSStefan Eßer 	BC_INST_NUM,
138252884aeSStefan Eßer 
139*44d4804dSStefan Eßer 	/// Push a variable onto the results stack.
140*44d4804dSStefan Eßer 	BC_INST_VAR,
141*44d4804dSStefan Eßer 
142*44d4804dSStefan Eßer 	/// Push an array element onto the results stack.
143*44d4804dSStefan Eßer 	BC_INST_ARRAY_ELEM,
144*44d4804dSStefan Eßer 
145*44d4804dSStefan Eßer 	/// Push an array onto the results stack. This is different from pushing an
146*44d4804dSStefan Eßer 	/// array *element* onto the results stack; it pushes a reference to the
147*44d4804dSStefan Eßer 	/// whole array. This is needed in bc for function arguments that are
148*44d4804dSStefan Eßer 	/// arrays. It is also needed for returning the length of an array.
149*44d4804dSStefan Eßer 	BC_INST_ARRAY,
150*44d4804dSStefan Eßer 
151*44d4804dSStefan Eßer 	/// Push a zero or a one onto the stack. These are special cased because it
152*44d4804dSStefan Eßer 	/// does help performance, particularly for one since inc/dec operators
153*44d4804dSStefan Eßer 	/// use it.
1543aa99676SStefan Eßer 	BC_INST_ZERO,
155252884aeSStefan Eßer 	BC_INST_ONE,
156252884aeSStefan Eßer 
157252884aeSStefan Eßer #if BC_ENABLED
158*44d4804dSStefan Eßer 	/// Push the last printed value onto the stack.
159252884aeSStefan Eßer 	BC_INST_LAST,
160252884aeSStefan Eßer #endif // BC_ENABLED
161*44d4804dSStefan Eßer 
162*44d4804dSStefan Eßer 	/// Push the value of any of the globals onto the stack.
163252884aeSStefan Eßer 	BC_INST_IBASE,
164252884aeSStefan Eßer 	BC_INST_OBASE,
165252884aeSStefan Eßer 	BC_INST_SCALE,
166*44d4804dSStefan Eßer 
167*44d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
168*44d4804dSStefan Eßer 	/// Push the value of the seed global onto the stack.
169252884aeSStefan Eßer 	BC_INST_SEED,
170*44d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
171*44d4804dSStefan Eßer 
172*44d4804dSStefan Eßer 	/// These are builtin functions.
173252884aeSStefan Eßer 	BC_INST_LENGTH,
174252884aeSStefan Eßer 	BC_INST_SCALE_FUNC,
175252884aeSStefan Eßer 	BC_INST_SQRT,
176252884aeSStefan Eßer 	BC_INST_ABS,
177*44d4804dSStefan Eßer 
178*44d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
179*44d4804dSStefan Eßer 	/// Another builtin function.
180252884aeSStefan Eßer 	BC_INST_IRAND,
181*44d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
182*44d4804dSStefan Eßer 
183*44d4804dSStefan Eßer 	/// Asciify.
184*44d4804dSStefan Eßer 	BC_INST_ASCIIFY,
185*44d4804dSStefan Eßer 
186*44d4804dSStefan Eßer 	/// Another builtin function.
187252884aeSStefan Eßer 	BC_INST_READ,
188*44d4804dSStefan Eßer 
189*44d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
190*44d4804dSStefan Eßer 	/// Another builtin function.
191252884aeSStefan Eßer 	BC_INST_RAND,
192*44d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
193*44d4804dSStefan Eßer 
194*44d4804dSStefan Eßer 	/// Return the max for the various globals.
195252884aeSStefan Eßer 	BC_INST_MAXIBASE,
196252884aeSStefan Eßer 	BC_INST_MAXOBASE,
197252884aeSStefan Eßer 	BC_INST_MAXSCALE,
198*44d4804dSStefan Eßer #if BC_ENABLE_EXTRA_MATH
199*44d4804dSStefan Eßer 	/// Return the max value returned by rand().
200252884aeSStefan Eßer 	BC_INST_MAXRAND,
201*44d4804dSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
202252884aeSStefan Eßer 
203*44d4804dSStefan Eßer 	/// This is slightly misnamed versus BC_INST_PRINT_POP. Well, it is in bc.
204*44d4804dSStefan Eßer 	/// dc uses this instruction to print, but not pop. That's valid in dc.
205*44d4804dSStefan Eßer 	/// However, in bc, it is *never* valid to print without popping. In bc,
206*44d4804dSStefan Eßer 	/// BC_INST_PRINT_POP is used to indicate when a string should be printed
207*44d4804dSStefan Eßer 	/// because of a print statement or whether it should be printed raw. The
208*44d4804dSStefan Eßer 	/// reason for this is because a print statement handles escaped characters.
209*44d4804dSStefan Eßer 	/// So BC_INST_PRINT_POP is for printing a string from a print statement,
210*44d4804dSStefan Eßer 	/// BC_INST_PRINT_STR is for printing a string by itself.
211*44d4804dSStefan Eßer 	///
212*44d4804dSStefan Eßer 	/// In dc, BC_INST_PRINT_POP prints and pops, and BC_INST_PRINT just prints.
213*44d4804dSStefan Eßer 	///
214*44d4804dSStefan Eßer 	/// Oh, and BC_INST_STR pushes a string onto the results stack.
215252884aeSStefan Eßer 	BC_INST_PRINT,
216252884aeSStefan Eßer 	BC_INST_PRINT_POP,
217252884aeSStefan Eßer 	BC_INST_STR,
218*44d4804dSStefan Eßer #if BC_ENABLED
219252884aeSStefan Eßer 	BC_INST_PRINT_STR,
220252884aeSStefan Eßer 
221*44d4804dSStefan Eßer 	/// Jumps unconditionally.
222252884aeSStefan Eßer 	BC_INST_JUMP,
223*44d4804dSStefan Eßer 
224*44d4804dSStefan Eßer 	/// Jumps if the top of the results stack is zero (condition failed). It
225*44d4804dSStefan Eßer 	/// turns out that we only want to jump when conditions fail to "skip" code.
226252884aeSStefan Eßer 	BC_INST_JUMP_ZERO,
227252884aeSStefan Eßer 
228*44d4804dSStefan Eßer 	/// Call a function.
229252884aeSStefan Eßer 	BC_INST_CALL,
230252884aeSStefan Eßer 
231*44d4804dSStefan Eßer 	/// Return the top of the stack to the caller.
232252884aeSStefan Eßer 	BC_INST_RET,
233*44d4804dSStefan Eßer 
234*44d4804dSStefan Eßer 	/// Return 0 to the caller.
235252884aeSStefan Eßer 	BC_INST_RET0,
236*44d4804dSStefan Eßer 
237*44d4804dSStefan Eßer 	/// Special return instruction for void functions.
238252884aeSStefan Eßer 	BC_INST_RET_VOID,
239252884aeSStefan Eßer 
240*44d4804dSStefan Eßer 	/// Special halt instruction.
241252884aeSStefan Eßer 	BC_INST_HALT,
242252884aeSStefan Eßer #endif // BC_ENABLED
243252884aeSStefan Eßer 
244*44d4804dSStefan Eßer 	/// Pop an item off of the results stack.
245252884aeSStefan Eßer 	BC_INST_POP,
246252884aeSStefan Eßer 
247*44d4804dSStefan Eßer 	/// Swaps the top two items on the results stack.
248252884aeSStefan Eßer 	BC_INST_SWAP,
249252884aeSStefan Eßer 
250*44d4804dSStefan Eßer 	/// Modular exponentiation.
251*44d4804dSStefan Eßer 	BC_INST_MODEXP,
252*44d4804dSStefan Eßer 
253*44d4804dSStefan Eßer 	/// Do divide and modulus at the same time.
254*44d4804dSStefan Eßer 	BC_INST_DIVMOD,
255*44d4804dSStefan Eßer 
256*44d4804dSStefan Eßer 	/// Turns a number into a string and prints it.
257*44d4804dSStefan Eßer 	BC_INST_PRINT_STREAM,
258*44d4804dSStefan Eßer 
259*44d4804dSStefan Eßer #if DC_ENABLED
260*44d4804dSStefan Eßer 
261*44d4804dSStefan Eßer 	/// dc's return; it pops an executing string off of the stack.
262*44d4804dSStefan Eßer 	BC_INST_POP_EXEC,
263*44d4804dSStefan Eßer 
264*44d4804dSStefan Eßer 	/// Unconditionally execute a string.
265*44d4804dSStefan Eßer 	BC_INST_EXECUTE,
266*44d4804dSStefan Eßer 
267*44d4804dSStefan Eßer 	/// Conditionally execute a string.
268*44d4804dSStefan Eßer 	BC_INST_EXEC_COND,
269*44d4804dSStefan Eßer 
270*44d4804dSStefan Eßer 	/// Prints each item on the results stack, separated by newlines.
271*44d4804dSStefan Eßer 	BC_INST_PRINT_STACK,
272*44d4804dSStefan Eßer 
273*44d4804dSStefan Eßer 	/// Pops everything off of the results stack.
274*44d4804dSStefan Eßer 	BC_INST_CLEAR_STACK,
275*44d4804dSStefan Eßer 
276*44d4804dSStefan Eßer 	/// Pushes the current length of a register stack onto the results stack.
277*44d4804dSStefan Eßer 	BC_INST_REG_STACK_LEN,
278*44d4804dSStefan Eßer 
279*44d4804dSStefan Eßer 	/// Pushes the current length of the results stack onto the results stack.
280*44d4804dSStefan Eßer 	BC_INST_STACK_LEN,
281*44d4804dSStefan Eßer 
282*44d4804dSStefan Eßer 	/// Pushes a copy of the item on the top of the results stack onto the
283*44d4804dSStefan Eßer 	/// results stack.
284*44d4804dSStefan Eßer 	BC_INST_DUPLICATE,
285*44d4804dSStefan Eßer 
286*44d4804dSStefan Eßer 	/// Copies the value in a register and pushes the copy onto the results
287*44d4804dSStefan Eßer 	/// stack.
288252884aeSStefan Eßer 	BC_INST_LOAD,
289*44d4804dSStefan Eßer 
290*44d4804dSStefan Eßer 	/// Pops an item off of a register stack and pushes it onto the results
291*44d4804dSStefan Eßer 	/// stack.
292252884aeSStefan Eßer 	BC_INST_PUSH_VAR,
293*44d4804dSStefan Eßer 
294*44d4804dSStefan Eßer 	/// Pops an item off of the results stack and pushes it onto a register's
295*44d4804dSStefan Eßer 	/// stack.
296252884aeSStefan Eßer 	BC_INST_PUSH_TO_VAR,
297252884aeSStefan Eßer 
298*44d4804dSStefan Eßer 	/// Quit.
299252884aeSStefan Eßer 	BC_INST_QUIT,
300*44d4804dSStefan Eßer 
301*44d4804dSStefan Eßer 	/// Quit executing some number of strings.
302252884aeSStefan Eßer 	BC_INST_NQUIT,
303*44d4804dSStefan Eßer 
304*44d4804dSStefan Eßer 	/// Push the depth of the execution stack onto the stack.
305*44d4804dSStefan Eßer 	BC_INST_EXEC_STACK_LEN,
306*44d4804dSStefan Eßer 
307252884aeSStefan Eßer #endif // DC_ENABLED
308252884aeSStefan Eßer 
309*44d4804dSStefan Eßer 	/// Invalid instruction.
310*44d4804dSStefan Eßer 	BC_INST_INVALID,
311252884aeSStefan Eßer 
312252884aeSStefan Eßer } BcInst;
313252884aeSStefan Eßer 
314*44d4804dSStefan Eßer /// Used by maps to identify where items are in the array.
315252884aeSStefan Eßer typedef struct BcId {
316*44d4804dSStefan Eßer 
317*44d4804dSStefan Eßer 	/// The name of the item.
318252884aeSStefan Eßer 	char *name;
319*44d4804dSStefan Eßer 
320*44d4804dSStefan Eßer 	/// The index into the array where the item is.
321252884aeSStefan Eßer 	size_t idx;
322*44d4804dSStefan Eßer 
323252884aeSStefan Eßer } BcId;
324252884aeSStefan Eßer 
325*44d4804dSStefan Eßer /// The location of a var, array, or array element.
326252884aeSStefan Eßer typedef struct BcLoc {
327*44d4804dSStefan Eßer 
328*44d4804dSStefan Eßer 	/// The index of the var or array.
329252884aeSStefan Eßer 	size_t loc;
330*44d4804dSStefan Eßer 
331*44d4804dSStefan Eßer 	/// The index of the array element. Only used for array elements.
332252884aeSStefan Eßer 	size_t idx;
333*44d4804dSStefan Eßer 
334252884aeSStefan Eßer } BcLoc;
335252884aeSStefan Eßer 
336*44d4804dSStefan Eßer /// An entry for a constant.
337252884aeSStefan Eßer typedef struct BcConst {
338*44d4804dSStefan Eßer 
339*44d4804dSStefan Eßer 	/// The original string as parsed from the source code.
340252884aeSStefan Eßer 	char *val;
341*44d4804dSStefan Eßer 
342*44d4804dSStefan Eßer 	/// The last base that the constant was parsed in.
343252884aeSStefan Eßer 	BcBigDig base;
344*44d4804dSStefan Eßer 
345*44d4804dSStefan Eßer 	/// The parsed constant.
346252884aeSStefan Eßer 	BcNum num;
347*44d4804dSStefan Eßer 
348252884aeSStefan Eßer } BcConst;
349252884aeSStefan Eßer 
350*44d4804dSStefan Eßer /// A function. This is also used in dc, not just bc. The reason is that strings
351*44d4804dSStefan Eßer /// are executed in dc, and they are converted to functions in order to be
352*44d4804dSStefan Eßer /// executed.
353252884aeSStefan Eßer typedef struct BcFunc {
354252884aeSStefan Eßer 
355*44d4804dSStefan Eßer 	/// The bytecode instructions.
356252884aeSStefan Eßer 	BcVec code;
357*44d4804dSStefan Eßer 
358252884aeSStefan Eßer #if BC_ENABLED
359*44d4804dSStefan Eßer 
360*44d4804dSStefan Eßer 	/// The labels. This is a vector of indices. The index is the index into
361*44d4804dSStefan Eßer 	/// the bytecode vector where the label is.
362252884aeSStefan Eßer 	BcVec labels;
363*44d4804dSStefan Eßer 
364*44d4804dSStefan Eßer 	/// The autos for the function. The first items are the parameters, and the
365*44d4804dSStefan Eßer 	/// arguments to the parameters must match the types in this vector.
366252884aeSStefan Eßer 	BcVec autos;
367*44d4804dSStefan Eßer 
368*44d4804dSStefan Eßer 	/// The number of parameters the function takes.
369252884aeSStefan Eßer 	size_t nparams;
370*44d4804dSStefan Eßer 
371252884aeSStefan Eßer #endif // BC_ENABLED
372252884aeSStefan Eßer 
373*44d4804dSStefan Eßer 	/// The strings encountered in the function.
374252884aeSStefan Eßer 	BcVec strs;
375*44d4804dSStefan Eßer 
376*44d4804dSStefan Eßer 	/// The constants encountered in the function.
377252884aeSStefan Eßer 	BcVec consts;
378252884aeSStefan Eßer 
379*44d4804dSStefan Eßer 	/// The function's name.
380252884aeSStefan Eßer 	const char *name;
381*44d4804dSStefan Eßer 
382252884aeSStefan Eßer #if BC_ENABLED
383*44d4804dSStefan Eßer 	/// True if the function is a void function.
384252884aeSStefan Eßer 	bool voidfn;
385252884aeSStefan Eßer #endif // BC_ENABLED
386252884aeSStefan Eßer 
387252884aeSStefan Eßer } BcFunc;
388252884aeSStefan Eßer 
389*44d4804dSStefan Eßer /// Types of results that can be pushed onto the results stack.
390252884aeSStefan Eßer typedef enum BcResultType {
391252884aeSStefan Eßer 
392*44d4804dSStefan Eßer 	/// Result is a variable.
393252884aeSStefan Eßer 	BC_RESULT_VAR,
394252884aeSStefan Eßer 
395*44d4804dSStefan Eßer 	/// Result is an array element.
396*44d4804dSStefan Eßer 	BC_RESULT_ARRAY_ELEM,
397*44d4804dSStefan Eßer 
398*44d4804dSStefan Eßer 	/// Result is an array. This is only allowed for function arguments or
399*44d4804dSStefan Eßer 	/// returning the length of the array.
400*44d4804dSStefan Eßer 	BC_RESULT_ARRAY,
401*44d4804dSStefan Eßer 
402*44d4804dSStefan Eßer 	/// Result is a string.
403252884aeSStefan Eßer 	BC_RESULT_STR,
404252884aeSStefan Eßer 
405*44d4804dSStefan Eßer 	/// Result is a temporary. This is used for the result of almost all
406*44d4804dSStefan Eßer 	/// expressions.
407252884aeSStefan Eßer 	BC_RESULT_TEMP,
408252884aeSStefan Eßer 
409*44d4804dSStefan Eßer 	/// Special casing the two below gave performance improvements.
410*44d4804dSStefan Eßer 
411*44d4804dSStefan Eßer 	/// Result is a 0.
4123aa99676SStefan Eßer 	BC_RESULT_ZERO,
413*44d4804dSStefan Eßer 
414*44d4804dSStefan Eßer 	/// Result is a 1. Useful for inc/dec operators.
415252884aeSStefan Eßer 	BC_RESULT_ONE,
416252884aeSStefan Eßer 
417252884aeSStefan Eßer #if BC_ENABLED
418*44d4804dSStefan Eßer 
419*44d4804dSStefan Eßer 	/// Result is the special "last" variable.
420252884aeSStefan Eßer 	BC_RESULT_LAST,
421*44d4804dSStefan Eßer 
422*44d4804dSStefan Eßer 	/// Result is the return value of a void function.
423252884aeSStefan Eßer 	BC_RESULT_VOID,
424252884aeSStefan Eßer #endif // BC_ENABLED
425*44d4804dSStefan Eßer 
426*44d4804dSStefan Eßer 	/// Result is the value of ibase.
427252884aeSStefan Eßer 	BC_RESULT_IBASE,
428*44d4804dSStefan Eßer 
429*44d4804dSStefan Eßer 	/// Result is the value of obase.
430252884aeSStefan Eßer 	BC_RESULT_OBASE,
431*44d4804dSStefan Eßer 
432*44d4804dSStefan Eßer 	/// Result is the value of scale.
433252884aeSStefan Eßer 	BC_RESULT_SCALE,
434*44d4804dSStefan Eßer 
435252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH
436*44d4804dSStefan Eßer 
437*44d4804dSStefan Eßer 	/// Result is the value of seed.
438252884aeSStefan Eßer 	BC_RESULT_SEED,
439*44d4804dSStefan Eßer 
440252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH
441252884aeSStefan Eßer 
442252884aeSStefan Eßer } BcResultType;
443252884aeSStefan Eßer 
444*44d4804dSStefan Eßer /// A union to store data for various result types.
445252884aeSStefan Eßer typedef union BcResultData {
446*44d4804dSStefan Eßer 
447*44d4804dSStefan Eßer 	/// A number. Strings are stored here too; they are numbers with
448*44d4804dSStefan Eßer 	/// cap == 0 && num == NULL. The string's index into the strings vector is
449*44d4804dSStefan Eßer 	/// stored in the scale field. But this is only used for strings stored in
450*44d4804dSStefan Eßer 	/// variables.
451252884aeSStefan Eßer 	BcNum n;
452*44d4804dSStefan Eßer 
453*44d4804dSStefan Eßer 	/// A vector.
454252884aeSStefan Eßer 	BcVec v;
455*44d4804dSStefan Eßer 
456*44d4804dSStefan Eßer 	/// A variable, array, or array element reference. This could also be a
457*44d4804dSStefan Eßer 	/// string if a string is not stored in a variable (dc only).
458252884aeSStefan Eßer 	BcLoc loc;
459*44d4804dSStefan Eßer 
460252884aeSStefan Eßer } BcResultData;
461252884aeSStefan Eßer 
462*44d4804dSStefan Eßer /// A tagged union for results.
463252884aeSStefan Eßer typedef struct BcResult {
464*44d4804dSStefan Eßer 
465*44d4804dSStefan Eßer 	/// The tag. The type of the result.
466252884aeSStefan Eßer 	BcResultType t;
467*44d4804dSStefan Eßer 
468*44d4804dSStefan Eßer 	/// The data. The data for the result.
469252884aeSStefan Eßer 	BcResultData d;
470*44d4804dSStefan Eßer 
471252884aeSStefan Eßer } BcResult;
472252884aeSStefan Eßer 
473*44d4804dSStefan Eßer /// An instruction pointer. This is how bc knows where in the bytecode vector,
474*44d4804dSStefan Eßer /// and which function, the current execution is.
475252884aeSStefan Eßer typedef struct BcInstPtr {
476*44d4804dSStefan Eßer 
477*44d4804dSStefan Eßer 	/// The index of the currently executing function in the fns vector.
478252884aeSStefan Eßer 	size_t func;
479*44d4804dSStefan Eßer 
480*44d4804dSStefan Eßer 	/// The index into the bytecode vector of the *next* instruction.
481252884aeSStefan Eßer 	size_t idx;
482*44d4804dSStefan Eßer 
483*44d4804dSStefan Eßer 	/// The length of the results vector when this function started executing.
484*44d4804dSStefan Eßer 	/// This is mostly used for bc where functions should not affect the results
485*44d4804dSStefan Eßer 	/// of their callers.
486252884aeSStefan Eßer 	size_t len;
487*44d4804dSStefan Eßer 
488252884aeSStefan Eßer } BcInstPtr;
489252884aeSStefan Eßer 
490*44d4804dSStefan Eßer /// Types of identifiers.
491252884aeSStefan Eßer typedef enum BcType {
492*44d4804dSStefan Eßer 
493*44d4804dSStefan Eßer 	/// Variable.
494252884aeSStefan Eßer 	BC_TYPE_VAR,
495*44d4804dSStefan Eßer 
496*44d4804dSStefan Eßer 	/// Array.
497252884aeSStefan Eßer 	BC_TYPE_ARRAY,
498*44d4804dSStefan Eßer 
499252884aeSStefan Eßer #if BC_ENABLED
500*44d4804dSStefan Eßer 
501*44d4804dSStefan Eßer 	/// Array reference.
502252884aeSStefan Eßer 	BC_TYPE_REF,
503*44d4804dSStefan Eßer 
504252884aeSStefan Eßer #endif // BC_ENABLED
505*44d4804dSStefan Eßer 
506252884aeSStefan Eßer } BcType;
507252884aeSStefan Eßer 
508*44d4804dSStefan Eßer #if BC_ENABLED
509*44d4804dSStefan Eßer /// An auto variable in bc.
510*44d4804dSStefan Eßer typedef struct BcAuto {
511*44d4804dSStefan Eßer 
512*44d4804dSStefan Eßer 	/// The index of the variable in the vars or arrs vectors.
513*44d4804dSStefan Eßer 	size_t idx;
514*44d4804dSStefan Eßer 
515*44d4804dSStefan Eßer 	/// The type of the variable.
516*44d4804dSStefan Eßer 	BcType type;
517*44d4804dSStefan Eßer 
518*44d4804dSStefan Eßer } BcAuto;
519*44d4804dSStefan Eßer #endif // BC_ENABLED
520*44d4804dSStefan Eßer 
521*44d4804dSStefan Eßer /// Forward declaration.
522252884aeSStefan Eßer struct BcProgram;
523252884aeSStefan Eßer 
524*44d4804dSStefan Eßer /**
525*44d4804dSStefan Eßer  * Initializes a function.
526*44d4804dSStefan Eßer  * @param f     The function to initialize.
527*44d4804dSStefan Eßer  * @param name  The name of the function. The string is assumed to be owned by
528*44d4804dSStefan Eßer  *              some other entity.
529*44d4804dSStefan Eßer  */
530252884aeSStefan Eßer void bc_func_init(BcFunc *f, const char* name);
531*44d4804dSStefan Eßer 
532*44d4804dSStefan Eßer /**
533*44d4804dSStefan Eßer  * Inserts an auto into the function.
534*44d4804dSStefan Eßer  * @param f     The function to insert into.
535*44d4804dSStefan Eßer  * @param p     The program. This is to search for the variable or array name.
536*44d4804dSStefan Eßer  * @param name  The name of the auto to insert.
537*44d4804dSStefan Eßer  * @param type  The type of the auto.
538*44d4804dSStefan Eßer  * @param line  The line in the source code where the insert happened. This is
539*44d4804dSStefan Eßer  *              solely for error reporting.
540*44d4804dSStefan Eßer  */
541252884aeSStefan Eßer void bc_func_insert(BcFunc *f, struct BcProgram* p, char* name,
542252884aeSStefan Eßer                     BcType type, size_t line);
543252884aeSStefan Eßer 
544*44d4804dSStefan Eßer /**
545*44d4804dSStefan Eßer  * Resets a function in preparation for it to be reused. This can happen in bc
546*44d4804dSStefan Eßer  * because it is a dynamic language and functions can be redefined.
547*44d4804dSStefan Eßer  * @param f  The functio to reset.
548*44d4804dSStefan Eßer  */
549*44d4804dSStefan Eßer void bc_func_reset(BcFunc *f);
550*44d4804dSStefan Eßer 
551*44d4804dSStefan Eßer #ifndef NDEBUG
552*44d4804dSStefan Eßer /**
553*44d4804dSStefan Eßer  * Frees a function. This is a destructor. This is only used in debug builds
554*44d4804dSStefan Eßer  * because all functions are freed at exit. We free them in debug builds to
555*44d4804dSStefan Eßer  * check for memory leaks.
556*44d4804dSStefan Eßer  * @param func  The function to free as a void pointer.
557*44d4804dSStefan Eßer  */
558*44d4804dSStefan Eßer void bc_func_free(void *func);
559*44d4804dSStefan Eßer #endif // NDEBUG
560*44d4804dSStefan Eßer 
561*44d4804dSStefan Eßer /**
562*44d4804dSStefan Eßer  * Initializes an array, which is the array type in bc and dc source code. Since
563*44d4804dSStefan Eßer  * variables and arrays are both arrays (see the development manual,
564*44d4804dSStefan Eßer  * manuals/development.md#execution, for more information), the @a nums
565*44d4804dSStefan Eßer  * parameter tells bc whether to initialize an array of numbers or an array of
566*44d4804dSStefan Eßer  * arrays of numbers. If the latter, it does a recursive call with nums set to
567*44d4804dSStefan Eßer  * true.
568*44d4804dSStefan Eßer  * @param a     The array to initialize.
569*44d4804dSStefan Eßer  * @param nums  True if the array should be for numbers, false if it should be
570*44d4804dSStefan Eßer  *              for vectors.
571*44d4804dSStefan Eßer  */
572252884aeSStefan Eßer void bc_array_init(BcVec *a, bool nums);
573*44d4804dSStefan Eßer 
574*44d4804dSStefan Eßer /**
575*44d4804dSStefan Eßer  * Copies an array to another array. This is used to do pass arrays to functions
576*44d4804dSStefan Eßer  * that do not take references to arrays. The arrays are passed entirely by
577*44d4804dSStefan Eßer  * value, which means that they need to be copied.
578*44d4804dSStefan Eßer  * @param d  The destination array.
579*44d4804dSStefan Eßer  * @param s  The source array.
580*44d4804dSStefan Eßer  */
581252884aeSStefan Eßer void bc_array_copy(BcVec *d, const BcVec *s);
582252884aeSStefan Eßer 
583*44d4804dSStefan Eßer /**
584*44d4804dSStefan Eßer  * Frees a string stored in a function. This is a destructor.
585*44d4804dSStefan Eßer  * @param string  The string to free as a void pointer.
586*44d4804dSStefan Eßer  */
587252884aeSStefan Eßer void bc_string_free(void *string);
588*44d4804dSStefan Eßer 
589*44d4804dSStefan Eßer /**
590*44d4804dSStefan Eßer  * Frees a constant stored in a function. This is a destructor.
591*44d4804dSStefan Eßer  * @param constant  The constant to free as a void pointer.
592*44d4804dSStefan Eßer  */
593252884aeSStefan Eßer void bc_const_free(void *constant);
594*44d4804dSStefan Eßer 
595*44d4804dSStefan Eßer /**
596*44d4804dSStefan Eßer  * Clears a result. It sets the type to BC_RESULT_TEMP and clears the union by
597*44d4804dSStefan Eßer  * clearing the BcNum in the union. This is to ensure that bc does not use
598*44d4804dSStefan Eßer  * uninitialized data.
599*44d4804dSStefan Eßer  * @param r  The result to clear.
600*44d4804dSStefan Eßer  */
601252884aeSStefan Eßer void bc_result_clear(BcResult *r);
602*44d4804dSStefan Eßer 
603*44d4804dSStefan Eßer /**
604*44d4804dSStefan Eßer  * Copies a result into another. This is done for things like duplicating the
605*44d4804dSStefan Eßer  * top of the results stack or copying the result of an assignment to put back
606*44d4804dSStefan Eßer  * on the results stack.
607*44d4804dSStefan Eßer  * @param d    The destination result.
608*44d4804dSStefan Eßer  * @param src  The source result.
609*44d4804dSStefan Eßer  */
610252884aeSStefan Eßer void bc_result_copy(BcResult *d, BcResult *src);
611*44d4804dSStefan Eßer 
612*44d4804dSStefan Eßer /**
613*44d4804dSStefan Eßer  * Frees a result. This is a destructor.
614*44d4804dSStefan Eßer  * @param result  The result to free as a void pointer.
615*44d4804dSStefan Eßer  */
616252884aeSStefan Eßer void bc_result_free(void *result);
617252884aeSStefan Eßer 
618*44d4804dSStefan Eßer /**
619*44d4804dSStefan Eßer  * Expands an array to @a len. This can happen because in bc, you do not have to
620*44d4804dSStefan Eßer  * explicitly initialize elements of an array. If you access an element that is
621*44d4804dSStefan Eßer  * not initialized, the array is expanded to fit it, and all missing elements
622*44d4804dSStefan Eßer  * are initialized to 0 if they are numbers, or arrays with one element of 0.
623*44d4804dSStefan Eßer  * This function does that expansion.
624*44d4804dSStefan Eßer  * @param a    The array to expand.
625*44d4804dSStefan Eßer  * @param len  The length to expand to.
626*44d4804dSStefan Eßer  */
627252884aeSStefan Eßer void bc_array_expand(BcVec *a, size_t len);
628*44d4804dSStefan Eßer 
629*44d4804dSStefan Eßer /**
630*44d4804dSStefan Eßer  * Compare two BcId's and return the result. Since they are just comparing the
631*44d4804dSStefan Eßer  * names in the BcId, I return the result from strcmp() exactly. This is used by
632*44d4804dSStefan Eßer  * maps in their binary search.
633*44d4804dSStefan Eßer  * @param e1  The first id.
634*44d4804dSStefan Eßer  * @param e2  The second id.
635*44d4804dSStefan Eßer  * @return    The result of strcmp() on the BcId's names.
636*44d4804dSStefan Eßer  */
637252884aeSStefan Eßer int bc_id_cmp(const BcId *e1, const BcId *e2);
638252884aeSStefan Eßer 
639*44d4804dSStefan Eßer #if BC_ENABLED
640*44d4804dSStefan Eßer 
641*44d4804dSStefan Eßer /**
642*44d4804dSStefan Eßer  * Returns non-zero if the bytecode instruction i is an assignment instruction.
643*44d4804dSStefan Eßer  * @param i  The instruction to test.
644*44d4804dSStefan Eßer  * @return   Non-zero if i is an assignment instruction, zero otherwise.
645*44d4804dSStefan Eßer  */
646*44d4804dSStefan Eßer #define BC_INST_IS_ASSIGN(i) \
647*44d4804dSStefan Eßer 	((i) == BC_INST_ASSIGN || (i) == BC_INST_ASSIGN_NO_VAL)
648*44d4804dSStefan Eßer 
649*44d4804dSStefan Eßer /**
650*44d4804dSStefan Eßer  * Returns true if the bytecode instruction @a i requires the value to be
651*44d4804dSStefan Eßer  * returned for use.
652*44d4804dSStefan Eßer  * @param i  The instruction to test.
653*44d4804dSStefan Eßer  * @return   True if @a i requires the value to be returned for use, false
654*44d4804dSStefan Eßer  *           otherwise.
655*44d4804dSStefan Eßer  */
656*44d4804dSStefan Eßer #define BC_INST_USE_VAL(i) ((i) <= BC_INST_ASSIGN)
657*44d4804dSStefan Eßer 
658*44d4804dSStefan Eßer #else // BC_ENABLED
659*44d4804dSStefan Eßer 
660*44d4804dSStefan Eßer /**
661*44d4804dSStefan Eßer  * Returns non-zero if the bytecode instruction i is an assignment instruction.
662*44d4804dSStefan Eßer  * @param i  The instruction to test.
663*44d4804dSStefan Eßer  * @return   Non-zero if i is an assignment instruction, zero otherwise.
664*44d4804dSStefan Eßer  */
665*44d4804dSStefan Eßer #define BC_INST_IS_ASSIGN(i) ((i) == BC_INST_ASSIGN_NO_VAL)
666*44d4804dSStefan Eßer 
667*44d4804dSStefan Eßer /**
668*44d4804dSStefan Eßer  * Returns true if the bytecode instruction @a i requires the value to be
669*44d4804dSStefan Eßer  * returned for use.
670*44d4804dSStefan Eßer  * @param i  The instruction to test.
671*44d4804dSStefan Eßer  * @return   True if @a i requires the value to be returned for use, false
672*44d4804dSStefan Eßer  *           otherwise.
673*44d4804dSStefan Eßer  */
674*44d4804dSStefan Eßer #define BC_INST_USE_VAL(i) (false)
675*44d4804dSStefan Eßer 
676*44d4804dSStefan Eßer #endif // BC_ENABLED
677*44d4804dSStefan Eßer 
678252884aeSStefan Eßer #if BC_DEBUG_CODE
679*44d4804dSStefan Eßer /// Reference to string names for all of the instructions. For debugging.
680252884aeSStefan Eßer extern const char* bc_inst_names[];
681252884aeSStefan Eßer #endif // BC_DEBUG_CODE
682252884aeSStefan Eßer 
683*44d4804dSStefan Eßer /// References to the names of the main and read functions.
684252884aeSStefan Eßer extern const char bc_func_main[];
685252884aeSStefan Eßer extern const char bc_func_read[];
686252884aeSStefan Eßer 
687252884aeSStefan Eßer #endif // BC_LANG_H
688