mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-05 08:51:28 +00:00
[qfcc] Add parameterized types to Ruamoko
The end goal is to allow generic and/or template functions, but this allows types to be specified parametrically, eg vectors of specific type and width, with widths of one becoming scalars. Matrices are currently completely broken as I haven't decided on how to represent the columns (rows is represented by width (column-major storage)), and bools are only partially supported (need to sort out 32-bit vs 64-bit bools).
This commit is contained in:
parent
bdac574e69
commit
86b3d0db7b
4 changed files with 193 additions and 9 deletions
|
@ -65,7 +65,7 @@ typedef union rua_val_s {
|
|||
unsigned size;
|
||||
specifier_t spec;
|
||||
void *pointer; // for ensuring pointer values are null
|
||||
struct type_s *type;
|
||||
const struct type_s *type;
|
||||
const struct expr_s *expr;
|
||||
struct expr_s *mut_expr;
|
||||
struct element_s *element;
|
||||
|
|
|
@ -150,6 +150,7 @@ void new_typedef (const char *name, type_t *type);
|
|||
const type_t *field_type (const type_t *aux);
|
||||
const type_t *pointer_type (const type_t *aux);
|
||||
const type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure));
|
||||
const type_t *matrix_type (const type_t *ele_type, int cols, int rows) __attribute__((pure));
|
||||
const type_t *base_type (const type_t *vec_type) __attribute__((pure));
|
||||
|
||||
/** Return an integral type of same size as the provided type.
|
||||
|
@ -167,6 +168,21 @@ const type_t *base_type (const type_t *vec_type) __attribute__((pure));
|
|||
const type_t *int_type (const type_t *base) __attribute__((pure));
|
||||
const type_t *uint_type (const type_t *base) __attribute__((pure));
|
||||
|
||||
/** Return a bool type of same size as the provided type.
|
||||
|
||||
Any 32-bit type will produce type_bool (or one of bvec2, bvec3 or bvec4).
|
||||
Any 64-bit type will produce type_long (lor one of lvec2, lvec3, or lvec4).
|
||||
|
||||
Both type_width() and type_size() of the returned type will match the
|
||||
provided type.
|
||||
|
||||
\param base Type on which the return type will be based.
|
||||
\return Matching boolean type (bool, long, or a vector form), or
|
||||
null if no such match can be made.
|
||||
FIXME 64-bit bool types
|
||||
*/
|
||||
const type_t *bool_type (const type_t *base) __attribute__((pure));
|
||||
|
||||
/** Return a floating point type of same size as the provided type.
|
||||
|
||||
Any 32-bit type will produce type_float (or one of vec2, vec3 or vec4).
|
||||
|
@ -204,6 +220,7 @@ int is_integral (const type_t *type) __attribute__((pure));
|
|||
int is_real (const type_t *type) __attribute__((pure));
|
||||
int is_scalar (const type_t *type) __attribute__((pure));
|
||||
int is_nonscalar (const type_t *type) __attribute__((pure));
|
||||
int is_matrix (const type_t *type) __attribute__((pure));
|
||||
int is_math (const type_t *type) __attribute__((pure));
|
||||
int is_struct (const type_t *type) __attribute__((pure));
|
||||
int is_union (const type_t *type) __attribute__((pure));
|
||||
|
@ -215,6 +232,8 @@ int type_promotes (const type_t *dst, const type_t *src) __attribute__((pure));
|
|||
int type_same (const type_t *dst, const type_t *src) __attribute__((pure));
|
||||
int type_size (const type_t *type) __attribute__((pure));
|
||||
int type_width (const type_t *type) __attribute__((pure));
|
||||
int type_rows (const type_t *type) __attribute__((pure));
|
||||
int type_cols (const type_t *type) __attribute__((pure));
|
||||
int type_aligned_size (const type_t *type) __attribute__((pure));
|
||||
|
||||
void init_types (void);
|
||||
|
|
|
@ -160,6 +160,10 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
|||
%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE
|
||||
%token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS
|
||||
|
||||
%token AT_FIELD AT_POINTER AT_ARRAY
|
||||
%token AT_BASE AT_WIDTH AT_VECTOR AT_ROWS AT_COLS AT_MATRIX
|
||||
%token AT_INT AT_UINT AT_BOOL AT_FLOAT
|
||||
|
||||
%type <spec> storage_class save_storage
|
||||
%type <spec> typespec typespec_reserved typespec_nonreserved
|
||||
%type <spec> handle
|
||||
|
@ -172,6 +176,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
|||
%type <spec> param_declarator_nostarttypename
|
||||
%type <spec> absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec
|
||||
%type <spec> qc_comma
|
||||
%type <type> type_param type_expr type_ref
|
||||
|
||||
%type <attribute> attribute_list attribute
|
||||
|
||||
|
@ -899,6 +904,7 @@ typespec
|
|||
|
||||
typespec_reserved
|
||||
: TYPE_SPEC
|
||||
| type_expr { $$ = make_spec ($1, 0, 0, 0); }
|
||||
| algebra_specifier %prec LOW
|
||||
| algebra_specifier '.' attribute
|
||||
{
|
||||
|
@ -1019,6 +1025,66 @@ storage_class
|
|||
}
|
||||
;
|
||||
|
||||
type_expr
|
||||
: AT_FIELD '(' type_param ')' { $$ = field_type ($3); }
|
||||
| AT_POINTER '(' type_param ')' { $$ = pointer_type ($3); }
|
||||
| AT_ARRAY '(' type_param ')' { $$ = array_type ($3, 0); }
|
||||
| AT_ARRAY '(' type_param ',' expr ')'
|
||||
{
|
||||
auto count = $5;
|
||||
auto type = $3;
|
||||
if (!is_int_val (count)) {
|
||||
error (count, "count must be an int constant");
|
||||
} else {
|
||||
type = vector_type (type, expr_int (count));
|
||||
}
|
||||
$$ = type;
|
||||
}
|
||||
| AT_BASE '(' type_param ')' { $$ = base_type ($3); }
|
||||
| AT_VECTOR '(' type_param ')' { $$ = vector_type ($3, 0); }
|
||||
| AT_VECTOR '(' type_param ',' expr ')'
|
||||
{
|
||||
auto width = $5;
|
||||
auto type = $3;
|
||||
if (!is_int_val (width)) {
|
||||
error (width, "width must be an int constant");
|
||||
} else {
|
||||
type = vector_type (type, expr_int (width));
|
||||
}
|
||||
$$ = type;
|
||||
}
|
||||
| AT_MATRIX '(' type_param ')' { $$ = matrix_type ($3, 0, 0); }
|
||||
| AT_MATRIX '(' type_param ',' expr ',' expr ')'
|
||||
{
|
||||
auto cols = $5;
|
||||
auto rows = $7;
|
||||
auto type = $3;
|
||||
if (!is_int_val (cols)) {
|
||||
error (cols, "cols must be an int constant");
|
||||
} else if (!is_int_val (rows)) {
|
||||
error (rows, "rows must be an int constant");
|
||||
} else {
|
||||
type = matrix_type (type, expr_int (cols), expr_int (rows));
|
||||
}
|
||||
$$ = type;
|
||||
}
|
||||
| AT_INT '(' type_param ')' { $$ = int_type ($3); }
|
||||
| AT_UINT '(' type_param ')' { $$ = uint_type ($3); }
|
||||
| AT_BOOL '(' type_param ')' { $$ = bool_type ($3); }
|
||||
| AT_FLOAT '(' type_param ')' { $$ = float_type ($3); }
|
||||
;
|
||||
|
||||
type_param
|
||||
: type_expr
|
||||
| type_ref
|
||||
;
|
||||
|
||||
type_ref
|
||||
: TYPE_SPEC { $$ = $1.type; }
|
||||
| TYPE_NAME { $$ = $1.type; }
|
||||
| CLASS_NAME { $$ = $1->type; }
|
||||
;
|
||||
|
||||
attribute_list
|
||||
: attribute
|
||||
| attribute_list ',' attribute
|
||||
|
@ -1739,6 +1805,18 @@ unary_expr
|
|||
{
|
||||
$$ = sizeof_expr (0, $3.type);
|
||||
}
|
||||
| AT_WIDTH '(' type_param ')'
|
||||
{
|
||||
$$ = new_int_expr (type_width ($3), false);
|
||||
}
|
||||
| AT_ROWS '(' type_param ')'
|
||||
{
|
||||
$$ = new_int_expr (type_rows ($3), false);
|
||||
}
|
||||
| AT_COLS '(' type_param ')'
|
||||
{
|
||||
$$ = new_int_expr (type_cols ($3), false);
|
||||
}
|
||||
| vector_expr { $$ = new_vector_list ($1); }
|
||||
| obj_expr { $$ = $1; }
|
||||
;
|
||||
|
@ -2568,13 +2646,27 @@ static keyword_t qf_keywords[] = {
|
|||
|
||||
{"@hadamard", QC_HADAMARD, },
|
||||
{"@cross", QC_CROSS, },
|
||||
{"@dot", QC_DOT, },
|
||||
{"@dot", QC_DOT, },
|
||||
{"@wedge", QC_WEDGE, },
|
||||
{"@regressive", QC_REGRESSIVE, },
|
||||
{"@geometric", QC_GEOMETRIC, },
|
||||
{"@algebra", QC_ALGEBRA, },
|
||||
{"@algebra", QC_ALGEBRA, },
|
||||
{"@dual", QC_DUAL, },
|
||||
{"@undual", QC_UNDUAL, },
|
||||
|
||||
{"@field", QC_AT_FIELD, },
|
||||
{"@pointer", QC_AT_POINTER, },
|
||||
{"@array", QC_AT_ARRAY, },
|
||||
{"@base", QC_AT_BASE, },
|
||||
{"@width", QC_AT_WIDTH, },
|
||||
{"@vector", QC_AT_VECTOR, },
|
||||
{"@rows", QC_AT_ROWS, },
|
||||
{"@cols", QC_AT_COLS, },
|
||||
{"@matrix", QC_AT_MATRIX, },
|
||||
{"@int", QC_AT_INT, },
|
||||
{"@uint", QC_AT_UINT, },
|
||||
{"@bool", QC_AT_BOOL, },
|
||||
{"@float", QC_AT_FLOAT, },
|
||||
};
|
||||
|
||||
// These keywors are always available. Other than the @ keywords, they
|
||||
|
|
|
@ -105,12 +105,6 @@ type_t type_auto = {
|
|||
};
|
||||
#include "tools/qfcc/include/mat_types.h"
|
||||
|
||||
#define VEC_TYPE(type_name, base_type) &type_##type_name,
|
||||
static type_t *vec_types[] = {
|
||||
#include "tools/qfcc/include/vec_types.h"
|
||||
0
|
||||
};
|
||||
|
||||
type_t type_bool = {
|
||||
.type = ev_int, //FIXME create bool type?
|
||||
.name = "bool",
|
||||
|
@ -140,6 +134,22 @@ type_t type_bvec4 = {
|
|||
.meta = ty_basic,
|
||||
};
|
||||
|
||||
#define VEC_TYPE(type_name, base_type) &type_##type_name,
|
||||
static type_t *vec_types[] = {
|
||||
#include "tools/qfcc/include/vec_types.h"
|
||||
&type_bool,
|
||||
&type_bvec2,
|
||||
&type_bvec3,
|
||||
&type_bvec4,
|
||||
0
|
||||
};
|
||||
|
||||
#define MAT_TYPE(type_name, base_type, align_as) &type_##type_name,
|
||||
static type_t *mat_types[] = {
|
||||
#include "tools/qfcc/include/mat_types.h"
|
||||
0
|
||||
};
|
||||
|
||||
type_t *type_nil;
|
||||
type_t *type_default;
|
||||
type_t *type_long_int;
|
||||
|
@ -664,6 +674,21 @@ vector_type (const type_t *ele_type, int width)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const type_t *
|
||||
matrix_type (const type_t *ele_type, int cols, int rows)
|
||||
{
|
||||
if (cols == 1) {
|
||||
return vector_type (ele_type, rows);
|
||||
}
|
||||
for (type_t **mtype = mat_types; *mtype; mtype++) {
|
||||
if ((*mtype)->type == ele_type->type
|
||||
&& (*mtype)->width == rows) {
|
||||
return *mtype;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const type_t *
|
||||
base_type (const type_t *vec_type)
|
||||
{
|
||||
|
@ -712,6 +737,22 @@ uint_type (const type_t *base)
|
|||
return vector_type (base, width);
|
||||
}
|
||||
|
||||
const type_t *
|
||||
bool_type (const type_t *base)
|
||||
{
|
||||
int width = type_width (base);
|
||||
base = base_type (base);
|
||||
if (!base) {
|
||||
return 0;
|
||||
}
|
||||
if (type_size (base) == 1) {
|
||||
base = &type_bool;
|
||||
} else if (type_size (base) == 2) {
|
||||
base = &type_long;
|
||||
}
|
||||
return vector_type (base, width);
|
||||
}
|
||||
|
||||
const type_t *
|
||||
float_type (const type_t *base)
|
||||
{
|
||||
|
@ -1212,6 +1253,15 @@ is_scalar (const type_t *type)
|
|||
return is_real (type) || is_integral (type);
|
||||
}
|
||||
|
||||
int
|
||||
is_matrix (const type_t *type)
|
||||
{
|
||||
if (!type || type->meta != ty_basic) {
|
||||
return 0;
|
||||
}
|
||||
return -1;//FIXME
|
||||
}
|
||||
|
||||
int
|
||||
is_nonscalar (const type_t *type)
|
||||
{
|
||||
|
@ -1457,6 +1507,29 @@ type_width (const type_t *type)
|
|||
internal_error (0, "invalid type meta: %d", type->meta);
|
||||
}
|
||||
|
||||
int
|
||||
type_cols (const type_t *type)
|
||||
{
|
||||
if (is_matrix (type)) {
|
||||
return 0; //FIXME
|
||||
} else {
|
||||
// non-matrices have only 1 column
|
||||
return type_width (type);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
type_rows (const type_t *type)
|
||||
{
|
||||
if (is_matrix (type)) {
|
||||
return 0; //FIXME
|
||||
} else {
|
||||
// vectors are vertical (includes vector and quaternion), other types
|
||||
// have width of 1, thus rows == width
|
||||
return type_width (type);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
type_aligned_size (const type_t *type)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue