Skip to content

Instantly share code, notes, and snippets.

@lpereira
Created June 11, 2011 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lpereira/1020604 to your computer and use it in GitHub Desktop.
Save lpereira/1020604 to your computer and use it in GitHub Desktop.
minifinf
#include <stdio.h>
#include <string.h>
typedef void (*NativeFunction)(int *ip);
typedef struct _Instruction Instruction;
struct _Instruction {
unsigned int opcode;
unsigned long parameter;
};
enum {
CALL, NCALL, RET, NUMBER
};
static const char *instruction_names[] = { "CALL", "NCALL", "RET", "NUMBER" };
int stack[32], stack_ptr = 0;
int trace = 0;
void push(int number)
{
stack[stack_ptr++] = number;
}
int pop()
{
return stack[--stack_ptr];
}
Instruction *get_next_instruction(Instruction *instructions, int *ip)
{
return &instructions[(*ip)++];
}
void gen_call(Instruction *instructions, int *ip, int scope_index)
{
Instruction *instruction = get_next_instruction(instructions, ip);
instruction->opcode = CALL;
instruction->parameter = scope_index;
}
void gen_ncall(Instruction *instructions, int *ip, NativeFunction native_function)
{
Instruction *instruction = get_next_instruction(instructions, ip);
instruction->opcode = NCALL;
instruction->parameter = (unsigned long)native_function;
}
void gen_ret(Instruction *instructions, int *ip)
{
Instruction *instruction = get_next_instruction(instructions, ip);
instruction->opcode = RET;
instruction->parameter = 0;
}
void gen_number(Instruction *instructions, int *ip, int n)
{
Instruction *instruction = get_next_instruction(instructions, ip);
instruction->opcode = NUMBER;
instruction->parameter = n;
}
void native_goto(int *ip)
{
*ip = pop();
}
void native_hello(int *ip)
{
printf("Hello, World!\n");
(*ip)++;
}
void open_scope(Instruction *instructions, int ip)
{
Instruction *instruction;
for (instruction = &instructions[ip]; instruction; instruction = &instructions[ip]) {
if (trace)
printf("%04d %-6s %ld\n", ip, instruction_names[instruction->opcode], instruction->parameter);
switch (instruction->opcode) {
case CALL:
open_scope(instructions, instruction->parameter);
ip++;
break;
case NCALL:
{
NativeFunction nf = (NativeFunction)instruction->parameter;
nf(&ip);
}
break;
case RET:
return;
case NUMBER:
push(instruction->parameter);
ip++;
}
}
}
int main(void)
{
Instruction instructions[32];
int ip = 0;
memset(instructions, 0, sizeof(instructions));
trace = !!getenv("FINFTRACE");
/* 0 */ gen_ncall(instructions, &ip, native_hello);
/* 1 */ gen_call(instructions, &ip, 3);
/* 2 */ gen_ret(instructions, &ip);
/* 3 */ gen_number(instructions, &ip, 2);
/* 4 */ gen_ncall(instructions, &ip, native_goto);
open_scope(instructions, 0);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment