mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 14:58:50 +00:00
lapce fix
This commit is contained in:
parent
b55a3c80b6
commit
5814b3f90a
1 changed files with 180 additions and 140 deletions
|
|
@ -1,154 +1,167 @@
|
||||||
/* Lama SM Bytecode interpreter */
|
/* Lama SM Bytecode interpreter */
|
||||||
|
|
||||||
# include <string.h>
|
#include <string.h>
|
||||||
# include <stdio.h>
|
#include <stdio.h>
|
||||||
# include <errno.h>
|
#include <errno.h>
|
||||||
# include <stdib.h>
|
#include <stdlib.h>
|
||||||
# include "../runtime/runtime.h"
|
#include "../runtime/runtime.h"
|
||||||
|
|
||||||
void *__start_custom_data;
|
void *__start_custom_data;
|
||||||
void *__stop_custom_data;
|
void *__stop_custom_data;
|
||||||
|
|
||||||
/* The unpacked representation of bytecode file */
|
/* The unpacked representation of bytecode file */
|
||||||
typedef struct {
|
typedef struct
|
||||||
char *string_ptr; /* A pointer to the beginning of the string table */
|
{
|
||||||
int *public_ptr; /* A pointer to the beginning of publics table */
|
char *string_ptr; /* A pointer to the beginning of the string table */
|
||||||
char *code_ptr; /* A pointer to the bytecode itself */
|
int *public_ptr; /* A pointer to the beginning of publics table */
|
||||||
int *global_ptr; /* A pointer to the global area */
|
char *code_ptr; /* A pointer to the bytecode itself */
|
||||||
int stringtab_size; /* The size (in bytes) of the string table */
|
int *global_ptr; /* A pointer to the global area */
|
||||||
int global_area_size; /* The size (in words) of global area */
|
int stringtab_size; /* The size (in bytes) of the string table */
|
||||||
int public_symbols_number; /* The number of public symbols */
|
int global_area_size; /* The size (in words) of global area */
|
||||||
char buffer[0];
|
int public_symbols_number; /* The number of public symbols */
|
||||||
|
char buffer[0];
|
||||||
} bytefile;
|
} bytefile;
|
||||||
|
|
||||||
/* Gets a string from a string table by an index */
|
/* Gets a string from a string table by an index */
|
||||||
char* get_string (bytefile *f, int pos) {
|
char *get_string(bytefile *f, int pos)
|
||||||
|
{
|
||||||
return &f->string_ptr[pos];
|
return &f->string_ptr[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets a name for a public symbol */
|
/* Gets a name for a public symbol */
|
||||||
char* get_public_name (bytefile *f, int i) {
|
char *get_public_name(bytefile *f, int i)
|
||||||
return get_string (f, f->public_ptr[i*2]);
|
{
|
||||||
|
return get_string(f, f->public_ptr[i * 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets an offset for a publie symbol */
|
/* Gets an offset for a publie symbol */
|
||||||
int get_public_offset (bytefile *f, int i) {
|
int get_public_offset(bytefile *f, int i)
|
||||||
return f->public_ptr[i*2+1];
|
{
|
||||||
|
return f->public_ptr[i * 2 + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads a binary bytecode file by name and unpacks it */
|
/* Reads a binary bytecode file by name and unpacks it */
|
||||||
bytefile* read_file (char *fname) {
|
bytefile *read_file(char *fname)
|
||||||
FILE *f = fopen (fname, "rb");
|
{
|
||||||
|
FILE *f = fopen(fname, "rb");
|
||||||
long size;
|
long size;
|
||||||
bytefile *file;
|
bytefile *file;
|
||||||
|
|
||||||
if (f == 0) {
|
if (f == 0)
|
||||||
failure ("%s\n", strerror (errno));
|
{
|
||||||
|
failure("%s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fseek (f, 0, SEEK_END) == -1) {
|
if (fseek(f, 0, SEEK_END) == -1)
|
||||||
failure ("%s\n", strerror (errno));
|
{
|
||||||
|
failure("%s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
file = (bytefile*) malloc (sizeof(int)*4 + (size = ftell (f)));
|
file = (bytefile *)malloc(sizeof(int) * 4 + (size = ftell(f)));
|
||||||
|
|
||||||
if (file == 0) {
|
if (file == 0)
|
||||||
failure ("*** FAILURE: unable to allocate memory.\n");
|
{
|
||||||
|
failure("*** FAILURE: unable to allocate memory.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
rewind (f);
|
rewind(f);
|
||||||
|
|
||||||
if (size != fread (&file->stringtab_size, 1, size, f)) {
|
if (size != fread(&file->stringtab_size, 1, size, f))
|
||||||
failure ("%s\n", strerror (errno));
|
{
|
||||||
|
failure("%s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose (f);
|
fclose(f);
|
||||||
|
|
||||||
file->string_ptr = &file->buffer [file->public_symbols_number * 2 * sizeof(int)];
|
file->string_ptr = &file->buffer[file->public_symbols_number * 2 * sizeof(int)];
|
||||||
file->public_ptr = (int*) file->buffer;
|
file->public_ptr = (int *)file->buffer;
|
||||||
file->code_ptr = &file->string_ptr [file->stringtab_size];
|
file->code_ptr = &file->string_ptr[file->stringtab_size];
|
||||||
file->global_ptr = (int*) malloc (file->global_area_size * sizeof (int));
|
file->global_ptr = (int *)malloc(file->global_area_size * sizeof(int));
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disassembles the bytecode pool */
|
/* Disassembles the bytecode pool */
|
||||||
void disassemble (FILE *f, bytefile *bf) {
|
void disassemble(FILE *f, bytefile *bf)
|
||||||
|
{
|
||||||
|
|
||||||
# define INT (ip += sizeof (int), *(int*)(ip - sizeof (int)))
|
#define INT (ip += sizeof(int), *(int *)(ip - sizeof(int)))
|
||||||
# define BYTE *ip++
|
#define BYTE *ip++
|
||||||
# define STRING get_string (bf, INT)
|
#define STRING get_string(bf, INT)
|
||||||
# define FAIL failure ("ERROR: invalid opcode %d-%d\n", h, l)
|
#define FAIL failure("ERROR: invalid opcode %d-%d\n", h, l)
|
||||||
|
|
||||||
char *ip = bf->code_ptr;
|
char *ip = bf->code_ptr;
|
||||||
char *ops [] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
char *ops[] = {"+", "-", "*", "/", "%", "<", "<=", ">", ">=", "==", "!=", "&&", "!!"};
|
||||||
char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
char *pats[] = {"=str", "#string", "#array", "#sexp", "#ref", "#val", "#fun"};
|
||||||
char *lds [] = {"LD", "LDA", "ST"};
|
char *lds[] = {"LD", "LDA", "ST"};
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
char x = BYTE,
|
char x = BYTE,
|
||||||
h = (x & 0xF0) >> 4,
|
h = (x & 0xF0) >> 4,
|
||||||
l = x & 0x0F;
|
l = x & 0x0F;
|
||||||
|
|
||||||
fprintf (f, "0x%.8x:\t", ip-bf->code_ptr-1);
|
fprintf(f, "0x%.8x:\t", ip - bf->code_ptr - 1);
|
||||||
|
|
||||||
switch (h) {
|
switch (h)
|
||||||
|
{
|
||||||
case 15:
|
case 15:
|
||||||
goto stop;
|
goto stop;
|
||||||
|
|
||||||
/* BINOP */
|
/* BINOP */
|
||||||
case 0:
|
case 0:
|
||||||
fprintf (f, "BINOP\t%s", ops[l-1]);
|
fprintf(f, "BINOP\t%s", ops[l - 1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
switch (l) {
|
switch (l)
|
||||||
case 0:
|
{
|
||||||
fprintf (f, "CONST\t%d", INT);
|
case 0:
|
||||||
|
fprintf(f, "CONST\t%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
fprintf (f, "STRING\t%s", STRING);
|
fprintf(f, "STRING\t%s", STRING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
fprintf (f, "SEXP\t%s ", STRING);
|
fprintf(f, "SEXP\t%s ", STRING);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
fprintf (f, "STI");
|
fprintf(f, "STI");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
fprintf (f, "STA");
|
fprintf(f, "STA");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
fprintf (f, "JMP\t0x%.8x", INT);
|
fprintf(f, "JMP\t0x%.8x", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
fprintf (f, "END");
|
fprintf(f, "END");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
fprintf (f, "RET");
|
fprintf(f, "RET");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
fprintf (f, "DROP");
|
fprintf(f, "DROP");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
fprintf (f, "DUP");
|
fprintf(f, "DUP");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
fprintf (f, "SWAP");
|
fprintf(f, "SWAP");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 11:
|
case 11:
|
||||||
fprintf (f, "ELEM");
|
fprintf(f, "ELEM");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -159,76 +172,99 @@ void disassemble (FILE *f, bytefile *bf) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
fprintf (f, "%s\t", lds[h-2]);
|
fprintf(f, "%s\t", lds[h - 2]);
|
||||||
switch (l) {
|
switch (l)
|
||||||
case 0: fprintf (f, "G(%d)", INT); break;
|
{
|
||||||
case 1: fprintf (f, "L(%d)", INT); break;
|
case 0:
|
||||||
case 2: fprintf (f, "A(%d)", INT); break;
|
fprintf(f, "G(%d)", INT);
|
||||||
case 3: fprintf (f, "C(%d)", INT); break;
|
break;
|
||||||
default: FAIL;
|
case 1:
|
||||||
|
fprintf(f, "L(%d)", INT);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(f, "A(%d)", INT);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
fprintf(f, "C(%d)", INT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FAIL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
switch (l) {
|
switch (l)
|
||||||
case 0:
|
{
|
||||||
fprintf (f, "CJMPz\t0x%.8x", INT);
|
case 0:
|
||||||
|
fprintf(f, "CJMPz\t0x%.8x", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
fprintf (f, "CJMPnz\t0x%.8x", INT);
|
fprintf(f, "CJMPnz\t0x%.8x", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
fprintf (f, "BEGIN\t%d ", INT);
|
fprintf(f, "BEGIN\t%d ", INT);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
fprintf (f, "CBEGIN\t%d ", INT);
|
fprintf(f, "CBEGIN\t%d ", INT);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
fprintf (f, "CLOSURE\t0x%.8x", INT);
|
fprintf(f, "CLOSURE\t0x%.8x", INT);
|
||||||
{int n = INT;
|
{
|
||||||
for (int i = 0; i<n; i++) {
|
int n = INT;
|
||||||
switch (BYTE) {
|
for (int i = 0; i < n; i++)
|
||||||
case 0: fprintf (f, "G(%d)", INT); break;
|
{
|
||||||
case 1: fprintf (f, "L(%d)", INT); break;
|
switch (BYTE)
|
||||||
case 2: fprintf (f, "A(%d)", INT); break;
|
{
|
||||||
case 3: fprintf (f, "C(%d)", INT); break;
|
case 0:
|
||||||
default: FAIL;
|
fprintf(f, "G(%d)", INT);
|
||||||
}
|
break;
|
||||||
}
|
case 1:
|
||||||
|
fprintf(f, "L(%d)", INT);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fprintf(f, "A(%d)", INT);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
fprintf(f, "C(%d)", INT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
fprintf (f, "CALLC\t%d", INT);
|
fprintf(f, "CALLC\t%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
fprintf (f, "CALL\t0x%.8x ", INT);
|
fprintf(f, "CALL\t0x%.8x ", INT);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
fprintf (f, "TAG\t%s ", STRING);
|
fprintf(f, "TAG\t%s ", STRING);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
fprintf (f, "ARRAY\t%d", INT);
|
fprintf(f, "ARRAY\t%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
fprintf (f, "FAIL\t%d", INT);
|
fprintf(f, "FAIL\t%d", INT);
|
||||||
fprintf (f, "%d", INT);
|
fprintf(f, "%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
fprintf (f, "LINE\t%d", INT);
|
fprintf(f, "LINE\t%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -237,29 +273,31 @@ void disassemble (FILE *f, bytefile *bf) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
fprintf (f, "PATT\t%s", pats[l]);
|
fprintf(f, "PATT\t%s", pats[l]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: {
|
case 7:
|
||||||
switch (l) {
|
{
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
fprintf (f, "CALL\tLread");
|
fprintf(f, "CALL\tLread");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
fprintf (f, "CALL\tLwrite");
|
fprintf(f, "CALL\tLwrite");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
fprintf (f, "CALL\tLlength");
|
fprintf(f, "CALL\tLlength");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
fprintf (f, "CALL\tLstring");
|
fprintf(f, "CALL\tLstring");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
fprintf (f, "CALL\tBarray\t%d", INT);
|
fprintf(f, "CALL\tBarray\t%d", INT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -272,30 +310,32 @@ void disassemble (FILE *f, bytefile *bf) {
|
||||||
FAIL;
|
FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf (f, "\n");
|
fprintf(f, "\n");
|
||||||
}
|
} while (1);
|
||||||
while (1);
|
stop:
|
||||||
stop: fprintf (f, "<end>\n");
|
fprintf(f, "<end>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dumps the contents of the file */
|
/* Dumps the contents of the file */
|
||||||
void dump_file (FILE *f, bytefile *bf) {
|
void dump_file(FILE *f, bytefile *bf)
|
||||||
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf (f, "String table size : %d\n", bf->stringtab_size);
|
fprintf(f, "String table size : %d\n", bf->stringtab_size);
|
||||||
fprintf (f, "Global area size : %d\n", bf->global_area_size);
|
fprintf(f, "Global area size : %d\n", bf->global_area_size);
|
||||||
fprintf (f, "Number of public symbols: %d\n", bf->public_symbols_number);
|
fprintf(f, "Number of public symbols: %d\n", bf->public_symbols_number);
|
||||||
fprintf (f, "Public symbols :\n");
|
fprintf(f, "Public symbols :\n");
|
||||||
|
|
||||||
for (i=0; i < bf->public_symbols_number; i++)
|
for (i = 0; i < bf->public_symbols_number; i++)
|
||||||
fprintf (f, " 0x%.8x: %s\n", get_public_offset (bf, i), get_public_name (bf, i));
|
fprintf(f, " 0x%.8x: %s\n", get_public_offset(bf, i), get_public_name(bf, i));
|
||||||
|
|
||||||
fprintf (f, "Code:\n");
|
fprintf(f, "Code:\n");
|
||||||
disassemble (f, bf);
|
disassemble(f, bf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char* argv[]) {
|
int main(int argc, char *argv[])
|
||||||
bytefile *f = read_file (argv[1]);
|
{
|
||||||
dump_file (stdout, f);
|
bytefile *f = read_file(argv[1]);
|
||||||
|
dump_file(stdout, f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue