+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))
+ ? fold_constgen_float(fold, fold_immvalue_float(a) / fold_immvalue_float(b))
+ : NULL;
+ }
+
+ if (isvectoronly(a)) {
+ if (fold_possible(a) && fold_possible(b))
+ return fold_constgen_vector(fold, vec3_mulvf(fold_immvalue_vector(a), 1.0f / fold_immvalue_float(b)));
+ else if (fold_possible(b))
+ return fold_constgen_float (fold, 1.0f / fold_immvalue_float(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;
+}
+
+static GMQCC_INLINE ast_expression *fold_op_lteqgt(fold_t *fold, ast_value *a, ast_value *b) {
+ if (!isfloats(a, b))
+ return NULL;
+
+ if (fold_immvalue_float(a) < fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[2];/* -1 */
+ if (fold_immvalue_float(a) == fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[0];/* 0 */
+ if (fold_immvalue_float(a) > fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[1];/* 1 */
+
+ return NULL;
+}
+