Home | History | Annotate | Line # | Download | only in lisp
      1 /*
      2  * Copyright (c) 2002 by The XFree86 Project, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  *
     22  * Except as contained in this notice, the name of the XFree86 Project shall
     23  * not be used in advertising or otherwise to promote the sale, use or other
     24  * dealings in this Software without prior written authorization from the
     25  * XFree86 Project.
     26  *
     27  * Author: Paulo Csar Pereira de Andrade
     28  */
     29 
     30 /* $XFree86: xc/programs/xedit/lisp/bytecode.h,v 1.5tsi Exp $ */
     31 
     32 #include "lisp/private.h"
     33 
     34 #ifndef Lisp_Bytecode_h
     35 #define Lisp_Bytecode_h
     36 
     37 /* Number of arguments for &REST functions with no side effects,
     38  * i.e. does not need to allocate new cells to build argument list.
     39  * If this value is changed, it is also required to add more
     40  * XBC_BCONS? opcodes and change ExecuteBytecode() */
     41 #define MAX_BCONS	8
     42 
     43 typedef enum {
     44     XBP_CONSP,
     45     XBP_LISTP,
     46     XBP_NUMBERP
     47 } LispBytePredicate;
     48 
     49 typedef enum {
     50     XBC_NOOP,
     51 
     52     XBC_INV,		/* If NIL loaded, change to T else to NIL */
     53     XBC_NIL,		/* Load NIL */
     54     XBC_T,		/* Load T */
     55 
     56     XBC_PRED,		/* Preffix for predicate test */
     57 	/* Followed by byte indicating test */
     58 
     59     XBC_CAR,		/* Set loaded value to it's car */
     60     XBC_CDR,		/* Set loaded value to it's cdr */
     61 
     62     XBC_CAR_SET,	/* Set local variable to CAR or CDR of loaded value */
     63     XBC_CDR_SET,
     64 	/* Offset of local variable follows */
     65 
     66     /* Sets C[AD]R of top of builtin stack with
     67      * loaded value and pop builtin stack */
     68     XBC_RPLACA,
     69     XBC_RPLACD,
     70 
     71     /* Push only one argument in builtin stack, and call directly
     72      * LispObjectCompare without the need of pushing the second arguument */
     73     XBC_EQ,
     74     XBC_EQL,
     75     XBC_EQUAL,
     76     XBC_EQUALP,
     77 
     78     XBC_LENGTH,
     79     XBC_LAST,
     80     XBC_NTHCDR,
     81 
     82     XBC_CAR_PUSH,	/* Pushes CAR or CDR of loaded value to builtin stack */
     83     XBC_CDR_PUSH,
     84 
     85     XBC_PUSH,		/* Push argument in builtin stack */
     86     XBC_PUSH_NIL,	/* Pushes NIL in builtin stack */
     87     XBC_PUSH_UNSPEC,	/* Pushes #<UNSPEC> in builtin stack */
     88     XBC_PUSH_T,		/* Pushes T in builtin stack */
     89     XBC_PUSH_NIL_N,	/* Pushes NIL in the builtin stack N times */
     90     XBC_PUSH_UNSPEC_N,	/* Pushes #<UNSPEC> in the builtin stack N times */
     91 
     92 
     93 	/* The builtin stack base is saved when entering the bytecode
     94 	 * interpreter, and the bytecode does not reenter from builtin
     95 	 * functions, yet, so there is no need, for XBC_BSAVE and
     96 	 * XBC_BREST instructions */
     97 
     98     XBC_LET,		/* Push loaded value to stack */
     99     XBC_LETX,		/* Push loaded value to stack and bind */
    100 	/*  Next byte(s) are the symbol offset */
    101     XBC_LET_NIL,	/* Push loaded value to stack */
    102     XBC_LETX_NIL,	/* Push loaded value to stack and bind */
    103 	/*  Next byte(s) are the symbol offset */
    104 
    105     XBC_LETBIND,	/* Bind locally added variables */
    106 	/* Followed by number of symbols to bind */
    107 
    108     XBC_UNLET,		/* Unbind locally binded variables */
    109 	/* Followed by number of symbols to unbind */
    110 
    111     XBC_LOAD,		/* Load argument already from the stack */
    112 	/* Followed by  offset follows the opcode */
    113     XBC_LOAD_LET,	/* Load argument and push */
    114     XBC_LOAD_LETX,	/* Load argument,  push and bind */
    115 	/* Followed by a short and the atom to be bound */
    116     XBC_LOAD_PUSH,
    117 
    118     XBC_LOADCON,	/* Load a literal constant */
    119 	/* Next bytes are the constant object */
    120     XBC_LOADCON_LET,	/* Load a literal constant and push */
    121     XBC_LOADCON_LETX,	/* Load a literal constant, push and bind */
    122 	/* Followed by object constant and symbol to be bound */
    123     XBC_LOADCON_PUSH,
    124 
    125     /* Load CAR or CDR of local variable */
    126     XBC_LOAD_CAR,
    127     XBC_LOAD_CDR,
    128 
    129     /* Change local variable value to it's CAR or CDR */
    130     XBC_LOAD_CAR_STORE,
    131     XBC_LOAD_CDR_STORE,
    132 
    133     XBC_LOADCON_SET,
    134 	/* Followed by constant offset and local variable offset */
    135 
    136     XBC_LOADSYM,	/* Load object symbol value */
    137 	/* The object atom pointer follows de opcode */
    138     XBC_LOADSYM_LET,	/* Load object symbol value and push */
    139     XBC_LOADSYM_LETX,	/* Load object symbol value, push and bind */
    140 	/* The symbol atom name and bounded atom name to be bound follows */
    141     XBC_LOADSYM_PUSH,
    142 
    143     XBC_LOAD_SET,	/* Set value of local variable to the value of another */
    144 	/* Followed by two shorts */
    145     XBC_LOAD_CAR_SET,	/* Like LOAD_SET, but apply CAR or CDR in the value */
    146     XBC_LOAD_CDR_SET,
    147 
    148     XBC_SET,		/* Change value of local variable */
    149 	/* A short integer with relative offset follows opcode */
    150     XBC_SETSYM,		/* Change value of symbol */
    151 	/* The atom symbol pointer follows opcode */
    152 
    153     XBC_SET_NIL,	/* Like XBC_SET but sets the local variable to NIL */
    154 
    155     XBC_CALL,		/* Call builtin function */
    156 	/* 1 byte follows telling how many arguments to use */
    157 	/* LispBuiltin pointer follows opcode */
    158 
    159     XBC_CALL_SET,
    160 	/* Like BCALL, but also followed by an short index of local variable */
    161 
    162     XBC_BYTECALL,	/* Call bytecode */
    163 	/* 1 byte for number of arguments */
    164 	/* 1 byte for index in bytecode table */
    165 
    166     XBC_FUNCALL,
    167 	/* Opcode followed by function and arguments objects, to
    168 	 * be evaluated at run time, as it was not resolved at
    169 	 * bytecode generation time (or is not implemented in
    170 	 * the bytecode compiler) */
    171 
    172 
    173     XBC_LETREC,		/* Recursive function call */
    174 	/* 1 byte follows telling how many arguments the funtion receives */
    175 
    176     /* Helper for math functions. Uses a preallocated CONS,
    177      * setting it's CAR to the loaded value, and in the same step
    178      * pushes the CONS to the builtin stack */
    179     XBC_BCONS,
    180     /* Like BCONS but it is a list of 2 arguments, first argument
    181      * is saved on the stack, replace with list of 2 arguments */
    182     XBC_BCONS1,
    183     /* Like BCONS1 but it is a list of 3 arguments, first arguments
    184      * are saved on the stack, replace with list of first stack
    185      * argument with list or 3 arguments, and pop stack  */
    186     XBC_BCONS2,
    187     XBC_BCONS3,
    188     XBC_BCONS4,
    189     XBC_BCONS5,
    190     XBC_BCONS6,
    191     XBC_BCONS7,
    192 
    193     /* Build a CONS */
    194     XBC_CCONS,		/* Make CONS of two constants */
    195 	/* Constants follow opcode */
    196     XBC_CSTAR,		/* Save the CAR of the CONS */
    197     XBC_CFINI,		/* Loaded value is the CDR */
    198 
    199     /* These are to help in interactively building lists */
    200     XBC_LSTAR,		/* Start building a list in the gc protected stack */
    201     XBC_LCONS,		/* Add loaded object to list */
    202     XBC_LFINI,		/* List is finished */
    203 
    204     /* Inconditional jumps */
    205     XBC_JUMP,		/* Jump relative to following signed int */
    206 
    207     /* Conditional jumps, if true */
    208     XBC_JUMPT,		/* Jump relative to following signed int */
    209 
    210     /* Conditional jumps, if false */
    211     XBC_JUMPNIL,	/* Jump relative to following signed int */
    212 
    213     /* Structure field access and type check */
    214     XBC_STRUCT,
    215     XBC_STRUCTP,
    216 
    217     XBC_RETURN		/* Resume bytecode execution */
    218 } LispByteOpcode;
    219 
    220 
    221 struct _LispBytecode {
    222     unsigned char *code;	/* Bytecode data */
    223     long length;		/* length of bytecode stream */
    224 };
    225 
    226 /*
    227  * Prototypes
    228  */
    229 void LispBytecodeInit(void);
    230 
    231 LispObj *Lisp_Compile(LispBuiltin*);
    232 LispObj *Lisp_Disassemble(LispBuiltin*);
    233 
    234 LispObj *LispCompileForm(LispObj*);
    235 LispObj *LispExecuteBytecode(LispObj*);
    236 
    237 void Com_And(LispCom*, LispBuiltin*);
    238 void Com_Block(LispCom*, LispBuiltin*);
    239 void Com_C_r(LispCom*, LispBuiltin*);
    240 void Com_Cond(LispCom*, LispBuiltin*);
    241 void Com_Cons(LispCom*, LispBuiltin*);
    242 void Com_Consp(LispCom*, LispBuiltin*);
    243 void Com_Dolist(LispCom*, LispBuiltin*);
    244 void Com_Eq(LispCom*, LispBuiltin*);
    245 void Com_Go(LispCom*, LispBuiltin*);
    246 void Com_If(LispCom*, LispBuiltin*);
    247 void Com_Last(LispCom*, LispBuiltin*);
    248 void Com_Length(LispCom*, LispBuiltin*);
    249 void Com_Let(LispCom*, LispBuiltin*);
    250 void Com_Letx(LispCom*, LispBuiltin*);
    251 void Com_Listp(LispCom*, LispBuiltin*);
    252 void Com_Loop(LispCom*, LispBuiltin*);
    253 void Com_Nthcdr(LispCom*, LispBuiltin*);
    254 void Com_Null(LispCom*, LispBuiltin*);
    255 void Com_Numberp(LispCom*, LispBuiltin*);
    256 void Com_Or(LispCom*, LispBuiltin*);
    257 void Com_Progn(LispCom*, LispBuiltin*);
    258 void Com_Return(LispCom*, LispBuiltin*);
    259 void Com_ReturnFrom(LispCom*, LispBuiltin*);
    260 void Com_Rplac_(LispCom*, LispBuiltin*);
    261 void Com_Setq(LispCom*, LispBuiltin*);
    262 void Com_Tagbody(LispCom*, LispBuiltin*);
    263 void Com_Unless(LispCom*, LispBuiltin*);
    264 void Com_Until(LispCom*, LispBuiltin*);
    265 void Com_When(LispCom*, LispBuiltin*);
    266 void Com_While(LispCom*, LispBuiltin*);
    267 
    268 #endif /* Lisp_Bytecode_h */
    269