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_nil, ///< umm, nil, null. nuff said (0 of any type)
ex_string, ///< string constant (expr_t::e::string_val)
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)
ex_value, ///< constant value (::ex_value_t)
} expr_type;
/** Binary and unary expressions.
@ -163,6 +153,22 @@ typedef struct {
struct expr_s *step; ///< time step until the next state
} 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)
typedef struct expr_s {
@ -181,23 +187,11 @@ typedef struct expr_s {
struct def_s *def; ///< def reference expression
struct symbol_s *symbol; ///< symbol reference expression
ex_temp_t temp; ///< temporary variable expression
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
ex_value_t value; ///< constant value
} e;
} expr_t;
extern etype_t qc_types[];
extern struct type_s *ev_types[];
extern expr_type expr_types[];
/** Report a type mismatch error.
@ -368,6 +362,7 @@ expr_t *new_name_expr (const char *name);
(expr_t::e::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.
@ -376,6 +371,7 @@ expr_t *new_string_expr (const char *string_val);
(expr_t::e::float_val).
*/
expr_t *new_float_expr (float float_val);
float expr_float (expr_t *e);
/** 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 *new_vector_expr (const float *vector_val);
const float *expr_vector (expr_t *e);
/** 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 *new_quaternion_expr (const float *quaternion_val);
const float *expr_quaternion (expr_t *e);
/** 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 *new_integer_expr (int integer_val);
/** 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);
int expr_integer (expr_t *e);
/** 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 *new_short_expr (short short_val);
short expr_short (expr_t *e);
/** 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_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.
\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 convert_int (expr_t *e);
void convert_uint (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_uint (expr_t *e);
void convert_nil (expr_t *e, struct type_s *t);
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;
category_t *cat;
if (sel->type != ex_pointer
&& sel->e.pointer.type != type_SEL.t.fldptr.type) {
if (sel->type != ex_value && sel->e.value.type != ev_pointer
&& sel->e.value.v.pointer.type != type_SEL.t.fldptr.type) {
error (sel, "not a selector");
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))
return e;
s1 = e1->e.string_val ? e1->e.string_val : "";
s2 = e2->e.string_val ? e2->e.string_val : "";
s1 = expr_string (e1);
s2 = expr_string (e2);
if (!s1)
s1 = "";
if (!s2)
s2 = "";
switch (op) {
case '+':
@ -104,36 +108,32 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
dstring_clearstr (temp_str);
dstring_appendstr (temp_str, s1);
dstring_appendstr (temp_str, s2);
e1->e.string_val = save_string (temp_str->str);
e = new_string_expr (save_string (temp_str->str));
break;
case LT:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) < 0;
e = new_integer_expr (strcmp (s1, s2) < 0);
break;
case GT:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) > 0;
e = new_integer_expr (strcmp (s1, s2) > 0);
break;
case LE:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) <= 0;
e = new_integer_expr (strcmp (s1, s2) <= 0);
break;
case GE:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) >= 0;
e = new_integer_expr (strcmp (s1, s2) >= 0);
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) == 0;
e = new_integer_expr (strcmp (s1, s2) == 0);
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = strcmp (s1, s2) != 0;
e = new_integer_expr (strcmp (s1, s2));
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
static expr_t *
@ -143,15 +143,18 @@ convert_to_float (expr_t *e)
return e;
switch (e->type) {
case ex_integer:
convert_int (e);
return e;
case ex_uinteger:
convert_uint (e);
return e;
case ex_short:
convert_short (e);
return e;
case ex_value:
switch (e->e.value.type) {
case ev_integer:
convert_int (e);
return e;
case ev_short:
convert_short (e);
return e;
default:
internal_error (e, 0);
}
break;
case ex_def:
case ex_expr:
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;
if (op == '*' && is_constant (e1) && e1->e.float_val == 1)
if (op == '*' && is_constant (e1) && expr_float (e1) == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->e.float_val == 1)
if (op == '*' && is_constant (e2) && expr_float (e2) == 1)
return e1;
if (op == '*' && is_constant (e1) && e1->e.float_val == 0)
if (op == '*' && is_constant (e1) && expr_float (e1) == 0)
return e1;
if (op == '*' && is_constant (e2) && e2->e.float_val == 0)
if (op == '*' && is_constant (e2) && expr_float (e2) == 0)
return e2;
if (op == '/' && is_constant (e2) && e2->e.float_val == 1)
if (op == '/' && is_constant (e2) && expr_float (e2) == 1)
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");
if (op == '/' && is_constant (e1) && e1->e.float_val == 0)
if (op == '/' && is_constant (e1) && expr_float (e1) == 0)
return e1;
if (op == '+' && is_constant (e1) && e1->e.float_val == 0)
if (op == '+' && is_constant (e1) && expr_float (e1) == 0)
return e2;
if (op == '+' && is_constant (e2) && e2->e.float_val == 0)
if (op == '+' && is_constant (e2) && expr_float (e2) == 0)
return e1;
if (op == '-' && is_constant (e2) && e2->e.float_val == 0)
if (op == '-' && is_constant (e2) && expr_float (e2) == 0)
return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e;
f1 = e1->e.float_val;
f2 = e2->e.float_val;
f1 = expr_float (e1);
f2 = expr_float (e2);
switch (op) {
case '+':
e1->e.float_val += f2;
e = new_float_expr (f1 + f2);
break;
case '-':
e1->e.float_val -= f2;
e = new_float_expr (f1 - f2);
break;
case '*':
e1->e.float_val *= f2;
e = new_float_expr (f1 * f2);
break;
case '/':
if (!f2)
return error (e1, "divide by zero");
e1->e.float_val /= f2;
e = new_float_expr (f1 / f2);
break;
case '&':
e1->e.float_val = (int) f1 & (int) f2;
e = new_float_expr ((int)f1 & (int)f2);
break;
case '|':
e1->e.float_val = (int) f1 | (int) f2;
e = new_float_expr ((int)f1 | (int)f2);
break;
case '^':
e1->e.float_val = (int) f1 ^ (int) f2;
e = new_float_expr ((int)f1 ^ (int)f2);
break;
case '%':
e1->e.float_val = (int) f1 % (int) f2;
e = new_float_expr ((int)f1 % (int)f2);
break;
case SHL:
e1->e.float_val = (int) f1 << (int) f2;
e = new_float_expr ((int)f1 << (int)f2);
break;
case SHR:
e1->e.float_val = (int) f1 >> (int) f2;
e = new_float_expr ((int)f1 >> (int)f2);
break;
case AND:
e1->type = ex_integer;
e1->e.integer_val = f1 && f2;
e = new_integer_expr (f1 && f2);
break;
case OR:
e1->type = ex_integer;
e1->e.integer_val = f1 || f2;
e = new_integer_expr (f1 || f2);
break;
case LT:
e1->type = ex_integer;
e1->e.integer_val = f1 < f2;
e = new_integer_expr (f1 < f2);
break;
case GT:
e1->type = ex_integer;
e1->e.integer_val = f1 > f2;
e = new_integer_expr (f1 > f2);
break;
case LE:
e1->type = ex_integer;
e1->e.integer_val = f1 <= f2;
e = new_integer_expr (f1 <= f2);
break;
case GE:
e1->type = ex_integer;
e1->e.integer_val = f1 >= f2;
e = new_integer_expr (f1 >= f2);
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = f1 == f2;
e = new_integer_expr (f1 == f2);
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = f1 != f2;
e = new_integer_expr (f1 != f2);
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
static expr_t *
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};
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;
}
if (op == '*' && is_constant (e1) && e1->type == ex_float
&& e1->e.float_val == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
return e1;
if (op == '*' && is_constant (e1) && e1->type == ex_float
&& e1->e.float_val == 0)
if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
return new_vector_expr (vec3_origin);
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& 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)
if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
return e1;
if (op == '/' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 0)
if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
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;
if (op == '+' && is_constant (e2) && VectorIsZero (e2->e.vector_val))
if (op == '+' && is_constant (e2) && VectorIsZero (expr_vector (e2)))
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;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e;
v1 = e1->e.vector_val;
v2 = e2->e.vector_val;
v1 = expr_vector (e1);
v2 = expr_vector (e2);
switch (op) {
case '+':
VectorAdd (v1, v2, v1);
VectorAdd (v1, v2, v);
e = new_vector_expr (v);
break;
case '-':
VectorSubtract (v1, v2, v1);
VectorSubtract (v1, v2, v);
e = new_vector_expr (v);
break;
case '/':
if (!v2[0])
return error (e1, "divide by zero");
VectorScale (v1, 1 / v2[0], v1);
VectorScale (v1, 1 / v2[0], v);
break;
case '*':
if (get_type (e2) == &type_vector) {
e1->type = ex_float;
e1->e.float_val = DotProduct (v1, v2);
e = new_float_expr (DotProduct (v1, v2));
} else {
VectorScale (v1, v2[0], v1);
VectorScale (v1, v2[0], v);
e = new_vector_expr (v);
}
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = VectorCompare (v1, v2);
e = new_integer_expr (VectorCompare (v1, v2));
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = !VectorCompare (v1, v2);
e = new_integer_expr (!VectorCompare (v1, v2));
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
static expr_t *
@ -498,18 +496,21 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
static expr_t *
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};
expr_t *t;
if (get_type (e1) != &type_quaternion) {
if (op != '*')
if (op != '*' || op != '/')
return error (e1, "invalid operand for quaternion");
t = e1;
e->e.expr.e1 = e1 = e2;
e2 = t;
if (op == '*') {
t = e1;
e->e.expr.e1 = e1 = e2;
e2 = t;
}
}
if (get_type (e2) != &type_quaternion) {
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;
}
if (op == '*' && is_constant (e1) && e1->type == ex_float
&& e1->e.float_val == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 1)
if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
return e1;
if (op == '*' && is_constant (e1) && e1->type == ex_float
&& e1->e.float_val == 0)
if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
return new_quaternion_expr (quat_origin);
if (op == '*' && is_constant (e2) && e2->type == ex_float
&& 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)
if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
return e1;
if (op == '/' && is_constant (e2) && e2->type == ex_float
&& e2->e.float_val == 0)
if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
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;
if (op == '+' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val))
if (op == '+' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
return e1;
if (op == '-' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val))
if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e;
q1 = e1->e.quaternion_val;
q2 = e2->e.quaternion_val;
q1 = expr_quaternion (e1);
q2 = expr_quaternion (e2);
switch (op) {
case '+':
QuatAdd (q1, q2, q1);
QuatAdd (q1, q2, q);
e = new_quaternion_expr (q);
break;
case '-':
QuatSubtract (q1, q2, q1);
QuatSubtract (q1, q2, q);
e = new_quaternion_expr (q);
break;
case '/':
if (!q2[0])
return error (e1, "divide by zero");
QuatScale (q1, 1 / q2[0], q1);
q1[3] /= q2[0];
if (is_float_val (e2)) {
QuatScale (q1, 1 / expr_float (e2), q);
} else {
QuatInverse (q2, q);
QuatScale (q2, expr_float (e1), q);
}
e = new_quaternion_expr (q);
break;
case '*':
if (get_type (e2) == &type_quaternion) {
QuatMult (q1, q2, q1);
QuatMult (q1, q2, q);
} else {
QuatScale (q1, q2[0], q1);
q1[3] *= q2[0];
QuatScale (q1, q2[0], q);
}
e = new_quaternion_expr (q);
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = QuatCompare (q1, q2);
e = new_integer_expr (QuatCompare (q1, q2));
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = !QuatCompare (q1, q2);
e = new_integer_expr (!QuatCompare (q1, q2));
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
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))
return error (e1, "invalid operand for integer");
if (e1->type == ex_short)
if (is_short_val (e1))
convert_short_int (e1);
if (e2->type == ex_short)
if (is_short_val (e2))
convert_short_int (e2);
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;
}
if (op == '*' && is_constant (e1) && e1->e.integer_val == 1)
if (op == '*' && is_constant (e1) && expr_integer (e1) == 1)
return e2;
if (op == '*' && is_constant (e2) && e2->e.integer_val == 1)
if (op == '*' && is_constant (e2) && expr_integer (e2) == 1)
return e1;
if (op == '*' && is_constant (e1) && e1->e.integer_val == 0)
if (op == '*' && is_constant (e1) && expr_integer (e1) == 0)
return e1;
if (op == '*' && is_constant (e2) && e2->e.integer_val == 0)
if (op == '*' && is_constant (e2) && expr_integer (e2) == 0)
return e2;
if (op == '/' && is_constant (e2) && e2->e.integer_val == 1)
if (op == '/' && is_constant (e2) && expr_integer (e2) == 1)
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");
if (op == '/' && is_constant (e1) && e1->e.integer_val == 0)
if (op == '/' && is_constant (e1) && expr_integer (e1) == 0)
return e1;
if (op == '+' && is_constant (e1) && e1->e.integer_val == 0)
if (op == '+' && is_constant (e1) && expr_integer (e1) == 0)
return e2;
if (op == '+' && is_constant (e2) && e2->e.integer_val == 0)
if (op == '+' && is_constant (e2) && expr_integer (e2) == 0)
return e1;
if (op == '-' && is_constant (e2) && e2->e.integer_val == 0)
if (op == '-' && is_constant (e2) && expr_integer (e2) == 0)
return e1;
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
return e;
i1 = e1->e.integer_val;
i2 = e2->e.integer_val;
i1 = expr_integer (e1);
i2 = expr_integer (e2);
switch (op) {
case '+':
e1->e.integer_val += i2;
e = new_integer_expr (i1 + i2);
break;
case '-':
e1->e.integer_val -= i2;
e = new_integer_expr (i1 - i2);
break;
case '*':
e1->e.integer_val *= i2;
e = new_integer_expr (i1 * i2);
break;
case '/':
if (options.warnings.integer_divide)
warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
e1->e.integer_val /= i2;
e = new_integer_expr (i1 / i2);
break;
case '&':
e1->e.integer_val = i1 & i2;
e = new_integer_expr (i1 & i2);
break;
case '|':
e1->e.integer_val = i1 | i2;
e = new_integer_expr (i1 | i2);
break;
case '^':
e1->e.integer_val = i1 ^ i2;
e = new_integer_expr (i1 ^ i2);
break;
case '%':
e1->e.integer_val = i1 % i2;
e = new_integer_expr (i1 % i2);
break;
case SHL:
e1->e.integer_val = i1 << i2;
e = new_integer_expr (i1 << i2);
break;
case SHR:
e1->e.integer_val = i1 >> i2;
e = new_integer_expr (i1 >> i2);
break;
case AND:
e1->e.integer_val = i1 && i2;
e = new_integer_expr (i1 && i2);
break;
case OR:
e1->e.integer_val = i1 || i2;
e = new_integer_expr (i1 || i2);
break;
case LT:
e1->type = ex_integer;
e1->e.integer_val = i1 < i2;
e = new_integer_expr (i1 < i2);
break;
case GT:
e1->type = ex_integer;
e1->e.integer_val = i1 > i2;
e = new_integer_expr (i1 > i2);
break;
case LE:
e1->type = ex_integer;
e1->e.integer_val = i1 <= i2;
e = new_integer_expr (i1 <= i2);
break;
case GE:
e1->type = ex_integer;
e1->e.integer_val = i1 >= i2;
e = new_integer_expr (i1 >= i2);
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = i1 == i2;
e = new_integer_expr (i1 == i2);
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = i1 != i2;
e = new_integer_expr (i1 != i2);
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
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))
return e;
i1 = e1->e.short_val;
i2 = e2->e.short_val;
i1 = expr_short (e1);
i2 = expr_short (e2);
switch (op) {
case '+':
e1->e.short_val += i2;
e = new_short_expr (i1 + i2);
break;
case '-':
e1->e.short_val -= i2;
e = new_short_expr (i1 - i2);
break;
case '*':
e1->e.short_val *= i2;
e = new_short_expr (i1 * i2);
break;
case '/':
if (options.warnings.integer_divide)
warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
e1->e.short_val /= i2;
e = new_short_expr (i1 / i2);
break;
case '&':
e1->e.short_val = i1 & i2;
e = new_short_expr (i1 & i2);
break;
case '|':
e1->e.short_val = i1 | i2;
e = new_short_expr (i1 | i2);
break;
case '^':
e1->e.short_val = i1 ^ i2;
e = new_short_expr (i1 ^ i2);
break;
case '%':
e1->e.short_val = i1 % i2;
e = new_short_expr (i1 % i2);
break;
case SHL:
e1->e.short_val = i1 << i2;
e = new_short_expr (i1 << i2);
break;
case SHR:
e1->e.short_val = i1 >> i2;
e = new_short_expr (i1 >> i2);
break;
case AND:
e1->e.short_val = i1 && i2;
e = new_short_expr (i1 && i2);
break;
case OR:
e1->e.short_val = i1 || i2;
e = new_short_expr (i1 || i2);
break;
case LT:
e1->type = ex_integer;
e1->e.integer_val = i1 < i2;
e = new_integer_expr (i1 < i2);
break;
case GT:
e1->type = ex_integer;
e1->e.integer_val = i1 > i2;
e = new_integer_expr (i1 > i2);
break;
case LE:
e1->type = ex_integer;
e1->e.integer_val = i1 <= i2;
e = new_integer_expr (i1 <= i2);
break;
case GE:
e1->type = ex_integer;
e1->e.integer_val = i1 >= i2;
e = new_integer_expr (i1 >= i2);
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = i1 == i2;
e = new_integer_expr (i1 == i2);
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = i1 != i2;
e = new_integer_expr (i1 != i2);
break;
default:
internal_error (e1, 0);
}
return e1;
e->file = e1->file;
e->line = e1->line;
return e;
}
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);
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 = #");
return 0;
}
@ -554,9 +554,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
sym->s.func->sym = sym;
add_function (sym->s.func);
bi = bi_val->e.integer_val;
if (bi_val->type == ex_integer)
bi = (int)bi_val->e.float_val;
if (is_integer_val (bi_val))
bi = expr_integer (bi_val);
else
bi = expr_float (bi_val);
sym->s.func->builtin = bi;
//reloc_def_func (sym->s.func, def->ofs);
build_function (sym->s.func);

View file

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

View file

@ -350,7 +350,7 @@ selector_index (const char *sel_id)
selector_t *
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);
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);
}
} 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");
}
}

View file

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

View file

@ -365,7 +365,7 @@ non_field_type
| non_field_type array_decl
{
if ($2)
$$ = array_type ($1, $2->e.integer_val);
$$ = array_type ($1, $2->e.value.v.integer_val);
else
$$ = pointer_type ($1);
}
@ -465,7 +465,8 @@ array_decl
: '[' fexpr ']'
{
$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");
$$ = 0;
} else {

View file

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

View file

@ -220,7 +220,7 @@ type
: 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;
if (val) {
val = constant_expr (val);
if (val->type < ex_nil)
if (!is_constant (val))
error (val, "non-constant initializer");
else if (val->type != ex_integer)
else if (!is_integer_val (val))
error (val, "invalid initializer type");
else
value = val->e.integer_val;
value = expr_integer (val);
}
name->s.value = value;
symtab_addsymbol (enum_tab, name);

View file

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