iffiIP->needMove = true;
}
+// A - CREATE a new INTERCAL instruction
+static void FingerIFFIcreate(instructionPointer * ip)
+{
+ // arguments: line number on TOS, signature as 0gnirts beneath it
+ FUNGEDATATYPE l = StackPop(ip->stack);
+ char * restrict str = StackPopString(ip->stack);
+ ick_create(str, l);
+}
+
// C - In markmode COME FROM the top of stack
static void FingerIFFIcomeFrom(instructionPointer * ip)
{
}
}
+// D - Push information about a CREATED instruction argument
+static void FingerIFFIcreateData(instructionPointer * ip)
+{
+ // Arguments: argument's index (0-based) on TOS
+ // Return: the following values (from bottom to top):
+ // The argument's data type, in bits
+ // Whether the argument is an array variable
+ // 0 if the argument is not a variable, or its number if it is
+ // The argument's value at the time the CREATED instruction was called
+ // The argument's value now (same as previous if -a was not used)
+ FUNGEDATATYPE i;
+
+ i = StackPop(ip->stack);
+
+ StackPush(ip->stack, ick_c_i_width(i));
+ StackPush(ip->stack, ick_c_i_isarray(i));
+ StackPush(ip->stack, ick_c_i_varnumber(i));
+ StackPush(ip->stack, ick_c_i_value(i));
+ StackPush(ip->stack, ick_c_i_getvalue(i));
+}
+
// F - FORGET NEXT stack entries equal to top of stack
static void FingerIFFIforget(instructionPointer * ip)
{
ick_iffi_forgetcount = f;
}
+// G - Get the value of an INTERCAL scalar variable
+static void FingerIFFIvarGet(instructionPointer * ip)
+{
+ // arguments: var number on TOS
+ // var numbers are positive for onespot, negative for twospot
+ // return: the value of the variable
+
+ FUNGEDATATYPE v;
+
+ v = StackPop(ip->stack);
+
+ if (v == 0) {
+ ipReverse(ip);
+ } else if (v > 0) {
+ StackPush(ip->stack, ick_getonespot(v));
+ } else {
+ StackPush(ip->stack, ick_gettwospot(-v));
+ }
+}
+
// L - Use top of stack as a line label for this point
static void FingerIFFIlabel(instructionPointer * ip)
{
ick_iffi_breakloop = 1;
}
+// S - Set the value of an INTERCAL scalar variable
+static void FingerIFFIvarSet(instructionPointer * ip)
+{
+ // arguments: var number on TOS, new value beneath it
+ // var numbers are positive for onespot, negative for twospot
+ // return: the value of the variable
+
+ FUNGEDATATYPE v, d;
+
+ v = StackPop(ip->stack);
+ d = StackPop(ip->stack);
+
+ if (v == 0) {
+ ipReverse(ip);
+ } else if (v > 0) {
+ ick_setonespot(v, d);
+ } else {
+ ick_settwospot(-v, d);
+ }
+}
+
+// V - Assign to a CREATEd instruction argument
+static void FingerIFFIargSet(instructionPointer * ip)
+{
+ // arguments: 0-based argument index on TOS, new value beneath it
+ // note that this is a NOP unless -a was used when compiling
+ FUNGEDATATYPE i, d;
+
+ i = StackPop(ip->stack);
+ d = StackPop(ip->stack);
+
+ ick_c_i_setvalue(i, d);
+}
+
// X - In markmode NEXT FROM the top of stack
static void FingerIFFInextFrom(instructionPointer * ip)
{
}
}
-bool FingerIFFIload(instructionPointer * ip)
+// Y - Marks the end of initialisation
+static void FingerIFFIyield(instructionPointer * ip)
{
- static int firstload = 1;
+ static bool firstload = true;
ick_iffi_breakloop = firstload;
- firstload = 0;
+ if (! firstload)
+ ipReverse(ip);
+ firstload = false;
+}
+
+bool FingerIFFIload(instructionPointer * ip)
+{
+ ManagerAddOpcode(IFFI, 'A', create)
ManagerAddOpcode(IFFI, 'C', comeFrom)
+ ManagerAddOpcode(IFFI, 'D', createData)
ManagerAddOpcode(IFFI, 'F', forget)
+ ManagerAddOpcode(IFFI, 'G', varGet)
ManagerAddOpcode(IFFI, 'L', label)
ManagerAddOpcode(IFFI, 'M', marker)
ManagerAddOpcode(IFFI, 'N', next)
ManagerAddOpcode(IFFI, 'R', resume)
+ ManagerAddOpcode(IFFI, 'S', varSet)
+ ManagerAddOpcode(IFFI, 'V', argSet)
ManagerAddOpcode(IFFI, 'X', nextFrom)
+ ManagerAddOpcode(IFFI, 'Y', yield)
return true;
}
long long ix, iy, dx, dy;
};
+// Externally-visible functions from IFFI.c
bool FingerIFFIload(instructionPointer * ip);
-
void ick_InterpreterMainLoop(void);
+// Communication variables with ecto_b98
extern unsigned short ick_iffi_forgetcount;
extern int ick_iffi_nexting;
extern int ick_iffi_comingfrom;
extern int ick_iffi_breakloop;
extern int ick_iffi_inmarkmode;
+// Communication variables with the compiled .cio file
extern const char * ick_iffi_befungeString;
+
+// Communication variables with the runtime library
extern int ick_printflow;
+// Accessors and mutators for INTERCAL storage
+extern void ick_create(char*, unsigned long);
+extern uint16_t ick_getonespot(unsigned short);
+extern void ick_setonespot(unsigned short, uint16_t);
+extern uint32_t ick_gettwospot(unsigned short);
+extern void ick_settwospot(unsigned short, uint32_t);
+extern int ick_c_i_width(int);
+extern int ick_c_i_isarray(int);
+extern unsigned short ick_c_i_varnumber(int);
+extern uint32_t ick_c_i_value(int);
+extern uint32_t ick_c_i_getvalue(int);
+extern void ick_c_i_setvalue(int, uint32_t);
+
#endif