mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[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.
This commit is contained in:
parent
7b80ec2a14
commit
b43fe9ddc5
1 changed files with 86 additions and 0 deletions
|
@ -34,6 +34,7 @@
|
||||||
#include "QF/math/bitop.h"
|
#include "QF/math/bitop.h"
|
||||||
|
|
||||||
#include "tools/qfcc/include/algebra.h"
|
#include "tools/qfcc/include/algebra.h"
|
||||||
|
#include "tools/qfcc/include/class.h"
|
||||||
#include "tools/qfcc/include/diagnostic.h"
|
#include "tools/qfcc/include/diagnostic.h"
|
||||||
#include "tools/qfcc/include/expr.h"
|
#include "tools/qfcc/include/expr.h"
|
||||||
#include "tools/qfcc/include/qfcc.h"
|
#include "tools/qfcc/include/qfcc.h"
|
||||||
|
@ -73,6 +74,90 @@ proc_uexpr (const expr_t *expr)
|
||||||
return unary_expr (expr->expr.op, e1);
|
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 *
|
static const expr_t *
|
||||||
proc_block (const expr_t *expr)
|
proc_block (const expr_t *expr)
|
||||||
{
|
{
|
||||||
|
@ -271,6 +356,7 @@ expr_process (const expr_t *expr)
|
||||||
static process_f funcs[ex_count] = {
|
static process_f funcs[ex_count] = {
|
||||||
[ex_expr] = proc_expr,
|
[ex_expr] = proc_expr,
|
||||||
[ex_uexpr] = proc_uexpr,
|
[ex_uexpr] = proc_uexpr,
|
||||||
|
[ex_field] = proc_field,
|
||||||
[ex_block] = proc_block,
|
[ex_block] = proc_block,
|
||||||
[ex_symbol] = proc_symbol,
|
[ex_symbol] = proc_symbol,
|
||||||
[ex_vector] = proc_vector,
|
[ex_vector] = proc_vector,
|
||||||
|
|
Loading…
Reference in a new issue