*
* This file is thus, split into two parts.
*/
-ast_expression **fold_const_values = NULL;
-
static GMQCC_INLINE bool fold_possible(const ast_value *val) {
return ast_istype((ast_expression*)val, ast_value) &&
val->hasvalue && (val->cvq == CV_CONST) &&
#define isstring(X) (isstringonly(X) && fold_possible(X))
#define isfloats(X,Y) (isfloat (X) && isfloat (Y))
#define isvectors(X,Y) (isvector (X) && isvector(Y))
-#define isstrings(X,Y) (isstring (X) && isstring(Y))
+/*#define isstrings(X,Y) (isstring (X) && isstring(Y))*/
/*
* Implementation of basic vector math for vec3_t, for trivial constant
return (a.x * b.x + a.y * b.y + a.z * b.z);
}
-
static GMQCC_INLINE vec3_t vec3_mulvf(vec3_t a, qcfloat_t b) {
vec3_t out;
out.x = a.x * b;
return out;
}
-
-static GMQCC_INLINE float fold_immvalue_float(ast_value *expr) {
- return expr->constval.vfloat;
-}
-static GMQCC_INLINE vec3_t fold_immvalue_vector(ast_value *expr) {
- return expr->constval.vvec;
-}
-static GMQCC_INLINE const char *fold_immvalue_string(ast_value *expr) {
- return expr->constval.vstring;
+static GMQCC_INLINE bool vec3_pbool(vec3_t a) {
+ return (a.x && a.y && a.z);
}
+#define fold_immvalue_float(E) ((E)->constval.vfloat)
+#define fold_immvalue_vector(E) ((E)->constval.vvec)
+#define fold_immvalue_string(E) ((E)->constval.vstring)
fold_t *fold_init(parser_t *parser) {
fold_t *fold = (fold_t*)mem_a(sizeof(fold_t));
return NULL;
}
+static GMQCC_INLINE bool fold_immediate_true(fold_t *fold, ast_value *v) {
+ switch (v->expression.vtype) {
+ case TYPE_FLOAT: return !!v->constval.vfloat;
+ case TYPE_INTEGER: return !!v->constval.vint;
+ case TYPE_VECTOR: return OPTS_FLAG(CORRECT_LOGIC) ? vec3_pbool(v->constval.vvec) : !!v->constval.vvec.x;
+ case TYPE_STRING:
+ if (!v->constval.vstring)
+ return false;
+ if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
+ return true;
+ return !!v->constval.vstring[0];
+ default:
+ compile_error(fold_ctx(fold), "internal error: fold_immediate_true on invalid type");
+ break;
+ }
+ return !!v->constval.vfunc;
+}
+
static GMQCC_INLINE ast_expression *fold_op_div(fold_t *fold, ast_value *a, ast_value *b) {
if (isfloatonly(a)) {
return (fold_possible(a) && fold_possible(b))
return NULL;
}
+static GMQCC_INLINE ast_expression *fold_op_andor(fold_t *fold, ast_value *a, ast_value *b, bool isor) {
+ if (fold_possible(a) && fold_possible(b)) {
+ if (OPTS_FLAG(PERL_LOGIC)) {
+ if (fold_immediate_true(fold, b))
+ return (ast_expression*)b;
+ } else {
+ return ((isor) ? (fold_immediate_true(fold, a) || fold_immediate_true(fold, b))
+ : (fold_immediate_true(fold, a) && fold_immediate_true(fold, b)))
+ ? (ast_expression*)fold->imm_float[1] /* 1.0f */
+ : (ast_expression*)fold->imm_float[0]; /* 0.0f */
+ }
+ }
+ return NULL;
+}
+
ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **opexprs) {
ast_value *a = (ast_value*)opexprs[0];
ast_value *b = (ast_value*)opexprs[1];
return isfloat(a) ? fold_constgen_float (fold, ~(qcint_t)fold_immvalue_float(a))
: NULL;
- case opid1('*'): return fold_op_mul(fold, a, b);
- case opid1('/'): return fold_op_div(fold, a, b);
- /* TODO: seperate function for this case */
- return NULL;
- case opid2('|','|'):
- /* TODO: seperate function for this case */
- return NULL;
- case opid2('&','&'):
- /* TODO: seperate function for this case */
- return NULL;
+ case opid1('*'): return fold_op_mul (fold, a, b);
+ case opid1('/'): return fold_op_div (fold, a, b);
+ case opid2('|','|'): return fold_op_andor(fold, a, b, true);
+ case opid2('&','&'): return fold_op_andor(fold, a, b, false);
case opid2('?',':'):
/* TODO: seperate function for this case */
return NULL;