exprs[0], exprs[1]);
break;
case opid1('^'):
- compile_error(ast_ctx(exprs[0]), "Not Yet Implemented: bit-xor via ^");
- return false;
+ /*
+ * ^ can be implemented as:
+ * (LHS | RHS) & ~(LHS & RHS)
+ * to implement ~ we need to use -1-X, as you can see the
+ * whole process ends up becoming:
+ * (LHS | RHS) & (-1 - (LHS & RHS))
+ */
+ #define TRY_TYPE(I) \
+ if (exprs[(I)]->vtype != TYPE_FLOAT) { \
+ ast_type_to_string(exprs[(I)], ty1, sizeof(ty1)); \
+ compile_error ( \
+ ast_ctx(exprs[(I)]), \
+ "invalid type for bit-xor in %s: %s", \
+ ty1, \
+ ((I) == 0) \
+ ? "left-hand-side of expression" \
+ : "right-hand-side of expression" \
+ ); \
+ return false; \
+ }
+ TRY_TYPE(0)
+ TRY_TYPE(1)
+ #undef TRY_TYPE
+
+ if(CanConstFold(exprs[0], exprs[1])) {
+ out = (ast_expression*)parser_const_float(parser, (float)((qcint)(ConstF(0)) ^ ((qcint)(ConstF(1)))));
+ } else {
+ out = (ast_expression*)
+ ast_binary_new(
+ ctx,
+ INSTR_BITAND,
+ (ast_expression*)ast_binary_new(
+ ctx,
+ INSTR_BITOR,
+ exprs[0],
+ exprs[1]
+ ),
+ (ast_expression*)ast_binary_new(
+ ctx,
+ INSTR_SUB_F,
+ (ast_expression*)parser_const_float_neg1(parser),
+ (ast_expression*)ast_binary_new(
+ ctx,
+ INSTR_BITAND,
+ exprs[0],
+ exprs[1]
+ )
+ )
+ );
+ }
+ break;
case opid2('<','<'):
case opid2('>','>'):
ast_expression *idx, *out;
ast_value *typevar;
ast_value *funtype = parser->function->vtype;
+ lex_ctx ctx = parser_ctx(parser);
if (!parser->function->varargs) {
parseerror(parser, "function has no variable argument list");
return NULL;
}
- lex_ctx ctx = parser_ctx(parser);
-
if (!parser_next(parser) || parser->tok != '(') {
parseerror(parser, "expected parameter index and type in parenthesis");
return NULL;
* it in the predef table. And diagnose it better :)
*/
if (!OPTS_FLAG(FTEPP_PREDEFS) && ftepp_predef_exists(parser_tokval(parser))) {
- parseerror(parser, "unexpected ident: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
+ parseerror(parser, "unexpected identifier: %s (use -fftepp-predef to enable pre-defined macros)", parser_tokval(parser));
return false;
}
correct_free(&corr);
if (correct) {
- parseerror(parser, "unexpected ident: %s (did you mean %s?)", parser_tokval(parser), correct);
+ parseerror(parser, "unexpected identifier: %s (did you mean %s?)", parser_tokval(parser), correct);
mem_d(correct);
return false;
}
}
- parseerror(parser, "unexpected ident: %s", parser_tokval(parser));
+ parseerror(parser, "unexpected identifier: %s", parser_tokval(parser));
return false;
}
}
while (true)
{
if (parser->tok == TOKEN_TYPENAME) {
- parseerror(parser, "unexpected typename");
+ parseerror(parser, "unexpected typename `%s`", parser_tokval(parser));
goto onerr;
}
{
if (!parser_global_statement(parser)) {
if (parser->tok == TOKEN_EOF)
- parseerror(parser, "unexpected eof");
+ parseerror(parser, "unexpected end of file");
else if (compile_errors)
parseerror(parser, "there have been errors, bailing out");
lex_close(parser->lex);