I want to code a basic interpreter / scripting language.
Like basically each line of the script is an opcode on 32 bits and the interpret will read by default one opcode after the other (so one line after the other), except if there's a jump or something like that.
I also want to be able to store values (like int), on any given line, and read it later...
In this possible? isn't there a really simple language that is exactly like that that I could look up? What I'm unsure how to do is how to store commands on 32 bits and values on 32 bits in the same adress space
Yes, here is tons of resources about compiler design. SICP includes a whole chapter about it iirc. A basic google search give a tutorial and an online textbook.
OP here
for instance my program input before converted to opcodes would be:
line 1 - STORE 349 (ie store a value here)
line 2 - INCR 1 (increment adress 1 by 1)
line 3 - PRINT 1 (print what is at adress 1)
line 4 - GOTO 2
I don't know if it's possible to make it work if all opcodes should fit on 1 line (ie 32 bits) and each line can also store a value
But I don't want to have variable opcodes and complex stuff, I just want to be able to iterate on memory locations of the same size
Are you retarded? You are basically asking "how do I read data from a file?" Also why would you use a 32 bit opcode? I bet 256 ops aka 8 bits is just fine.#define OP_HALT 0
#define OP_INC 1
#define OP_OUT 2
#define CHUNK 256
typedef struct {
uint8_t *code;
uint32_t ip;
uint32_t register;
uint8_t halt;
} mach;
int execfile(const char *file, mach *m) {
m->code = malloc(CHUNK);
if (code == NULL) return 1;
int fd = open(file, O_RDONLY);
if (fd == -1) {
free(m->code);
return 1;
}
// TODO roll your own memory management for dynamic allocs
read(fd, m->code, CHUNK);
// Exec code until halt
while (execop(m)) {}
free(m->code);
return 0;
}
int execop(mach *m) {
// Is machine halted?
if (m->halt) return 1;
uint8_t op;
op = m->code[m->ip];
m->ip++;
// One byte ops
switch(op) {
case OP_HLT:
m->halt = 1;
return 0;
case OP_OUT:
printf("Register: %i\n", m->register);
return 0;
}
uint32_t arg;
// Ops with arg
arg = (uint32_t) m->code[m->ip];
m->ip += 4;
switch (op) {
case OP_INC:
mach->register += arg;
return 0;
default:
// Invalid opcode
return 1;
}
}
And no, I didn't test it, I just wrote it in 5 minutes.