equi

A self-descriptive stack-based PC platform
git clone git://git.luxferre.top/equi.git
Log | Files | Refs | README | LICENSE

commit f99b95fcd2f2f870da3411e4de8cdd043a92fd30
parent aaf98b5dbb8651dac906bfb0271f1912f08d73f3
Author: Luxferre <lux@ferre>
Date:   Wed, 10 Aug 2022 16:49:46 +0300

Implemented variable-length literals and strings

Diffstat:
Mequi.c | 47++++++++++++++++++++---------------------------
1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/equi.c b/equi.c @@ -40,8 +40,6 @@ #define ushort unsigned short /* basic 16-bit integer */ #define uchar unsigned char /* basic 8-bit integer */ #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 CR 13u /* Character return code */ #define LF 10u /* Line feed code */ @@ -263,24 +261,14 @@ uchar a2d(uchar a) { return (a < 0x3aU) ? (a - 0x30U) : (a - 55U); } -/* shape 2-byte vlaue on the main stack from the 4 values of the literal stack */ -void pushLitVal(strict) { - uchar p1, p2, p3, p4; - if(ram.lsp < 4U) { /* if we don't strictly expect 4 bytes, do nothing */ - if(strict) trapout(STACK_UNDERFLOW); - else { - ram.lsp = 0; /* clear the literal stack */ - return; - } - } - 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 */ - } +/* shape 2-byte vlaue on the main stack from up to 4 values of the literal stack */ +void pushLitVal() { + uchar p[4U] = {0,0,0,0}, i, thr = 4U; + if(ram.lsp < 4U) thr = ram.lsp; + for(i=0;i<thr;++i) + p[3-i] = a2d(popLit()); + pushMain((p[0]<<12U) | (p[1]<<8U) | (p[2]<<4U) | p[3]); + ram.lsp = 0; /* clear the literal stack */ } /* CCITT CRC16 helper */ @@ -324,11 +312,11 @@ void equi_main_loop() { /* then, check for compilation mode */ if(ram.CM) { 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); ram.cmdbuf[ram.pc] = INS_RET; /* in-place patch this instruction to R */ /* 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.clt[ram.cltp].loc = ram.cbp; /* stored the compiled code location from the most recent CBP value */ ++ram.cltp; /* increase the word */ @@ -346,7 +334,7 @@ void equi_main_loop() { } /* then trigger literal auto-push if applicable */ 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 */ case INS_IISTART: /* instruction ignore start */ ram.II = 1; /* raise II flag */ @@ -363,7 +351,7 @@ void equi_main_loop() { case INS_QUIT: /* gracefully quit the interpretation mode */ goto brx; case INS_LITINT: /* literal stack -> main stack as short */ - pushLitVal(1U); + pushLitVal(); break; case INS_LITSTR: /* literal stack -> each char at main stack as short */ while(ram.lsp) @@ -371,9 +359,9 @@ void equi_main_loop() { ram.lsp = 0; break; case INS_LITCALL: /* call the saved word from the literal */ - if(ram.lsp < CLT_ENTRY_LEN) + if(ram.lsp < 1) 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) if(ram.clt[pbuf].nhash == lhash) { ram.pc = ram.clt[pbuf].loc; @@ -526,6 +514,8 @@ void equi_main_loop() { /* unset interpretation mode flag and exit */ ram.IM = 0; ram.pc = ram.ibp = 65535U; + /* clear all stacks and CLT */ + ram.msp = ram.rsp = ram.lsp = ram.cltp = 0; } /* Equi VM entry point */ @@ -572,10 +562,13 @@ int main(int argc, char* argv[]) { cputc(instr); /* echo it */ #endif 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 */ + ram.cmdbuf[ram.ibp] = 0; /* replace itself with 0 */ ram.IM = 1; /* set the mandatory interpretation mode flag */ equi_main_loop(); /* and run the interpreter loop */ + cputc(CR); /* echo it */ cputc(LF); /* echo it */ cputc('>'); cputc(' ');