Move the constant expression values into their own struct.

This commit is contained in:
Bill Currie 2011-01-19 08:41:24 +09:00
parent ff6e1b4d6c
commit e08efe036b
13 changed files with 704 additions and 764 deletions

View file

@ -54,17 +54,7 @@ typedef enum {
ex_temp, ///< temporary variable (::ex_temp_t) ex_temp, ///< temporary variable (::ex_temp_t)
ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_nil, ///< umm, nil, null. nuff said (0 of any type)
ex_string, ///< string constant (expr_t::e::string_val) ex_value, ///< constant value (::ex_value_t)
ex_float, ///< float constant (expr_t::e::float_val)
ex_vector, ///< vector constant (expr_t::e::vector_val)
ex_entity, ///< entity constant (expr_t::e::entity_val)
ex_field, ///< field constant
ex_func, ///< function constant (expr_t::e::func_val)
ex_pointer, ///< pointer constant (expr_t::e::pointer)
ex_quaternion, ///< quaternion constant (expr_t::e::quaternion_val)
ex_integer, ///< integer constant (expr_t::e::integer_val)
ex_uinteger, ///< unsigned integer constant (expr_t::e::uinteger_val)
ex_short, ///< short constant (expr_t::e::short_val)
} expr_type; } expr_type;
/** Binary and unary expressions. /** Binary and unary expressions.
@ -163,6 +153,22 @@ typedef struct {
struct expr_s *step; ///< time step until the next state struct expr_s *step; ///< time step until the next state
} ex_state_t; } ex_state_t;
typedef struct ex_value_s {
etype_t type;
union {
const char *string_val; ///< string constant
float float_val; ///< float constant
float vector_val[3]; ///< vector constant
int entity_val; ///< entity constant
int func_val; ///< function constant
ex_pointer_t pointer; ///< pointer constant
float quaternion_val[4]; ///< quaternion constant
int integer_val; ///< integer constant
unsigned uinteger_val; ///< unsigned integer constant
short short_val; ///< short constant
} v;
} ex_value_t;
#define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val) #define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val)
typedef struct expr_s { typedef struct expr_s {
@ -181,23 +187,11 @@ typedef struct expr_s {
struct def_s *def; ///< def reference expression struct def_s *def; ///< def reference expression
struct symbol_s *symbol; ///< symbol reference expression struct symbol_s *symbol; ///< symbol reference expression
ex_temp_t temp; ///< temporary variable expression ex_temp_t temp; ///< temporary variable expression
ex_value_t value; ///< constant value
const char *string_val; ///< string constant
float float_val; ///< float constant
float vector_val[3]; ///< vector constant
int entity_val; ///< entity constant
int func_val; ///< function constant
ex_pointer_t pointer; ///< pointer constant
float quaternion_val[4]; ///< quaternion constant
int integer_val; ///< integer constant
unsigned uinteger_val; ///< unsigned integer constant
short short_val; ///< short constant
} e; } e;
} expr_t; } expr_t;
extern etype_t qc_types[];
extern struct type_s *ev_types[]; extern struct type_s *ev_types[];
extern expr_type expr_types[];
/** Report a type mismatch error. /** Report a type mismatch error.
@ -368,6 +362,7 @@ expr_t *new_name_expr (const char *name);
(expr_t::e::string_val). (expr_t::e::string_val).
*/ */
expr_t *new_string_expr (const char *string_val); expr_t *new_string_expr (const char *string_val);
const char *expr_string (expr_t *e);
/** Create a new float constant expression node. /** Create a new float constant expression node.
@ -376,6 +371,7 @@ expr_t *new_string_expr (const char *string_val);
(expr_t::e::float_val). (expr_t::e::float_val).
*/ */
expr_t *new_float_expr (float float_val); expr_t *new_float_expr (float float_val);
float expr_float (expr_t *e);
/** Create a new vector constant expression node. /** Create a new vector constant expression node.
@ -384,6 +380,7 @@ expr_t *new_float_expr (float float_val);
(expr_t::e::vector_val). (expr_t::e::vector_val).
*/ */
expr_t *new_vector_expr (const float *vector_val); expr_t *new_vector_expr (const float *vector_val);
const float *expr_vector (expr_t *e);
/** Create a new entity constant expression node. /** Create a new entity constant expression node.
@ -428,6 +425,7 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def);
(expr_t::e::quaternion_val). (expr_t::e::quaternion_val).
*/ */
expr_t *new_quaternion_expr (const float *quaternion_val); expr_t *new_quaternion_expr (const float *quaternion_val);
const float *expr_quaternion (expr_t *e);
/** Create a new integer constant expression node. /** Create a new integer constant expression node.
@ -436,14 +434,7 @@ expr_t *new_quaternion_expr (const float *quaternion_val);
(expr_t::e::integer_val). (expr_t::e::integer_val).
*/ */
expr_t *new_integer_expr (int integer_val); expr_t *new_integer_expr (int integer_val);
int expr_integer (expr_t *e);
/** Create a new unsigned integer constant expression node.
\param uinteger_val The unsigned integer constant being represented.
\return The new unsigned integer constant expression node
(expr_t::e::uinteger_val).
*/
expr_t *new_uinteger_expr (unsigned int uinteger_val);
/** Create a new short constant expression node. /** Create a new short constant expression node.
@ -452,6 +443,7 @@ expr_t *new_uinteger_expr (unsigned int uinteger_val);
(expr_t::e::short_val). (expr_t::e::short_val).
*/ */
expr_t *new_short_expr (short short_val); expr_t *new_short_expr (short short_val);
short expr_short (expr_t *e);
/** Check of the expression refers to a constant value. /** Check of the expression refers to a constant value.
@ -481,6 +473,13 @@ int is_math (int op);
*/ */
int is_logic (int op); int is_logic (int op);
int is_string_val (expr_t *e);
int is_float_val (expr_t *e);
int is_vector_val (expr_t *e);
int is_quaternion_val (expr_t *e);
int is_integer_val (expr_t *e);
int is_short_val (expr_t *e);
/** Convert a constant def to a constant expression. /** Convert a constant def to a constant expression.
\param var The def to convert. \param var The def to convert.
@ -572,12 +571,8 @@ expr_t *append_expr (expr_t *block, expr_t *e);
void print_expr (expr_t *e); void print_expr (expr_t *e);
void convert_int (expr_t *e); void convert_int (expr_t *e);
void convert_uint (expr_t *e);
void convert_short (expr_t *e); void convert_short (expr_t *e);
void convert_uint_int (expr_t *e);
void convert_int_uint (expr_t *e);
void convert_short_int (expr_t *e); void convert_short_int (expr_t *e);
void convert_short_uint (expr_t *e);
void convert_nil (expr_t *e, struct type_s *t); void convert_nil (expr_t *e, struct type_s *t);
expr_t *test_expr (expr_t *e, int test); expr_t *test_expr (expr_t *e, int test);

View file

@ -552,8 +552,8 @@ class_message_response (class_t *class, int class_msg, expr_t *sel)
class_t *c = class; class_t *c = class;
category_t *cat; category_t *cat;
if (sel->type != ex_pointer if (sel->type != ex_value && sel->e.value.type != ev_pointer
&& sel->e.pointer.type != type_SEL.t.fldptr.type) { && sel->e.value.v.pointer.type != type_SEL.t.fldptr.type) {
error (sel, "not a selector"); error (sel, "not a selector");
return 0; return 0;
} }

View file

@ -94,8 +94,12 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
s1 = e1->e.string_val ? e1->e.string_val : ""; s1 = expr_string (e1);
s2 = e2->e.string_val ? e2->e.string_val : ""; s2 = expr_string (e2);
if (!s1)
s1 = "";
if (!s2)
s2 = "";
switch (op) { switch (op) {
case '+': case '+':
@ -104,36 +108,32 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
dstring_clearstr (temp_str); dstring_clearstr (temp_str);
dstring_appendstr (temp_str, s1); dstring_appendstr (temp_str, s1);
dstring_appendstr (temp_str, s2); dstring_appendstr (temp_str, s2);
e1->e.string_val = save_string (temp_str->str); e = new_string_expr (save_string (temp_str->str));
break; break;
case LT: case LT:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2) < 0);
e1->e.integer_val = strcmp (s1, s2) < 0;
break; break;
case GT: case GT:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2) > 0);
e1->e.integer_val = strcmp (s1, s2) > 0;
break; break;
case LE: case LE:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2) <= 0);
e1->e.integer_val = strcmp (s1, s2) <= 0;
break; break;
case GE: case GE:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2) >= 0);
e1->e.integer_val = strcmp (s1, s2) >= 0;
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2) == 0);
e1->e.integer_val = strcmp (s1, s2) == 0;
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (strcmp (s1, s2));
e1->e.integer_val = strcmp (s1, s2) != 0;
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *
@ -143,15 +143,18 @@ convert_to_float (expr_t *e)
return e; return e;
switch (e->type) { switch (e->type) {
case ex_integer: case ex_value:
convert_int (e); switch (e->e.value.type) {
return e; case ev_integer:
case ex_uinteger: convert_int (e);
convert_uint (e); return e;
return e; case ev_short:
case ex_short: convert_short (e);
convert_short (e); return e;
return e; default:
internal_error (e, 0);
}
break;
case ex_def: case ex_def:
case ex_expr: case ex_expr:
case ex_uexpr: case ex_uexpr:
@ -209,108 +212,103 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
} }
e->e.expr.type = type; e->e.expr.type = type;
if (op == '*' && is_constant (e1) && e1->e.float_val == 1) if (op == '*' && is_constant (e1) && expr_float (e1) == 1)
return e2; return e2;
if (op == '*' && is_constant (e2) && e2->e.float_val == 1) if (op == '*' && is_constant (e2) && expr_float (e2) == 1)
return e1; return e1;
if (op == '*' && is_constant (e1) && e1->e.float_val == 0) if (op == '*' && is_constant (e1) && expr_float (e1) == 0)
return e1; return e1;
if (op == '*' && is_constant (e2) && e2->e.float_val == 0) if (op == '*' && is_constant (e2) && expr_float (e2) == 0)
return e2; return e2;
if (op == '/' && is_constant (e2) && e2->e.float_val == 1) if (op == '/' && is_constant (e2) && expr_float (e2) == 1)
return e1; return e1;
if (op == '/' && is_constant (e2) && e2->e.float_val == 0) if (op == '/' && is_constant (e2) && expr_float (e2) == 0)
return error (e, "division by zero"); return error (e, "division by zero");
if (op == '/' && is_constant (e1) && e1->e.float_val == 0) if (op == '/' && is_constant (e1) && expr_float (e1) == 0)
return e1; return e1;
if (op == '+' && is_constant (e1) && e1->e.float_val == 0) if (op == '+' && is_constant (e1) && expr_float (e1) == 0)
return e2; return e2;
if (op == '+' && is_constant (e2) && e2->e.float_val == 0) if (op == '+' && is_constant (e2) && expr_float (e2) == 0)
return e1; return e1;
if (op == '-' && is_constant (e2) && e2->e.float_val == 0) if (op == '-' && is_constant (e2) && expr_float (e2) == 0)
return e1; return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
f1 = e1->e.float_val; f1 = expr_float (e1);
f2 = e2->e.float_val; f2 = expr_float (e2);
switch (op) { switch (op) {
case '+': case '+':
e1->e.float_val += f2; e = new_float_expr (f1 + f2);
break; break;
case '-': case '-':
e1->e.float_val -= f2; e = new_float_expr (f1 - f2);
break; break;
case '*': case '*':
e1->e.float_val *= f2; e = new_float_expr (f1 * f2);
break; break;
case '/': case '/':
if (!f2) if (!f2)
return error (e1, "divide by zero"); return error (e1, "divide by zero");
e1->e.float_val /= f2; e = new_float_expr (f1 / f2);
break; break;
case '&': case '&':
e1->e.float_val = (int) f1 & (int) f2; e = new_float_expr ((int)f1 & (int)f2);
break; break;
case '|': case '|':
e1->e.float_val = (int) f1 | (int) f2; e = new_float_expr ((int)f1 | (int)f2);
break; break;
case '^': case '^':
e1->e.float_val = (int) f1 ^ (int) f2; e = new_float_expr ((int)f1 ^ (int)f2);
break; break;
case '%': case '%':
e1->e.float_val = (int) f1 % (int) f2; e = new_float_expr ((int)f1 % (int)f2);
break; break;
case SHL: case SHL:
e1->e.float_val = (int) f1 << (int) f2; e = new_float_expr ((int)f1 << (int)f2);
break; break;
case SHR: case SHR:
e1->e.float_val = (int) f1 >> (int) f2; e = new_float_expr ((int)f1 >> (int)f2);
break; break;
case AND: case AND:
e1->type = ex_integer; e = new_integer_expr (f1 && f2);
e1->e.integer_val = f1 && f2;
break; break;
case OR: case OR:
e1->type = ex_integer; e = new_integer_expr (f1 || f2);
e1->e.integer_val = f1 || f2;
break; break;
case LT: case LT:
e1->type = ex_integer; e = new_integer_expr (f1 < f2);
e1->e.integer_val = f1 < f2;
break; break;
case GT: case GT:
e1->type = ex_integer; e = new_integer_expr (f1 > f2);
e1->e.integer_val = f1 > f2;
break; break;
case LE: case LE:
e1->type = ex_integer; e = new_integer_expr (f1 <= f2);
e1->e.integer_val = f1 <= f2;
break; break;
case GE: case GE:
e1->type = ex_integer; e = new_integer_expr (f1 >= f2);
e1->e.integer_val = f1 >= f2;
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (f1 == f2);
e1->e.integer_val = f1 == f2;
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (f1 != f2);
e1->e.integer_val = f1 != f2;
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *
do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
{ {
float *v1, *v2; const float *v1, *v2;
vec3_t v;
static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0}; static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0};
expr_t *t; expr_t *t;
@ -342,69 +340,69 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
e->e.expr.type = &type_vector; e->e.expr.type = &type_vector;
} }
if (op == '*' && is_constant (e1) && e1->type == ex_float if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
&& e1->e.float_val == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
return e1; return e1;
if (op == '*' && is_constant (e1) && e1->type == ex_float if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
&& e1->e.float_val == 0)
return new_vector_expr (vec3_origin); return new_vector_expr (vec3_origin);
if (op == '*' && is_constant (e2) && e2->type == ex_float if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
&& e2->e.float_val == 0)
return new_vector_expr (vec3_origin);
if (op == '/' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
return e1; return e1;
if (op == '/' && is_constant (e2) && e2->type == ex_float if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
&& e2->e.float_val == 0)
return error (e, "division by zero"); return error (e, "division by zero");
if (op == '+' && is_constant (e1) && VectorIsZero (e1->e.vector_val)) if (op == '+' && is_constant (e1) && VectorIsZero (expr_vector (e1)))
return e2; return e2;
if (op == '+' && is_constant (e2) && VectorIsZero (e2->e.vector_val)) if (op == '+' && is_constant (e2) && VectorIsZero (expr_vector (e2)))
return e1; return e1;
if (op == '-' && is_constant (e2) && VectorIsZero (e2->e.vector_val)) if (op == '-' && is_constant (e1) && VectorIsZero (expr_vector (e1))) {
vec3_t v;
VectorNegate (expr_vector (e2), v);
e = new_vector_expr (v);
e->file = e2->file;
e->line = e2->line;
return e;
}
if (op == '-' && is_constant (e2) && VectorIsZero (expr_vector (e2)))
return e1; return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
v1 = e1->e.vector_val; v1 = expr_vector (e1);
v2 = e2->e.vector_val; v2 = expr_vector (e2);
switch (op) { switch (op) {
case '+': case '+':
VectorAdd (v1, v2, v1); VectorAdd (v1, v2, v);
e = new_vector_expr (v);
break; break;
case '-': case '-':
VectorSubtract (v1, v2, v1); VectorSubtract (v1, v2, v);
e = new_vector_expr (v);
break; break;
case '/': case '/':
if (!v2[0]) if (!v2[0])
return error (e1, "divide by zero"); return error (e1, "divide by zero");
VectorScale (v1, 1 / v2[0], v1); VectorScale (v1, 1 / v2[0], v);
break; break;
case '*': case '*':
if (get_type (e2) == &type_vector) { if (get_type (e2) == &type_vector) {
e1->type = ex_float; e = new_float_expr (DotProduct (v1, v2));
e1->e.float_val = DotProduct (v1, v2);
} else { } else {
VectorScale (v1, v2[0], v1); VectorScale (v1, v2[0], v);
e = new_vector_expr (v);
} }
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (VectorCompare (v1, v2));
e1->e.integer_val = VectorCompare (v1, v2);
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (!VectorCompare (v1, v2));
e1->e.integer_val = !VectorCompare (v1, v2);
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *
@ -498,18 +496,21 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
static expr_t * static expr_t *
do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2)
{ {
float *q1, *q2; const float *q1, *q2;
quat_t q;
static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0}; static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0};
expr_t *t; expr_t *t;
if (get_type (e1) != &type_quaternion) { if (get_type (e1) != &type_quaternion) {
if (op != '*') if (op != '*' || op != '/')
return error (e1, "invalid operand for quaternion"); return error (e1, "invalid operand for quaternion");
t = e1; if (op == '*') {
e->e.expr.e1 = e1 = e2; t = e1;
e2 = t; e->e.expr.e1 = e1 = e2;
e2 = t;
}
} }
if (get_type (e2) != &type_quaternion) { if (get_type (e2) != &type_quaternion) {
e->e.expr.e2 = e2 = convert_to_float (e2); e->e.expr.e2 = e2 = convert_to_float (e2);
@ -528,70 +529,65 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2)
e->e.expr.type = &type_quaternion; e->e.expr.type = &type_quaternion;
} }
if (op == '*' && is_constant (e1) && e1->type == ex_float if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
&& e1->e.float_val == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
return e1; return e1;
if (op == '*' && is_constant (e1) && e1->type == ex_float if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
&& e1->e.float_val == 0)
return new_quaternion_expr (quat_origin); return new_quaternion_expr (quat_origin);
if (op == '*' && is_constant (e2) && e2->type == ex_float if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
&& e2->e.float_val == 0)
return new_quaternion_expr (quat_origin);
if (op == '/' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
return e1; return e1;
if (op == '/' && is_constant (e2) && e2->type == ex_float if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
&& e2->e.float_val == 0)
return error (e, "division by zero"); return error (e, "division by zero");
if (op == '+' && is_constant (e1) && QuatIsZero (e1->e.quaternion_val)) if (op == '+' && is_constant (e1) && QuatIsZero (expr_quaternion (e1)))
return e2; return e2;
if (op == '+' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val)) if (op == '+' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
return e1; return e1;
if (op == '-' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val)) if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
return e1; return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
q1 = e1->e.quaternion_val; q1 = expr_quaternion (e1);
q2 = e2->e.quaternion_val; q2 = expr_quaternion (e2);
switch (op) { switch (op) {
case '+': case '+':
QuatAdd (q1, q2, q1); QuatAdd (q1, q2, q);
e = new_quaternion_expr (q);
break; break;
case '-': case '-':
QuatSubtract (q1, q2, q1); QuatSubtract (q1, q2, q);
e = new_quaternion_expr (q);
break; break;
case '/': case '/':
if (!q2[0]) if (is_float_val (e2)) {
return error (e1, "divide by zero"); QuatScale (q1, 1 / expr_float (e2), q);
QuatScale (q1, 1 / q2[0], q1); } else {
q1[3] /= q2[0]; QuatInverse (q2, q);
QuatScale (q2, expr_float (e1), q);
}
e = new_quaternion_expr (q);
break; break;
case '*': case '*':
if (get_type (e2) == &type_quaternion) { if (get_type (e2) == &type_quaternion) {
QuatMult (q1, q2, q1); QuatMult (q1, q2, q);
} else { } else {
QuatScale (q1, q2[0], q1); QuatScale (q1, q2[0], q);
q1[3] *= q2[0];
} }
e = new_quaternion_expr (q);
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (QuatCompare (q1, q2));
e1->e.integer_val = QuatCompare (q1, q2);
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (!QuatCompare (q1, q2));
e1->e.integer_val = !QuatCompare (q1, q2);
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *
@ -606,10 +602,10 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2)
if (!valid_op (op, valid)) if (!valid_op (op, valid))
return error (e1, "invalid operand for integer"); return error (e1, "invalid operand for integer");
if (e1->type == ex_short) if (is_short_val (e1))
convert_short_int (e1); convert_short_int (e1);
if (e2->type == ex_short) if (is_short_val (e2))
convert_short_int (e2); convert_short_int (e2);
if (is_compare (op) || is_logic (op)) { if (is_compare (op) || is_logic (op)) {
@ -621,100 +617,96 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2)
e->e.expr.type = &type_integer; e->e.expr.type = &type_integer;
} }
if (op == '*' && is_constant (e1) && e1->e.integer_val == 1) if (op == '*' && is_constant (e1) && expr_integer (e1) == 1)
return e2; return e2;
if (op == '*' && is_constant (e2) && e2->e.integer_val == 1) if (op == '*' && is_constant (e2) && expr_integer (e2) == 1)
return e1; return e1;
if (op == '*' && is_constant (e1) && e1->e.integer_val == 0) if (op == '*' && is_constant (e1) && expr_integer (e1) == 0)
return e1; return e1;
if (op == '*' && is_constant (e2) && e2->e.integer_val == 0) if (op == '*' && is_constant (e2) && expr_integer (e2) == 0)
return e2; return e2;
if (op == '/' && is_constant (e2) && e2->e.integer_val == 1) if (op == '/' && is_constant (e2) && expr_integer (e2) == 1)
return e1; return e1;
if (op == '/' && is_constant (e2) && e2->e.integer_val == 0) if (op == '/' && is_constant (e2) && expr_integer (e2) == 0)
return error (e, "division by zero"); return error (e, "division by zero");
if (op == '/' && is_constant (e1) && e1->e.integer_val == 0) if (op == '/' && is_constant (e1) && expr_integer (e1) == 0)
return e1; return e1;
if (op == '+' && is_constant (e1) && e1->e.integer_val == 0) if (op == '+' && is_constant (e1) && expr_integer (e1) == 0)
return e2; return e2;
if (op == '+' && is_constant (e2) && e2->e.integer_val == 0) if (op == '+' && is_constant (e2) && expr_integer (e2) == 0)
return e1; return e1;
if (op == '-' && is_constant (e2) && e2->e.integer_val == 0) if (op == '-' && is_constant (e2) && expr_integer (e2) == 0)
return e1; return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
i1 = e1->e.integer_val; i1 = expr_integer (e1);
i2 = e2->e.integer_val; i2 = expr_integer (e2);
switch (op) { switch (op) {
case '+': case '+':
e1->e.integer_val += i2; e = new_integer_expr (i1 + i2);
break; break;
case '-': case '-':
e1->e.integer_val -= i2; e = new_integer_expr (i1 - i2);
break; break;
case '*': case '*':
e1->e.integer_val *= i2; e = new_integer_expr (i1 * i2);
break; break;
case '/': case '/':
if (options.warnings.integer_divide) if (options.warnings.integer_divide)
warning (e2, "%d / %d == %d", i1, i2, i1 / i2); warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
e1->e.integer_val /= i2; e = new_integer_expr (i1 / i2);
break; break;
case '&': case '&':
e1->e.integer_val = i1 & i2; e = new_integer_expr (i1 & i2);
break; break;
case '|': case '|':
e1->e.integer_val = i1 | i2; e = new_integer_expr (i1 | i2);
break; break;
case '^': case '^':
e1->e.integer_val = i1 ^ i2; e = new_integer_expr (i1 ^ i2);
break; break;
case '%': case '%':
e1->e.integer_val = i1 % i2; e = new_integer_expr (i1 % i2);
break; break;
case SHL: case SHL:
e1->e.integer_val = i1 << i2; e = new_integer_expr (i1 << i2);
break; break;
case SHR: case SHR:
e1->e.integer_val = i1 >> i2; e = new_integer_expr (i1 >> i2);
break; break;
case AND: case AND:
e1->e.integer_val = i1 && i2; e = new_integer_expr (i1 && i2);
break; break;
case OR: case OR:
e1->e.integer_val = i1 || i2; e = new_integer_expr (i1 || i2);
break; break;
case LT: case LT:
e1->type = ex_integer; e = new_integer_expr (i1 < i2);
e1->e.integer_val = i1 < i2;
break; break;
case GT: case GT:
e1->type = ex_integer; e = new_integer_expr (i1 > i2);
e1->e.integer_val = i1 > i2;
break; break;
case LE: case LE:
e1->type = ex_integer; e = new_integer_expr (i1 <= i2);
e1->e.integer_val = i1 <= i2;
break; break;
case GE: case GE:
e1->type = ex_integer; e = new_integer_expr (i1 >= i2);
e1->e.integer_val = i1 >= i2;
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (i1 == i2);
e1->e.integer_val = i1 == i2;
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (i1 != i2);
e1->e.integer_val = i1 != i2;
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *
@ -741,76 +733,72 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2)
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2)) if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e; return e;
i1 = e1->e.short_val; i1 = expr_short (e1);
i2 = e2->e.short_val; i2 = expr_short (e2);
switch (op) { switch (op) {
case '+': case '+':
e1->e.short_val += i2; e = new_short_expr (i1 + i2);
break; break;
case '-': case '-':
e1->e.short_val -= i2; e = new_short_expr (i1 - i2);
break; break;
case '*': case '*':
e1->e.short_val *= i2; e = new_short_expr (i1 * i2);
break; break;
case '/': case '/':
if (options.warnings.integer_divide) if (options.warnings.integer_divide)
warning (e2, "%d / %d == %d", i1, i2, i1 / i2); warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
e1->e.short_val /= i2; e = new_short_expr (i1 / i2);
break; break;
case '&': case '&':
e1->e.short_val = i1 & i2; e = new_short_expr (i1 & i2);
break; break;
case '|': case '|':
e1->e.short_val = i1 | i2; e = new_short_expr (i1 | i2);
break; break;
case '^': case '^':
e1->e.short_val = i1 ^ i2; e = new_short_expr (i1 ^ i2);
break; break;
case '%': case '%':
e1->e.short_val = i1 % i2; e = new_short_expr (i1 % i2);
break; break;
case SHL: case SHL:
e1->e.short_val = i1 << i2; e = new_short_expr (i1 << i2);
break; break;
case SHR: case SHR:
e1->e.short_val = i1 >> i2; e = new_short_expr (i1 >> i2);
break; break;
case AND: case AND:
e1->e.short_val = i1 && i2; e = new_short_expr (i1 && i2);
break; break;
case OR: case OR:
e1->e.short_val = i1 || i2; e = new_short_expr (i1 || i2);
break; break;
case LT: case LT:
e1->type = ex_integer; e = new_integer_expr (i1 < i2);
e1->e.integer_val = i1 < i2;
break; break;
case GT: case GT:
e1->type = ex_integer; e = new_integer_expr (i1 > i2);
e1->e.integer_val = i1 > i2;
break; break;
case LE: case LE:
e1->type = ex_integer; e = new_integer_expr (i1 <= i2);
e1->e.integer_val = i1 <= i2;
break; break;
case GE: case GE:
e1->type = ex_integer; e = new_integer_expr (i1 >= i2);
e1->e.integer_val = i1 >= i2;
break; break;
case EQ: case EQ:
e1->type = ex_integer; e = new_integer_expr (i1 == i2);
e1->e.integer_val = i1 == i2;
break; break;
case NE: case NE:
e1->type = ex_integer; e = new_integer_expr (i1 != i2);
e1->e.integer_val = i1 != i2;
break; break;
default: default:
internal_error (e1, 0); internal_error (e1, 0);
} }
return e1; e->file = e1->file;
e->line = e1->line;
return e;
} }
static expr_t * static expr_t *

File diff suppressed because it is too large Load diff

View file

@ -543,7 +543,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
error (bi_val, "%s redefined", sym->name); error (bi_val, "%s redefined", sym->name);
return 0; return 0;
} }
if (bi_val->type != ex_integer && bi_val->type != ex_float) { if (!is_integer_val (bi_val) && !is_float_val (bi_val)) {
error (bi_val, "invalid constant for = #"); error (bi_val, "invalid constant for = #");
return 0; return 0;
} }
@ -554,9 +554,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
sym->s.func->sym = sym; sym->s.func->sym = sym;
add_function (sym->s.func); add_function (sym->s.func);
bi = bi_val->e.integer_val; if (is_integer_val (bi_val))
if (bi_val->type == ex_integer) bi = expr_integer (bi_val);
bi = (int)bi_val->e.float_val; else
bi = expr_float (bi_val);
sym->s.func->builtin = bi; sym->s.func->builtin = bi;
//reloc_def_func (sym->s.func, def->ofs); //reloc_def_func (sym->s.func, def->ofs);
build_function (sym->s.func); build_function (sym->s.func);

View file

@ -170,53 +170,48 @@ ReuseConstant (expr_t *expr, def_t *def)
cn = 0; cn = 0;
if (e.type == ex_nil) if (e.type == ex_nil)
convert_nil (&e, def->type); convert_nil (&e, def->type);
switch (e.type) { if (!is_constant (&e))
case ex_entity: abort ();
switch (extract_type (&e)) {
case ev_entity:
tab = entity_imm_defs; tab = entity_imm_defs;
type = &type_entity; type = &type_entity;
break; break;
case ex_field: case ev_field:
tab = field_imm_defs; tab = field_imm_defs;
type = &type_field; type = &type_field;
break; break;
case ex_func: case ev_func:
tab = func_imm_defs; tab = func_imm_defs;
type = &type_function; type = &type_function;
break; break;
case ex_pointer: case ev_pointer:
tab = pointer_imm_defs; tab = pointer_imm_defs;
type = &type_pointer; type = &type_pointer;
break; break;
case ex_integer: case ev_integer:
case ex_uinteger:
if (!def || def->type != &type_float) { if (!def || def->type != &type_float) {
tab = integer_imm_defs; tab = integer_imm_defs;
//FIXME type = &type_integer;
//if (e.type == ex_uinteger)
// type = &type_uinteger;
//else
type = &type_integer;
break; break;
} }
if (e.type == ex_uinteger) e.e.value.v.float_val = expr_integer (&e);
e.e.float_val = e.e.uinteger_val; e.e.value.type = ev_float;
else e.type = ex_value;
e.e.float_val = e.e.integer_val; case ev_float:
e.type = ex_float;
case ex_float:
tab = float_imm_defs; tab = float_imm_defs;
type = &type_float; type = &type_float;
break; break;
case ex_string: case ev_string:
e.e.integer_val = ReuseString (e.e.string_val); e.e.value.v.integer_val = ReuseString (expr_string (&e));
tab = string_imm_defs; tab = string_imm_defs;
type = &type_string; type = &type_string;
break; break;
case ex_vector: case ev_vector:
tab = vector_imm_defs; tab = vector_imm_defs;
type = &type_vector; type = &type_vector;
break; break;
case ex_quaternion: case ev_quat:
tab = quaternion_imm_defs; tab = quaternion_imm_defs;
type = &type_quaternion; type = &type_quaternion;
break; break;
@ -269,22 +264,22 @@ ReuseConstant (expr_t *expr, def_t *def)
cn->initialized = cn->constant = 1; cn->initialized = cn->constant = 1;
cn->nosave = 1; cn->nosave = 1;
// copy the immediate to the global area // copy the immediate to the global area
switch (e.type) { switch (e.e.value.type) {
case ex_string: case ev_string:
reloc = new_reloc (cn->ofs, rel_def_string); reloc = new_reloc (cn->ofs, rel_def_string);
break; break;
case ex_func: case ev_func:
if (e.e.func_val) if (e.e.value.v.func_val)
reloc = new_reloc (cn->ofs, rel_def_func); reloc = new_reloc (cn->ofs, rel_def_func);
break; break;
case ex_field: case ev_field:
if (e.e.pointer.def) if (e.e.value.v.pointer.def)
reloc_def_field_ofs (e.e.pointer.def, cn->ofs); reloc_def_field_ofs (e.e.value.v.pointer.def, cn->ofs);
break; break;
case ex_pointer: case ev_pointer:
if (e.e.pointer.def) { if (e.e.value.v.pointer.def) {
EMIT_DEF_OFS (G_INT (cn->ofs), e.e.pointer.def); EMIT_DEF_OFS (G_INT (cn->ofs), e.e.value.v.pointer.def);
e.e.pointer.def->users--; e.e.value.v.pointer.def->users--;
} }
break; break;
default: default:

View file

@ -350,7 +350,7 @@ selector_index (const char *sel_id)
selector_t * selector_t *
get_selector (expr_t *sel) get_selector (expr_t *sel)
{ {
selector_t _sel = {0, 0, sel->e.pointer.val}; selector_t _sel = {0, 0, sel->e.value.v.pointer.val};
_sel.index /= type_size (type_SEL.t.fldptr.type); _sel.index /= type_size (type_SEL.t.fldptr.type);
return (selector_t *) Hash_FindElement (sel_index_hash, &_sel); return (selector_t *) Hash_FindElement (sel_index_hash, &_sel);
} }
@ -534,7 +534,7 @@ method_check_params (method_t *method, expr_t *args)
mtype->t.func.param_types[i], t); mtype->t.func.param_types[i], t);
} }
} else { } else {
if (e->type == ex_integer && options.warnings.vararg_integer) if (is_integer_val (e) && options.warnings.vararg_integer)
warning (e, "passing integer consant into ... function"); warning (e, "passing integer consant into ... function");
} }
} }

View file

@ -124,7 +124,7 @@ STRING \"(\\.|[^"\\])*\"
const char *c = yytext + yyleng - 1; const char *c = yytext + yyleng - 1;
int i = strtol (yytext, 0, 0); int i = strtol (yytext, 0, 0);
if (*c == 'u' || *c == 'U') if (*c == 'u' || *c == 'U')
yylval.expr = new_uinteger_expr (i); yylval.expr = new_integer_expr (i);//FIXME
else else
yylval.expr = new_integer_expr (i); yylval.expr = new_integer_expr (i);
return CONST; return CONST;

View file

@ -365,7 +365,7 @@ non_field_type
| non_field_type array_decl | non_field_type array_decl
{ {
if ($2) if ($2)
$$ = array_type ($1, $2->e.integer_val); $$ = array_type ($1, $2->e.value.v.integer_val);
else else
$$ = pointer_type ($1); $$ = pointer_type ($1);
} }
@ -465,7 +465,8 @@ array_decl
: '[' fexpr ']' : '[' fexpr ']'
{ {
$2 = constant_expr ($2); $2 = constant_expr ($2);
if ($2->type != ex_integer || $2->e.integer_val < 1) { if (($2->type != ex_value && $2->e.value.type != ev_integer)
|| $2->e.value.v.integer_val < 1) {
error (0, "invalid array size"); error (0, "invalid array size");
$$ = 0; $$ = 0;
} else { } else {

View file

@ -610,15 +610,13 @@ finish_compilation (void)
return !errors; return !errors;
if (options.code.progsversion != PROG_ID_VERSION) { if (options.code.progsversion != PROG_ID_VERSION) {
e.type = ex_integer; e = *new_integer_expr (type_size (&type_param));
e.e.integer_val = type_size (&type_param);
ReuseConstant (&e, get_def (&type_integer, ".param_size", pr.scope, ReuseConstant (&e, get_def (&type_integer, ".param_size", pr.scope,
st_global)); st_global));
} }
if (options.code.debug) { if (options.code.debug) {
e.type = ex_string; e = *new_string_expr (debugfile);
e.e.string_val = debugfile;
ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope, ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope,
st_global)); st_global));
} }

View file

@ -220,7 +220,7 @@ type
: standard_type : standard_type
| ARRAY '[' CONST RANGE CONST ']' OF standard_type | ARRAY '[' CONST RANGE CONST ']' OF standard_type
{ {
$$ = based_array_type ($8, $3->e.integer_val, $5->e.integer_val); $$ = based_array_type ($8, expr_integer ($3), expr_integer ($5));
} }
; ;

View file

@ -163,12 +163,12 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val)
value = ((symbol_t *)(*enum_tab->symtail))->s.value + 1; value = ((symbol_t *)(*enum_tab->symtail))->s.value + 1;
if (val) { if (val) {
val = constant_expr (val); val = constant_expr (val);
if (val->type < ex_nil) if (!is_constant (val))
error (val, "non-constant initializer"); error (val, "non-constant initializer");
else if (val->type != ex_integer) else if (!is_integer_val (val))
error (val, "invalid initializer type"); error (val, "invalid initializer type");
else else
value = val->e.integer_val; value = expr_integer (val);
} }
name->s.value = value; name->s.value = value;
symtab_addsymbol (enum_tab, name); symtab_addsymbol (enum_tab, name);

View file

@ -52,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] =
#include "qfcc.h" #include "qfcc.h"
#include "reloc.h" #include "reloc.h"
#include "switch.h" #include "switch.h"
#include "symtab.h"
#include "type.h" #include "type.h"
#include "qc-parse.h" #include "qc-parse.h"
@ -64,6 +65,14 @@ typedef struct case_node_s {
struct case_node_s *left, *right; struct case_node_s *left, *right;
} case_node_t; } case_node_t;
static uintptr_t
get_value (expr_t *e)
{
if (e->type == ex_symbol)
return e->e.symbol->s.value;
return e->e.value.v.integer_val;
}
static uintptr_t static uintptr_t
get_hash (void *_cl, void *unused) get_hash (void *_cl, void *unused)
{ {
@ -71,9 +80,7 @@ get_hash (void *_cl, void *unused)
if (!cl->value) if (!cl->value)
return 0; return 0;
if (cl->value->type == ex_string) return get_value (cl->value);
return (uintptr_t) cl->value->e.string_val;
return cl->value->e.integer_val;
} }
static int static int
@ -83,16 +90,17 @@ compare (void *_cla, void *_clb, void *unused)
case_label_t *clb = (case_label_t *) _clb; case_label_t *clb = (case_label_t *) _clb;
expr_t *v1 = cla->value; expr_t *v1 = cla->value;
expr_t *v2 = clb->value; expr_t *v2 = clb->value;
uintptr_t val1, val2;
if (v1 == v2) if (v1 == v2)
return 1; return 1;
if ((v1 && !v2) || (!v1 && v2)) if ((v1 && !v2) || (!v1 && v2))
return 0; return 0;
if (v1->type != v2->type) if (extract_type (v1) != extract_type (v2))
return 0; return 0;
if (v1->type == ex_string) val1 = get_value (v1);
return v1->e.string_val == v2->e.string_val; val2 = get_value (v1);
return v1->e.integer_val == v2->e.integer_val; return val1 == val2;
} }
struct expr_s * struct expr_s *
@ -145,22 +153,20 @@ label_compare (const void *_a, const void *_b)
const case_label_t **b = (const case_label_t **) _b; const case_label_t **b = (const case_label_t **) _b;
const char *s1, *s2; const char *s1, *s2;
switch ((*a)->value->type) { if (is_string_val ((*a)->value)) {
case ex_string: s1 = expr_string ((*a)->value);
s1 = (*a)->value->e.string_val ? (*a)->value->e.string_val : ""; if (!s1)
s2 = (*b)->value->e.string_val ? (*b)->value->e.string_val : ""; s1 = "";
return strcmp (s1, s2); s2 = expr_string ((*b)->value);
break; if (!s2)
case ex_float: s2 = "";
return (*a)->value->e.float_val - (*b)->value->e.float_val; return strcmp (s1, s2);
break; } else if (is_float_val ((*a)->value)) {
case ex_integer: return expr_float ((*a)->value) - expr_float ((*b)->value);
return (*a)->value->e.integer_val - (*b)->value->e.integer_val; } else if (is_integer_val ((*a)->value)) {
break; return expr_integer ((*a)->value) - expr_integer ((*b)->value);
default:
error (0, "internal compiler error in switch");
abort ();
} }
internal_error (0, "in switch");
} }
static case_node_t * static case_node_t *
@ -178,11 +184,11 @@ new_case_node (expr_t *low, expr_t *high)
} else { } else {
int size; int size;
if (low->type != ex_integer) { if (!is_integer_val (low)) {
error (low, "switch: internal error"); error (low, "switch: internal error");
abort (); abort ();
} }
size = high->e.integer_val - low->e.integer_val + 1; size = expr_integer (high) - expr_integer (low) + 1;
node->labels = calloc (size, sizeof (case_node_t *)); node->labels = calloc (size, sizeof (case_node_t *));
} }
node->left = node->right = 0; node->left = node->right = 0;
@ -223,18 +229,18 @@ build_case_tree (case_label_t **labels, int count, int range)
if (!nodes) if (!nodes)
Sys_Error ("out of memory"); Sys_Error ("out of memory");
if (range && labels[0]->value->type == ex_integer) { if (range && is_integer_val (labels[0]->value)) {
for (i = 0; i < count - 1; i = j, num_nodes++) { for (i = 0; i < count - 1; i = j, num_nodes++) {
for (j = i + 1; j < count; j++) { for (j = i + 1; j < count; j++) {
if (labels[j]->value->e.integer_val if (expr_integer (labels[j]->value)
- labels[j - 1]->value->e.integer_val > 1) - expr_integer (labels[j - 1]->value) > 1)
break; break;
} }
nodes[num_nodes] = new_case_node (labels[i]->value, nodes[num_nodes] = new_case_node (labels[i]->value,
labels[j - 1]->value); labels[j - 1]->value);
for (k = i; k < j; k++) for (k = i; k < j; k++)
nodes[num_nodes]->labels[labels[k]->value->e.integer_val nodes[num_nodes]->labels[expr_integer (labels[k]->value)
- labels[i]->value->e.integer_val] - expr_integer (labels[i]->value)]
= labels[k]->label; = labels[k]->label;
} }
if (i < count) { if (i < count) {
@ -297,15 +303,15 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
build_switch (sw, tree->right, op, sw_val, temp, default_label); build_switch (sw, tree->right, op, sw_val, temp, default_label);
} }
} else { } else {
int low = tree->low->e.integer_val; int low = expr_integer (tree->low);
int high = tree->high->e.integer_val; int high = expr_integer (tree->high);
def_t *def; def_t *def;
expr_t *table; expr_t *table;
const char *name = new_label_name (); const char *name = new_label_name ();
int i; int i;
expr_t *range = binary_expr ('-', tree->high, tree->low); expr_t *range = binary_expr ('-', tree->high, tree->low);
range->type = ex_uinteger; range = fold_constants (range);
//FIXME unsigned int better? //FIXME unsigned int better?
def = get_def (array_type (&type_integer, high - low + 1), name, def = get_def (array_type (&type_integer, high - low + 1), name,