home *** CD-ROM | disk | FTP | other *** search
- /* Kevo -- a prototype-based object-oriented language */
- /* (c) Antero Taivalsaari 1991-1993 */
- /* Some parts (c) Antero Taivalsaari 1986-1988 */
- /* prim.c: Portable system primitives */
-
- #include "global.h"
- #include "portGlobal.h"
-
- /*---------------------------------------------------------------------------*/
- /* Special user-level execution primitives */
-
- /*
- Most of the definitions in this file are visible to the user via
- the 'SystemRoot' context, although many of the primitives should not
- be invoked directly. The definitions whose names have been put within
- parentheses (xxx) or square brackets <xxx> are those that should be invoked
- only if you relly know what you are doing. Direct invocation of these primitives
- will probably crash the system.
- */
-
- /* execute ( object -- ) */
- /* execute an object given its identity */
- void pExecute()
- {
- execute((OBJECT*)popData());
- }
-
-
- /* <executeStore> ( store -- ) */
- /* execute code given the memory address where the code begins */
- /* This operation should not normally be called directly, because */
- /* resizing etc. may physically move the location of code */
- void pExecStore()
- {
- pushReturn((int*)ip);
- ip = (int**)popData();
- }
-
-
- /* exit ( -- ) */
- /* end the execution of a thread and return to the next level */
- void pExit()
- {
- ip = (int**)popReturn();
- }
-
-
- /* freeExit ( storeAddress -- ) */
- /* end the execution of a thread and return to the next level */
- /* deallocate the store space of the code, too */
- /* This operation is used to finalize the execution of */
- /* interactively typed code */
- void pFreeExit()
- {
- free((void*)popData());
- ip = (int**)popReturn();
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Data access primitives */
-
- /* (=sharedVar) ( -- addr ) */
- /* return the address of a task-independent (shared) variable */
- void pSharedVar()
- {
- pushData((int)ip);
- ip = (int**)popReturn();
- }
-
-
- /* (=taskVar) ( -- addr ) */
- /* return the address of a task-specific variable */
- /* '*up' is a shorthand for getting the address of up's store part (->mfa)' */
- void pTaskVar()
- {
- pushData((int)((int*)*up + (int)*ip));
- ip = (int**)popReturn();
- }
-
-
- /* (=sharedConst) ( -- value ) */
- /* return the value of a task-independent (shared) constant */
- void pSharedConst()
- {
- pushData((int)*ip);
- ip = (int**)popReturn();
- }
-
-
- /* (=taskConst) ( -- value ) */
- /* return the value of a task-specific constant */
- void pTaskConst()
- {
- pushData(*((int*)*up + (int)*ip));
- ip = (int**)popReturn();
- }
-
-
- /* (=context) ( -- object ) */
- /* return the identity (self) of a context object (object-oriented object) */
- void pContext()
- {
- /* 'op' is a pointer to latest object (handle). */
- /* It is updated by the inner interpreter */
- ip = (int**)popReturn();
- pushData((int)op);
-
- /*
- Old implementation:
- Comment: This implementation does not yield the same result
- when executed directly and via "' xxx execute". I haven't noticed
- this to cause any trouble, but 'op' is safer.
-
- ip = (int**)popReturn();
- pushData((int)*(ip-1));
- */
- }
-
-
- /* (=REF) ( -- value ) <or> ( value -- ) */
- /* return/assign value from/to a shared to-variable */
- void pREF()
- {
- if ((*up)->assigning) {
- /* Store the value to the slot */
- *ip = (int*)popData();
- (*up)->assigning--;
- }
- else {
- /* Fetch the value from the slot */
- pushData((int)*ip);
- }
- ip = (int**)popReturn();
- }
-
-
- /* (=VAR) ( -- value ) <or> ( value -- ) */
- /* return/assign value from/to an OOP object-specific to-variable */
- void pVAR()
- {
- int* address = (int*)*topContext + (int)*ip;
-
- if ((*up)->assigning) {
- /* Store the value to the slot */
- *address = popData();
- (*up)->assigning--;
- }
- else {
- /* Fetch the value from the slot */
- pushData(*address);
- }
- ip = (int**)popReturn();
- }
-
-
- /* (->) ( -- ) */
- /* Increment the value of the 'assigning' variable so as to */
- /* enforce assigment next time (=REF) or (=VAR) is executed */
- void pIncAss()
- {
- (*up)->assigning++;
- }
-
-
- /* (lit) ( -- l ) */
- /* load a literal to the data stack */
- void pLit()
- {
- pushData((int)*ip++);
- }
-
-
- /* ("lit) ( -- straddr ) */
- /* load a string literal (address) to the data stack */
- /* Remember: string literals should not contain double carats (^^) or */
- /* carriage returns: image files containing such characters will not read */
- void pStrLit()
- {
- pushData((int)*ip++);
- }
-
-
- /* (=sharedVector) ( -- ) */
- void pSharedVector()
- /* task-independent (shared) vector execution (vector is a memory */
- /* location which contains a pointer to an executable code object) */
- {
- OBJECT* object = (OBJECT*)*ip;
- ip = (int**)popReturn();;
- execute(object);
- }
-
-
- /* (=taskVector) ( -- ) */
- /* task-specific vectored execution */
- /* '*up' is a shorthand for getting the address of up's store part (->mfa)' */
- void pTaskVector()
- {
- OBJECT* object = (OBJECT*)(*((int*)*up + (int)*ip));
- ip = (int**)popReturn();
- execute(object);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Temporary variable (block) operations */
-
- /* These operations allow the definition of temporary variables (blocks). */
- /* They allow you to considerably reduce the need for stack juggling operations */
-
- /* Note that in the current implementation blocks should not be nested */
- /* because the references to temporaries have access to the latest frame */
- /* only; thus, references from within blocks to temporaries defined in outer */
- /* blocks will be incorrect. Otherwise, blocks work just fine (even with DO-LOOPs). */
-
- /* Also keep in mind that the return stack is by default quite small */
- /* and it DOESN'T grow automatically. Thus, if you use a lot of temps, */
- /* you'd better allocate enough space using 'resizeReturnStack'. */
-
- /* ({) ( -- ) */
- /* Open a frame for temporary variables (runtime operation) */
- void pOpenFrame()
- {
- pushReturn((int*)(*up)->fp); /* Store the previous frame pointer to RStack */
- (*up)->fp = returnSp; /* Set the frame pointer */
- }
-
-
- /* (}) ( -- ) */
- /* Close the current frame (runtime operation) */
- void pCloseFrame()
- {
- returnSp = (*up)->fp;
- (*up)->fp = (int**)popReturn();
- }
-
-
- /* <temp> ( data -- ) <or> ( -- ) */
- /* Allocate a temporary variable within the current frame (runtime operation) */
- /* This is a to-operation, which either initializes the temporary variable */
- /* with the desired value, or alternatively initializes it to zero */
- void pAllocTemp()
- {
- if ((*up)->assigning) {
- pushReturn((int*)popData());
- (*up)->assigning--;
- }
- else pushReturn(0);
- }
-
-
- /* temp: ( data -- ) <or> ( -- data ) */
- /* Access the value of a temporary variable (runtime operation) */
- /* using the index which is given as a literal parameter (follows this */
- /* operation in the thread). This too is a to-variable, which either */
- /* stores or fetches the value depending on the assignment counter. */
- void pAccessTemp()
- {
- int* address = (int*)(*up)->fp + (int)*ip;
-
- if ((*up)->assigning) {
- /* Store the value to the slot in the frame */
- *address = popData();
- (*up)->assigning--;
- }
- else {
- /* Fetch the value from the slot in the frame */
- pushData(*address);
- }
-
- /* Skip the offset value */
- ip++;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Data stack operations */
-
- /* Kevo implements most of Forth's traditional data stack operations */
- /* Owing to the presence of temporary variables (blocks), most of these */
- /* operations are not however needed too often */
-
- /* drop ( l -- ) */
- /* drop the topmost item in the data stack */
- void pDrop()
- {
- nPopData(1);
- }
-
-
- /* 2drop ( l1 l2 -- ) */
- /* drop two topmost items in the data stack */
- void pDrop2()
- {
- nPopData(2); /* This is a macro (see 'global.h') */
- }
-
-
- /* over ( l1 l2 -- l1 l2 l1 ) */
- /* copy the second item in the stack to the top */
- void pOver()
- {
- pushData(secondData);
- }
-
-
- /* 2over ( l1 l2 l3 l4 -- l1 l2 l3 l4 l1 l2 ) */
- /* the same as 'over' but do two items at a time */
- void pOver2()
- {
- int a = thirdData;
- int b = fourthData;
- pushData(b);
- pushData(a);
- }
-
-
- /* dup ( l -- l l ) */
- /* duplicate the topmost stack item */
- void pDup()
- {
- pushData(topData);
- }
-
-
- /* 2dup ( l1 l2 -- l1 l2 l1 l2 ) */
- /* duplicate two topmost stack items */
- void pDup2()
- {
- int a = topData;
- int b = secondData;
- pushData(b);
- pushData(a);
- }
-
-
- /* ?dup ( l -- l l ) tai ( 0 -- 0 ) */
- /* duplicate the topmost stack item if it is nonzero */
- void pQDup()
- {
- if (topData) pushData(topData);
- }
-
-
- /* nip ( l1 l2 -- l2 ) */
- /* drop the second item in the data stack */
- void pNip()
- {
- int temp = popData();
- topData = temp;
- }
-
-
- /* tuck ( l1 l2 -- l2 l1 l2 ) */
- /* copy the topmost stack item and tuck in under the second one */
- void pTuck()
- {
- int a = topData;
- int b = secondData;
- secondData = a;
- topData = b;
- pushData(a);
- }
-
-
- /* swap ( l1 l2 -- l2 l1 ) */
- /* change the two topmost stack items with each other */
- void pSwap()
- {
- int a = topData;
- int b = secondData;
- topData = b;
- secondData = a;
- }
-
-
- /* 2swap ( l1 l2 l3 l4 -- l3 l4 l1 l2 ) */
- /* same as 'swap' but do two items at a time */
- void pSwap2()
- {
- int a = topData;
- int b = secondData;
- int c = thirdData;
- int d = fourthData;
- fourthData = b;
- thirdData = a;
- secondData = d;
- topData = c;
- }
-
-
- /* rot ( l1 l2 l3 -- l2 l3 l1 ) */
- /* rotate the third topmost item in the stack to the top */
- void pRot()
- {
- int a = topData;
- int b = secondData;
- int c = thirdData;
- thirdData = b;
- secondData = a;
- topData = c;
- }
-
-
- /* -rot ( l1 l2 l3 -- l3 l1 l2 ) */
- /* rotate the topmost item in the stack to the third position */
- void pRor()
- {
- int a = topData;
- int b = secondData;
- int c = thirdData;
- thirdData = a;
- secondData = c;
- topData = b;
- }
-
-
- /* pick ( l -- l ) */
- /* pick the nth item in the data stack and copy it to the top */
- /* top of the stack = 1, next = 2, etc. */
- /* Note that indexing is different than in ANSI Forth */
- void pPick()
- {
- int temp;
- int n = topData;
- nPopData(n); /* Macro: see 'global.h' */
- temp = topData;
- nPushData(n); /* - " - */
- topData = temp;
- }
-
-
- /* roll ( n -- ) */
- /*
- If n > 0, bring the n'th item in the data stack to the top
- by rolling the first n items
- e.g., 1 2 3 4 5 -> 5 roll -> 2 3 4 5 1
-
- If n < 0, move the top item in the stack to the -n'th place
- e.g., 1 2 3 4 5 -> -5 roll -> 5 1 2 3 4
- */
- void pRoll()
- {
- int* tempSp;
- int temp;
- int n = popData();
-
- if (n == 0) return;
-
- if (n > 0) {
- tempSp = dataSp - n + 1;
- temp = *tempSp++;
-
- while (tempSp <= dataSp) {
- n = *tempSp--;
- *tempSp = n; tempSp += 2;
- }
- topData = temp;
- }
- else {
- tempSp = dataSp + n + 1;
- temp = *dataSp;
-
- while (tempSp <= dataSp) {
- n = *tempSp;
- *tempSp = temp;
- tempSp++; temp = n;
- }
- }
- }
-
-
- /* depth ( -- l ) */
- /* push the depth of data stack to the top of data stack */
- /* (depth itself is not included in the count) */
- void pDepth()
- {
- pushData(dataSp - dataStackBottom());
- }
-
-
- /* .s ( -- ) */
- /* Print the contents of data stack to outfile, */
- /* trying to decompile possible names and types. */
- void pPrintStack()
- {
- int* ptr = dataStackBottom();
- if (dataSp <= dataStackBottom()) return;
-
- while (dataSp >= ++ptr) {
- PAIR* pair = findNameForward(*ptr);
-
- if (pair) ownPrintf("%s ", pair->nfa);
- else {
- pair = findTypeForward(*ptr);
- if (pair) {
- ownPrintf("%s:", pair->nfa);
- ownPrintf("%d ", *ptr);
- }
- else ownPrintf("%d ", *ptr);
- }
- }
- }
-
-
- /* resizeDataStack ( newSize task -- ) */
- /* resize the data stack of the given task */
- void pResizeData()
- {
- TASK** thisTask = (TASK**)popData();
- int newSize = popData();
-
- resizeDataStack(thisTask, newSize);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Return stack operations */
-
- /*
- These should not be used (except for i, j, rdepth and .rs),
- unless you really know what you are doing.
- */
-
- /* >r ( l -- ) */
- /* push a value to the return stack */
- void pToR()
- {
- pushReturn((int*)popData());
- }
-
-
- /* r@ ( -- l ) */
- /* fetch the value of the topmost item in the return stack */
- void pRFetch()
- {
- pushData((int)topReturn);
- }
-
-
- /* r> ( -- l ) */
- /* pop the topmost item in the return stack to the data stack */
- void pRFrom()
- {
- pushData((int)popReturn());
- }
-
-
- /* i ( -- l ) */
- /* fetch the value of the topmost item in the return stack */
- void pI()
- {
- pushData((int)topReturn);
- }
-
-
- /* j ( -- l ) */
- /* push the index of the second nested loop to the data stack */
- void pJ()
- {
- pushData((int)fourthReturn);
- }
-
-
- /* rdepth ( -- l ) */
- /* push the depth of the return stack to the data stack */
- void pRDepth()
- {
- pushData(returnSp - returnStackBottom());
- }
-
-
- /* dup>r ( l -- l ) */
- /* push a value to the return stack without deleting it from data stack */
- void pDupToR()
- {
- pushReturn((int*)topData);
- }
-
-
- /* r>drop ( -- ) */
- /* drop a value from the return stack */
- void pRFromDrop()
- {
- nPopReturn(1);
- }
-
-
- /* .rs ( -- ) */
- /* print the contents of the return stack to outfile */
- /* in decompiled form. Segmentation violations may cause */
- /* some problems (in Unix) */
- void pPrintRStack()
- {
- int** ptr = returnStackBottom();
-
- if (returnSp <= returnStackBottom()) return;
-
- while (returnSp >= ++ptr) {
- PAIR* pair = findNameForward(maskedFetch(*ptr));
-
- if (pair) ownPrintf("%s ", pair->nfa);
- else ownPrintf("%d ", *ptr);
- }
- }
-
-
- /* resizeReturnStack ( newSize task -- ) */
- /* resize the return stack of the given task */
- void pResizeReturn()
- {
- TASK** thisTask = (TASK**)popData();
- int newSize = popData();
-
- resizeReturnStack(thisTask, newSize);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Memory operations */
-
- /* @ ( adr -- l ) */
- /* fetch the contents of a memory location to data stack */
- void pFetch()
- {
- int* address = (int*)topData;
- topData = *address;
- }
-
-
- /* ! ( l adr -- ) */
- /* store a value to a certain memory location */
- void pStore()
- {
- int* address = (int*)popData();
- *address = popData();
- }
-
-
- /* +! ( l adr -- ) */
- /* add a value to a certain memory location */
- void pAddStore()
- {
- int* address = (int*)popData();
- *address += popData();
- }
-
-
- /* b@ ( adr -- b ) */
- /* fetch the contents of a certain byte in memory */
- void pBFetch()
- {
- char* address = (char*)topData;
- topData = (int)(*address & 0xff);
- }
-
-
- /* b! ( b adr -- ) */
- /* store a value to a certain byte in memory */
- void pBStore()
- {
- char* address = (char*)popData();
- *address = (char)popData();
- }
-
-
- /* b+! ( b adr -- ) */
- /* add a value to a certain byte in memory */
- void pBAddStore()
- {
- char* address = (char*)popData();
- *address += (char)popData();
- }
-
-
- /* w@ ( adr -- w ) */
- /* fetch the contents of a certain word (16 bits) in memory */
- void pWFetch()
- {
- short* address = (short*)topData;
- topData = (int)(*address & 0xffff);
- }
-
-
- /* w! ( w adr -- ) */
- /* store a value to a certain word (16 bits) in memory */
- void pWStore()
- {
- short* address = (short*)popData();
- *address = (short)popData();
- }
-
-
- /* w+! ( w adr -- ) */
- /* add a value to a certain word (16 bits) in memory */
- void pWAddStore()
- {
- short* address = (short*)popData();
- *address += (short)popData();
- }
-
-
- /* align ( l -- l ) */
- /* given an address, return the address of the next aligned memory location */
- void pAlign()
- {
- topData = ((topData+CELL-1)/CELL)*CELL;
- }
-
-
- /* on ( addr -- ) */
- /* set a certain memory location to TRUE (-1) */
- void pOn()
- {
- int* address = (int*)popData();
- *address = TRUE;
- }
-
-
- /* off ( addr -- ) */
- /* set a certain memory location to FALSE (0) */
- void pOff()
- {
- int* address = (int*)popData();
- *address = FALSE;
- }
-
-
- /* boff ( addr -- ) */
- /* set a certain byte to zero */
- void pBOff()
- {
- char* address = (char*)popData();
- *address = 0;
- }
-
-
- /* woff ( addr -- ) */
- /* set a certain word (16 bits) to zero */
- void pWOff()
- {
- short* address = (short*)popData();
- *address = 0;
- }
-
-
- /* ++ ( addr -- ) */
- /* increment a certain memory location by one */
- void pInc()
- {
- int* address = (int*)popData();
- (*address)++;
- }
-
-
- /* cell++ ( addr -- ) */
- /* increment a certain memory location by CELL (typically 4) */
- void pCellInc()
- {
- int** address = (int**)popData();
- (*address)++;
- }
-
-
- /* -- ( addr -- ) */
- /* decrement a certain memory location by one */
- void pDec()
- {
- int* address = (int*)popData();
- (*address)--;
- }
-
-
- /* cell-- ( addr -- ) */
- /* decrement a certain memory location by CELL (typically 4) */
- void pCellDec()
- {
- int** address = (int**)popData();
- (*address)--;
- }
-
-
- /* toggle ( l adr -- ) */
- /* set bits in a certain memory location */
- void pToggle()
- {
- int* addr = (int*)popData();
- *addr |= popData();
- }
-
-
- /* untoggle ( l adr -- ) */
- /* clear bits in a certain memory location */
- void pUntoggle()
- {
- int* addr = (int*)popData();
- *addr &= ~popData();
- }
-
-
- /* btoggle ( l adr -- ) */
- /* set bits in a certain byte in memory */
- void pBToggle()
- {
- char* addr = (char*)popData();
- *addr |= (char)popData();
- }
-
-
- /* buntoggle ( l adr -- ) */
- /* clear bits in a certain byte in memory */
- void pBUntoggle()
- {
- char* addr = (char*)popData();
- *addr &= ~(char)popData();
- }
-
-
- /* move ( adr1 len adr2 -- ) */
- /* move a memory region of certain length (in bytes) to another address, */
- /* ensuring that no overlapping will occur */
- void pMove()
- {
- char* target = (char*)popData();
- int n = popData();
- char* source = (char*)popData();
- char *cp;
-
- /* There was no 'memmove()' standard function in SUN libraries, */
- /* so I had to write one myself */
-
- if (target == source || n <= 0) return;
-
- if (target < source) {
- for (cp = target; n--;) *cp++ = *source++;
- }
- else {
- source += n;
- for (cp = target + n; n--;) *--cp = *--source;
- }
- }
-
-
- /* fill ( adr len ch -- ) */
- /* fill a memory area of certain length (in bytes) with a certain character */
- void pFill()
- {
- char c = (char)popData();
- int n = popData();
- char* target = (char*)popData();
-
- if (n <= 0) return;
- for (; n--;) *target++ = c;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* String management */
-
- /* count ( adr -- adr len ) */
- /* return the length of a null-terminated (ASCIZ) string */
- void pCount()
- {
- pushData(strlen((char*)topData));
- }
-
-
- /* match ( adr1 addr2 -- -1 <OR> 0 <OR> 1 ) */
- /* compare two ASCIZ strings */
- void pMatch()
- {
- char* addr2 = (char*)popData();
- char* addr1 = (char*)topData;
- topData = strcmp(addr1, addr2);
- }
-
-
- /* scan ( addr char -- addr ) */
- /* Find first matching character starting from an address */
- /* Scan until found or end of string (null char) */
- void pScan()
- {
- char c = (char)popData();
- char* address = (char*)topData;
-
- while(*address != c && *address) address++;
- topData = (int)address;
- }
-
-
- /* scanWhite ( addr -- addr ) */
- /* Find first whitespace character starting from an address */
- /* Scan until found or end of string (null char) */
- void pScanWhite()
- {
- char* address = (char*)topData;
-
- while (*address != ' ' && *address != '\t' && *address) address++;
- topData = (int)address;
- }
-
-
- /* skip ( addr char -- addr ) */
- /* Find first character which is not "char" starting from an address
- and return its address */
- void pSkip()
- {
- char c = (char)popData();
- char* address = (char*)topData;
-
- while (*address == c) address++;
- topData = (int)address;
- }
-
-
- /* skipWhite ( addr -- addr ) */
- /* Skip all white space characters starting from an address */
- void pSkipWhite()
- {
- char* address = (char*)topData;
-
- while (*address == ' ' || *address == '\t') address++;
- topData = (int)address;
- }
-
-
- /* enclose ( addr char -- ) */
- /* Find first matching character starting from an address */
- /* and replace that character by a zero (thus forming an */
- /* ASCIZ string). */
- void pEnclose()
- {
- char c = (char)popData();
- char* address = (char*)popData();
-
- while (*address != c && *address) address++;
- *address = 0;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Arithmetics */
-
- /* + ( l1 l2 -- l1+l2 ) */
- /* add two topmost data stack items */
- void pPlus()
- {
- topData = popData() + topData;
- }
-
-
- /* - ( l1 l2 -- l1-l2 ) */
- /* subtract the topmost item in the data stack from the second topmost one */
- void pMinus()
- {
- int temp = popData();
- topData -= temp;
- }
-
-
- /* * ( l1 l2 -- l1*l2 ) */
- /* multiply two topmost items in the data stack */
- void pMultiply()
- {
- topData = popData() * topData;
- }
-
-
- /* / ( l1 l2 -- l1/l2 ) */
- /* divide the second topmost item in the datastack by the topmost one */
- void pDivide()
- {
- int temp = popData();
- if (!temp) {
- ownPrintf("-- Division by zero");
- execute((*up)->errorVector);
- }
- else topData /= temp;
- }
-
-
- /* mod ( l1 l2 -- mod(l1/l2) ) */
- /* save as '/', but return modulus instead */
- void pModulo()
- {
- int temp = popData();
- topData %= temp;
- }
-
-
- /* /mod ( l l -- mod quot ) */
- /* same as '/' or 'mod', but return both modulus and quotient */
- void pDivMod()
- {
- int divisor = topData;
- int dividend = secondData;
- secondData = dividend % divisor;
- topData = dividend / divisor;
- }
-
-
- /* u/ ( l1 l2 -- l1/l2 ) */
- /* unsigned division */
- void pUDivide()
- {
- unsigned temp = popData();
- topData /= temp;
- }
-
-
- /* umod ( l1 l2 -- umod(l1/l2) ) */
- /* unsigned modulus */
- void pUModulo()
- {
- unsigned temp = popData();
- topData %= temp;
- }
-
-
- /* u/mod ( l1 l2 -- mod quot ) */
- /* unsigned modulus and division */
- void pUDivMod()
- {
- unsigned divisor = topData;
- unsigned dividend = secondData;
- secondData = dividend % divisor;
- topData = dividend / divisor;
- }
-
-
- /* 1+ ( l -- l+1 ) */
- /* add one to the topmost item in the data stack */
- void pAdd1()
- {
- topData += 1;
- }
-
-
- /* 2+ ( l -- l+2 ) */
- /* add two to the topmost item in the data stack */
- void pAdd2()
- {
- topData += 2;
- }
-
-
- /* CELL+ ( l -- l+CELL ) */
- /* add CELL to the topmost item in the data stack */
- void pAddCell()
- {
- topData += CELL;
- }
-
-
- /* 1- ( l -- l-1 ) */
- /* subtract one from the topmost item in the data stack */
- void pSub1()
- {
- topData -= 1;
- }
-
-
- /* 2- ( l -- l-2 ) */
- /* subtract two from the topmost item in the data stack */
- void pSub2()
- {
- topData -= 2;
- }
-
-
- /* CELL- ( l -- l-CELL ) */
- /* subtract CELL from the topmost item in the data stack */
- void pSubCell()
- {
- topData -= CELL;
- }
-
-
- /* 2* ( l1 -- l1*2 ) */
- /* multiply the topmost item in the data stack by two */
- void pMul2()
- {
- topData *= 2;
- }
-
-
- /* 2/ ( l1 -- l1/2 ) */
- /* divide the topmost item in the data stack by two */
- void pDiv2()
- {
- topData /= 2;
- }
-
-
- /* CELL* ( l1 -- l1*CELL ) */
- /* multiply the topmost item in the data stack by CELL */
- void pMulCell()
- {
- topData *= CELL;
- }
-
-
- /* CELL/ ( l1 -- l1/CELL) */
- /* divide the topmost item in the data stack by CELL */
- void pDivCell()
- {
- topData /= CELL;
- }
-
-
- /* abs ( l -- l ) */
- /* absolute value the topmost item in the data stack */
- void pAbs()
- {
- topData = abs(topData);
- }
-
-
- /* negate +/- ( l -- -l ) */
- /* negate (two's complement) the topmost item in the data stack */
- void pNegate()
- {
- topData = 0 - topData;
- }
-
-
- /* min ( l l -- l ) */
- /* return the minimum of the two topmost items in the data stack */
- void pMin()
- {
- int a = popData();
- int b = topData;
- topData = (a < b) ? a : b;
- }
-
-
- /* max ( l l -- l ) */
- /* return the maximum of the two topmost items in the data stack */
- void pMax()
- {
- int a = popData();
- int b = topData;
- topData = (a > b) ? a : b;
- }
-
-
- /* between ( l low high -- f ) */
- /* return a flag telling whether a value is between/including certain values */
- void pBetween()
- {
- int high = popData();
- int low = popData();
- int val = topData;
- topData = (val >= low && val <= high) ? TRUE : FALSE;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Literals */
-
- /* 0 ( -- 0 ) */
- /* load zero to the data stack */
- void pZero()
- {
- pushData(0);
- }
-
-
- /* 1 ( -- 1 ) */
- /* load one to the data stack */
- void pOne()
- {
- pushData(1);
- }
-
-
- /* 2 ( -- 2 ) */
- /* load two to the data stack */
- void pTwo()
- {
- pushData(2);
- }
-
-
- /* CELL ( -- CELL ) */
- /* load CELL to the data stack */
- void pCell()
- {
- pushData(CELL);
- }
-
-
- /* false ( -- false ) */
- /* load FALSE (0) to the data stack */
- void pFalse()
- {
- pushData(FALSE);
- }
-
-
- /* true ( -- true ) */
- /* load TRUE (-1) to the data stack */
- void pTrue()
- {
- pushData(TRUE);
- }
-
-
- /* "immediate" ( -- ImmedFlag ) */
- /* load the immediate flag to the data stack */
- void pImmedFlag()
- {
- pushData(ImmedFlag);
- }
-
-
- /* "hidden" ( -- hiddenFlag ) */
- /* load the hidden flag to the data stack */
- void pHiddenFlag()
- {
- pushData(HiddenFlag);
- }
-
-
- /* "smudge" ( -- SmudgeFlag ) */
- /* load the smudge flag to the data stack */
- void pSmudgeFlag()
- {
- pushData(SmudgeFlag);
- }
-
-
- /* #threads ( -- #threads ) */
- /* return the number of threads in the hashed dictionary structure */
- void pThreads()
- {
- pushData(CONTEXTSIZE);
- }
-
-
- /* "thisOnly" ( -- literal ) */
- /* Return a literal denoting that one object only should be modified */
- void pLitThisOnly()
- {
- pushData(THIS_ONLY);
- }
-
-
- /* "wholeFamily" ( -- literal ) */
- /* Return a literal denoting that whole family should be modified */
- void pLitWholeFamily()
- {
- pushData(WHOLE_FAMILY);
- }
-
-
- /* "derivatives" ( -- literal ) */
- /* Return a literal denoting that all derivatives should be modified */
- void pLitDerivatives()
- {
- pushData(DERIVATIVES);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Conditional tests */
-
- /* 0= ( l -- f ) */
- /* return true if the topmost item in data stack is zero, false otherwise */
- void pEqual0()
- {
- topData = (!topData) ? TRUE : FALSE;
- }
-
-
- /* 0<> ( l -- f ) */
- /* return true if the topmost item in data stack is <> 0, false otherwise */
- void pNotEqual0()
- {
- topData = topData ? TRUE : FALSE;
- }
-
-
- /* 0> ( l -- f ) */
- /* return true if the topmost item in data stack is > 0, false otherwise */
- void pGreater0()
- {
- topData = (topData > 0) ? TRUE : FALSE;
- }
-
-
- /* 0< ( l -- f ) */
- /* return true if the topmost item in data stack is < 0, false otherwise */
- void pLess0()
- {
- topData = (topData < 0) ? TRUE : FALSE;
- }
-
-
- /* = ( l l -- f ) */
- /* return true if two topmost items in data stack are equal, false otherwise */
- void pEqual()
- {
- int temp = popData();
- topData = (topData == temp) ? TRUE : FALSE;
- }
-
-
- /* <> ( l l -- f ) */
- /* return true if two topmost items in stack are not equal, false otherwise */
- void pNotEqual()
- {
- int temp = popData();
- topData = (topData != temp) ? TRUE : FALSE;
- }
-
-
- /* < ( l l -- f ) */
- /* return true if the second topmost item is less than the topmost one */
- void pLess()
- {
- int temp = popData();
- topData = (topData < temp) ? TRUE : FALSE;
- }
-
-
- /* <= ( l l -- f ) */
- /* return true if the second topmost item is <= than the topmost one */
- void pLessEq()
- {
- int temp = popData();
- topData = (topData <= temp) ? TRUE : FALSE;
- }
-
-
- /* > ( l l -- f ) */
- /* return true if the second topmost item is greater than the topmost one */
- void pGreater()
- {
- int temp = popData();
- topData = (topData > temp) ? TRUE : FALSE;
- }
-
-
- /* >= ( l l -- f ) */
- /* return true if the second topmost item is >= than the topmost one */
- void pGreaterEq()
- {
- int temp = popData();
- topData = (topData >= temp) ? TRUE : FALSE;
- }
-
-
- /* u< ( l l -- f ) */
- /* same as '<' but unsigned */
- void pULess()
- {
- unsigned temp = popData();
- topData = ((unsigned)topData < temp) ? TRUE : FALSE;
- }
-
-
- /* u> ( l l -- f ) */
- /* same as '>' but unsigned */
- void pUGreater()
- {
- unsigned temp = popData();
- topData = ((unsigned)topData > temp) ? TRUE : FALSE;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Logical operations */
-
- /* and ( l l -- l ) */
- /* return the logical AND of the two topmost items in the data stack */
- void pAnd()
- {
- int temp = popData();
- topData &= temp;
- }
-
-
- /* or ( l l -- l ) */
- /* return the logical OR of the two topmost items in the data stack */
- void pOr()
- {
- int temp = popData();
- topData |= temp;
- }
-
-
- /* xor ( l l -- l ) */
- /* return the logical XOR of the two topmost items in the data stack */
- void pXor()
- {
- int temp = popData();
- topData ^= temp;
- }
-
-
- /* not ( l -- ~l ) */
- /* return one's complement */
- void pNot()
- {
- topData = ~topData;
- }
-
-
- /* << ( l -- l ) */
- /* Shift left */
- void pShiftLeft()
- {
- topData <<= 1;
- }
-
-
- /* >> ( l -- l ) */
- /* Shift right */
- void pShiftRight()
- {
- topData >>= 1;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Control structure primitives */
-
- /* (branch) ( -- ) */
- /* unconditional branch */
- void pBranch()
- {
- ip += (int)*ip;
- }
-
-
- /* (if) ( f -- ) */
- /* conditional branch: branch if the topmost item in the data stack is <> 0 */
- void poIf()
- {
- if (popData()) ip++;
- else ip += (int)*ip;
- }
-
-
- /* (do) ( high low -- ) */
- /* loop beginning: push loop index and limit to return stack */
- /* if initial index higher than limit, branch */
- void poDo()
- {
- register int low = popData();
- register int limit = popData();
-
- if (low > limit) ip += (int)*ip;
- else {
- pushReturn((int*)(ip+(int)*ip)); /* Push loop exit address (for 'leave') */
- pushReturn((int*)limit); /* Push loop index limit */
- pushReturn((int*)low); /* Push loop start index */
- ip++; /* Skip the offset */
- }
- }
-
-
- /* (-do) ( high low -- ) */
- /* loop beginning: push loop index and limit to return stack */
- /* this version does not have initial checks, so it can be used */
- /* for +LOOPs with negative increments */
- void poStraightDo()
- {
- register int low = popData();
- register int limit = popData();
-
- pushReturn((int*)(ip+(int)*ip)); /* Push loop exit address (for 'leave') */
- pushReturn((int*)limit); /* Push loop index limit */
- pushReturn((int*)low); /* Push loop start index */
- ip++; /* Skip the offset */
- }
-
-
- /* (loop) ( -- ) */
- /* loop end: if index is greater than limit, end loop */
- /* else increment index by one */
- void poLoop()
- {
- register int index = (int)topReturn;
- register int limit = (int)secondReturn;
-
- if (index < limit) { /* If index is still below the limit */
- topReturn=(int*)(index+1); /* Increment index */
- ip += (int)*ip; /* and go back to the beginning of the loop */
- }
- else {
- nPopReturn(3); /* Otherwise remove return stack effects */
- ip++; /* and continue (skip the address) */
- }
- }
-
-
- /* (+loop) ( l -- ) */
- /* loop end: if index is greater than limit, end loop */
- /* else increment index by the topmost item in the data stack */
- void poAddLoop()
- {
- /* This is otherwise the same as (loop) above but index increment
- does not necessarily have to be 1 (increment is taken from the
- data stack) */
- register int incr = popData();
- register int index = (int)topReturn;
- register int limit = (int)secondReturn;
-
- if (incr > 0) {
- if (index < limit) { /* If index is still below the limit */
- topReturn=(int*)(index+incr); /* Increment index */
- ip += (int)*ip; /* and go back to the beginning of the loop */
- }
- else {
- nPopReturn(3); /* Otherwise remove return stack effects */
- ip++; /* and continue (skip the address) */
- }
- }
- else {
- if (index > limit) { /* If index is still over the limit */
- topReturn=(int*)(index+incr); /* Increment index */
- ip += (int)*ip; /* and go back to the beginning of the loop */
- }
- else {
- nPopReturn(3); /* Otherwise remove return stack effects */
- ip++; /* and continue (skip the address) */
- }
- }
- }
-
-
- /* unloop ( -- ) */
- /* remove the loop parameters from the return stack */
- /* This operation can be used before forcing an 'exit' from within a DO-loop */
- void pUnloop()
- {
- nPopReturn(3);
- }
-
-
- /* leave ( -- ) */
- /* Jump to the end of the loop (continue normal execution) */
- void pLeave()
- {
- /*
- Old implementation:
- topReturn = secondReturn; Copy limit to index.
- */
-
- /* New implementation */
- ip = (int**)thirdReturn; /* Force jump */
- nPopReturn(3); /* Remove stack effects */
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Auxiliary system operations */
-
- /* reboot ( -- ) */
- /*
- Empty the return stack and reboot the system starting with the
- next operation in the current thread. Note that 'debugTask' will be
- reset, because after initializing the return stack, resume operation
- would no longer operate correctly.
- */
- void pReboot()
- {
- OBJECT* bootObj = (OBJECT*)*ip;
-
- resetReturn();
- ip = (int**)bootObj->mfa;
- debugTask = NIL;
- ownLongJmp();
- }
-
-
- /* This is one of the most important operations in computer programming :-) */
- /* noop ( -- ) */
- /* do nothing */
- void pNoop()
- { }
-
-
- /*---------------------------------------------------------------------------*/
- /* Multitasker primitives */
-
- /* up ( -- addr ) */
- /* User task area pointer */
- /* Denotes the currently executing task */
- void pUp()
- {
- pushData((int)&up);
- }
-
-
- /* multitasking ( -- addr ) */
- /* This primitive variable determines whether multitasking is allowed or not */
- pMultitasking()
- {
- pushData((int)&multitasking);
- }
-
-
- /* running ( task -- flag ) */
- /* Check if a certain task is currently running (TRUE) or suspended (FALSE) */
- void pRunning()
- {
- topData = isActivated((TASK**)topData);
- }
-
-
- /* #tasks ( -- number ) */
- /* How many tasks there are currently in total */
- void pCountTasks()
- {
- pushData(taskCount);
- }
-
-
- /* #running ( -- number ) */
- /* How many tasks there are currently running */
- void pCountRunningTasks()
- {
- pushData(runningCount);
- }
-
-
- /* basePriority ( -- addressOfBasePriority ) */
- /* How many tasks there are currently running */
- void pBasePriority()
- {
- pushData((int)&basePriority);
- }
-
-
- /* taskingMode ( -- mode ) */
- /* return FALSE if the multitasking is preemptive */
- void pMtaskMode()
- {
- pushData(mtaskMode);
- }
-
-
- /* preemptive ( -- ) */
- /* Set preemptive multitasking mode */
- pPreemptive()
- {
- if (mtaskMode != PREEMPTIVE) longjmp(p_inner, TRUE);
- }
-
-
- /* cooperative ( -- ) */
- /* Set cooperative multitasking mode */
- pCooperative()
- {
- if (mtaskMode != COOPERATIVE) cooperativeInterpreter();
- }
-
-
- /* <| ( -- ) */
- /* disable multitasking (starts a critical region) */
- pIOff()
- {
- if (!inProtRegion) mtStore = multitasking;
- inProtRegion++;
- multitasking = FALSE;
- }
-
-
- /* |> ( -- ) */
- /* enable multitasking (ends a critical region). Does 'yield' automatically */
- pIOn()
- {
- if (inProtRegion > 0) {
- if (--inProtRegion == 0) {
- multitasking = mtStore;
- yield();
- }
- }
- }
-
-
- /* activate ( task -- ) */
- /* Activate a task (allow the task to continue its previous execution) */
- void pActivate()
- {
- /* See 'tasks.c' */
- activateTask((TASK**)popData());
- }
-
-
- /* suspend ( task -- ) */
- /* Suspend a task (cancel its execution until it is reactivated) by */
- /* removing it from the round-robin chain. This operation operates */
- /* only if the task is in the round-robin chain, and the task is */
- /* not the only running task in the system (because otherwise */
- /* the system would die). */
- void pSuspend()
- {
- suspendTask((TASK**)popData());
- }
-
-
- /* does ( operation task -- ) */
- /* Reset the behavior of a task. The task must be suspended. */
- void pTaskDoes()
- {
- TASK** newTask = (TASK**)popData();
- OBJECT* bootOper = (OBJECT*)popData();
-
- setTaskBehavior(newTask, bootOper);
- }
-
-
- /* <buildBGTask> ( -- task ) */
- /* Create a new background task by copying the current one */
- /* The task shares the window with its creator */
- void pBuildBGTask()
- {
- pushData((int)buildTask());
- }
-
-
- /* <deleteTask> ( task -- ) */
- /* Delete a task provided that it is not running */
- void pDeleteTask()
- {
- if (!deleteTask((TASK**)popData()))
- fprintf(confile, "== Cannot delete the only active task in the system ==\n");
- }
-
-
- /* <killTask> ( task -- ) */
- /*
- This is a stronger version of <deleteTask> which will delete a task
- even if the task was current active.
- */
- void pKillTask()
- {
- if (!killTask((TASK**)popData()))
- fprintf(confile, "== Cannot kill the only active task in the system ==\n");
- }
-
-
- /* raisePriority ( task -- ) */
- /* Multiply (raise) the priority of the requested task by two */
- void pRaisePriority()
- {
- TASK** thisTask = (TASK**)popData();
- (*thisTask)->priority *= 2;
- }
-
-
- /* lowerPriority ( task -- ) */
- /* Divide (lower) the priority of the requested task by two */
- /* Don't do to zero priority, though */
- void pLowerPriority()
- {
- TASK** thisTask = (TASK**)popData();
- int pr = (*thisTask)->priority;
- if (pr && pr > 1) (*thisTask)->priority /= 2;
- else (*thisTask)->priority = 1;
- }
-
-
- /* resetPriorities ( -- ) */
- /* Reset the priority of all the tasks to 'basePriority' */
- void pResetPriorities()
- {
- TASK** thisTask = firstTask;
-
- fprintf(confile, "== Setting the priority of all tasks to %d (current base priority) ==\n",
- basePriority);
-
- while(thisTask) {
- (*thisTask)->priority = basePriority;
- thisTask = (*thisTask)->nextTask;
- }
- }
-
-
- /*
- These special stack operations are needed to allow the data and context
- stacks of tasks to be initialized from other tasks.
- */
-
- /* >taskData ( data task -- ) */
- /* Push a value to another task's data stack */
- void pToTaskData()
- {
- TASK** targetTask = (TASK**)popData();
- int data = popData();
-
- toTaskData(targetTask, data);
- }
-
-
- /* >taskReturn ( data task -- ) */
- /* Push a value to another task's return stack */
- /* The task must not be active at the moment */
- void pToTaskReturn()
- {
- TASK** targetTask = (TASK**)popData();
- int data = popData();
-
- toTaskReturn(targetTask, data);
- }
-
-
- /* >taskContext ( data task -- ) */
- /* Push a value to another task's context stack */
- /* The task must not be active at the moment */
- void pToTaskCtxt()
- {
- TASK** targetTask = (TASK**)popData();
- int data = popData();
-
- toTaskCtxt(targetTask,data);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Context (dictionary) management */
-
- /* searchThis ( str contextObj -- pair TRUE <or> FALSE ) */
- /* Search if a certain name can be found in a certain context */
- void pSearchThis()
- {
- OBJECT* ctxtObj = (OBJECT*)popData();
- char* str = (char*)popData();
- PAIR* pair;
-
- pushData((int)(pair = findPairInThis(getContext(ctxtObj), str)));
- if (pair) pushData(TRUE);
- }
-
-
- /* search ( str -- pair TRUE <or> FALSE ) */
- /* Search if a certain name can be found in the predefined search path */
- void pSearch()
- {
- char* str = (char*)popData();
- PAIR* pair;
-
- pushData((int)(pair = findPairBackward(str)));
- if (pair) pushData(TRUE);
- }
-
-
- /* immediate? ( pair -- TRUE/FALSE ) */
- /* check if a certain name is designated immediate */
- void pQImmed()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (pair->ffa & ImmedFlag) > 0 ? TRUE : FALSE;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Number management */
-
- /* number ( addr -- number TRUE <or> FALSE ) */
- /* check if the string in an address is a valid decimal, octal or hex number */
- void pNumber()
- {
- char* addr = (char*)topData;
-
- char* temp;
- char** endPtr = &temp;
-
- int result = strtol(addr, endPtr, 0);
- if (!**endPtr) {
- topData = result;
- pushData(TRUE);
- }
- else topData = FALSE;
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Implementation structure management primitives */
-
- /* <buildContext> ( object -- context ) */
- /* build a new context and return its address */
- /* The first member of the clone family will be 'object' */
- void pBuildCtxt()
- {
- OBJECT* object = (OBJECT*)topData;
- CONTEXT* context = createContext();
- addToList(context->cloneFamily, object);
- topData = (int)context;
- }
-
-
- /* <buildName> ( straddr contextObject -- pair ) */
- /* build a name part and include it in a context */
- void pBuildPair()
- {
- OBJECT* ctxtObj = (OBJECT*)popData();
- char* name = (char*)popData();
- char* newName;
- newName = allocStrCpy(name);
- pushData((int)addPair(getContext(ctxtObj), newName, NIL));
- }
-
-
- /* <buildObject> ( size -- object ) */
- /* build a new object of given size, initializing its memory to zeros */
- void pBuildObj()
- {
- int size = popData();
- pushData((int)createClosure(size));
- }
-
-
- /* <mkdir> ( -- object ) */
- /* build a new object-oriented object with a clone family */
- /* the only member of the clone family will be the object itself */
- void pBuildDir()
- {
- OBJECT* object = createClosure(2);
- CONTEXT* context = createContext();
- object->mfa->efa = (int*)oContext;
- object->mfa->pfa = (int*)context;
- addToList(context->cloneFamily, object);
- pushData((int)object);
- }
-
-
- /* <buildStore> ( size -- store ) */
- /* build a new storage part of an object, initialized to zeros */
- void pBuildStore()
- {
- int size = popData();
- pushData((int)createStore(size));
- }
-
-
- /* <buildString> ( straddr -- straddr ) */
- /* allocate a string */
- void pBuildStr()
- {
- char* addr = (char*)popData();
- pushData((int)allocStrCpy(addr));
- }
-
-
- /* <deleteName> ( pair -- ) */
- /* remove a name from its context */
- void pDeleteName()
- {
- PAIR* pair = (PAIR*)popData();
-
- unlinkPair(pair);
- free(pair);
- }
-
-
- /* <renameName> ( pair newNameString -- ) */
- /* rename a pair */
- void pRenameName()
- {
- char* newName = (char*)popData();
- PAIR* pair = (PAIR*)popData();
-
- renamePair(pair, newName);
- }
-
-
- /* <shallowCopy> ( oldObject -- newObject ) */
- /* shallow copy an existing OOP object */
- void pShallowCopyObj()
- {
- topData = (int)cloneObject((OBJECT*)topData);
- }
-
-
- /* <derive> ( object -- ) */
- /* ensure the individuality of the OOP object before the object is modified */
- /* by duplicating its context if there are multiple copies of the object */
- void pDeriveObject()
- {
- deriveObject((OBJECT*)popData());
- }
-
-
- /* <resize> ( newsize object -- ) */
- /* resize an existing object. If new size is more than old size, */
- /* the newly allocated extra memory is initialized to zeros */
- /* Size are given in CELLs */
- void pResizeObj()
- {
- OBJECT* object = (OBJECT*)popData();
- int newsize = popData();
-
- resizeClosure(object, newsize);
- }
-
-
- /* <expand> ( more object -- ) */
- /* expand the size of an existing object, initializing the extra memory to 0 */
- /* Size is given in CELLs */
- void pExpandObj()
- {
- OBJECT* object = (OBJECT*)popData();
- int more = popData();
-
- if (more > 0) resizeClosure(object, object->sfa+more);
- }
-
-
- /* <expandFamily> ( more object -- ) */
- /* expand the size of all the objects in the clone family of the given object */
- /* initializing the extra memory to 0 */
- void pExpandFamily()
- {
- OBJECT* object = (OBJECT*)popData();
- int more = popData();
-
- if (more > 0) resizeFamilyMembers(object, object->sfa+more);
- }
-
-
- /* <optimize> ( object -- ) */
- /* optimize the memory consumption of an object by removing all the trailing */
- /* zeros from its end. This op should be used for closure objects only */
- void pOptimizeObj()
- {
- OBJECT* object = (OBJECT*)popData();
- int size = object->sfa;
- int* addr = (int*)object->mfa + size - 1;
-
- /* If primitive, do nothing */
- if (size == 0) return;
-
- while (!*addr) addr--;
- size = addr - (int*)object->mfa + 1;
-
- if (size > 0) resizeClosure(object, size);
- }
-
-
- /* <dispose> ( object -- ) */
- /* dispose of OOP object by removing it from its clone family */
- /* and by deallocating its storage space */
- void pDisposeObject()
- {
- OBJECT* object = (OBJECT*)popData();
- WindowPtr browserWindow;
-
- /*
- Remove the object from its clone family, deleting the clone family
- and reorganizing the family hierarchy if needed.
- */
- removeFromItsFamily(object);
-
- /* yyy warning: the code below is non-portable */
- /* To ensure integrity, we must close the possible browser to this object */
- browserWindow = findBrowser(object);
- if (browserWindow) deleteBrowser(browserWindow);
-
- free(object);
- }
-
-
- /* <free> ( addr -- ) */
- /* Free heap memory (this is the same as 'free' in C */
- void pFree()
- {
- free((void*)popData());
- }
-
-
- /* <freeStore> ( object -- ) */
- /* Free the store part of an object, provided that the object is not a primitive */
- /* (primitives do not have a store part) */
- void pFreeStore()
- {
- OBJECT* object = (OBJECT*)popData();
-
- if (object->sfa) free(object->mfa);
- }
-
-
- /* <recompile> ( oldProperty changedPair -- ) */
- /* starting from a (changed) pair, rebind all the references to the */
- /* old property in the corresponding object to the new property */
- void pRecompile()
- {
- PAIR* changedPair = (PAIR*)popData();
- OBJECT* oldProperty = (OBJECT*)popData();
-
- recompileProperty(changedPair, oldProperty);
- }
-
-
- /* <rebind> ( fromPair -- ) */
- /* starting from the given pair, check the early bindings and */
- /* rebind if necessary */
- void pRebind()
- {
- PAIR* fromPair = (PAIR*)popData();
-
- rebindContext(fromPair, NIL, NIL);
- }
-
-
- /* <reorganize> ( whoToModify object -- ) */
- /* Notify the system that the given object has changed, and its location */
- /* in the clone family hierarchy must be taken into reconsideration */
- void pReorganize()
- {
- OBJECT* object = (OBJECT*)popData();
- int whoToModify = popData();
-
- confirmObjectType(object, whoToModify, REMOVING_SOMETHING);
- }
-
-
- /* <rePair> ( pair object -- pair ) */
- /* This is a temporary implementation:
- Since 'pair' may no longer be in the context of 'object' after executing
- <derive>, we must find the first pair in 'object's context with the same
- ofa field as in 'pair'.
- */
- void pRePair()
- {
- OBJECT* object = (OBJECT*)popData();
- PAIR* pair = (PAIR*)topData;
-
- CONTEXT* context = getContext(object);
- OBJECT* target = pair->ofa;
- PAIR* thisPair = context->firstPair;
-
- while (thisPair) {
- if (thisPair->ofa == target) {
- topData = (int)thisPair;
- return;
- }
- thisPair = thisPair->sfa;
- }
-
- topData = NIL;
- fprintf(confile, "== Integrity error detected: pair not found in '<rePair>' ==\n");
- reportIntegrityError();
- ownLongJmp();
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Implementation structure offsets */
-
- /* name>object ( pair -- object ) */
- /* given a name part, return the identity of the corresponding object */
- void pPairToObj()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)pair->ofa;
- }
-
-
- /* name'object ( pair -- ofa ) */
- /* return the address of the 'object' (OFA) field in a name part */
- void pPairOFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->ofa;
- }
-
-
- /* name'name ( pair -- nfa ) */
- /* return the address of the 'name' (NFA) field in a name part */
- void pPairNFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->nfa;
- }
-
-
- /* name'flags ( pair -- ffa ) */
- /* return the address of the 'flags' (FFA) field in a name part */
- void pPairFFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->ffa;
- }
-
-
- /* name'prev ( pair -- lfa ) */
- /* return the address of the 'prev' (LFA) field in a name part */
- void pPairLFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->lfa;
- }
-
-
- /* name'succ ( pair -- lfa ) */
- /* return the address of the 'succ' (SFA) field in a name part */
- void pPairSFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->sfa;
- }
-
-
- /* name'context ( pair -- cfa ) */
- /* return the address of the 'context' (CFA) field in a name part */
- void pPairCFA()
- {
- PAIR* pair = (PAIR*)topData;
- topData = (int)&pair->cfa;
- }
-
-
- /* object>name ( object -- pair TRUE <OR> FALSE ) */
- /* given an object, return the possible corresponding name part */
- void pObjToPair()
- {
- OBJECT* object = (OBJECT*)topData;
- PAIR* pair;
-
- topData = (int)(pair = findNameBackward(object));
- if (pair) pushData(TRUE);
- }
-
-
- /* object>typename ( object -- pair TRUE <OR> FALSE ) */
- /* given an OOP object, return the first possible corresponding name part */
- /* which refers to the same context as the given object. This can be */
- /* regarded as the "type" of that OOP object. */
- void pObjToTypeName()
- {
- OBJECT* ctxtObject = (OBJECT*)topData;
- PAIR* pair;
-
- topData = (int)(pair = findTypeForward(ctxtObject));
- if (pair) pushData(TRUE);
- }
-
-
- /* object>store ( object -- store ) */
- /* given an object, return the address of its store part */
- void pObjToStore()
- {
- OBJECT* object = (OBJECT*)topData;
- topData = (int)object->mfa;
- }
-
-
- /* object'store ( object -- mfa ) */
- /* return the address of the 'store' (MFA) field in an object header */
- void pObjectMFA()
- {
- OBJECT* object = (OBJECT*)topData;
- topData = (int)&object->mfa;
- }
-
-
- /* object'size ( object -- sfa ) */
- /* return the address of the 'size' (SFA) field in an object header */
- void pObjectSFA()
- {
- OBJECT* object = (OBJECT*)topData;
- topData = (int)&object->sfa;
- }
-
-
- /* object>context ( contextObject -- context ) */
- /* return the context of the given OOP object */
- /* ensuring that the object really is a valid OOP object */
- /* with its own context. */
- void pObjToContext()
- {
- OBJECT* object = (OBJECT*)topData;
-
- if (!isContextObject(object)) {
- ownPrintf("-- Invalid parameter received by 'object>context'");
- execute((*up)->errorVector);
- }
- else topData = (int)getContext(object);
- }
-
-
- /* context'thread ( thread context -- pairAddr ) */
- /* return the name referred to from the n'th thread in a context */
- /* Indexing starts from zero */
- void pContextThread()
- {
- CONTEXT* context = (CONTEXT*)popData();
- int thread = topData;
-
- topData = (int)&(context->lastPair[thread]);
- }
-
-
- /* context'first ( context -- pairAddr ) */
- /* return the first name in a context (beginning of succ link) */
- void pContextFirst()
- {
- CONTEXT* context = (CONTEXT*)topData;
-
- topData = (int)&context->firstPair;
- }
-
-
- /* context'latest ( context -- pairAddr ) */
- /* return the latest defined name in a context */
- void pContextLatest()
- {
- CONTEXT* context = (CONTEXT*)topData;
-
- topData = (int)&context->latestPair;
- }
-
-
- /* context'family ( context -- cloneFamily ) */
- /* this is needed for concatenation-based object-oriented programming: */
- /* return the clone family of the given OOP object */
- /* clone family is represented as a LIST object (lists.c) */
- void pContextFamily()
- {
- CONTEXT* context = (CONTEXT*)topData;
-
- topData = (int)&context->cloneFamily;
- }
-
-
- /* context'parents ( context -- parentFamilyList ) */
- /* return the LIST object containing the parent families of the given OOP object */
- void pContextParents()
- {
- CONTEXT* context = (CONTEXT*)topData;
-
- topData = (int)&context->parentFamilies;
- }
-
-
- /* context'children ( context -- childFamilyList ) */
- /* return the LIST object containing the child families of the given OOP object */
- void pContextChildren()
- {
- CONTEXT* context = (CONTEXT*)topData;
-
- topData = (int)&context->childFamilies;
- }
-
-
- /* checkSystemValidity ( -- ) */
- /* Perform integrity checks for every context in the system */
- /* This allows us to recognize memory leaks, dangling pointers etc. */
- void pCheckSystem()
- {
- /* The first context in the context list is always 'rootContext' */
- /* However, since rootContext is so big (= time-consuming to check) */
- /* we start from the next context */
- CONTEXT* thisContext = rootContext->nextContext;
-
- while (thisContext) {
- checkIntegrity(thisContext);
- thisContext = thisContext->nextContext;
- }
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Debugging, decompilation, and tracing primitives */
- /* Most of these primitives can be found from separate files */
-
- /* see ( object -- ) */
- /* decompile the definition of an object */
- void pSee()
- {
- /* See 'image.c' */
- decompile((OBJECT*)popData());
- yield();
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Basic file interface */
-
- /* "write" ( -- "write" ) */
- /* return address of a string denoting file "write" mode */
- void pWriteMode()
- {
- pushData((int)"w");
- }
-
-
- /* "append" ( -- "append" ) */
- /* return address of a string denoting file "append" mode */
- void pAppendMode()
- {
- pushData((int)"a");
- }
-
-
- /* pushInfile ( string -- ) */
- /* push current input file to the task-specific file stack, and */
- /* open a new file for reading instead. */
- void pPushInfile()
- {
- char* fileName = (char*)popData();
-
- pushInfile(fileName);
- }
-
-
- /* popInfile ( -- ) */
- /* Close the current input file and return to the previous one */
- /* Do not close 'stdin', though. */
- void pPopInfile()
- {
- popInfile();
- }
-
-
- /* resetInfiles ( -- ) */
- /* Reset the input file stack. */
- /* Close all the input files except the first. */
- void pResetInfiles()
- {
- while(infileSp > 0) popInfile();
- }
-
-
- /* pushOutfile ( string mode -- ) */
- /* push current output file to the task-specific file stack, and */
- /* open a new file for writing or appending instead. */
- void pPushOutfile()
- {
- char* mode = (char*)popData();
- char* fileName = (char*)popData();
-
- pushOutfile(fileName, mode);
- }
-
-
- /* popOutfile ( -- ) */
- /* Close the current output file and return to the previous one */
- /* Do not close stdout or stderr, though. */
- void pPopOutfile()
- {
- popOutfile();
- }
-
-
- /* resetOutfiles ( -- ) */
- /* Reset output file stack. */
- /* Close all the output files except the first. */
- void pResetOutfiles()
- {
- while(outfileSp > 0) popOutfile();
- }
-
-
- /* errorTo ( -- ) */
- /* Push error file to outfile stack. */
- /* This allows a task to print to the screen even though it was */
- /* currently loading a file */
- void pErrfilePush()
- {
- pushToOFS(errfile);
- }
-
-
- /* consoleTo ( -- ) */
- /* Push console file to outfile stack */
- /* This allows tasks to print to the console window. */
- void pConfilePush()
- {
- pushToOFS(confile);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* Object-oriented primitives */
-
- /* self ( -- self ) */
- /* return self */
- void pSelf()
- {
- pushData((int)topContext);
- }
-
-
- /* & ( -- self ) */
- /* return the identity of the receiver of the previous message */
- void pPrevSelf()
- {
- pushData((int)prevContext);
- }
-
-
- /* >self ( object -- ) */
- /* push an item to the context stack */
- void pToSelf()
- {
- pushContext((int*)popData());
- }
-
-
- /* self> ( -- object ) */
- /* pop an item from the context stack */
- void pSelfFrom()
- {
- pushData((int)popContext());
- }
-
-
- /* self>drop ( -- ) */
- /* drop an item from the context stack */
- void pSelfDrop()
- {
- (void)popContext();
- }
-
-
- /* cdepth ( -- l ) */
- /* push the depth of context stack to the top of data stack */
- void pCDepth()
- {
- pushData(contextSp - contextStackBottom());
- }
-
-
- /* .cs ( -- ) */
- /* print the contents of context stack to outfile */
- /* try to decompile possible object types */
- void pPrintCStack()
- {
- int* ptr = (int*)contextStackBottom();
-
- if (contextSp <= contextStackBottom()) return;
-
- while ((int*)contextSp >= ++ptr) {
- PAIR* pair = findTypeForward(*ptr);
-
- if (pair) {
- ownPrintf("%s:", pair->nfa);
- ownPrintf("%d ", *ptr);
- }
- else {
- pair = findNameForward(*ptr);
- if (pair) ownPrintf("%s ", pair->nfa);
- else ownPrintf("%d ", *ptr);
- }
- }
- }
-
-
- /* resizeContextStack ( newSize task -- ) */
- /* resize the context stack of the given task */
- void pResizeContext()
- {
- TASK** thisTask = (TASK**)popData();
- int newSize = popData();
-
- resizeContextStack(thisTask, newSize);
- }
-
-
- /* >send ( object messageString -- ) */
- /* Send a message to an object */
- /* Note that context stack must be popped after a call to '>send' */
- /* This cannot be done here, because we need to execute threaded code */
- void pSend()
- {
- char* string = (char*)popData();
- OBJECT* object = (OBJECT*)popData();
- PAIR* pair = messageLookUp(object, string);
-
- pushContext((int*)object);
-
- if (pair) execute(pair->ofa);
- else {
- fprintf(confile, "== Message binding error."); showTaskID();
- ownPrintf("-- Cannot bind \"%s\"", string);
- execute((*up)->errorVector);
- }
- }
-
-
- /* >resend ( thisPair -- ) */
- /* Resend a message to the current object, starting from 'thisPair' */
- /* This operations is the equivalent of super-reference in Smalltalk */
- /* Unlike Smalltalk, >resend does not take any identifier as an argument */
- /* (previous identifier is used implicitly) */
- void pResend()
- {
- PAIR* prevPair = (PAIR*)popData();
- PAIR* superPair = selfLookUp(prevPair->lfa, prevPair->nfa);
-
- if (superPair) execute(superPair->ofa);
- else {
- fprintf(confile, "== Message binding error."); showTaskID();
- ownPrintf("-- Cannot bind (resend) \"%s\"", prevPair->nfa);
- execute((*up)->errorVector);
- }
- }
-
-
- /* respondsTo ( string object -- flag ) */
- /* Check if the object is capable of answering to the requested message */
- /* (given as a string). Note that the result value is actually not a flag, */
- /* but the address of the found pair (or NIL) */
- void pRespondsTo()
- {
- OBJECT* object = (OBJECT*)popData();
- char* message = (char*)popData();
-
- pushData((int)respondsTo(object, message));
- }
-
-
- /* hasContext ( object -- flag ) */
- /* Check if the given address is a valid OOP object identity */
- void pHasContext()
- {
- topData = isContextObject((OBJECT*)topData);
- }
-
-
- /* >area ( object -- addrOfFirstDataSlot )
- /* Return the address of the first data slot of an object */
- /* DATAOFFSET is a macro that tells how many cells each instance has */
- /* before the actual data slots begin */
- pToArea()
- {
- topData = (int)((int*)((OBJECT*)topData)->mfa + DATAOFFSET);
- }
-
-
- /* area0 ( -- addrOfFirstDataSlot ) */
- /* Return the address of the first data slot of the current object */
- pAreaZero()
- {
- pushData((int)((int*)((OBJECT*)topContext)->mfa + DATAOFFSET));
- }
-
-
- /* area# ( -- sizeOfArea ) */
- /* Return the size of the current object's data area (in cells) */
- pAreaSize()
- {
- pushData(((OBJECT*)topContext)->sfa - DATAOFFSET);
- }
-
-
- /*---------------------------------------------------------------------------*/
- /* InitPrimitives(): initialize the name space (primitive operations) */
-
- void initPrimitives()
- {
- /* Execution primitives */
- addPair(rootContext, "exit", oExit = createPrimitive(pExit));
- addPair(rootContext, "freeExit", createPrimitive(pFreeExit)); hide();
- addPair(rootContext, "<executeStore>",createPrimitive(pExecStore)); hide();
- addPair(rootContext, "execute", createPrimitive(pExecute));
-
-
- /* Data access primitives */
- addPair(rootContext, "(=sharedVar)", oSharedVar = createPrimitive(pSharedVar)); hide();
- addPair(rootContext, "(=taskVar)", oTaskVar = createPrimitive(pTaskVar)); hide();
- addPair(rootContext, "(=sharedConst)",oSharedConst= createPrimitive(pSharedConst)); hide();
- addPair(rootContext, "(=taskConst)", oTaskConst = createPrimitive(pTaskConst)); hide();
- addPair(rootContext, "(=context)", oContext = createPrimitive(pContext)); hide();
- addPair(rootContext, "(=REF)", oREF = createPrimitive(pREF)); hide();
- addPair(rootContext, "(=VAR)", oVAR = createPrimitive(pVAR)); hide();
- addPair(rootContext, "(->)", createPrimitive(pIncAss)); hide();
- addPair(rootContext, "(lit)", oLit = createPrimitive(pLit)); hide();
- addPair(rootContext, "(\"lit)", oStrLit = createPrimitive(pStrLit)); hide();
- addPair(rootContext, "(=sharedVector)", createPrimitive(pSharedVector)); hide();
- addPair(rootContext, "(=taskVector)", createPrimitive(pTaskVector)); hide();
-
-
- /* Data stack primitives */
- addPair(rootContext, "dup", createPrimitive(pDup));
- addPair(rootContext, "2dup", createPrimitive(pDup2));
- addPair(rootContext, "?dup", createPrimitive(pQDup));
- addPair(rootContext, "drop", createPrimitive(pDrop));
- addPair(rootContext, "2drop", createPrimitive(pDrop2));
- addPair(rootContext, "swap", createPrimitive(pSwap));
- addPair(rootContext, "2swap", createPrimitive(pSwap2));
- addPair(rootContext, "over", createPrimitive(pOver));
- addPair(rootContext, "2over", createPrimitive(pOver2));
- addPair(rootContext, "rot", createPrimitive(pRot));
- addPair(rootContext, "-rot", createPrimitive(pRor));
- addPair(rootContext, "nip", createPrimitive(pNip));
- addPair(rootContext, "tuck", createPrimitive(pTuck));
- addPair(rootContext, "pick", createPrimitive(pPick));
- addPair(rootContext, "roll", createPrimitive(pRoll));
- addPair(rootContext, "depth", createPrimitive(pDepth));
- addPair(rootContext, "resetSp", createPrimitive(resetData));
- addPair(rootContext, ".s", createPrimitive(pPrintStack));
- addPair(rootContext, "resizeDataStack",createPrimitive(pResizeData));
-
-
- /* Return stack primitives */
- addPair(rootContext, ">r", createPrimitive(pToR));
- addPair(rootContext, "r@", createPrimitive(pRFetch));
- addPair(rootContext, "r>", createPrimitive(pRFrom));
- addPair(rootContext, "i", createPrimitive(pI));
- addPair(rootContext, "j", createPrimitive(pJ));
- addPair(rootContext, "rdepth", createPrimitive(pRDepth));
- addPair(rootContext, "dup>r", createPrimitive(pDupToR));
- addPair(rootContext, "r>drop", createPrimitive(pRFromDrop));
- addPair(rootContext, ".rs", createPrimitive(pPrintRStack));
- addPair(rootContext, "resizeReturnStack",createPrimitive(pResizeReturn));
-
-
- /* Temporary variable (block) primitives */
- addPair(rootContext, "({)", createPrimitive(pOpenFrame));
- addPair(rootContext, "(})", createPrimitive(pCloseFrame));
- addPair(rootContext, "<temp>", createPrimitive(pAllocTemp));
- addPair(rootContext, "temp:", createPrimitive(pAccessTemp));
-
-
- /* Memory primitives */
- addPair(rootContext, "@", createPrimitive(pFetch));
- addPair(rootContext, "!", createPrimitive(pStore));
- addPair(rootContext, "+!", createPrimitive(pAddStore));
- addPair(rootContext, "b@", createPrimitive(pBFetch));
- addPair(rootContext, "b!", createPrimitive(pBStore));
- addPair(rootContext, "b+!", createPrimitive(pBAddStore));
- addPair(rootContext, "w@", createPrimitive(pWFetch));
- addPair(rootContext, "w!", createPrimitive(pWStore));
- addPair(rootContext, "w+!", createPrimitive(pWAddStore));
- addPair(rootContext, "on", createPrimitive(pOn));
- addPair(rootContext, "off", createPrimitive(pOff));
- addPair(rootContext, "boff", createPrimitive(pBOff));
- addPair(rootContext, "woff", createPrimitive(pWOff));
- addPair(rootContext, "++", createPrimitive(pInc));
- addPair(rootContext, "cell++", createPrimitive(pCellInc));
- addPair(rootContext, "--", createPrimitive(pDec));
- addPair(rootContext, "cell--", createPrimitive(pCellDec));
- addPair(rootContext, "toggle", createPrimitive(pToggle));
- addPair(rootContext, "untoggle", createPrimitive(pUntoggle));
- addPair(rootContext, "btoggle", createPrimitive(pBToggle));
- addPair(rootContext, "buntoggle", createPrimitive(pBUntoggle));
- addPair(rootContext, "align", createPrimitive(pAlign));
- addPair(rootContext, "move", createPrimitive(pMove));
- addPair(rootContext, "fill", createPrimitive(pFill));
-
-
- /* String primitives */
- addPair(rootContext, "count", createPrimitive(pCount));
- addPair(rootContext, "match", createPrimitive(pMatch));
- addPair(rootContext, "scan", createPrimitive(pScan));
- addPair(rootContext, "scanWhite", createPrimitive(pScanWhite));
- addPair(rootContext, "skip", createPrimitive(pSkip));
- addPair(rootContext, "skipWhite", createPrimitive(pSkipWhite));
- addPair(rootContext, "enclose", createPrimitive(pEnclose));
-
-
- /* Integer arithmetic primitives */
- addPair(rootContext, "+", createPrimitive(pPlus));
- addPair(rootContext, "-", createPrimitive(pMinus));
- addPair(rootContext, "*", createPrimitive(pMultiply));
- addPair(rootContext, "/", createPrimitive(pDivide));
- addPair(rootContext, "mod", createPrimitive(pModulo));
- addPair(rootContext, "/mod", createPrimitive(pDivMod));
- addPair(rootContext, "u/", createPrimitive(pUDivide));
- addPair(rootContext, "umod", createPrimitive(pUModulo));
- addPair(rootContext, "u/mod", createPrimitive(pUDivMod));
- addPair(rootContext, "1+", createPrimitive(pAdd1));
- addPair(rootContext, "2+", createPrimitive(pAdd2));
- addPair(rootContext, "cell+", createPrimitive(pAddCell));
- addPair(rootContext, "1-", createPrimitive(pSub1));
- addPair(rootContext, "2-", createPrimitive(pSub2));
- addPair(rootContext, "cell-", createPrimitive(pSubCell));
- addPair(rootContext, "2*", createPrimitive(pMul2));
- addPair(rootContext, "2/", createPrimitive(pDiv2));
- addPair(rootContext, "cell*", createPrimitive(pMulCell));
- addPair(rootContext, "cell/", createPrimitive(pDivCell));
- addPair(rootContext, "abs", createPrimitive(pAbs));
- addPair(rootContext, "negate", createPrimitive(pNegate));
- addPair(rootContext, "+/-", createPrimitive(pNegate));
-
-
- /* Literal primitives */
- addPair(rootContext, "zero", createPrimitive(pZero));
- addPair(rootContext, "one", createPrimitive(pOne));
- addPair(rootContext, "cell", createPrimitive(pCell));
- addPair(rootContext, "false", createPrimitive(pFalse));
- addPair(rootContext, "true", createPrimitive(pTrue));
- addPair(rootContext, "\"write\"", createPrimitive(pWriteMode));
- addPair(rootContext, "\"append\"", createPrimitive(pAppendMode));
- addPair(rootContext, "\"immediate\"", createPrimitive(pImmedFlag));
- addPair(rootContext, "\"hidden\"", createPrimitive(pHiddenFlag));
- addPair(rootContext, "\"smudge\"", createPrimitive(pSmudgeFlag));
- addPair(rootContext, "#threads", createPrimitive(pThreads));
- addPair(rootContext, "\"thisOnly\"",createPrimitive(pLitThisOnly)); hide();
- addPair(rootContext, "\"wholeFamily\"",createPrimitive(pLitWholeFamily)); hide();
- addPair(rootContext, "\"derivatives\"",createPrimitive(pLitDerivatives)); hide();
-
-
- /* Comparison primitives */
- addPair(rootContext, "0=", createPrimitive(pEqual0));
- addPair(rootContext, "0<>", createPrimitive(pNotEqual0));
- addPair(rootContext, "0<", createPrimitive(pLess0));
- addPair(rootContext, "0>", createPrimitive(pGreater0));
- addPair(rootContext, "=", createPrimitive(pEqual));
- addPair(rootContext, "<>", createPrimitive(pNotEqual));
- addPair(rootContext, "<", createPrimitive(pLess));
- addPair(rootContext, "<=", createPrimitive(pLessEq));
- addPair(rootContext, ">", createPrimitive(pGreater));
- addPair(rootContext, ">=", createPrimitive(pGreaterEq));
- addPair(rootContext, "u<", createPrimitive(pULess));
- addPair(rootContext, "u>", createPrimitive(pUGreater));
- addPair(rootContext, "min", createPrimitive(pMin));
- addPair(rootContext, "max", createPrimitive(pMax));
- addPair(rootContext, "between", createPrimitive(pBetween));
-
-
- /* Logical primitives */
- addPair(rootContext, "and", createPrimitive(pAnd));
- addPair(rootContext, "or", createPrimitive(pOr));
- addPair(rootContext, "xor", createPrimitive(pXor));
- addPair(rootContext, "not", createPrimitive(pNot));
- addPair(rootContext, "<<", createPrimitive(pShiftLeft));
- addPair(rootContext, ">>", createPrimitive(pShiftRight));
-
-
- /* Control structure primitives */
- addPair(rootContext, "(branch)", createPrimitive(pBranch)); hide();
- addPair(rootContext, "(if)", createPrimitive(poIf)); hide();
- addPair(rootContext, "(do)", createPrimitive(poDo)); hide();
- addPair(rootContext, "(-do)", createPrimitive(poStraightDo)); hide();
- addPair(rootContext, "(loop)", createPrimitive(poLoop)); hide();
- addPair(rootContext, "(+loop)", createPrimitive(poAddLoop)); hide();
- addPair(rootContext, "unloop", createPrimitive(pUnloop));
- addPair(rootContext, "leave", createPrimitive(pLeave));
-
-
- /* System primitives */
- addPair(rootContext, "reboot", createPrimitive(pReboot)); hide();
- addPair(rootContext, "noop", createPrimitive(pNoop));
-
-
- /* Debugging, decompilation, and tracing primitives */
- addPair(rootContext, "debugExit", createPrimitive(debugExit)); hide();
- addPair(rootContext, "resume", createPrimitive(resume));
- addPair(rootContext, "trace", createPrimitive(traceInterpreter));
- addPair(rootContext, "fullTrace", createPrimitive(fullTraceInterpreter));
- addPair(rootContext, "endTrace", createPrimitive(ownLongJmp));
- addPair(rootContext, "see", createPrimitive(pSee));
- /* addPair(rootContext, "image", createPrimitive(pImage)); */
-
-
- /* Multitasker primitives */
- addPair(rootContext, "up", createPrimitive(pUp));
- addPair(rootContext, "multitasking",createPrimitive(pMultitasking));
- addPair(rootContext, "running", createPrimitive(pRunning));
- addPair(rootContext, "#tasks", createPrimitive(pCountTasks));
- addPair(rootContext, "#running", createPrimitive(pCountRunningTasks));
- addPair(rootContext, "basePriority",createPrimitive(pBasePriority));
- addPair(rootContext, "taskingMode",createPrimitive(pMtaskMode));
- addPair(rootContext, "preemptive", createPrimitive(pPreemptive));
- addPair(rootContext, "cooperative",createPrimitive(pCooperative));
- addPair(rootContext, "yield", createPrimitive(yield));
- addPair(rootContext, "<|", createPrimitive(pIOff));
- addPair(rootContext, "|>", createPrimitive(pIOn));
- addPair(rootContext, "activate", createPrimitive(pActivate));
- addPair(rootContext, "suspend", createPrimitive(pSuspend));
- addPair(rootContext, "does", createPrimitive(pTaskDoes));
- addPair(rootContext, "raisePriority", createPrimitive(pRaisePriority));
- addPair(rootContext, "lowerPriority", createPrimitive(pLowerPriority));
- addPair(rootContext, "resetPriorities",createPrimitive(pResetPriorities));
- addPair(rootContext, ">taskData", createPrimitive(pToTaskData));
- addPair(rootContext, ">taskReturn", createPrimitive(pToTaskReturn));
- addPair(rootContext, ">taskContext", createPrimitive(pToTaskCtxt));
-
-
- /* File primitives */
- addPair(rootContext, "pushInfile", createPrimitive(pPushInfile));
- addPair(rootContext, "popInfile", createPrimitive(pPopInfile));
- addPair(rootContext, "resetInfiles", createPrimitive(pResetInfiles));
- addPair(rootContext, "pushOutfile", createPrimitive(pPushOutfile));
- addPair(rootContext, "popOutfile", createPrimitive(pPopOutfile));
- addPair(rootContext, "resetOutfiles", createPrimitive(pResetOutfiles));
- addPair(rootContext, "errorTo", createPrimitive(pErrfilePush));
- addPair(rootContext, "consoleTo", createPrimitive(pConfilePush));
-
-
- /* Block file primitives */
- /* (defined in a separate file) */
- addPair(rootContext, "open-blockfile",createPrimitive(pOpenBlockFile));
- addPair(rootContext, "close-blockfile",createPrimitive(pCloseBlockFile));
- addPair(rootContext, "block", createPrimitive(pBlock));
- addPair(rootContext, "update", createPrimitive(pUpdate));
- addPair(rootContext, "discard", createPrimitive(pDiscard));
- addPair(rootContext, "save-buffers", createPrimitive(pSaveBuffers));
- addPair(rootContext, "empty-buffers", createPrimitive(pEmptyBuffers));
- addPair(rootContext, "more", createPrimitive(pMore));
- addPair(rootContext, "capacity", createPrimitive(pCapacity));
-
-
- /* Dictionary primitives */
- addPair(rootContext, "number", createPrimitive(pNumber));
- addPair(rootContext, "search", createPrimitive(pSearch));
- addPair(rootContext, "searchThis", createPrimitive(pSearchThis));
- addPair(rootContext, "immediate?", createPrimitive(pQImmed));
-
-
- /* Internal structure primitives */
- addPair(rootContext, "<buildContext>",createPrimitive(pBuildCtxt)); hide();
- addPair(rootContext, "<buildName>", createPrimitive(pBuildPair)); hide();
- addPair(rootContext, "<buildObject>", createPrimitive(pBuildObj)); hide();
- addPair(rootContext, "<buildStore>", createPrimitive(pBuildStore)); hide();
- addPair(rootContext, "<buildString>", createPrimitive(pBuildStr)); hide();
- addPair(rootContext, "<buildBGTask>", createPrimitive(pBuildBGTask)); hide();
- addPair(rootContext, "<deleteTask>", createPrimitive(pDeleteTask)); hide();
- addPair(rootContext, "<killTask>", createPrimitive(pKillTask)); hide();
- addPair(rootContext, "<deleteName>", createPrimitive(pDeleteName)); hide();
- addPair(rootContext, "<renameName>", createPrimitive(pRenameName)); hide();
- addPair(rootContext, "<mkdir>", createPrimitive(pBuildDir)); hide();
- addPair(rootContext, "<shallowCopy>", createPrimitive(pShallowCopyObj)); hide();
- addPair(rootContext, "<derive>", createPrimitive(pDeriveObject)); hide();
- addPair(rootContext, "<resize>", createPrimitive(pResizeObj)); hide();
- addPair(rootContext, "<expand>", createPrimitive(pExpandObj)); hide();
- addPair(rootContext, "<expandFamily>",createPrimitive(pExpandFamily)); hide();
- addPair(rootContext, "<optimize>", createPrimitive(pOptimizeObj)); hide();
- addPair(rootContext, "<dispose>", createPrimitive(pDisposeObject)); hide();
- addPair(rootContext, "<free>", createPrimitive(pFree)); hide();
- addPair(rootContext, "<freeStore>", createPrimitive(pFreeStore)); hide();
- addPair(rootContext, "<recompile>", createPrimitive(pRecompile)); hide();
- addPair(rootContext, "<rebind>", createPrimitive(pRebind)); hide();
- addPair(rootContext, "<reorganize>", createPrimitive(pReorganize)); hide();
- addPair(rootContext, "<rePair>", createPrimitive(pRePair)); hide();
-
-
- /* Internal structure offsets */
- addPair(rootContext, "name>object", createPrimitive(pPairToObj)); hide();
- addPair(rootContext, "name'object", createPrimitive(pPairOFA)); hide();
- addPair(rootContext, "name'name", createPrimitive(pPairNFA)); hide();
- addPair(rootContext, "name'flags", createPrimitive(pPairFFA)); hide();
- addPair(rootContext, "name'prev", createPrimitive(pPairLFA)); hide();
- addPair(rootContext, "name'succ", createPrimitive(pPairSFA)); hide();
- addPair(rootContext, "name'context", createPrimitive(pPairCFA)); hide();
- addPair(rootContext, "object>name", createPrimitive(pObjToPair)); hide();
- addPair(rootContext, "object>typename",createPrimitive(pObjToTypeName)); hide();
- addPair(rootContext, "object>store", createPrimitive(pObjToStore)); hide();
- addPair(rootContext, "object'store", createPrimitive(pObjectMFA)); hide();
- addPair(rootContext, "object'size", createPrimitive(pObjectSFA)); hide();
- addPair(rootContext, "object>context",createPrimitive(pObjToContext)); hide();
- addPair(rootContext, "context'thread",createPrimitive(pContextThread)); hide();
- addPair(rootContext, "context'first", createPrimitive(pContextFirst)); hide();
- addPair(rootContext, "context'latest",createPrimitive(pContextLatest)); hide();
- addPair(rootContext, "context'family",createPrimitive(pContextFamily)); hide();
- addPair(rootContext, "context'parents",createPrimitive(pContextParents)); hide();
- addPair(rootContext, "context'children",createPrimitive(pContextChildren)); hide();
- addPair(rootContext, "checkSystemValidity",createPrimitive(pCheckSystem));
-
-
- /* Object-oriented primitives */
- addPair(rootContext, "self", createPrimitive(pSelf));
- addPair(rootContext, "&", createPrimitive(pPrevSelf));
- addPair(rootContext, ">self", createPrimitive(pToSelf)); hide();
- addPair(rootContext, "self>", createPrimitive(pSelfFrom)); hide();
- addPair(rootContext, "self>drop", createPrimitive(pSelfDrop)); hide();
- addPair(rootContext, "resetCp", createPrimitive(resetContext)); hide();
- addPair(rootContext, "cdepth", createPrimitive(pCDepth));
- addPair(rootContext, ".cs", createPrimitive(pPrintCStack));
- addPair(rootContext, "resizeContextStack",createPrimitive(pResizeContext));
- addPair(rootContext, ">send", createPrimitive(pSend)); hide();
- addPair(rootContext, ">resend", createPrimitive(pResend)); hide();
- addPair(rootContext, "respondsTo",createPrimitive(pRespondsTo));
- addPair(rootContext, "hasContext", createPrimitive(pHasContext));
- addPair(rootContext, ">area", createPrimitive(pToArea));
- addPair(rootContext, "area0", createPrimitive(pAreaZero));
- addPair(rootContext, "area#", createPrimitive(pAreaSize));
-
- }
-
-
-