fixed bug in image compiler; GST parser now understands categories
[k8lst.git] / src / lstcore / k8lst.h
blobb2e5669d0fa538aac26fd7f0dcd059a6097a837f
1 /*
2 * Global definitions for the LittleSmalltalk virtual machine
4 * ---------------------------------------------------------------
5 * Little Smalltalk, Version 5
7 * Copyright (C) 1987-2005 by Timothy A. Budd
8 * Copyright (C) 2007 by Charles R. Childers
9 * Copyright (C) 2005-2007 by Danny Reinhold
10 * Copyright (C) 2010 by Ketmar // Vampire Avalon
12 * ============================================================================
13 * This license applies to the virtual machine and to the initial image of
14 * the Little Smalltalk system and to all files in the Little Smalltalk
15 * packages except the files explicitly licensed with another license(s).
16 * ============================================================================
17 * Permission is hereby granted, free of charge, to any person obtaining a copy
18 * of this software and associated documentation files (the "Software"), to deal
19 * in the Software without restriction, including without limitation the rights
20 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 * copies of the Software, and to permit persons to whom the Software is
22 * furnished to do so, subject to the following conditions:
24 * The above copyright notice and this permission notice shall be included in
25 * all copies or substantial portions of the Software.
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 * DEALINGS IN THE SOFTWARE.
35 #ifndef LST_GLOBS_H
36 #define LST_GLOBS_H
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
42 #include <limits.h>
43 #include <stdint.h>
44 #include <stdio.h>
47 #define LST_IMAGE_VERSION 6
48 #define LST_IMAGE_SIGNATURE "LST5 Image File\x1a\x00"
50 #define LST_VERSION_STRING "Little Smalltalk version 5.2 (pre-beta)"
53 typedef uint32_t LstUInt;
54 typedef int32_t LstInt;
55 typedef int64_t LstLInt;
56 typedef double LstFloat;
59 #if defined(__MINGW32__) || defined(WINDOWS) || defined(WIN32) || defined(_WIN32)
60 # define LST_ON_WINDOWS 1
61 # include <io.h>
62 # define lstLNull 0L
63 # define mkstemp mktemp
64 # define lstOSName "Windows"
65 #else
66 # define lstLNull 0LL
67 # ifdef __linux__
68 # define lstOSName "GNU/Linux"
69 # else
70 # define lstOSName "Unix"
71 # endif
72 #endif
75 extern unsigned int lstDebugFlag; /* true if we are debugging */
77 extern unsigned int lstInfoCacheHit;
78 extern unsigned int lstInfoCacheMiss;
79 extern unsigned int lstInfoLiteralHit;
80 extern unsigned int lstInfoIVarHit;
82 extern unsigned int lstGCCount;
85 /* symbolic definitions for the bytecodes */
86 enum {
87 lstBCExtended, /* 0 */
88 lstBCPushInstance, /* 1 */
89 lstBCPushArgument, /* 2 */
90 lstBCPushTemporary, /* 3 */
91 lstBCPushLiteral, /* 4 */
92 lstBCPushConstant, /* 5 */
93 lstBCAssignInstance, /* 6 */
94 lstBCAssignArgument, /* 7 */
95 lstBCAssignTemporary, /* 8 */
96 lstBCMarkArguments, /* 9 */
97 lstBCPushBlock, /* 10 */
98 lstBCSendUnary, /* 11 */
99 lstBCSendBinary, /* 12 */
100 lstBCSendMessage, /* 13 */
101 lstBCDoPrimitive, /* 14 */
102 lstBCDoSpecial /* 15 */
106 /* types of special instructions (opcode 15) */
107 enum {
108 lstBXBreakpoint, /* 0 */
109 lstBXSelfReturn, /* 1 */
110 lstBXStackReturn, /* 2 */
111 lstBXBlockReturn, /* 3 */
112 lstBXDuplicate, /* 4 */
113 lstBXPopTop, /* 5 */
114 lstBXBranch, /* 6 */
115 lstBXBranchIfTrue, /* 7 */
116 lstBXBranchIfFalse, /* 8 */
117 lstBXBranchIfNil, /* 9 */
118 lstBXBranchIfNotNil, /* 10 */
119 lstBXSendToSuper, /* 11 */
120 lstBXThisContext /* 12 */
124 /* special constants */
126 /* constants 0 to 9 are the integers 0 to 9 */
127 enum {
128 lstBLNilConst, /* 0 */
129 lstBLTrueConst, /* 1 */
130 lstBLFalseConst /* 2 */
131 /* n-3: SmallInt constant */
135 /* Return values from doExecute: primitive */
136 enum {
137 lstReturnError = 2, /* 2: error: called */
138 lstReturnBadMethod, /* 3: Unknown method for object */
139 lstReturnReturned, /* 4: Top level method returned */
140 lstReturnTimeExpired, /* 5: Time quantum exhausted */
141 lstReturnBreak, /* 6: lstBXBreakpoint instruction */
142 lstReturnYield, /* 7: process yielded (can be continued) */
143 lstReturnAPISuspended /* 8: suspended from C API; Smalltalk code will never see this */
147 /* The following are the objects with ``hard-wired'' field offsets */
149 /* A Process has two fields
150 * * a current context
151 * * status of process (running, waiting, etc)
153 enum {
154 lstIVcontextInProcess,
155 lstIVstatusInProcess,
156 lstIVresultInProcess,
157 lstIVrunningInProcess,
158 lstProcessSize
163 * A Context has:
164 * * method (which has bytecode pointer)
165 * * bytecode offset (an integer)
166 * * arguments
167 * * temporaries and stack
168 * * stack pointer
170 enum {
171 lstIVmethodInContext,
172 lstIVargumentsInContext,
173 lstIVtemporariesInContext,
174 lstIVstackInContext,
175 lstIVbytePointerInContext,
176 lstIVstackTopInContext,
177 lstIVpreviousContextInContext,
178 lstIVprocOwnerInContext,
179 lstContextSize
184 * A Block is subclassed from Context
185 * shares fields with creator, plus a couple new ones
187 enum {
188 lstIVmethodInBlock = lstIVmethodInContext,
189 lstIVargumentsInBlock = lstIVargumentsInContext,
190 lstIVtemporariesInBlock = lstIVtemporariesInContext,
191 lstIVstackInBlock = lstIVstackInContext,
192 lstIVstackTopInBlock = lstIVstackTopInContext,
193 lstIVpreviousContextInBlock = lstIVpreviousContextInContext,
194 lstIVprocOwnerInBlock = lstIVprocOwnerInContext,
195 lstIVargumentLocationInBlock = lstContextSize,
196 lstIVcreatingContextInBlock,
197 /* the following are saved in different place so they don't get clobbered */
198 lstIVbytePointerInBlock,
199 lstIVargCountInBlock,
200 lstBlockSize
205 * A Method has:
206 * * name (a Symbol)
207 * * bytecodes
208 * * literals
209 * * stack size
210 * * temp size
212 enum {
213 lstIVnameInMethod,
214 lstIVbyteCodesInMethod,
215 lstIVliteralsInMethod,
216 lstIVstackSizeInMethod,
217 lstIVtemporarySizeInMethod,
218 lstIVclassInMethod,
219 lstIVtextInMethod,
220 lstIVargCountInMethod,
221 lstIVdebugInfoInMethod,
222 lstIVargNamesInMethod,
223 lstIVtempNamesInMethod,
224 lstIVdbgDataInMethod,
225 lstIVoptimDoneInMethod,
226 lstIVretResInMethod,
227 lstIVcategoryInMethod,
228 lstIVinvokeCountInMethod,
229 lstMethodSize
234 * A Class has:
235 * * pointer to parent class
236 * * pointer to tree of methods
238 enum {
239 lstIVnameInClass,
240 lstIVparentClassInClass,
241 lstIVmethodsInClass,
242 lstIVinstanceSizeInClass,
243 lstIVvariablesInClass,
244 lstIVpackageInClass,
245 lstClassSize
249 /* MetaSymbol */
250 enum {
251 lstIVsymbolsInMetaSymbol = lstClassSize,
252 lstMetaSymbolSize
256 /* MetaChar */
257 enum {
258 lstIVcharsInMetaChar = lstClassSize,
259 lstMetaCharSize
263 /* MetaSmall */
264 enum {
265 lstIVseedInMetaSmallInt = lstClassSize,
266 lstMetaSmallIntSize
271 * A Package has:
272 * * name (a Symbol)
273 * * version (SmallInt)
274 * * requiremets (list of PackageRequirement objects)
276 enum {
277 lstIVclassesInPackage, /* dictionary: symbol, class */
278 lstIVnameInPackage, /* symbol */
279 lstIVversionInPackage, /* smallint */
280 lstIVrequiresInPackage, /* dictionary: symbol(pkgname), version(smallint)/nil(any) */
281 lstPackageSize
284 enum {
285 lstIVpackagesInMetaPackage = lstClassSize, /* dictionary: symbol, package instance */
286 lstIVcurrentInMetaPackage,
287 lstMetaPackageSize
291 /* PackageRequirement */
293 enum {
294 nameInPackageReq,
295 versionInPackageReq,
296 PackageReqSize
302 * A node in a tree has
303 * * value field
304 * * left subtree
305 * * right subtree
307 enum {
308 lstIVvalueInNode,
309 lstIVleftInNode,
310 lstIVrightInNode,
311 lstNodeSize
315 /* misc iv defines */
316 enum {
317 lstIVrootInTree = 0,
318 lstIVreceiverInArguments = 0,
323 * The fundamental data type is the object.
324 * The first field in an object is a size, the low order two
325 * bits being used to maintain:
326 * * binary flag, used if data is binary
327 * * indirection flag, used if object has been relocated
328 * The next data field is the class
329 * The following fields are either objects, or character values
331 * The initial image is loaded into static memory space --
332 * space which is never garbage collected
333 * This improves speed, as these items are not moved during GC
335 #define LST_OBJECT_HEADER \
336 LstUInt size; \
337 lstObject *stclass; \
338 LstFinLink *fin;
341 typedef struct lstObject lstObject;
342 typedef struct LstFinLink LstFinLink;
345 typedef void (*LstFinalizerFn) (lstObject *o, void *udata);
347 struct LstFinLink {
348 LstFinLink *prev;
349 LstFinLink *next;
350 lstObject *obj;
351 LstFinalizerFn fin;
352 void *udata;
356 struct lstObject {
357 LST_OBJECT_HEADER
358 lstObject *data[0];
359 } __attribute__((__packed__));
363 * byte objects are used to represent strings and symbols; bytes per word must be correct
365 typedef struct lstByteObject lstByteObject;
366 struct lstByteObject {
367 LST_OBJECT_HEADER
368 unsigned char bytes[0];
369 } __attribute__((__packed__));
372 #define LST_BYTES_PER_WORD (sizeof(lstObject *))
374 #define lstBytePtr(x) (((lstByteObject *)(x))->bytes)
378 * SmallInt objects are used to represent short integers.
379 * They are encoded as 31 bits, signed, with the low bit set to 1.
380 * This distinguishes them from all other objects, which are longword
381 * aligned and are proper C memory pointers.
383 #if 0
384 # define LST_IS_SMALLINT(x) ((((int)(x)) & 0x01) != 0)
385 # define LST_FITS_SMALLINT(x) ((((int)(x)) >= INT_MIN/2) && (((int)(x)) <= INT_MAX/2))
386 # define LST_64FITS_SMALLINT(x) (((x) >= INT_MIN/2) && ((x) <= INT_MAX/2))
387 #else
388 # define LST_IS_SMALLINT(x) ((((intptr_t)(x)) & 0x01) != 0)
389 # define LST_FITS_SMALLINT(x) ((((int)(x)) >= (-(__INT_MAX__))/2) && (((int)(x)) <= __INT_MAX__/2))
390 # define LST_64FITS_SMALLINT(x) (((x) >= (-(__INT_MAX__))/2) && ((x) <= __INT_MAX__/2))
391 #endif
392 #define LST_CLASS(x) (LST_IS_SMALLINT(x) ? lstSmallIntClass : ((x)->stclass))
395 * The "size" field is the top 30 bits; the bottom two are flags
397 #define LST_SIZE(op) ((op)->size >> 2)
398 #define LST_SETSIZE(op, val) ((op)->size = ((val) << 2))
399 #define LST_FLAG_GC_BHEART (0x01)
400 #define LST_FLAG_BIN (0x02)
401 #define LST_IS_BYTES(x) (((x)->size&LST_FLAG_BIN) != 0)
402 static inline int LST_IS_BYTES_EX (lstObject *x) { return !LST_IS_SMALLINT(x) && LST_IS_BYTES(x); }
406 * roots for the memory space
407 * these are traced down during memory management
408 * lstRootStack is the dynamic stack
409 * staticRoots are values in static memory that point to
410 * dynamic values
412 #define LST_ROOTSTACK_LIMIT 550
413 extern lstObject *lstRootStack[];
414 extern LstUInt lstRootTop;
415 extern void lstAddStaticRoot (lstObject **);
418 #define LST_MAX_BIN_MSG 14
419 /* The following are roots for the file out */
420 extern lstObject *lstNilObj;
421 extern lstObject *lstTrueObj;
422 extern lstObject *lstFalseObj;
423 extern lstObject *lstBooleanClass;
424 extern lstObject *lstSmallIntClass;
425 extern lstObject *lstCharClass;
426 extern lstObject *lstArrayClass;
427 extern lstObject *lstBlockClass;
428 extern lstObject *lstContextClass;
429 extern lstObject *lstProcessClass;
430 extern lstObject *lstStringClass;
431 extern lstObject *lstSymbolClass;
432 extern lstObject *lstByteArrayClass;
433 extern lstObject *lstByteCodeClass;
434 extern lstObject *lstMethodClass;
435 extern lstObject *lstGlobalObj;
436 extern lstObject *lstBinMsgs[LST_MAX_BIN_MSG]; /* '<'; '<='; '+', ... */
437 extern lstObject *lstIntegerClass;
438 extern lstObject *lstFloatClass;
439 extern lstObject *lstBadMethodSym; /* 'doesNotUnderstand:' */
440 /* Smalltalk entry points */
441 extern lstObject *lstInitMethod;
442 extern lstObject *lstLoadMethod;
443 extern lstObject *lstDoStrMethod;
444 extern lstObject *lstReplMethod;
445 extern lstObject *lstNewSymMethod;
446 extern lstObject *lstSetGlobMethod;
449 /* must be defined by the main program */
450 extern void lstFatal (const char *a, unsigned int b);
451 extern void lstBackTrace (lstObject *aContext);
454 /* entry points */
455 extern void lstMemoryInit (int staticsz, int dynamicsz);
456 extern void lstMemoryDeinit (void);
458 extern int lstReadImage (FILE *fp);
459 extern int lstWriteImage (FILE *fp, int noSrc);
461 extern void lstGC (void);
462 extern void lstShowCalledMethods (void);
464 extern lstObject *lstStaticAlloc (int sz);
465 extern lstByteObject *lstStaticAllocBin (int sz);
466 extern lstObject *lstMemAlloc (int sz);
467 extern lstByteObject *lstMemAllocBin (int sz);
469 /* internal functions for interpreter */
470 extern void lstSwapObjects (lstObject *array1, lstObject *array2, LstUInt size);
471 extern int lstBulkReplace (lstObject *dest, lstObject *start, lstObject *stop, lstObject *src, lstObject *repStart);
473 /* do write, register static root if necessary */
474 extern void lstWriteBarrier (lstObject **dest, lstObject *src);
477 typedef lstObject *(*LSTPrimitiveFn) (int primitiveNumber, lstObject **args, int argc); /* return NULL if failed (not lstNilObj!) */
478 typedef void (*LSTPrimitiveClearFn) (int primitiveNumber);
480 extern const char *lstFindPrimitiveName (int idx);
481 extern int lstFindPrimitiveIdx (const char *name); /* -1: no such primitive */
483 extern int lstFindExtPrimitiveByName (const char *name);
484 extern int lstRegisterExtPrimitive (const char *name, LSTPrimitiveFn pfn, LSTPrimitiveClearFn cfn); /* -1: error; other: primitive index */
485 extern void lstClearExtPrimitives (void);
487 extern LSTPrimitiveFn lstFindExtPrimitiveFn (int idx);
489 extern void lstPrimitivesClear (void);
492 typedef struct {
493 const char *name;
494 LSTPrimitiveFn pfn;
495 LSTPrimitiveClearFn cfn;
496 } LSTExtPrimitiveTable;
498 extern int lstRegisterExtPrimitiveTable (const LSTExtPrimitiveTable *tbl); /* return success flag */
502 #define lstIntValue(x) ((int)(((intptr_t)(x)) >> 1))
503 #define lstNewInt(x) ((lstObject *)((((intptr_t)(x)) << 1) | 0x01))
505 extern lstObject *lstNewLongInt (LstLInt val); /* create new Integer (64-bit) */
506 extern lstObject *lstNewFloat (LstFloat val);
508 #define lstNewInteger(x) (LST_64FITS_SMALLINT(x) ? lstNewInt(x) : lstNewLongInt(x))
510 static inline LstLInt lstLIntValue (const lstObject *o) {
511 const LstLInt *v = (const LstLInt *)o->data;
512 return *v;
514 static inline LstFloat lstFloatValue (const lstObject *o) {
515 const LstFloat *v = (const LstFloat *)o->data;
516 return *v;
519 #define lstLIntValue(o) (*((LstLInt *)lstConstPtr(o)))
520 #define lstFloatValue(o) (*((LstFloat *)lstConstPtr(o)))
523 extern lstObject *lstNewString (const char *str);
524 extern int lstGetString (char *buf, int bufsize, const lstObject *str); /* return 0 on ok or necessary buffer size */
525 extern lstObject *lstNewBinary (const void *p, LstUInt l);
526 extern lstObject *lstNewBCode (const void *p, LstUInt l);
527 extern lstObject *lstNewArray (int size);
529 extern lstObject *lstAllocInstance (int size, lstObject *cl);
531 extern lstObject *lstDictFind (const lstObject *dict, const char *name);
533 /* WARNING: this works only when obj is instance of something, and aclass is not! */
534 extern int lstIsKindOf (const lstObject *obj, const lstObject *aclass); /* returns true(!0) or false(0) */
536 extern lstObject *lstFindGlobal (const char *name);
538 /* WARNING: CAN'T BE CALLED FROM PRIMITIVE! */
539 extern lstObject *lstNewSymbol (const char *name);
541 /* WARNING: CAN'T BE CALLED FROM PRIMITIVE! */
542 extern int lstSetGlobal (const char *name, lstObject *val);
544 extern lstObject *lstFindMethod (lstObject *stclass, const char *method);
546 extern void lstSetFinalizer (lstObject *o, LstFinalizerFn fn, void *udata);
547 extern void *lstGetUData (lstObject *o);
549 /* both returns lstReturnXXX */
550 extern int lstExecute (lstObject *aProcess, int ticks, int locked);
551 extern int lstResume (void);
552 extern int lstCanResume (void);
553 extern void lstResetResume (void);
555 /* arg==NULL: no argument
556 * result==NULL: don't need result
557 * remember, that result can be collected by GC on next allocation
559 extern int lstRunMethodWithArg (lstObject *method, lstObject *inClass, lstObject *arg, lstObject **result, int locked);
562 /* types in image file */
563 enum {
564 LST_IMGOT_NULL,
565 LST_IMGOT_OBJECT,
566 LST_IMGOT_SMALLINT,
567 LST_IMGOT_BCODE,
568 LST_IMGOT_BARRAY,
569 LST_IMGOT_REF,
570 LST_IMGOT_NIL,
571 LST_IMGOT_MAX
574 extern void lstFlushMethodCache (void);
577 extern unsigned int lstImgReadWord (FILE *fp);
578 extern void lstImgWriteWord (FILE *fp, int i);
580 extern int32_t lstImgReadDWord (FILE *fp);
581 extern void lstImgWriteDWord (FILE *fp, int32_t i);
584 #define LST_FINALIZER(name) \
585 static void name (lstObject *obj, void *udata)
587 /* macro for primitives */
588 #define LST_PRIMFN(name) \
589 static lstObject *name (int primitiveNumber, lstObject **args, int argc)
591 #define LST_PRIMFN_NONSTATIC(name) \
592 lstObject *name (int primitiveNumber, lstObject **args, int argc)
594 #define LST_PRIMCLEARFN(name) \
595 static void name (int primitiveNumber)
597 #define LST_PRIMARGC (argc)
598 #define LST_PRIMARG(n) (args[n])
601 static inline void lstRootPush (lstObject *o) {
602 if (lstRootTop >= LST_ROOTSTACK_LIMIT) lstFatal("out of root stack", 0);
603 lstRootStack[lstRootTop++] = o;
607 static inline lstObject *lstRootPop (void) {
608 if (lstRootTop < 1) lstFatal("root stack underflow", 0);
609 return lstRootStack[--lstRootTop];
613 #define LST_TS_LIMIT 512
614 extern lstObject **lstTempStack[LST_TS_LIMIT];
615 extern int lstTempSP;
617 #define LST_ENTER_BLOCK() int _lstCurTSP_ = lstTempSP
618 #define LST_LEAVE_BLOCK() lstTempSP = _lstCurTSP_
620 #define LST_NEW_TEMP(name) lstObject *name = NULL; lstTempStack[lstTempSP++] = &name
621 #define LST_TEMP(name) lstTempStack[lstTempSP++] = &name
624 typedef int (*LstEventCheckFn) (int *ticksLeft);
625 /* this must return eid (!0) to call callback */
626 extern LstEventCheckFn lstEventCheck;
628 extern int lstEvtCheckLeft; /* # of executed instructions before event check */
630 extern int lstExecUserBreak; /* set this to non-zero to suspend current lstExecute() and return lstReturnAPISuspended */
633 #ifdef __cplusplus
635 #endif
636 #endif