mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-30 08:20:40 +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;
|
unsigned size;
|
||||||
specifier_t spec;
|
specifier_t spec;
|
||||||
void *pointer; // for ensuring pointer values are null
|
void *pointer; // for ensuring pointer values are null
|
||||||
struct type_s *type;
|
const struct type_s *type;
|
||||||
const struct expr_s *expr;
|
const struct expr_s *expr;
|
||||||
struct expr_s *mut_expr;
|
struct expr_s *mut_expr;
|
||||||
struct element_s *element;
|
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 *field_type (const type_t *aux);
|
||||||
const type_t *pointer_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 *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));
|
const type_t *base_type (const type_t *vec_type) __attribute__((pure));
|
||||||
|
|
||||||
/** Return an integral type of same size as the provided type.
|
/** 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 *int_type (const type_t *base) __attribute__((pure));
|
||||||
const type_t *uint_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.
|
/** 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).
|
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_real (const type_t *type) __attribute__((pure));
|
||||||
int is_scalar (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_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_math (const type_t *type) __attribute__((pure));
|
||||||
int is_struct (const type_t *type) __attribute__((pure));
|
int is_struct (const type_t *type) __attribute__((pure));
|
||||||
int is_union (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_same (const type_t *dst, const type_t *src) __attribute__((pure));
|
||||||
int type_size (const type_t *type) __attribute__((pure));
|
int type_size (const type_t *type) __attribute__((pure));
|
||||||
int type_width (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));
|
int type_aligned_size (const type_t *type) __attribute__((pure));
|
||||||
|
|
||||||
void init_types (void);
|
void init_types (void);
|
||||||
|
|
|
@ -160,6 +160,10 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
||||||
%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE
|
%token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE
|
||||||
%token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS
|
%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> storage_class save_storage
|
||||||
%type <spec> typespec typespec_reserved typespec_nonreserved
|
%type <spec> typespec typespec_reserved typespec_nonreserved
|
||||||
%type <spec> handle
|
%type <spec> handle
|
||||||
|
@ -172,6 +176,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc);
|
||||||
%type <spec> param_declarator_nostarttypename
|
%type <spec> param_declarator_nostarttypename
|
||||||
%type <spec> absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec
|
%type <spec> absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec
|
||||||
%type <spec> qc_comma
|
%type <spec> qc_comma
|
||||||
|
%type <type> type_param type_expr type_ref
|
||||||
|
|
||||||
%type <attribute> attribute_list attribute
|
%type <attribute> attribute_list attribute
|
||||||
|
|
||||||
|
@ -899,6 +904,7 @@ typespec
|
||||||
|
|
||||||
typespec_reserved
|
typespec_reserved
|
||||||
: TYPE_SPEC
|
: TYPE_SPEC
|
||||||
|
| type_expr { $$ = make_spec ($1, 0, 0, 0); }
|
||||||
| algebra_specifier %prec LOW
|
| algebra_specifier %prec LOW
|
||||||
| algebra_specifier '.' attribute
|
| 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_list
|
||||||
: attribute
|
: attribute
|
||||||
| attribute_list ',' attribute
|
| attribute_list ',' attribute
|
||||||
|
@ -1739,6 +1805,18 @@ unary_expr
|
||||||
{
|
{
|
||||||
$$ = sizeof_expr (0, $3.type);
|
$$ = 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); }
|
| vector_expr { $$ = new_vector_list ($1); }
|
||||||
| obj_expr { $$ = $1; }
|
| obj_expr { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
@ -2568,13 +2646,27 @@ static keyword_t qf_keywords[] = {
|
||||||
|
|
||||||
{"@hadamard", QC_HADAMARD, },
|
{"@hadamard", QC_HADAMARD, },
|
||||||
{"@cross", QC_CROSS, },
|
{"@cross", QC_CROSS, },
|
||||||
{"@dot", QC_DOT, },
|
{"@dot", QC_DOT, },
|
||||||
{"@wedge", QC_WEDGE, },
|
{"@wedge", QC_WEDGE, },
|
||||||
{"@regressive", QC_REGRESSIVE, },
|
{"@regressive", QC_REGRESSIVE, },
|
||||||
{"@geometric", QC_GEOMETRIC, },
|
{"@geometric", QC_GEOMETRIC, },
|
||||||
{"@algebra", QC_ALGEBRA, },
|
{"@algebra", QC_ALGEBRA, },
|
||||||
{"@dual", QC_DUAL, },
|
{"@dual", QC_DUAL, },
|
||||||
{"@undual", QC_UNDUAL, },
|
{"@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
|
// 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"
|
#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_t type_bool = {
|
||||||
.type = ev_int, //FIXME create bool type?
|
.type = ev_int, //FIXME create bool type?
|
||||||
.name = "bool",
|
.name = "bool",
|
||||||
|
@ -140,6 +134,22 @@ type_t type_bvec4 = {
|
||||||
.meta = ty_basic,
|
.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_nil;
|
||||||
type_t *type_default;
|
type_t *type_default;
|
||||||
type_t *type_long_int;
|
type_t *type_long_int;
|
||||||
|
@ -664,6 +674,21 @@ vector_type (const type_t *ele_type, int width)
|
||||||
return 0;
|
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 *
|
const type_t *
|
||||||
base_type (const type_t *vec_type)
|
base_type (const type_t *vec_type)
|
||||||
{
|
{
|
||||||
|
@ -712,6 +737,22 @@ uint_type (const type_t *base)
|
||||||
return vector_type (base, width);
|
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 *
|
const type_t *
|
||||||
float_type (const type_t *base)
|
float_type (const type_t *base)
|
||||||
{
|
{
|
||||||
|
@ -1212,6 +1253,15 @@ is_scalar (const type_t *type)
|
||||||
return is_real (type) || is_integral (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
|
int
|
||||||
is_nonscalar (const type_t *type)
|
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);
|
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
|
int
|
||||||
type_aligned_size (const type_t *type)
|
type_aligned_size (const type_t *type)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue