Implemented variable-length literals and strings
This commit is contained in:
@@ -40,8 +40,6 @@
|
|||||||
#define ushort unsigned short /* basic 16-bit integer */
|
#define ushort unsigned short /* basic 16-bit integer */
|
||||||
#define uchar unsigned char /* basic 8-bit integer */
|
#define uchar unsigned char /* basic 8-bit integer */
|
||||||
#define WS sizeof(ushort) /* Equi word size in bytes */
|
#define WS sizeof(ushort) /* Equi word size in bytes */
|
||||||
#define CLT_ENTRY_LEN 6u /* Amount of significant compiled word characters */
|
|
||||||
#define CLT_ENTRY_SIZE (CLT_ENTRY_LEN + WS) /* Full size in bytes taken by one CLT entry */
|
|
||||||
#define BS 8u /* Backspace character code */
|
#define BS 8u /* Backspace character code */
|
||||||
#define CR 13u /* Character return code */
|
#define CR 13u /* Character return code */
|
||||||
#define LF 10u /* Line feed code */
|
#define LF 10u /* Line feed code */
|
||||||
@@ -263,24 +261,14 @@ uchar a2d(uchar a) {
|
|||||||
return (a < 0x3aU) ? (a - 0x30U) : (a - 55U);
|
return (a < 0x3aU) ? (a - 0x30U) : (a - 55U);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shape 2-byte vlaue on the main stack from the 4 values of the literal stack */
|
/* shape 2-byte vlaue on the main stack from up to 4 values of the literal stack */
|
||||||
void pushLitVal(strict) {
|
void pushLitVal() {
|
||||||
uchar p1, p2, p3, p4;
|
uchar p[4U] = {0,0,0,0}, i, thr = 4U;
|
||||||
if(ram.lsp < 4U) { /* if we don't strictly expect 4 bytes, do nothing */
|
if(ram.lsp < 4U) thr = ram.lsp;
|
||||||
if(strict) trapout(STACK_UNDERFLOW);
|
for(i=0;i<thr;++i)
|
||||||
else {
|
p[3-i] = a2d(popLit());
|
||||||
ram.lsp = 0; /* clear the literal stack */
|
pushMain((p[0]<<12U) | (p[1]<<8U) | (p[2]<<4U) | p[3]);
|
||||||
return;
|
ram.lsp = 0; /* clear the literal stack */
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p4 = a2d(popLit());
|
|
||||||
p3 = a2d(popLit());
|
|
||||||
p2 = a2d(popLit());
|
|
||||||
p1 = a2d(popLit());
|
|
||||||
pushMain((p1<<12U) | (p2<<8U) | (p3<<4U) | p4);
|
|
||||||
ram.lsp = 0; /* clear the literal stack */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CCITT CRC16 helper */
|
/* CCITT CRC16 helper */
|
||||||
@@ -324,11 +312,11 @@ void equi_main_loop() {
|
|||||||
/* then, check for compilation mode */
|
/* then, check for compilation mode */
|
||||||
if(ram.CM) {
|
if(ram.CM) {
|
||||||
if(instr == INS_CMEND) { /* trigger word compilation logic as per the spec */
|
if(instr == INS_CMEND) { /* trigger word compilation logic as per the spec */
|
||||||
if(ram.lsp < CLT_ENTRY_LEN)
|
if(ram.lsp < 1)
|
||||||
trapout(STACK_UNDERFLOW);
|
trapout(STACK_UNDERFLOW);
|
||||||
ram.cmdbuf[ram.pc] = INS_RET; /* in-place patch this instruction to R */
|
ram.cmdbuf[ram.pc] = INS_RET; /* in-place patch this instruction to R */
|
||||||
/* hash and save compiled word */
|
/* hash and save compiled word */
|
||||||
ram.clt[ram.cltp].nhash = crc16(&ram.literal_stack[ram.lsp-CLT_ENTRY_LEN], CLT_ENTRY_LEN);
|
ram.clt[ram.cltp].nhash = crc16(&ram.literal_stack[0], ram.lsp);
|
||||||
ram.lsp = 0; /* clear the literal stack */
|
ram.lsp = 0; /* clear the literal stack */
|
||||||
ram.clt[ram.cltp].loc = ram.cbp; /* stored the compiled code location from the most recent CBP value */
|
ram.clt[ram.cltp].loc = ram.cbp; /* stored the compiled code location from the most recent CBP value */
|
||||||
++ram.cltp; /* increase the word */
|
++ram.cltp; /* increase the word */
|
||||||
@@ -346,7 +334,7 @@ void equi_main_loop() {
|
|||||||
}
|
}
|
||||||
/* then trigger literal auto-push if applicable */
|
/* then trigger literal auto-push if applicable */
|
||||||
if(ram.lsp > 0 && instr != INS_LITSTR && instr != INS_LITCALL && instr != INS_LITINT && instr != INS_CMSTART)
|
if(ram.lsp > 0 && instr != INS_LITSTR && instr != INS_LITCALL && instr != INS_LITINT && instr != INS_CMSTART)
|
||||||
pushLitVal(0);
|
pushLitVal();
|
||||||
switch(instr) { /* then perform all main interpretation logic */
|
switch(instr) { /* then perform all main interpretation logic */
|
||||||
case INS_IISTART: /* instruction ignore start */
|
case INS_IISTART: /* instruction ignore start */
|
||||||
ram.II = 1; /* raise II flag */
|
ram.II = 1; /* raise II flag */
|
||||||
@@ -363,7 +351,7 @@ void equi_main_loop() {
|
|||||||
case INS_QUIT: /* gracefully quit the interpretation mode */
|
case INS_QUIT: /* gracefully quit the interpretation mode */
|
||||||
goto brx;
|
goto brx;
|
||||||
case INS_LITINT: /* literal stack -> main stack as short */
|
case INS_LITINT: /* literal stack -> main stack as short */
|
||||||
pushLitVal(1U);
|
pushLitVal();
|
||||||
break;
|
break;
|
||||||
case INS_LITSTR: /* literal stack -> each char at main stack as short */
|
case INS_LITSTR: /* literal stack -> each char at main stack as short */
|
||||||
while(ram.lsp)
|
while(ram.lsp)
|
||||||
@@ -371,9 +359,9 @@ void equi_main_loop() {
|
|||||||
ram.lsp = 0;
|
ram.lsp = 0;
|
||||||
break;
|
break;
|
||||||
case INS_LITCALL: /* call the saved word from the literal */
|
case INS_LITCALL: /* call the saved word from the literal */
|
||||||
if(ram.lsp < CLT_ENTRY_LEN)
|
if(ram.lsp < 1)
|
||||||
trapout(STACK_UNDERFLOW);
|
trapout(STACK_UNDERFLOW);
|
||||||
lhash = crc16(&ram.literal_stack[ram.lsp-CLT_ENTRY_LEN], CLT_ENTRY_LEN);
|
lhash = crc16(&ram.literal_stack[0], ram.lsp);
|
||||||
for(pbuf=0;pbuf<CLT_ENTRIES_MAX;++pbuf)
|
for(pbuf=0;pbuf<CLT_ENTRIES_MAX;++pbuf)
|
||||||
if(ram.clt[pbuf].nhash == lhash) {
|
if(ram.clt[pbuf].nhash == lhash) {
|
||||||
ram.pc = ram.clt[pbuf].loc;
|
ram.pc = ram.clt[pbuf].loc;
|
||||||
@@ -526,6 +514,8 @@ void equi_main_loop() {
|
|||||||
/* unset interpretation mode flag and exit */
|
/* unset interpretation mode flag and exit */
|
||||||
ram.IM = 0;
|
ram.IM = 0;
|
||||||
ram.pc = ram.ibp = 65535U;
|
ram.pc = ram.ibp = 65535U;
|
||||||
|
/* clear all stacks and CLT */
|
||||||
|
ram.msp = ram.rsp = ram.lsp = ram.cltp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Equi VM entry point */
|
/* Equi VM entry point */
|
||||||
@@ -572,10 +562,13 @@ int main(int argc, char* argv[]) {
|
|||||||
cputc(instr); /* echo it */
|
cputc(instr); /* echo it */
|
||||||
#endif
|
#endif
|
||||||
ram.II = 0;
|
ram.II = 0;
|
||||||
} else if(instr == LF) { /* process carriage return */
|
} else if(instr == CR || instr == LF) { /* process carriage return or linefeed */
|
||||||
|
cputc(CR); /* echo it */
|
||||||
cputc(LF); /* echo it */
|
cputc(LF); /* echo it */
|
||||||
|
ram.cmdbuf[ram.ibp] = 0; /* replace itself with 0 */
|
||||||
ram.IM = 1; /* set the mandatory interpretation mode flag */
|
ram.IM = 1; /* set the mandatory interpretation mode flag */
|
||||||
equi_main_loop(); /* and run the interpreter loop */
|
equi_main_loop(); /* and run the interpreter loop */
|
||||||
|
cputc(CR); /* echo it */
|
||||||
cputc(LF); /* echo it */
|
cputc(LF); /* echo it */
|
||||||
cputc('>');
|
cputc('>');
|
||||||
cputc(' ');
|
cputc(' ');
|
||||||
|
|||||||
Reference in New Issue
Block a user