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 César 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
43typedef enum {
44    XBP_CONSP,
45    XBP_LISTP,
46    XBP_NUMBERP
47} LispBytePredicate;
48
49typedef 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
221struct _LispBytecode {
222    unsigned char *code;	/* Bytecode data */
223    long length;		/* length of bytecode stream */
224};
225
226/*
227 * Prototypes
228 */
229void LispBytecodeInit(void);
230
231LispObj *Lisp_Compile(LispBuiltin*);
232LispObj *Lisp_Disassemble(LispBuiltin*);
233
234LispObj *LispCompileForm(LispObj*);
235LispObj *LispExecuteBytecode(LispObj*);
236
237void Com_And(LispCom*, LispBuiltin*);
238void Com_Block(LispCom*, LispBuiltin*);
239void Com_C_r(LispCom*, LispBuiltin*);
240void Com_Cond(LispCom*, LispBuiltin*);
241void Com_Cons(LispCom*, LispBuiltin*);
242void Com_Consp(LispCom*, LispBuiltin*);
243void Com_Dolist(LispCom*, LispBuiltin*);
244void Com_Eq(LispCom*, LispBuiltin*);
245void Com_Go(LispCom*, LispBuiltin*);
246void Com_If(LispCom*, LispBuiltin*);
247void Com_Last(LispCom*, LispBuiltin*);
248void Com_Length(LispCom*, LispBuiltin*);
249void Com_Let(LispCom*, LispBuiltin*);
250void Com_Letx(LispCom*, LispBuiltin*);
251void Com_Listp(LispCom*, LispBuiltin*);
252void Com_Loop(LispCom*, LispBuiltin*);
253void Com_Nthcdr(LispCom*, LispBuiltin*);
254void Com_Null(LispCom*, LispBuiltin*);
255void Com_Numberp(LispCom*, LispBuiltin*);
256void Com_Or(LispCom*, LispBuiltin*);
257void Com_Progn(LispCom*, LispBuiltin*);
258void Com_Return(LispCom*, LispBuiltin*);
259void Com_ReturnFrom(LispCom*, LispBuiltin*);
260void Com_Rplac_(LispCom*, LispBuiltin*);
261void Com_Setq(LispCom*, LispBuiltin*);
262void Com_Tagbody(LispCom*, LispBuiltin*);
263void Com_Unless(LispCom*, LispBuiltin*);
264void Com_Until(LispCom*, LispBuiltin*);
265void Com_When(LispCom*, LispBuiltin*);
266void Com_While(LispCom*, LispBuiltin*);
267
268#endif /* Lisp_Bytecode_h */
269