mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Support references in expressions
While a reference var can't be initialized yet, using them seems to work in that they get dereferenced when the value needs to be read or written (though I haven't seen any generated code for them yet).
This commit is contained in:
parent
164c949796
commit
af42b8e221
5 changed files with 60 additions and 19 deletions
|
@ -979,6 +979,7 @@ const expr_t *conditional_expr (const expr_t *cond, const expr_t *e1,
|
|||
const expr_t *incop_expr (int op, const expr_t *e, int postop);
|
||||
const expr_t *array_expr (const expr_t *array, const expr_t *index);
|
||||
const expr_t *deref_pointer_expr (const expr_t *pointer);
|
||||
const expr_t *pointer_deref (const expr_t *pointer);
|
||||
const expr_t *offset_pointer_expr (const expr_t *pointer, const expr_t *offset);
|
||||
const expr_t *address_expr (const expr_t *e1, const type_t *t);
|
||||
const expr_t *build_if_statement (int not, const expr_t *test, const expr_t *s1,
|
||||
|
|
|
@ -254,6 +254,13 @@ param_mismatch (const expr_t *e, int param, const char *fn,
|
|||
get_type_string (t2));
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
reference_error (const expr_t *e, const type_t *dst, const type_t *src)
|
||||
{
|
||||
return error (e, "cannot bind reference of type %s to %s",
|
||||
get_type_string (dst), get_type_string (src));
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
test_error (const expr_t *e, const type_t *t)
|
||||
{
|
||||
|
@ -1988,7 +1995,8 @@ vararg_integer (const expr_t *e)
|
|||
}
|
||||
|
||||
const expr_t *
|
||||
build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *params)
|
||||
build_function_call (const expr_t *fexpr, const type_t *ftype,
|
||||
const expr_t *params)
|
||||
{
|
||||
int param_count = 0;
|
||||
expr_t *call;
|
||||
|
@ -2010,7 +2018,6 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (ftype->func.num_params < -1) {
|
||||
if (options.code.max_params >= 0
|
||||
&& arg_count > options.code.max_params) {
|
||||
|
@ -2066,15 +2073,24 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
|||
}
|
||||
if (i < param_count) {
|
||||
auto param_type = ftype->func.param_types[i];
|
||||
if (e->type == ex_nil)
|
||||
e = convert_nil (e, t = param_type);
|
||||
if (e->type == ex_bool)
|
||||
e = convert_from_bool (e, param_type);
|
||||
if (e->type == ex_error) {
|
||||
err = e;
|
||||
continue;
|
||||
}
|
||||
auto param_qual = ftype->func.param_quals[i];
|
||||
|
||||
if (is_reference (param_type) && param_qual != pq_in) {
|
||||
internal_error (e, "qualified reference param (not yet)");
|
||||
}
|
||||
if (is_reference (param_type) && !is_reference (t)) {
|
||||
if (!is_lvalue (e)) {
|
||||
err = error (e, "cannot pass non-lvalue by reference");
|
||||
}
|
||||
if (!err && dereference_type (param_type) != t) {
|
||||
err = reference_error (e, param_type, t);
|
||||
}
|
||||
} else if (!is_reference (param_type) && is_reference (t)) {
|
||||
t = dereference_type (t);
|
||||
}
|
||||
if (e->type == ex_nil) {
|
||||
t = param_type;
|
||||
}
|
||||
if (param_qual == pq_out || param_qual == pq_inout) {
|
||||
//FIXME should be able to use something like *foo() as
|
||||
//an out or inout arg
|
||||
|
@ -2102,13 +2118,9 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
|||
}
|
||||
t = param_type;
|
||||
} else {
|
||||
if (e->type == ex_nil)
|
||||
e = convert_nil (e, t = type_nil);
|
||||
if (e->type == ex_bool)
|
||||
e = convert_from_bool (e, get_type (e));
|
||||
if (is_int_val (e)
|
||||
&& options.code.progsversion == PROG_ID_VERSION)
|
||||
e = cast_expr (&type_float, e);
|
||||
if (e->type == ex_nil) {
|
||||
t = type_nil;
|
||||
}
|
||||
if (options.code.promote_float) {
|
||||
if (is_scalar (get_type (e)) && is_float (get_type (e))) {
|
||||
t = &type_double;
|
||||
|
@ -2180,7 +2192,18 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *par
|
|||
inout->inout.out = e;
|
||||
e = inout;
|
||||
} else {
|
||||
e = cast_expr (arg_types[i], e);
|
||||
if (is_reference (arg_types[i])) {
|
||||
if (is_reference (get_type (e))) {
|
||||
// just copy the param, so no op
|
||||
} else {
|
||||
e = address_expr (e, nullptr);
|
||||
}
|
||||
} else {
|
||||
if (is_reference (get_type (e))) {
|
||||
e = pointer_deref (e);
|
||||
}
|
||||
e = cast_expr (arg_types[i], e);
|
||||
}
|
||||
}
|
||||
expr_prepend_expr (args, e);
|
||||
}
|
||||
|
|
|
@ -320,6 +320,9 @@ assign_expr (const expr_t *dst, const expr_t *src)
|
|||
if ((expr = check_valid_lvalue (dst))) {
|
||||
return expr;
|
||||
}
|
||||
if (is_reference (get_type (dst))) {
|
||||
dst = pointer_deref (dst);
|
||||
}
|
||||
dst_type = get_type (dst);
|
||||
if (!dst_type) {
|
||||
internal_error (dst, "dst_type broke in assign_expr");
|
||||
|
@ -347,6 +350,9 @@ assign_expr (const expr_t *dst, const expr_t *src)
|
|||
return src;
|
||||
}
|
||||
}
|
||||
if (is_reference (get_type (src))) {
|
||||
src = pointer_deref (src);
|
||||
}
|
||||
src_type = get_type (src);
|
||||
if (!src_type) {
|
||||
internal_error (src, "src_type broke in assign_expr");
|
||||
|
|
|
@ -1333,6 +1333,13 @@ binary_expr (int op, const expr_t *e1, const expr_t *e2)
|
|||
if ((e = check_precedence (op, e1, e2)))
|
||||
return e;
|
||||
|
||||
if (is_reference (get_type (e1))) {
|
||||
e1 = pointer_deref (e1);
|
||||
}
|
||||
if (is_reference (get_type (e2))) {
|
||||
e2 = pointer_deref (e2);
|
||||
}
|
||||
|
||||
auto t1 = get_type (e1);
|
||||
auto t2 = get_type (e2);
|
||||
if (!t1 || !t2)
|
||||
|
|
|
@ -119,7 +119,7 @@ quat_negate (const expr_t *e)
|
|||
return new_vector_expr (q);
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
const expr_t *
|
||||
pointer_deref (const expr_t *e)
|
||||
{
|
||||
scoped_src_loc (e);
|
||||
|
@ -440,6 +440,10 @@ unary_expr (int op, const expr_t *e)
|
|||
return e;
|
||||
}
|
||||
|
||||
if (is_reference (get_type (e))) {
|
||||
e = pointer_deref (e);
|
||||
}
|
||||
|
||||
unary_type_t *unary_type = nullptr;
|
||||
auto t = get_type (e);
|
||||
|
||||
|
|
Loading…
Reference in a new issue