//
//      Compiler API for implementing a language definition, and using
//      the compiler inside a program
//

#ifndef __VMTYPE
#define __VMTYPE
typedef union VMTYPE
{
void *ptr;
unsigned int u32;
unsigned short u16;
unsigned char u8;
int i32;
short i16;
char i8;
} VMTYPE;
#endif

struct OPCODE
{
char *mnemonic;
unsigned int opcode;
char *parm;
void (*compile)(char **line);
void (*parse)(char **line);
char operands;
};

struct ICODE
{
int len;
VMTYPE *data;
int srcline;   // line of code referencing this
int variable;  // Variables are treated specially by the code generator
int arraysize;
int jump;      // Is it a jump?
struct KEYWORD *label; // Associated jump label (if any), either src or dest
ICODE *next;
};

struct KEYWORD
{
char *name;
void *value;
int arraysize;
int id;
int refcount;    // Number of times this variable is used
char type;
char *local;     // Name of function it's local to
char *localfile; // File it's local to (if any)
KEYWORD *next;
};

struct STRUCTURE
{
char *name;			// member name
char type;			// data type
char *access;		// access rights (R/W/none,special)
void *position;		// Address of the member in the Template object
					// The first entry in the structure has the address of
					// the base structure but is othewise blank
void *newspec;
};

struct OBJCODE
	{
	char *name;
	VMTYPE *code;
	int size;
	int codelen;
	char hidden;
	char Class;
	};


extern OPCODE vmspec[];
extern STRUCTURE *pe_datatypes[];
extern char pe_vartypes[];
extern char *pe_parm;
extern char *pe_localfile;
extern OBJCODE *pe_output;
extern int PE_FastBuild;

// Low-level API, mainly for language definition

extern ICODE *add_byte(unsigned char byte);
extern void add_opcode(unsigned int opcode);
extern ICODE *add_dword(int word);
extern ICODE *add_number(int word);
extern void add_string(char *string);
extern void add_operator(char *string);
extern void add_variable(char *name);
extern void add_intmember(char *name);
extern void add_objmember(char *name);
extern void add_strmember(char *name);
extern void add_truestrmember(char *name);
extern void add_array(char *name, char t);
extern void add_jump(char *name);
void mk_lineno(char *str,int line, char *end); // Hash for virtual labels
extern int pe_getnumber(char *r);        // Get a number (or constant)
extern int pe_getvariable(char *r);      // Get a number (or constant)
extern int pe_isnumber(char *r);         // Is the string numeric?
extern int start_icode();
extern int finish_icode();
extern void output_icode();
extern KEYWORD *add_keyword(char *name, char type, char *func);
extern KEYWORD *add_symbol_val(char *name, char type, int value);
extern KEYWORD *add_symbol_ptr(char *name, char type, void *value);
extern int get_keyword(char *name, char type, char *func);
extern KEYWORD *find_keyword(char *name, char type, char *func);
extern KEYWORD *find_keyword_global(char *name, char type, char *func);
extern void PeDump(long line, char *a, char *b);
extern void extract_string(char *dest, char *src);
extern int read_ifstack();
extern int explore_ifstack(int offset);
extern void push_ifstack(int id);
extern void pop_ifstack();

extern OPCODE *vmp;
extern KEYWORD *labelpending;
extern int srcline,icode_len,pe_numfuncs,pe_lineid;
extern char *curfunc;
extern char *pevm_context;
extern char **pe_outputfuncnames;
extern void **pe_global;
extern unsigned int pe_globals;

// Top-level API

extern void compiler_init();
extern void compiler_openfile(char *n);
extern int compiler_parse();
extern void compiler_build(OBJCODE *pe);
extern void compiler_closefile();
extern void compiler_term();

// VM Api

extern void CallVM(char *function);
extern void CallVMnum(int pos);
extern void InitVM();
extern char *CurrentVM();

// VM data access modes

#define ACC_IMMEDIATE 0
#define ACC_INDIRECT 1
#define ACC_MEMBER 2
#define ACC_ARRAY 4
#define ACC_IMMSTR 8
#define ACC_JUMP 64
#define ACC_OPERATOR 128

