[qfcc] Implement dot and cross product for Ruamoko

With explicit operators, even. While they're a tad verbose, they're at
least unambiguous and most importantly have the right precedence (or at
least adjustable precedence if I got it wrong, but vector ops having
high precedence than scalar or component seems reasonable to me).
This commit is contained in:
Bill Currie 2022-01-30 14:14:15 +09:00
parent 46ce37160b
commit d8f6a9445e
5 changed files with 36 additions and 1 deletions

View file

@ -90,6 +90,8 @@ get_op_string (int op)
case SHR: return ">>";
case '.': return ".";
case 'C': return "<cast>";
case CROSS: return "@cross";
case DOT: return "@dot";
default:
return "unknown";
}

View file

@ -52,6 +52,7 @@ static expr_t *func_compare (int op, expr_t *e1, expr_t *e2);
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2);
static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2);
static expr_type_t string_string[] = {
{'+', &type_string},
@ -145,7 +146,9 @@ static expr_type_t vector_float[] = {
static expr_type_t vector_vector[] = {
{'+', &type_vector},
{'-', &type_vector},
{'*', &type_float},
{DOT, &type_vector},
{CROSS, &type_vector},
{'*', 0, 0, 0, vector_multiply},
{EQ, 0, 0, 0, vector_compare},
{NE, 0, 0, 0, vector_compare},
{0, 0}
@ -738,6 +741,20 @@ vector_compare (int op, expr_t *e1, expr_t *e2)
return new_horizontal_expr (hop, e, &type_int);
}
static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2)
{
expr_t *e = new_binary_expr ('*', e1, e2);
if (options.code.progsversion < PROG_VERSION) {
// vector * vector is dot product in v6 progs (ick)
e->e.expr.type = &type_float;
} else {
// component-wise multiplication
e->e.expr.type = &type_vector;
}
return e;
}
static expr_t *
double_compare (int op, expr_t *e1, expr_t *e2)
{

View file

@ -386,6 +386,9 @@ static keyword_t qf_keywords[] = {
{"@args", ARGS, 0 },
{"@va_list", TYPE, &type_va_list },
{"@param", TYPE, &type_param },
{"@cross", CROSS, 0 },
{"@dot", DOT, 0 },
};
// These keywors are always available. Other than @system and @overload, they

View file

@ -139,6 +139,7 @@ int yylex (void);
%left SHL SHR
%left '+' '-'
%left '*' '/' '%' MOD
%left CROSS DOT
%right <op> SIZEOF UNARY INCOP
%left HYPERUNARY
%left '.' '(' '['
@ -1621,6 +1622,8 @@ expr
| expr '^' expr { $$ = binary_expr ('^', $1, $3); }
| expr '%' expr { $$ = binary_expr ('%', $1, $3); }
| expr MOD expr { $$ = binary_expr (MOD, $1, $3); }
| expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); }
| expr DOT expr { $$ = binary_expr (DOT, $1, $3); }
;
texpr

View file

@ -604,6 +604,8 @@ convert_op (int op)
case SHL: return "shl";
case SHR: return "shr";
case '.': return "load";
case CROSS: return "cross";
case DOT: return "dot";
default:
return 0;
}
@ -1568,6 +1570,14 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
if (strcmp (opcode, "ne") == 0 && is_string (get_type (e->e.expr.e1))) {
opcode = "cmp";
}
if (strcmp (opcode, "dot") == 0) {
if (is_vector (get_type (e->e.expr.e1))) {
opcode = "vdot";
}
if (is_quaternion (get_type (e->e.expr.e1))) {
opcode = "qdot";
}
}
s = new_statement (st_expr, opcode, e);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);