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