From b43fe9ddc5b72e2e9f62419cad4683e78c1632ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Nov 2024 12:15:24 +0900 Subject: [PATCH] [qfcc] Process field expressions I'm not sure they work yet as the spirv output doesn't support them yet, but after an lvalue fix (next), this gets field accesses to code-gen. --- tools/qfcc/source/expr_process.c | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index a36813bb0..dd1e731b8 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -34,6 +34,7 @@ #include "QF/math/bitop.h" #include "tools/qfcc/include/algebra.h" +#include "tools/qfcc/include/class.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/qfcc.h" @@ -73,6 +74,90 @@ proc_uexpr (const expr_t *expr) return unary_expr (expr->expr.op, e1); } +static const expr_t * +proc_field (const expr_t *expr) +{ + auto object = expr_process (expr->field.object); + auto member = expr->field.member; + if (is_error (object)) { + return object; + } + if (object->type == ex_symbol && object->symbol->sy_type == sy_namespace) { + if (member->type != ex_symbol) { + return error (member, "symbol required for namespace access"); + } + auto namespace = object->symbol->namespace; + auto sym = symtab_lookup (namespace, member->symbol->name); + if (!sym) { + return error (member, "%s not in %s namespace", + member->symbol->name, object->symbol->name); + } + return new_symbol_expr (sym); + } + + auto obj_type = get_type (object); + if (!obj_type) { + return new_error_expr (); + } + + if (is_reference (obj_type)) { + obj_type = dereference_type (obj_type); + object = pointer_deref (object); + } + + if (is_class (obj_type)) { + //Class instance variables aren't allowed and thus declaring one + //is treated as an error, so this is a follow-on error. + return new_error_expr (); + } + if (is_pointer (obj_type)) { + auto ref_type = dereference_type (obj_type); + if (!(is_struct (ref_type) || is_union (ref_type) + || is_class (ref_type))) { + return type_mismatch (object, member, '.'); + } + object = pointer_deref (object); + obj_type = ref_type; + } + if (is_algebra (obj_type)) { + return algebra_field_expr (object, member); + } + if (is_entity (obj_type)) { + obj_type = &type_entity; + } + if (is_nonscalar (obj_type)) { + auto field = get_struct_field (obj_type, object, member); + if (!field) { + if (member->type != ex_symbol) { + return error (member, "invalid swizzle"); + } + return new_swizzle_expr (object, member->symbol->name); + } + member = new_symbol_expr (field); + } else if (is_struct (obj_type) || is_union (obj_type)) { + auto field = get_struct_field (obj_type, object, member); + if (!field) { + return new_error_expr (); + } + member = new_symbol_expr (field); + } else if (is_class (obj_type)) { + if (member->type != ex_symbol) { + return error (member, "invalid class member access"); + } + auto class = obj_type->class; + auto sym = member->symbol; + int protected = class_access (current_class, class); + auto ivar = class_find_ivar (class, protected, sym->name); + if (!ivar) { + return new_error_expr (); + } + member = new_symbol_expr (ivar); + } + auto e = new_field_expr (object, member); + e->field.type = member->symbol->type; + return e; +} + static const expr_t * proc_block (const expr_t *expr) { @@ -271,6 +356,7 @@ expr_process (const expr_t *expr) static process_f funcs[ex_count] = { [ex_expr] = proc_expr, [ex_uexpr] = proc_uexpr, + [ex_field] = proc_field, [ex_block] = proc_block, [ex_symbol] = proc_symbol, [ex_vector] = proc_vector,