From 92b476bf042eebcec9362a673005b9e3b2e90fdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Jan 2025 18:26:44 +0900 Subject: [PATCH] [qfcc] Make type attribute functions usable in expressions Unfortunately, this require using different syntax for the two cases: type.attr works in cases where types are expected, but not in expressions (lots of shift/reduce and reduce/reduce conflicts). However, treating type like an Objective-C class works nicely, though `[type attrib(params)]` looks a little odd. However, this allows using generic types to provide function calls (eg, converting texture coordinates). --- tools/qfcc/include/attribute.h | 1 + tools/qfcc/source/attribute.c | 17 +++++++++++------ tools/qfcc/source/dot_expr.c | 7 +++++-- tools/qfcc/source/qc-parse.y | 11 ++++++++++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/include/attribute.h b/tools/qfcc/include/attribute.h index a5ffaa2a9..022b8be24 100644 --- a/tools/qfcc/include/attribute.h +++ b/tools/qfcc/include/attribute.h @@ -38,6 +38,7 @@ typedef struct attribute_s { } attribute_t; struct expr_s; +attribute_t *new_attrfunc(const char *name, const struct expr_s *params); attribute_t *new_attribute(const char *name, const struct expr_s *params); #endif//attribute_h diff --git a/tools/qfcc/source/attribute.c b/tools/qfcc/source/attribute.c index a22c72d87..247b41a48 100644 --- a/tools/qfcc/source/attribute.c +++ b/tools/qfcc/source/attribute.c @@ -40,6 +40,16 @@ ALLOC_STATE (attribute_t, attributes); +attribute_t * +new_attrfunc (const char *name, const expr_t *params) +{ + attribute_t *attr; + ALLOC (16384, attribute_t, attributes, attr); + attr->name = save_string (name); + attr->params = params; + return attr; +} + attribute_t * new_attribute(const char *name, const expr_t *params) { @@ -68,10 +78,5 @@ new_attribute(const char *name, const expr_t *params) if (err) { return nullptr; } - - attribute_t *attr; - ALLOC (16384, attribute_t, attributes, attr); - attr->name = save_string (name); - attr->params = params; - return attr; + return new_attrfunc (name, params); } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 79defeaf1..65356748d 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -351,8 +351,11 @@ print_type_expr (dstring_t *dstr, const expr_t *e, int level, int id, } } else if (e->typ.attrib) { auto attrib = e->typ.attrib; - _print_expr (dstr, attrib->params, level + 1, id, nullptr); - dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, attrib->params); + if (attrib->params) { + _print_expr (dstr, attrib->params, level + 1, id, nullptr); + dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, + attrib->params); + } str = attrib->name; } else if (e->typ.sym) { str = e->typ.sym->name; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f48735309..a36e0f6c1 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -189,7 +189,7 @@ int yylex (YYSTYPE *yylval, YYLTYPE *yylloc); %type initdecl notype_initdecl %type initdecls notype_initdecls -%type attribute_list attribute +%type attribute_list attribute attrfunc %type function_params %type qc_func_params qc_param_list qc_first_param qc_param @@ -1392,6 +1392,11 @@ attribute | NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); } ; +attrfunc + : NAME %prec LOW { $$ = new_attrfunc ($1->name, 0); } + | NAME '(' expr_list ')' { $$ = new_attrfunc ($1->name, $3); } + ; + tag : NAME ; algebra_specifier @@ -2839,6 +2844,10 @@ obj_messageexpr scoped_src_loc ($receiver); $$ = new_message_expr ($receiver, $messageargs); } + | '[' TYPE_NAME[spec] attrfunc ']' + { + $$ = type_attribute ($spec, $attrfunc); + } ; receiver