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))
+ */
+ if (NotSameType(TYPE_FLOAT)) {
+ compile_error(ctx, "invalid types used in expression: cannot perform bit operations between types %s and %s",
+ type_name[exprs[0]->vtype],
+ type_name[exprs[1]->vtype]);
+ return false;
+ }
+
+ if(CanConstFold(exprs[0], exprs[1])) {
+ out = (ast_expression*)parser_const_float(parser, (float)((qcint)(ConstF(0)) ^ ((qcint)(ConstF(1)))));
+ } else {
+ ast_binary *expr = 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]
+ )
+ );
+ expr->refs = AST_REF_NONE;
+
+ out = (ast_expression*)
+ ast_binary_new(
+ ctx,
+ INSTR_BITAND,
+ (ast_expression*)ast_binary_new(
+ ctx,
+ INSTR_BITOR,
+ exprs[0],
+ exprs[1]
+ ),
+ (ast_expression*)expr
+ );
+ }
+ break;
case opid2('<','<'):
case opid2('>','>'):
} else {
ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]);
- eq->refs = (ast_binary_ref)false; /* references nothing */
+ eq->refs = AST_REF_NONE;
/* if (lt) { */
out = (ast_expression*)ast_ternary_new(ctx,
for (i = 0; i < paramcount; ++i)
vec_push(call->params, sy->out[fid+1 + i].out);
vec_shrinkby(sy->out, paramcount);
- (void)!ast_call_check_types(call);
+ (void)!ast_call_check_types(call, parser->function->vtype->expression.varparam);
if (parser->max_param_count < paramcount)
parser->max_param_count = paramcount;
ast_expression *idx, *out;
ast_value *typevar;
ast_value *funtype = parser->function->vtype;
+ lex_ctx ctx = parser_ctx(parser);
- lex_ctx ctx = parser_ctx(parser);
+ if (!parser->function->varargs) {
+ parseerror(parser, "function has no variable argument list");
+ return NULL;
+ }
if (!parser_next(parser) || parser->tok != '(') {
parseerror(parser, "expected parameter index and type in parenthesis");
return NULL;
if (parser->tok != ',') {
- ast_unref(idx);
- parseerror(parser, "expected comma after parameter index");
- return NULL;
+ if (parser->tok != ')') {
+ ast_unref(idx);
+ parseerror(parser, "expected comma after parameter index");
+ return NULL;
+ }
+ /* vararg piping: ...(start) */
+ out = (ast_expression*)ast_argpipe_new(ctx, idx);
+ return out;
}
if (!parser_next(parser) || (parser->tok != TOKEN_IDENT && parser->tok != TOKEN_TYPENAME)) {
return NULL;
}
-#if 0
- if (!parser_next(parser)) {
- ast_unref(idx);
- ast_delete(typevar);
- parseerror(parser, "parse error after vararg");
- return NULL;
- }
-#endif
-
- if (!parser->function->varargs) {
- ast_unref(idx);
- ast_delete(typevar);
- parseerror(parser, "function has no variable argument list");
- return NULL;
- }
-
if (funtype->expression.varparam &&
!ast_compare_type((ast_expression*)typevar, (ast_expression*)funtype->expression.varparam))
{
* 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;
}
* We should also consider adding correction tables for
* other things as well.
*/
- if (OPTS_OPTION_BOOL(OPTION_CORRECTION)) {
+ if (OPTS_OPTION_BOOL(OPTION_CORRECTION) && strlen(parser_tokval(parser)) <= 16) {
correction_t corr;
correct_init(&corr);
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;
}
}
vec_push(func->blocks, block);
-
+
parser->function = old;
if (!parser_leaveblock(parser))
{
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);