From: Peep P. <so...@us...> - 2004-06-07 15:38:05
|
Update of /cvsroot/agd/server/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6920 Modified Files: compile.c compile.h Log Message: * Fixed included headers * Renamed curr_f to curr_fun * New compiler, no need for block_history etc * Changed the define_id system somewhat (to work with the new compiler) * New operator operand-checking system * Removed uses of array_t Index: compile.h =================================================================== RCS file: /cvsroot/agd/server/src/compile.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- compile.h 1 Apr 2004 19:17:14 -0000 1.12 +++ compile.h 7 Jun 2004 15:37:55 -0000 1.13 @@ -16,30 +16,28 @@ int type; int lpc_type; /* The datatype of the id. Return type for functions. */ int has_been_called; - array_t *args; /* For ID_FUN_PROT and ID_FUN */ + + int *args; /*For ID_FUN_PROT and ID_FUN*/ + int numarg; } def_id_t; -void define_id(char *name, int type, int lpc_type, array_t *args); + +def_id_t *define_id(char *name, int type, int lpc_type, int *args, int numarg); def_id_t *find_id(char *name); typedef struct { - int side_effect, lval; + int side_effect; int type, direct_type; - array_t arr; } expr_t; int check_operand(int operator, int opr1, int opr2); int get_fun_index(object_t *ob, char *fun); -void add_variable(array_t *vars, int scope); -void add_function(def_id_t *idp, int lineno, array_t *code); +void add_function(def_id_t *idp, int lineno/*, int **code, int codelen*/); +void add_token(long int t); +void add_two_tokens(long int t1, long int t2); +def_id_t *add_variable(char *name, int lpc_type, int type); void redeclaration_error(def_id_t *id, int new_type); -int compare_args(array_t *arg1, array_t *arg2); - -void new_block_level(void); -array_t add_block(array_t *stmt); -void end_block_level(void); - /* Warnings and errors. */ extern int compile_errors, compile_warnings; Index: compile.c =================================================================== RCS file: /cvsroot/agd/server/src/compile.c,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- compile.c 3 Apr 2004 20:20:11 -0000 1.21 +++ compile.c 7 Jun 2004 15:37:55 -0000 1.22 @@ -1,19 +1,24 @@ +#include <stdlib.h> #include <stdio.h> #include <errno.h> -#include "sys.h" +#include <sys/time.h> +#include <time.h> + +#include "config.h" #include "compile_options.h" -#include "array.h" + +#include "sys.h" #include "lpc.h" +#include "list.h" #include "object.h" #include "compile.h" -#include "net.h" -#include "interpret.h" +#include "instr.h" #include "lang.h" extern object_t *this_ob; -static program_t *this_prog; -static function_t *curr_f; /* TODO: rename to curr_fun. */ +program_t *this_prog; +function_t *curr_fun; static char *this_file; int compile_errors, compile_warnings; @@ -22,10 +27,11 @@ int scope_level; int numlvars, numgvars, numdfuns, numlfuns; -array_t local_ids, global_ids; - -static array_t *curr_block; -static array_t block_history; +/* These are arrays to pointers. realloc might + * move the memory segments, and we have + * pointers to this memory - that would get corrupted. */ +def_id_t **local_ids, **global_ids; +int num_local_ids, num_global_ids; #if YYDEBUG extern int yydebug; @@ -36,15 +42,26 @@ extern FILE *yyin; /* define_id functions. */ -void define_id(char *name, int type, int lpc_type, array_t *args) +def_id_t *define_id(char *name, int type, int lpc_type, int *args, int numarg) { def_id_t *idp; - idp = type_xmalloc(def_id_t); - memset(idp, 0, sizeof(def_id_t)); - idp->name = name; + + idp = xmalloc(sizeof(def_id_t)); + if(type == ID_DFUN) { + num_global_ids++; + global_ids = xrealloc(global_ids, num_global_ids * sizeof(def_id_t*)); + global_ids[num_global_ids - 1] = idp; + } else { + num_local_ids++; + local_ids = xrealloc(local_ids, num_local_ids * sizeof(def_id_t*)); + local_ids[num_local_ids - 1] = idp; + } + + idp->name = stringdup(name); idp->type = type; idp->lpc_type = lpc_type; idp->args = args; + idp->numarg = numarg; idp->base_scope = scope_level; switch(type) { case ID_ARG: @@ -70,190 +87,131 @@ #ifdef DEBUG debug("define_id", "%s base_scope %d index %d\n", idp->name, idp->base_scope, idp->index); #endif - - if(type == ID_DFUN) - array_push(&global_ids, idp); - else - array_push(&local_ids, idp); + + return idp; } -/* Binary search! */ def_id_t *find_id(char *name) { - int i; def_id_t *idp; + int i; /* First search in local_ids. */ - for(i=0;i<local_ids.length;i++) { - idp = local_ids.data[i]; + for(i=0;i<num_local_ids;i++) { + idp = local_ids[i]; + if(idp->base_scope == -1) { + continue; + } if(!strcmp(name, idp->name)) return idp; } /* Then global_ids. */ - for(i=0;i<global_ids.length;i++) { - idp = global_ids.data[i]; + for(i=0;i<num_global_ids;i++) { + idp = global_ids[i]; + if(idp->base_scope == -1) { + continue; + } if(!strcmp(name, idp->name)) return idp; } - return NULL; } -void free_id(void *p) -{ - def_id_t *id = p; -/* xfree(id->name);*/ - if(id->args) - xfree(id->args); -} - void pop_scope() { int i; scope_level--; - for(i=0;i<local_ids.length;i++) { - def_id_t *id = local_ids.data[i]; - if((id->type == ID_LVAR || id->type == ID_ARG) && id->base_scope > scope_level) { -#ifdef DEBUG - debug("define_id", "freed lvar %s base_scope %d scope_level %d\n", id->name, id->base_scope, scope_level); -#endif -/* free_id(id);*/ - numlvars--; - array_remove(&local_ids, i); - i--; /* Element was removed, so don't increase index. */ - } else if(id->type == ID_GVAR && id->base_scope > scope_level) { -/* free_id(id);*/ - numgvars--; - array_remove(&local_ids, i); - i--; + for(i=0;i<num_local_ids;i++) { + def_id_t *id = local_ids[i]; + if(id->base_scope > scope_level) { +/* if(id->type == ID_LVAR || id->type == ID_ARG) { } + else if(id->type == ID_GVAR) { }*/ + id->base_scope = -1; /* Temporary hack until identifiers use hash tables. */ + xfree(id->name); + if(id->args) + xfree(id->args); } } } /* Operator argument checking functions and definitions. */ typedef struct { - int valid[4]; + /* int, string, object, array */ char *name; int num_operand; int both_same_type; /* For binary operators - must both operands be of the same type? */ + int valid_types; } operator_t; -static operator_t operator_table[F_HIGHEST-F_ADD]; +#define TYPE_INT 1 +#define TYPE_STRING 2 +#define TYPE_OBJECT 4 +#define TYPE_ARRAY 8 -#define SET_OPERATOR(op_name, num, bothsame, int_valid, str_valid, ob_valid) \ - operator_table[i].name = op_name;\ - operator_table[i].num_operand = num;\ - operator_table[i].both_same_type = bothsame;\ - operator_table[i].valid[0] = int_valid;\ - operator_table[i].valid[1] = str_valid;\ - operator_table[i].valid[3] = ob_valid +#define TYPE_IS TYPE_INT|TYPE_STRING +#define TYPE_ISA TYPE_IS|TYPE_ARRAY +#define TYPE_ALL TYPE_ISA|TYPE_OBJECT -void generate_operator_table(void) +/* Make sure these are always in the same order as in instr.h */ +static operator_t operator_table[] = { + {"+", 2, 0, TYPE_ISA}, + {"+=", 2, 0, TYPE_ISA}, + {"-", 2, 1, TYPE_INT|TYPE_ARRAY}, + {"-=", 2, 1, TYPE_INT|TYPE_ARRAY}, + {"*", 2, 1, TYPE_INT}, + {"*=", 2, 1, TYPE_INT}, + {"/", 2, 1, TYPE_INT}, + {"/=", 2, 0, TYPE_INT}, + {"%", 2, 1, TYPE_INT}, + {"%=", 2, 1, TYPE_INT}, + {"**", 2, 1, TYPE_INT}, + {"**=", 2, 1, TYPE_INT}, + {"!", 1, 0, TYPE_ALL}, + {"==", 2, 1, TYPE_ALL}, + {"!=", 2, 1, TYPE_ALL}, + {">", 2, 1, TYPE_IS}, + {">=", 2, 1, TYPE_IS}, + {"<", 2, 1, TYPE_IS}, + {"<=", 2, 1, TYPE_IS}, + {"minus", 1, 0, TYPE_INT}, + {"&&", 2, 0, TYPE_ALL}, + {"||", 2, 0, TYPE_ALL}, + {"postfix increment", 1, 0, TYPE_INT}, + {"prefix increment", 1, 0, TYPE_INT}, + {"postfix decrement", 1, 0, TYPE_INT}, + {"prefix decrement", 1, 0, TYPE_INT}, + {"..", 1, 0, TYPE_STRING|TYPE_ARRAY} +}; + +int is_operand_valid(int operand, operator_t *op) { - int i; - for(i=0;i<=F_HIGHEST;i++) { - /* 4 - T_INT, T_STRING, T_VOID(unused), T_OBJECT */ - switch(i + F_ADD) { - case F_ADD: - SET_OPERATOR("+", 2, 0, 1, 1, 0); - break; - case F_ADDA: - SET_OPERATOR("+=", 2, 0, 1, 1, 0); - break; - case F_GT: - SET_OPERATOR(">", 2, 1, 1, 1, 0); - break; - case F_GE: - SET_OPERATOR(">=", 2, 1, 1, 1, 0); - break; - case F_LT: - SET_OPERATOR("<", 2, 1, 1, 1, 0); - break; - case F_LE: - SET_OPERATOR("<=", 2, 1, 1, 1, 0); - break; - case F_MUL: - SET_OPERATOR("*", 2, 1, 1, 0, 0); - break; - case F_MULA: - SET_OPERATOR("*=", 2, 0, 1, 0, 0); - break; - case F_DIV: - SET_OPERATOR("/", 2, 1, 1, 0, 0); - break; - case F_DIVA: - SET_OPERATOR("/=", 2, 0, 1, 0, 0); - break; - case F_MOD: - SET_OPERATOR("%", 2, 1, 1, 0, 0); - break; - case F_MODA: - SET_OPERATOR("%=", 2, 0, 1, 0, 0); - break; - case F_SUB: - SET_OPERATOR("-", 2, 1, 1, 0, 0); - break; - case F_SUBA: - SET_OPERATOR("-=", 2, 0, 1, 0, 0); - break; - case F_POSTINC: - SET_OPERATOR("postfix increment", - 1, 0, 1, 0, 0); - break; - case F_POSTDEC: - SET_OPERATOR("postfix decrement", - 1, 0, 1, 0, 0); - break; - case F_PREINC: - SET_OPERATOR("prefix increment", - 1, 0, 1, 0, 0); - break; - case F_PREDEC: - SET_OPERATOR("prefix decrement", - 1, 0, 1, 0, 0); - break; - case F_NEG: - SET_OPERATOR("minus", 1, 0, 1, 0, 0); - break; - case F_NOT: - SET_OPERATOR("!", 1, 0, 1, 1, 1); - break; - case F_EQ: - SET_OPERATOR("==", 2, 1, 1, 1, 1); - break; - case F_NE: - SET_OPERATOR("!=", 2, 1, 1, 1, 1); - break; - case F_AND: - SET_OPERATOR("&&", 2, 0, 1, 1, 1); - break; - case F_OR: - SET_OPERATOR("||", 2, 0, 1, 1, 1); - break; - case F_INDEX: - SET_OPERATOR("[]", 1, 0, 0, 1, 0); - break; - case F_POW: - SET_OPERATOR("**", 2, 1, 1, 0, 0); - break; - case F_POWE: - SET_OPERATOR("**=", 2, 1, 1, 0, 0); - break; - } + int x; + + if(operand & T_ARRAY) + x = TYPE_ARRAY; + else switch(operand) { + case T_INT: x = TYPE_INT; break; + case T_STRING: x = TYPE_STRING; break; + case T_OBJECT: x = TYPE_OBJECT; break; } + + return op->valid_types & x; } -/* Checks if operand is a valid operand to operator. - * Returns 0 if it's not. */ +/* Checks if opr1 and opr2 are valid operands to operator. + * Returns 0 if not. */ /* Operand 0 means don't do any checking. */ int check_operand(int operator, int opr1, int opr2) { int ret; char buf[256]; /* Safe, since operator names - are set in the code. */ + can't be set runtime. */ operator_t *op; + if(operator == F_ASSIGN) + return; + if(!opr1) return; @@ -262,20 +220,23 @@ op = &operator_table[operator-F_ADD]; - if(op->valid[opr1-1] == 0 || + if(!is_operand_valid(opr1, op) || (op->num_operand == 2 && opr2 - && op->valid[opr2-1] == 0) + && !is_operand_valid(opr2, op)) || (op->both_same_type && opr1 != opr2)) { switch(op->num_operand) { - case 1: - sprintf(buf, "wrong type argument to unary "); - break; - case 2: - sprintf(buf, "invalid operands to binary "); - break; - case 3: - sprintf(buf, "invalid operands to trinary "); - break; + case 1: + sprintf(buf, "wrong type argument to unary "); + break; + case 2: + sprintf(buf, "invalid operands to binary "); + break; + case 3: + sprintf(buf, "invalid operands to trinary "); + break; + default: + comp_error("invalid num_operand in check_operand()"); + return; } sprintf(buf, "%s%s", buf, op->name); comp_error(buf); @@ -284,185 +245,85 @@ return 1; } -/* -int nametable_find(int type, char *name, array_t *a) -{ - nt_entry_t *e; - int high, low, i; - int scope = type & 0xF0; +/* Post-compilation functions. */ - low = -1; - high = a->length; - - while(high-low > 1) { - int result; - - i = (high + low) / 2; - e = a->data[i]; - - result = strcmp(name, e->name); - if(result == 0 && (e->type & 0xF0) == scope) - return e->index; - else if(result < 0) - high = i; - else - low = i; - } - - if(high + 1 >= a->length) { - return -1; - } - - e = a->data[high+1]; - if (strcmp(name, e->name) == 0) { - return e->index; - } else { - return -1; +void curr_fun_check(void) +{ + if(!curr_fun) { + curr_fun = xmalloc(sizeof(function_t)); + curr_fun->codelen = 0; + curr_fun->code = NULL; } } -*/ - - -/* Post-compilation functions. */ -#define curr_f_check() if(!curr_f) { \ - curr_f = type_xmalloc(function_t); \ - init_array(&curr_f->code); } - -void add_function(def_id_t *idp, int lineno, array_t *code) +void add_function(def_id_t *idp, int lineno/*, long int *code, int codelen*/) { - if(idp->index < this_prog->functions.length) { + if(idp->index < this_prog->numfunc) { + /* Adding a definition for a prototype. */ function_t *f; - /* Adding definition for a prototype. */ - f = this_prog->functions.data[idp->index]; + f = this_prog->functions[idp->index]; f->type = idp->lpc_type; - if(idp->args) - f->args = *idp->args; - if(code) - f->code = *code; + f->args = idp->args; + f->numarg = idp->numarg; +/* f->code = code; + f->codelen = codelen;*/ f->lineno = lineno; } else { - curr_f_check(); - curr_f->type = idp->lpc_type; - if(idp->args) - curr_f->args = *idp->args; - if(code) - curr_f->code = *code; - curr_f->lineno = lineno; - array_push(&this_prog->functions, curr_f); - /* This removes the need to generate a fun_table. */ - array_push(&this_prog->fun_table, idp->name); - curr_f = NULL; - } - -} - -void add_variable(array_t *vars, int type) -{ - int i, numvars, num; - array_t *target; - - for(i=0;i<vars->length;i++) { - variable_t *var = vars->data[i]; - array_t *assign = NULL; - if(var->type == T_SPECIAL) { - /* One way to do this would be to remember all the global assignments - * and later insert them into the create() function, if one is defined - * in the source. */ - type &= ~T_ARRAY; - if(type == ID_GVAR) { - comp_warning("initializing global variables unimplemented"); - } else /* LVAR */ { - assign = var->u.a->data[1]; - } - var = var->u.a->data[0]; - } + curr_fun_check(); + curr_fun->type = idp->lpc_type; + curr_fun->args = idp->args; +/* curr_fun->code = code;*/ + curr_fun->lineno = lineno; + + this_prog->numfunc++; + this_prog->functions = xrealloc(this_prog->functions, this_prog->numfunc * sizeof(function_t *)); + this_prog->functions[this_prog->numfunc-1] = curr_fun; - if(type == ID_GVAR) { - /* this_ob is set to the compiled object during compilation. */ - array_push(&this_ob->variables, var); - } else /* LVAR */{ - if(var->type & T_ARRAY) - array_push(curr_block, (void *) F_PUSH_VOID); - else switch(var->type & ~T_ARRAY) { - case T_INT: - array_push(curr_block, (void *) F_PUSH_INT); - if(var->u.i) { - printf("add_varible(): var->u.i is not 0!\n"); - } - array_push(curr_block, (void *) var->u.i); - break; - case T_STRING: - array_push(curr_block, (void *) F_PUSH_STRING); - if(var->u.s) { - printf("add_variable(): var->u.s is not null!\n"); - } - array_push(curr_block, (void *) var->u.s); - break; - case T_OBJECT: - array_push(curr_block, (void *) F_PUSH_NULL_OBJECT); - break; - default: - printf("warning: unknown type in add_variable() line %d\n", __LINE__); - break; - } - } + this_prog->fun_table = xrealloc(this_prog->fun_table, this_prog->numfunc * sizeof(char *)); + this_prog->fun_table[this_prog->numfunc-1] = idp->name; - define_id(var->name, type, var->type, NULL); - - /* Only for locals right now. But watch out! */ - if(assign) { - def_id_t *id; - /* Could use numlocals, since we just defined it. */ - id = find_id(var->name); - array_push(curr_block, (void *) F_PUSH_LVAR_LVALUE); - array_push(curr_block, (void *) id->index); - array_concat(curr_block, assign); - array_push(curr_block, (void *) F_ASSIGN); - array_push(curr_block, (void *) F_POP); /* Discard value off the stack. */ - } + curr_fun = NULL; } } -void new_block_level(void) -{ - scope_level++; - array_push(&block_history, curr_block); - curr_block = type_xmalloc(array_t); - init_array(curr_block); -} - -array_t add_block(array_t *stmt) +void add_token(long int t) { - array_t ret; - array_concat(curr_block, stmt); - ret = *curr_block; - xfree(curr_block); - return ret; + curr_fun_check(); + curr_fun->codelen++; + curr_fun->code = xrealloc(curr_fun->code, sizeof(long int) * curr_fun->codelen); + curr_fun->code[curr_fun->codelen-1] = t; } -void end_block_level(void) +void add_two_tokens(long int t1, long int t2) { - pop_scope(); - block_history.length--; - curr_block = block_history.data[block_history.length]; - /*block_history.data = realloc(block_history.data, - block_history.length);*/ + curr_fun_check(); + curr_fun->code = xrealloc(curr_fun->code, sizeof(long int) * (curr_fun->codelen+2)); + curr_fun->code[curr_fun->codelen++] = t1; + curr_fun->code[curr_fun->codelen++] = t2; } -int compare_args(array_t *arg1, array_t *arg2) +def_id_t *add_variable(char *name, int lpc_type, int type) { - int i; - if(arg2->length > arg1->length) - return -2; - if(arg2->length < arg1->length) - return -1; - for(i=0;i<arg1->length;i++) { -/* if(arg != (int)arg2->data[i] && (arg->type == T_INT && arg->u.i)) { - return i; - }*/ + if(type == ID_GVAR) { + variable_t *v; + + this_ob->numglobals++; + this_ob->globals = xrealloc(this_ob->globals, this_ob->numglobals * sizeof(variable_t)); + v = &this_ob->globals[this_ob->numglobals-1]; + v->name = name; + v->type = lpc_type; + } else /* LVAR */{ + if(type & T_ARRAY) { + add_token(F_PUSH_ARRAY); + add_two_tokens(T_VOID, 0); + } else switch(type & ~T_ARRAY) { + case T_INT: add_two_tokens(F_PUSH_INT, 0); break; + case T_STRING: add_two_tokens(F_PUSH_STRING, 0); break; + case T_OBJECT: add_token(F_PUSH_NULL_OBJECT); break; + } } - return 0; + + return define_id(name, type, lpc_type, NULL, 0); } void redeclaration_error(def_id_t *id, int new_type) @@ -495,18 +356,13 @@ /* This does the actual formatting. */ void display_error(char *s) { -/* char *buf;*/ if(start_with_newline) { -/* do_write("\n");*/ putchar('\n'); start_with_newline = 0; } -/* buf = xmalloc(strlen(s) + 256); - s*/printf(/*buf, */"%s:%d:%d: %s\n", this_file, + printf("%s:%d:%d: %s\n", this_file, yylloc.first_line, yylloc.first_column, s); -/* do_write(buf); - xfree(buf);*/ } /* This is the function called by bison, probably with the argument "parse error" @@ -525,18 +381,12 @@ { compile_errors = 0; - init_array(&this_prog->functions); - init_array(&this_prog->fun_table); - init_array(&this_ob->variables); + this_ob->numglobals = 0; numlvars = numgvars = 0; numdfuns = numlfuns = 0; + num_local_ids = 0; - /*curr_f_check();*/ - - free_array(&local_ids, free_id); - init_array(&block_history); - yylloc.first_line = yylloc.first_column = 1; yyreset(); } @@ -547,12 +397,12 @@ int check_fun_definitions(void) { int i; - for(i=0;i<local_ids.length;i++) { - def_id_t *id = local_ids.data[i]; + for(i=0;i<num_local_ids;i++) { + def_id_t *id = local_ids[i]; if(id->type == ID_FUN_PROT && id->has_been_called) { char *buf; buf = xmalloc(strlen(id->name) + 43); - sprintf(buf, "Function %s has been called, " + sprintf(buf, "function %s has been called, " "but not defined", id->name); comp_error(buf); xfree(buf); @@ -589,13 +439,12 @@ goto out; } - prog = type_xmalloc(program_t); + prog = xmalloc(sizeof(program_t)); memset(prog, 0, sizeof(program_t)); this_prog = prog; parse_init(); this_file = path; -/* curr_fn = ob->name;*/ #if defined(DEBUG) && YYDEBUG if(conf.debuglevel > 4) { @@ -637,7 +486,7 @@ if(conf.debuglevel > 1) { printf("Printing code for program %s:\n", path); printf("Globals: \n"); - print_var_arr(&this_ob->variables); +/* print_var_arr(&this_ob->globals);*/ printf("\n"); print_code(prog); } |