📄 interpret.c
字号:
static void restoreContext(RestartData *context){ Stack = context->stack; StackP = context->stackP; FrameP = context->frameP; PC = context->pc; InitiatingWindow = context->runWindow; FocusWindow = context->focusWindow;}static void freeSymbolTable(Symbol *symTab){ Symbol *s; while(symTab != NULL) { s = symTab; free(s->name); symTab = s->next; free((char *)s); } }#define POP(dataVal) \ if (StackP == Stack) \ return execError(StackUnderflowMsg, ""); \ dataVal = *--StackP; #define PUSH(dataVal) \ if (StackP >= &Stack[STACK_SIZE]) \ return execError(StackOverflowMsg, ""); \ *StackP++ = dataVal;#define PEEK(dataVal, peekIndex) \ dataVal = *(StackP - peekIndex - 1);#define POP_INT(number) \ if (StackP == Stack) \ return execError(StackUnderflowMsg, ""); \ --StackP; \ if (StackP->tag == STRING_TAG) { \ if (!StringToNum(StackP->val.str, &number)) \ return execError(StringToNumberMsg, ""); \ } else if (StackP->tag == INT_TAG) \ number = StackP->val.n; \ else \ return(execError("can't convert array to integer", NULL));#define POP_STRING(string) \ if (StackP == Stack) \ return execError(StackUnderflowMsg, ""); \ --StackP; \ if (StackP->tag == INT_TAG) { \ string = AllocString(TYPE_INT_STR_SIZE(int)); \ sprintf(string, "%d", StackP->val.n); \ } else if (StackP->tag == STRING_TAG) \ string = StackP->val.str; \ else \ return(execError("can't convert array to string", NULL)); #define PEEK_STRING(string, peekIndex) \ if ((StackP - peekIndex - 1)->tag == INT_TAG) { \ string = AllocString(TYPE_INT_STR_SIZE(int)); \ sprintf(string, "%d", (StackP - peekIndex - 1)->val.n); \ } \ else if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \ string = (StackP - peekIndex - 1)->val.str; \ } \ else { \ return(execError("can't convert array to string", NULL)); \ }#define PEEK_INT(number, peekIndex) \ if ((StackP - peekIndex - 1)->tag == STRING_TAG) { \ if (!StringToNum((StackP - peekIndex - 1)->val.str, &number)) { \ return execError(StringToNumberMsg, ""); \ } \ } else if ((StackP - peekIndex - 1)->tag == INT_TAG) { \ number = (StackP - peekIndex - 1)->val.n; \ } \ else { \ return(execError("can't convert array to string", NULL)); \ }#define PUSH_INT(number) \ if (StackP >= &Stack[STACK_SIZE]) \ return execError(StackOverflowMsg, ""); \ StackP->tag = INT_TAG; \ StackP->val.n = number; \ StackP++; #define PUSH_STRING(string) \ if (StackP >= &Stack[STACK_SIZE]) \ return execError(StackOverflowMsg, ""); \ StackP->tag = STRING_TAG; \ StackP->val.str = string; \ StackP++;#define BINARY_NUMERIC_OPERATION(operator) \ int n1, n2; \ DISASM_RT(PC-1, 1); \ STACKDUMP(2, 3); \ POP_INT(n2) \ POP_INT(n1) \ PUSH_INT(n1 operator n2) \ return STAT_OK;#define UNARY_NUMERIC_OPERATION(operator) \ int n; \ DISASM_RT(PC-1, 1); \ STACKDUMP(1, 3); \ POP_INT(n) \ PUSH_INT(operator n) \ return STAT_OK;/*** copy a symbol's value onto the stack** Before: Prog-> [Sym], next, ...** Stack-> next, ...** After: Prog-> Sym, [next], ...** Stack-> [SymValue], next, ...*/static int pushSymVal(void){ Symbol *s; int nArgs, argNum; DISASM_RT(PC-1, 2); STACKDUMP(0, 3); s = (Symbol *)*PC++; if (s->type == LOCAL_SYM) { *StackP = *(FrameP + s->value.val.n); } else if (s->type == GLOBAL_SYM || s->type == CONST_SYM) { *StackP = s->value; } else if (s->type == ARG_SYM) { nArgs = (FrameP-1)->val.n; argNum = s->value.val.n; if (argNum >= nArgs) return execError("referenced undefined argument: %s", s->name); if (argNum == N_ARGS_ARG_SYM) { StackP->tag = INT_TAG; StackP->val.n = nArgs; } else *StackP = *(FrameP + argNum - nArgs - 3); } else if (s->type == PROC_VALUE_SYM) { DataValue result; char *errMsg; if (!(s->value.val.subr)(FocusWindow, NULL, 0, &result, &errMsg)) return execError(errMsg, s->name); *StackP = result; } else return execError("reading non-variable: %s", s->name); if (StackP->tag == NO_TAG) return execError("variable not set: %s", s->name); StackP++; if (StackP >= &Stack[STACK_SIZE]) return execError(StackOverflowMsg, ""); return STAT_OK;}/*** Push an array (by reference) onto the stack** Before: Prog-> [ArraySym], makeEmpty, next, ...** Stack-> next, ...** After: Prog-> ArraySym, makeEmpty, [next], ...** Stack-> [elemValue], next, ...** makeEmpty is either true (1) or false (0): if true, and the element is not** present in the array, create it.*/static int pushArraySymVal(void){ Symbol *sym; DataValue *dataPtr; int initEmpty; DISASM_RT(PC-1, 3); STACKDUMP(0, 3); sym = (Symbol *)*PC; PC++; initEmpty = (int)*PC; PC++; if (sym->type == LOCAL_SYM) { dataPtr = FrameP + sym->value.val.n; } else if (sym->type == GLOBAL_SYM) { dataPtr = &sym->value; } else { return execError("assigning to non-lvalue array or non-array: %s", sym->name); } if (initEmpty && dataPtr->tag == NO_TAG) { dataPtr->tag = ARRAY_TAG; dataPtr->val.arrayPtr = ArrayNew(); } if (dataPtr->tag == NO_TAG) { return execError("variable not set: %s", sym->name); } *StackP = *dataPtr; StackP++; if (StackP >= &Stack[STACK_SIZE]) { return execError(StackOverflowMsg, ""); } return(STAT_OK);}/*** assign top value to next symbol**** Before: Prog-> [symbol], next, ...** Stack-> [value], next, ...** After: Prog-> symbol, [next], ...** Stack-> next, ...*/static int assign(void){ Symbol *sym; DataValue *dataPtr; DISASM_RT(PC-1, 2); STACKDUMP(1, 3); sym = (Symbol *)(*PC++); if (sym->type != GLOBAL_SYM && sym->type != LOCAL_SYM) { if (sym->type == ARG_SYM) return execError("assignment to function argument: %s", sym->name); else if (sym->type == PROC_VALUE_SYM) return execError("assignment to read-only variable: %s", sym->name); else return execError("assignment to non-variable: %s", sym->name); } if (StackP == Stack) return execError(StackUnderflowMsg, ""); --StackP; if (sym->type == LOCAL_SYM) dataPtr = (FrameP + sym->value.val.n); else dataPtr = &sym->value; if (StackP->tag == ARRAY_TAG) { ArrayCopy(dataPtr, StackP); } else { *dataPtr = *StackP; } return STAT_OK;}/*** copy the top value of the stack** Before: Stack-> value, next, ...** After: Stack-> value, value, next, ...*/static int dupStack(void){ DISASM_RT(PC-1, 1); STACKDUMP(1, 3); if (StackP >= &Stack[STACK_SIZE]) return execError(StackOverflowMsg, ""); *StackP = *(StackP - 1); StackP++; return STAT_OK;}/*** if left and right arguments are arrays, then the result is a new array** in which all the keys from both the right and left are copied** the values from the right array are used in the result array when the** keys are the same** Before: Stack-> value2, value1, next, ...** After: Stack-> resValue, next, ...*/static int add(void){ DataValue leftVal, rightVal, resultArray; int n1, n2; DISASM_RT(PC-1, 1); STACKDUMP(2, 3); PEEK(rightVal, 0) if (rightVal.tag == ARRAY_TAG) { PEEK(leftVal, 1) if (leftVal.tag == ARRAY_TAG) { SparseArrayEntry *leftIter, *rightIter; resultArray.tag = ARRAY_TAG; resultArray.val.arrayPtr = ArrayNew(); POP(rightVal) POP(leftVal) leftIter = arrayIterateFirst(&leftVal); rightIter = arrayIterateFirst(&rightVal); while (leftIter || rightIter) { int insertResult = 1; if (leftIter && rightIter) { int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter); if (compareResult < 0) { insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value); leftIter = arrayIterateNext(leftIter); } else if (compareResult > 0) { insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value); rightIter = arrayIterateNext(rightIter); } else { insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value); leftIter = arrayIterateNext(leftIter); rightIter = arrayIterateNext(rightIter); } } else if (leftIter) { insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value); leftIter = arrayIterateNext(leftIter); } else { insertResult = ArrayInsert(&resultArray, rightIter->key, &rightIter->value); rightIter = arrayIterateNext(rightIter); } if (!insertResult) { return(execError("array insertion failure", NULL)); } } PUSH(resultArray) } else { return(execError("can't mix math with arrays and non-arrays", NULL)); } } else { POP_INT(n2) POP_INT(n1) PUSH_INT(n1 + n2) } return(STAT_OK);}/*** if left and right arguments are arrays, then the result is a new array** in which only the keys which exist in the left array but not in the right** are copied** Before: Stack-> value2, value1, next, ...** After: Stack-> resValue, next, ...*/static int subtract(void){ DataValue leftVal, rightVal, resultArray; int n1, n2; DISASM_RT(PC-1, 1); STACKDUMP(2, 3); PEEK(rightVal, 0) if (rightVal.tag == ARRAY_TAG) { PEEK(leftVal, 1) if (leftVal.tag == ARRAY_TAG) { SparseArrayEntry *leftIter, *rightIter; resultArray.tag = ARRAY_TAG; resultArray.val.arrayPtr = ArrayNew(); POP(rightVal) POP(leftVal) leftIter = arrayIterateFirst(&leftVal); rightIter = arrayIterateFirst(&rightVal); while (leftIter) { int insertResult = 1; if (leftIter && rightIter) { int compareResult = arrayEntryCompare((rbTreeNode *)leftIter, (rbTreeNode *)rightIter); if (compareResult < 0) { insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value); leftIter = arrayIterateNext(leftIter); } else if (compareResult > 0) { rightIter = arrayIterateNext(rightIter); } else { leftIter = arrayIterateNext(leftIter); rightIter = arrayIterateNext(rightIter); } } else if (leftIter) { insertResult = ArrayInsert(&resultArray, leftIter->key, &leftIter->value); leftIter = arrayIterateNext(leftIter); } if (!insertResult) { return(execError("array insertion failure", NULL)); } } PUSH(resultArray) } else { return(execError("can't mix math with arrays and non-arrays", NULL)); } } else { POP_INT(n2) POP_INT(n1) PUSH_INT(n1 - n2) } return(STAT_OK);}/*** Other binary operators** Before: Stack-> value2, value1, next, ...** After: Stack-> resValue, next, ...**** Other unary operators** Before: Stack-> value, next, ...** After: Stack-> resValue, next, ...*/static int multiply(void){ BINARY_NUMERIC_OPERATION(*)}static int divide(void){ int n1, n2; DISASM_RT(PC-1, 1); STACKDUMP(2, 3); POP_INT(n2) POP_INT(n1) if (n2 == 0) { return execError("division by zero", ""); } PUSH_INT(n1 / n2) return STAT_OK;}static int modulo(void){ int n1, n2; DISASM_RT(PC-1, 1); STACKDUMP(2, 3); POP_INT(n2) POP_INT(n1) if (n2 == 0) { return execError("modulo by zero", ""); } PUSH_INT(n1 % n2) return STAT_OK;}static int negate(void){ UNARY_NUMERIC_OPERATION(-)}static int increment(void){ UNARY_NUMERIC_OPERATION(++)}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -