/* Copyright (C) 2001 Michael Leonhard
 * Mike Leonhard
 * mike at tamale dot net
 * http://tamale.net/
 */

#define BUFFERSIZE 1024
#define MODULESUFFIX ".so"

#define Sebae_VM_GetElement( foo ) foo = defn->insnlist[vm->insn++]; \
			assert( vm->insn < defn->numinsns ); \
			assert( foo > -1 && foo < vm->framesize );

#define Sebae_VM_AddToStack( foo ) vm->frame[ vm->framesize ] = foo; \
			vm->framesize++; \
			assert( vm->framesize < 256 ); \
			vm->stackheight++; \
			assert( vm->stackheight <= vm->stacksize );

#define Sebae_VM_AddToFPStack( foo ) vm->fpframe[ vm->framesize ] = foo; \
			vm->framesize++; \
			assert( vm->framesize < 256 ); \
			vm->stackheight++; \
			assert( vm->stackheight <= vm->stacksize );


struct Directive;
struct InstructionSet;
struct SebaeVM;

typedef int (*MagicDefnFunc)( struct SebaeVM *vm );
typedef int (*ProduceFunc)( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );

struct Directive {
	int num, i[4];
	char *token[4];
	};

struct InstructionSet {
	char name[16], num;
	int stackeffect, parameters;
	/*	parameters field:
		-1 single 32bit parameter
		0 no parameters
		1 one 8bit integer
		2 two 8bit integers
		3 three 8bit integers
		*/
	ProduceFunc produce;
	};

struct SebaeDefn {
	int vector, consume, produce, maxheight;
	int numinsns, sizeinsnlist, *insnlist, bytes;
	MagicDefnFunc magic;
	};

struct SebaePipe {
	int type, fd, flen, bytes;
	unsigned char *data;
	};

struct SebaeVM {
	int defn, insn, datapipe;
	
	struct SebaeDefn *newdefn;
	int linenumber, vector, height;
	char *workbuffer, *errortext;

	int numdefns, sizedefnlist;
	struct SebaeDefn *defnlist;

	int sizepipelist;
	struct SebaePipe *pipelist;
	
	int *stack, stacksize, stackheight, *frame, framesize;
	float *fpframe;

	int memsize;
	int *mem;
	};

/* assembly.c */
int Sebae_Assembly_GetFloat( struct SebaeVM *vm, struct Directive *directive, int t );
int Sebae_Assembly_GetInteger( struct SebaeVM *vm, struct Directive *directive, int t );
int Sebae_Assembly_IsInteger( struct SebaeVM *vm, struct Directive *directive, int t );
int Sebae_Assembly_LoadFile( struct SebaeVM *vm, char *fname );
char *Sebae_Assembly_Process( struct SebaeVM *vm, char *text );
int Sebae_Assembly_ProcessDirective( struct SebaeVM *vm, struct Directive *directive );
int Sebae_Assembly_ProcessStatement( struct SebaeVM *vm, char *statement );
int Sebae_Assembly_ProduceDATA( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );
int Sebae_Assembly_ProduceDEFN( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );
int Sebae_Assembly_ProduceDEFNTERMINAL( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );
int Sebae_Assembly_ProduceGENERIC( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );
int Sebae_Assembly_Read( struct SebaeVM *vm, int p );
int Sebae_Assembly_ReadParameters( struct SebaeVM *vm, struct InstructionSet *ientry, struct Directive *directive );
int Sebae_Assembly_Write( struct SebaeVM *vm, int p );
int Sebae_Assembly_WriteDefn( struct SebaeVM *vm, int p, struct SebaeDefn *defn );
int Sebae_Assembly_WriteFile( struct SebaeVM *vm, char *fname );

/* bytecode.c */
int Sebae_Bytecode_LoadFile( struct SebaeVM *vm, char *fname );
int Sebae_Bytecode_Read( struct SebaeVM *vm, int p );
int Sebae_Bytecode_ReadDefn( struct SebaeVM *vm, int p );
int Sebae_Bytecode_ReadDefnListLength( struct SebaeVM *vm, int p );
int Sebae_Bytecode_ReadInstruction( struct SebaeDefn *defn, struct SebaeVM *vm, int pipe );
int Sebae_Bytecode_ReadSignature( struct SebaeVM *vm, int p );
int Sebae_Bytecode_Write( struct SebaeVM *vm, int p );
int Sebae_Bytecode_WriteDefn( struct SebaeVM *vm, int p, struct SebaeDefn *defn );
int Sebae_Bytecode_WriteDefnListLength( struct SebaeVM *vm, int p );
int Sebae_Bytecode_WriteFile( struct SebaeVM *vm, char *fname );
int Sebae_Bytecode_WriteSignature( struct SebaeVM *vm, int p );

/* module.c */
int Sebae_Module_InstallMagicDefn( struct SebaeVM *vm, MagicDefnFunc magic, int consume, int produce );
int Sebae_Module_DoMagicDefn( struct SebaeVM *vm );
int Sebae_Module_Load( struct SebaeVM *vm );

/* pipe.c */
int Sebae_Pipe_BytesAvailable( struct SebaeVM *vm, int p );
int Sebae_Pipe_Free( struct SebaeVM *vm, int p );
int Sebae_Pipe_FromFile( struct SebaeVM *vm, char *fname );
int Sebae_Pipe_FromMemory( struct SebaeVM *vm, unsigned char *src, int len );
int Sebae_Pipe_New( struct SebaeVM *vm );
int Sebae_Pipe_Read( struct SebaeVM *vm, int p, unsigned char *dest, int len );
int Sebae_Pipe_ToFile( struct SebaeVM *vm, char *fname );
int Sebae_Pipe_Write( struct SebaeVM *vm, int p, unsigned char *src, int len );

/* sebae.h */
#define inum 30
#define dnum 32
extern struct InstructionSet iset[];

int Sebae_Error( struct SebaeVM *vm, char *text );
int Sebae_PError( struct SebaeVM *vm, char *text );
int Sebae_PrintError( struct SebaeVM *vm );

/* vm.c */
void Sebae_VM_AddInstruction( struct SebaeDefn *defn, int insn, int bytes );
int Sebae_VM_Destroy( struct SebaeVM *vm );
void Sebae_VM_FreeDefn( struct SebaeVM *vm, int d );
struct SebaeVM *Sebae_VM_New( int stacksize, int memsize );
struct SebaeDefn *Sebae_VM_NewDefn( struct SebaeVM *vm );
void Sebae_VM_Rewind( struct SebaeVM *vm );
int Sebae_VM_Tick( struct SebaeVM *vm );
