diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 1ed32f696..6b9bf3123 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -1,5 +1,4 @@ typedef enum { - ex_statement, ex_expr, // binary expression ex_uexpr, // unary expression ex_def, @@ -10,9 +9,6 @@ typedef enum { ex_quaternion, } expr_type; -typedef struct estatement_s { -} estatement_t; - typedef struct expr_s { struct expr_s *next; expr_type type; @@ -29,11 +25,11 @@ typedef struct expr_s { string_t string_val; float vector_val[3]; float quaternion_val[4]; - estatement_t *statement; } e; } expr_t; expr_t *new_expr (void); +expr_t *label_expr (void); void print_expr (expr_t *e); expr_t *binary_expr (int op, expr_t *e1, expr_t *e2); expr_t *unary_expr (int op, expr_t *e); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 098378f21..9f350f4b1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -13,7 +13,6 @@ static etype_t qc_types[] = { ev_void, ev_void, ev_void, - ev_void, ev_void, // FIXME ex_int ev_float, // ex_float ev_string, // ex_string @@ -36,7 +35,6 @@ static etype_t get_type (expr_t *e) { switch (e->type) { - case ex_statement: case ex_quaternion: //FIXME return ev_void; case ex_expr: @@ -58,18 +56,34 @@ get_type (expr_t *e) } expr_t * -new_expr () +new_expr (void) { return calloc (1, sizeof (expr_t)); } +expr_t * +label_expr (void) +{ + static int label = 0; + + expr_t *l = new_expr (); + l->type = ex_uexpr; + l->e.expr.op = 'l'; + l->e.expr.e1 = new_expr (); + l->e.expr.e1->type = ex_int; + l->e.expr.e1->e.int_val = label++; + return l; +} + void print_expr (expr_t *e) { printf (" "); + if (!e) { + printf ("(nil)"); + return; + } switch (e->type) { - case ex_statement: - break; case ex_expr: print_expr (e->e.expr.e1); if (e->e.expr.op == 'c') { @@ -420,8 +434,6 @@ unary_expr (int op, expr_t *e) switch (op) { case '-': switch (e->type) { - case ex_statement: - return ev_void; case ex_uexpr: if (e->e.expr.op == '-') return e->e.expr.e1; @@ -460,8 +472,6 @@ unary_expr (int op, expr_t *e) break; case '!': switch (e->type) { - case ex_statement: - return ev_void; case ex_uexpr: case ex_expr: case ex_def: diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 2c4da89fe..a20bc2c0a 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -21,6 +21,7 @@ void PR_PrintType(type_t*); type_t *parse_params (def_t *parms); function_t *new_function (void); void build_function (function_t *f); +void emit_function (function_t *f, expr_t *e); void build_scope (function_t *f, def_t *func); typedef struct { @@ -41,7 +42,6 @@ typedef struct { char *string_val; float vector_val[3]; float quaternion_val[4]; - estatement_t *statement; function_t *function; } @@ -66,7 +66,7 @@ typedef struct { %type type maybe_func %type param param_list def_item def_list def_name %type const expr arg_list -%type statement statements statement_block +%type statement statements statement_block %type begin_function %expect 1 @@ -223,10 +223,29 @@ opt_initializer | '=' begin_function statement_block end_function { build_function ($2); + emit_function ($2, $3); } - | '=' begin_function '[' expr ',' expr ']' statement_block end_function + | '=' '[' const ',' { - build_function ($2); + $$ = current_def; + } + def_name + { + current_def = $5; + } + ']' begin_function statement_block end_function + { + expr_t *e = new_expr (); + build_function ($9); + e->type = ex_expr; + e->e.expr.op = 's'; + e->e.expr.e1 = $3; + e->e.expr.e2 = new_expr (); + e->e.expr.e2->type = ex_def; + e->e.expr.e2->e.def = $6; + e->next = $10; + + emit_function ($9, e); } ; @@ -262,34 +281,181 @@ statements } | statements statement { -/* if ($1) { - estatement_t *s = $1; - while (s->next) - s = s->next; - s->next = $2; + if ($1) { + if ($2) { + expr_t *s = $1; + while (s->next) + s = s->next; + s->next = $2; + } $$ = $1; } else { $$ = $2; - }*/ + } } ; statement - : ';' {} + : ';' { $$ = 0; } | statement_block { $$ = $1; } - | RETURN expr ';' {} - | RETURN ';' {} - | WHILE '(' expr ')' statement {} - | DO statement WHILE '(' expr ')' ';' {} + | RETURN expr ';' + { + $$ = new_expr (); + $$->type = ex_uexpr; + $$->e.expr.op = 'r'; + $$->e.expr.e1 = $2; + } + | RETURN ';' + { + $$ = new_expr (); + $$->type = ex_uexpr; + $$->e.expr.op = 'r'; + } + | WHILE '(' expr ')' statement + { + expr_t *e = new_expr (); + expr_t *l1 = label_expr (); + expr_t *l2 = label_expr (); + + $$ = e; + + e->type = ex_expr; + e->e.expr.op = 'n'; + e->e.expr.e1 = $3; + e->e.expr.e2 = l2; + + e->next = l1; + e = e->next; + + e->next = $5; + while (e->next) + e = e->next; + + e->next = new_expr (); + e = e->next; + e->type = ex_expr; + e->e.expr.op = 'i'; + e->e.expr.e1 = $3; + e->e.expr.e2 = l1; + + e->next = l2; + } + | DO statement WHILE '(' expr ')' ';' + { + expr_t *e; + expr_t *l1 = label_expr (); + + $$ = e = l1; + + e->next = $2; + while (e->next) + e = e->next; + + e->next = new_expr (); + e = e->next; + e->type = ex_expr; + e->e.expr.op = 'i'; + e->e.expr.e1 = $5; + e->e.expr.e2 = l1; + + } | LOCAL type { current_type = $2; } - def_list ';' {} - | IF '(' expr ')' statement {} - | IF '(' expr ')' statement ELSE statement {} - | FOR '(' expr ';' expr ';' expr ')' statement {} - | expr ';' {} + def_list ';' { $$ = 0; } + | IF '(' expr ')' statement + { + expr_t *e = new_expr (); + expr_t *l1 = label_expr (); + + $$ = e; + + e->type = ex_expr; + e->e.expr.op = 'n'; + e->e.expr.e1 = $3; + e->e.expr.e2 = l1; + + e->next = $5; + while (e->next) + e = e->next; + + e->next = l1; + } + | IF '(' expr ')' statement ELSE statement + { + expr_t *e = new_expr (); + expr_t *l1 = label_expr (); + expr_t *l2 = label_expr (); + + $$ = e; + + e->type = ex_expr; + e->e.expr.op = 'n'; + e->e.expr.e1 = $3; + e->e.expr.e2 = l1; + + e->next = $5; + while (e->next) + e = e->next; + + e->next = new_expr (); + e = e->next; + e->type = ex_uexpr; + e->e.expr.op = 'g'; + e->e.expr.e1 = l2; + + e->next = l1; + e = e->next; + + e->next = $7; + while (e->next) + e = e->next; + + e->next = l2; + } + | FOR '(' expr ';' expr ';' expr ')' statement + { + expr_t *e; + expr_t *l1 = label_expr (); + expr_t *l2 = label_expr (); + + $$ = e = $3; + if (e) { + e->next = new_expr (); + e = e->next; + } else { + e = new_expr (); + } + e->type = ex_expr; + e->e.expr.op = 'n'; + e->e.expr.e1 = $5; + e->e.expr.e2 = l2; + + e->next = l1; + e = e->next; + + e->next = $9; + while (e->next) + e = e->next; + + e->next = $7; + if (e->next) + e = e->next; + + e->next = new_expr (); + e = e->next; + e->type = ex_expr; + e->e.expr.op = 'i'; + e->e.expr.e1 = $5; + e->e.expr.e2 = l1; + + e->next = l2; + } + | expr ';' + { + $$ = $1; + } ; expr @@ -454,3 +620,16 @@ build_function (function_t *f) for (i = 0; i < df->numparms; i++) df->parm_size[i] = type_size[f->def->type->parm_types[i]->type]; } + +void +emit_function (function_t *f, expr_t *e) +{ + PR_PrintType (f->def->type); + printf (" %s =\n{\n", f->def->name); + while (e) { + print_expr (e); + puts(""); + e = e->next; + } + printf ("}\n"); +}