mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[qfcc] Split out the obj-qc specific expr code
This commit is contained in:
parent
fb33a7f2a7
commit
ea042cf87a
3 changed files with 267 additions and 201 deletions
|
@ -41,7 +41,7 @@ bin_SCRIPTS= qfpreqcc
|
|||
common_src=\
|
||||
class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \
|
||||
diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \
|
||||
expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c \
|
||||
expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c expr_obj.c \
|
||||
flow.c function.c grab.c \
|
||||
idstuff.c \
|
||||
linker.c method.c \
|
||||
|
|
|
@ -1099,28 +1099,6 @@ expr_short (expr_t *e)
|
|||
internal_error (e, "not a short constant");
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_self_expr (void)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
sym = make_symbol (".self", &type_entity, pr.near_data, sc_extern);
|
||||
if (!sym->table)
|
||||
symtab_addsymbol (pr.symtab, sym);
|
||||
return new_symbol_expr (sym);
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_this_expr (void)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
sym = make_symbol (".this", field_type (&type_id), pr.near_data, sc_extern);
|
||||
if (!sym->table)
|
||||
symtab_addsymbol (pr.symtab, sym);
|
||||
return new_symbol_expr (sym);
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_alias_expr (type_t *type, expr_t *expr)
|
||||
{
|
||||
|
@ -2579,51 +2557,6 @@ cast_expr (type_t *dstType, expr_t *e)
|
|||
return c;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
selector_expr (keywordarg_t *selector)
|
||||
{
|
||||
dstring_t *sel_id = dstring_newstr ();
|
||||
expr_t *sel;
|
||||
symbol_t *sel_sym;
|
||||
symbol_t *sel_table;
|
||||
int index;
|
||||
|
||||
selector = copy_keywordargs (selector);
|
||||
selector = (keywordarg_t *) reverse_params ((param_t *) selector);
|
||||
selector_name (sel_id, selector);
|
||||
index = selector_index (sel_id->str);
|
||||
index *= type_size (type_SEL.t.fldptr.type);
|
||||
sel_sym = make_symbol ("_OBJ_SELECTOR_TABLE_PTR", &type_SEL,
|
||||
pr.near_data, sc_static);
|
||||
if (!sel_sym->table) {
|
||||
symtab_addsymbol (pr.symtab, sel_sym);
|
||||
sel_table = make_symbol ("_OBJ_SELECTOR_TABLE",
|
||||
array_type (type_SEL.t.fldptr.type, 0),
|
||||
pr.far_data, sc_extern);
|
||||
if (!sel_table->table)
|
||||
symtab_addsymbol (pr.symtab, sel_table);
|
||||
reloc_def_def (sel_table->s.def, sel_sym->s.def);
|
||||
}
|
||||
sel = new_symbol_expr (sel_sym);
|
||||
dstring_delete (sel_id);
|
||||
sel = new_binary_expr ('&', sel, new_short_expr (index));
|
||||
sel->e.expr.type = &type_SEL;
|
||||
return sel;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
protocol_expr (const char *protocol_name)
|
||||
{
|
||||
protocol_t *protocol = get_protocol (protocol_name, 0);
|
||||
|
||||
if (!protocol) {
|
||||
return error (0, "cannot find protocol declaration for `%s'",
|
||||
protocol_name);
|
||||
}
|
||||
class_t *proto_class = get_class (new_symbol ("Protocol"), 1);
|
||||
return new_pointer_expr (0, proto_class->type, protocol_def (protocol));
|
||||
}
|
||||
|
||||
expr_t *
|
||||
encode_expr (type_t *type)
|
||||
{
|
||||
|
@ -2636,139 +2569,6 @@ encode_expr (type_t *type)
|
|||
return e;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
super_expr (class_type_t *class_type)
|
||||
{
|
||||
symbol_t *sym;
|
||||
expr_t *super;
|
||||
expr_t *e;
|
||||
expr_t *super_block;
|
||||
class_t *class;
|
||||
|
||||
if (!class_type)
|
||||
return error (0, "`super' used outside of class implementation");
|
||||
|
||||
class = extract_class (class_type);
|
||||
|
||||
if (!class->super_class)
|
||||
return error (0, "%s has no super class", class->name);
|
||||
|
||||
sym = symtab_lookup (current_symtab, ".super");
|
||||
if (!sym || sym->table != current_symtab) {
|
||||
sym = new_symbol_type (".super", &type_obj_super);
|
||||
initialize_def (sym, 0, current_symtab->space, sc_local);
|
||||
}
|
||||
super = new_symbol_expr (sym);
|
||||
|
||||
super_block = new_block_expr ();
|
||||
|
||||
e = assign_expr (field_expr (super, new_name_expr ("self")),
|
||||
new_name_expr ("self"));
|
||||
append_expr (super_block, e);
|
||||
|
||||
e = new_symbol_expr (class_pointer_symbol (class));
|
||||
e = assign_expr (field_expr (super, new_name_expr ("class")),
|
||||
field_expr (e, new_name_expr ("super_class")));
|
||||
append_expr (super_block, e);
|
||||
|
||||
e = address_expr (super, 0, 0);
|
||||
super_block->e.block.result = e;
|
||||
return super_block;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
message_expr (expr_t *receiver, keywordarg_t *message)
|
||||
{
|
||||
expr_t *args = 0, **a = &args;
|
||||
expr_t *selector = selector_expr (message);
|
||||
expr_t *call;
|
||||
keywordarg_t *m;
|
||||
int self = 0, super = 0, class_msg = 0;
|
||||
type_t *rec_type;
|
||||
type_t *return_type;
|
||||
type_t *method_type = &type_IMP;
|
||||
class_t *class = 0;
|
||||
method_t *method;
|
||||
expr_t *send_msg;
|
||||
|
||||
if (receiver->type == ex_symbol
|
||||
&& strcmp (receiver->e.symbol->name, "super") == 0) {
|
||||
super = 1;
|
||||
|
||||
receiver = super_expr (current_class);
|
||||
|
||||
if (receiver->type == ex_error)
|
||||
return receiver;
|
||||
receiver = cast_expr (&type_id, receiver); //FIXME better way?
|
||||
class = extract_class (current_class);
|
||||
} else {
|
||||
if (receiver->type == ex_symbol) {
|
||||
if (strcmp (receiver->e.symbol->name, "self") == 0)
|
||||
self = 1;
|
||||
if (receiver->e.symbol->sy_type == sy_class) {
|
||||
class = receiver->e.symbol->type->t.class;
|
||||
class_msg = 1;
|
||||
receiver = new_symbol_expr (class_pointer_symbol (class));
|
||||
}
|
||||
} else if (receiver->type == ex_nil) {
|
||||
convert_nil (receiver, &type_id);
|
||||
}
|
||||
rec_type = get_type (receiver);
|
||||
|
||||
if (receiver->type == ex_error)
|
||||
return receiver;
|
||||
|
||||
if (rec_type == &type_id || rec_type == &type_Class) {
|
||||
} else {
|
||||
if (rec_type->type == ev_pointer)
|
||||
rec_type = rec_type->t.fldptr.type;
|
||||
if (!obj_is_class (rec_type))
|
||||
return error (receiver, "not a class/object");
|
||||
|
||||
if (self) {
|
||||
if (!class)
|
||||
class = extract_class (current_class);
|
||||
if (rec_type == &type_obj_class)
|
||||
class_msg = 1;
|
||||
} else {
|
||||
if (!class)
|
||||
class = rec_type->t.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return_type = &type_id;
|
||||
method = class_message_response (class, class_msg, selector);
|
||||
if (method)
|
||||
return_type = method->type->t.func.type;
|
||||
|
||||
for (m = message; m; m = m->next) {
|
||||
*a = m->expr;
|
||||
while ((*a)) {
|
||||
expr_file_line (selector, *a);
|
||||
a = &(*a)->next;
|
||||
}
|
||||
}
|
||||
*a = selector;
|
||||
a = &(*a)->next;
|
||||
*a = receiver;
|
||||
|
||||
send_msg = expr_file_line (send_message (super), receiver);
|
||||
if (method) {
|
||||
expr_t *err;
|
||||
if ((err = method_check_params (method, args)))
|
||||
return err;
|
||||
method_type = method->type;
|
||||
}
|
||||
call = build_function_call (send_msg, method_type, args);
|
||||
|
||||
if (call->type == ex_error)
|
||||
return receiver;
|
||||
|
||||
call->e.block.result = new_ret_expr (return_type);
|
||||
return call;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
sizeof_expr (expr_t *expr, struct type_s *type)
|
||||
{
|
||||
|
|
266
tools/qfcc/source/expr_obj.c
Normal file
266
tools/qfcc/source/expr_obj.c
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
expr_obj.c
|
||||
|
||||
Objective-QuakeC expression construction and manipulations
|
||||
|
||||
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2001/06/15
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/alloc.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "qfcc.h"
|
||||
#include "class.h"
|
||||
#include "def.h"
|
||||
#include "defspace.h"
|
||||
#include "diagnostic.h"
|
||||
#include "emit.h"
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "idstuff.h"
|
||||
#include "method.h"
|
||||
#include "options.h"
|
||||
#include "reloc.h"
|
||||
#include "shared.h"
|
||||
#include "strpool.h"
|
||||
#include "struct.h"
|
||||
#include "symtab.h"
|
||||
#include "type.h"
|
||||
#include "value.h"
|
||||
#include "qc-parse.h"
|
||||
|
||||
expr_t *
|
||||
new_self_expr (void)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
sym = make_symbol (".self", &type_entity, pr.near_data, sc_extern);
|
||||
if (!sym->table)
|
||||
symtab_addsymbol (pr.symtab, sym);
|
||||
return new_symbol_expr (sym);
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_this_expr (void)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
sym = make_symbol (".this", field_type (&type_id), pr.near_data, sc_extern);
|
||||
if (!sym->table)
|
||||
symtab_addsymbol (pr.symtab, sym);
|
||||
return new_symbol_expr (sym);
|
||||
}
|
||||
|
||||
expr_t *
|
||||
selector_expr (keywordarg_t *selector)
|
||||
{
|
||||
dstring_t *sel_id = dstring_newstr ();
|
||||
expr_t *sel;
|
||||
symbol_t *sel_sym;
|
||||
symbol_t *sel_table;
|
||||
int index;
|
||||
|
||||
selector = copy_keywordargs (selector);
|
||||
selector = (keywordarg_t *) reverse_params ((param_t *) selector);
|
||||
selector_name (sel_id, selector);
|
||||
index = selector_index (sel_id->str);
|
||||
index *= type_size (type_SEL.t.fldptr.type);
|
||||
sel_sym = make_symbol ("_OBJ_SELECTOR_TABLE_PTR", &type_SEL,
|
||||
pr.near_data, sc_static);
|
||||
if (!sel_sym->table) {
|
||||
symtab_addsymbol (pr.symtab, sel_sym);
|
||||
sel_table = make_symbol ("_OBJ_SELECTOR_TABLE",
|
||||
array_type (type_SEL.t.fldptr.type, 0),
|
||||
pr.far_data, sc_extern);
|
||||
if (!sel_table->table)
|
||||
symtab_addsymbol (pr.symtab, sel_table);
|
||||
reloc_def_def (sel_table->s.def, sel_sym->s.def);
|
||||
}
|
||||
sel = new_symbol_expr (sel_sym);
|
||||
dstring_delete (sel_id);
|
||||
sel = new_binary_expr ('&', sel, new_short_expr (index));
|
||||
sel->e.expr.type = &type_SEL;
|
||||
return sel;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
protocol_expr (const char *protocol_name)
|
||||
{
|
||||
protocol_t *protocol = get_protocol (protocol_name, 0);
|
||||
|
||||
if (!protocol) {
|
||||
return error (0, "cannot find protocol declaration for `%s'",
|
||||
protocol_name);
|
||||
}
|
||||
class_t *proto_class = get_class (new_symbol ("Protocol"), 1);
|
||||
return new_pointer_expr (0, proto_class->type, protocol_def (protocol));
|
||||
}
|
||||
|
||||
expr_t *
|
||||
super_expr (class_type_t *class_type)
|
||||
{
|
||||
symbol_t *sym;
|
||||
expr_t *super;
|
||||
expr_t *e;
|
||||
expr_t *super_block;
|
||||
class_t *class;
|
||||
|
||||
if (!class_type)
|
||||
return error (0, "`super' used outside of class implementation");
|
||||
|
||||
class = extract_class (class_type);
|
||||
|
||||
if (!class->super_class)
|
||||
return error (0, "%s has no super class", class->name);
|
||||
|
||||
sym = symtab_lookup (current_symtab, ".super");
|
||||
if (!sym || sym->table != current_symtab) {
|
||||
sym = new_symbol_type (".super", &type_obj_super);
|
||||
initialize_def (sym, 0, current_symtab->space, sc_local);
|
||||
}
|
||||
super = new_symbol_expr (sym);
|
||||
|
||||
super_block = new_block_expr ();
|
||||
|
||||
e = assign_expr (field_expr (super, new_name_expr ("self")),
|
||||
new_name_expr ("self"));
|
||||
append_expr (super_block, e);
|
||||
|
||||
e = new_symbol_expr (class_pointer_symbol (class));
|
||||
e = assign_expr (field_expr (super, new_name_expr ("class")),
|
||||
field_expr (e, new_name_expr ("super_class")));
|
||||
append_expr (super_block, e);
|
||||
|
||||
e = address_expr (super, 0, 0);
|
||||
super_block->e.block.result = e;
|
||||
return super_block;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
message_expr (expr_t *receiver, keywordarg_t *message)
|
||||
{
|
||||
expr_t *args = 0, **a = &args;
|
||||
expr_t *selector = selector_expr (message);
|
||||
expr_t *call;
|
||||
keywordarg_t *m;
|
||||
int self = 0, super = 0, class_msg = 0;
|
||||
type_t *rec_type;
|
||||
type_t *return_type;
|
||||
type_t *method_type = &type_IMP;
|
||||
class_t *class = 0;
|
||||
method_t *method;
|
||||
expr_t *send_msg;
|
||||
|
||||
if (receiver->type == ex_symbol
|
||||
&& strcmp (receiver->e.symbol->name, "super") == 0) {
|
||||
super = 1;
|
||||
|
||||
receiver = super_expr (current_class);
|
||||
|
||||
if (receiver->type == ex_error)
|
||||
return receiver;
|
||||
receiver = cast_expr (&type_id, receiver); //FIXME better way?
|
||||
class = extract_class (current_class);
|
||||
} else {
|
||||
if (receiver->type == ex_symbol) {
|
||||
if (strcmp (receiver->e.symbol->name, "self") == 0)
|
||||
self = 1;
|
||||
if (receiver->e.symbol->sy_type == sy_class) {
|
||||
class = receiver->e.symbol->type->t.class;
|
||||
class_msg = 1;
|
||||
receiver = new_symbol_expr (class_pointer_symbol (class));
|
||||
}
|
||||
} else if (receiver->type == ex_nil) {
|
||||
convert_nil (receiver, &type_id);
|
||||
}
|
||||
rec_type = get_type (receiver);
|
||||
|
||||
if (receiver->type == ex_error)
|
||||
return receiver;
|
||||
|
||||
if (rec_type == &type_id || rec_type == &type_Class) {
|
||||
} else {
|
||||
if (rec_type->type == ev_pointer)
|
||||
rec_type = rec_type->t.fldptr.type;
|
||||
if (!obj_is_class (rec_type))
|
||||
return error (receiver, "not a class/object");
|
||||
|
||||
if (self) {
|
||||
if (!class)
|
||||
class = extract_class (current_class);
|
||||
if (rec_type == &type_obj_class)
|
||||
class_msg = 1;
|
||||
} else {
|
||||
if (!class)
|
||||
class = rec_type->t.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return_type = &type_id;
|
||||
method = class_message_response (class, class_msg, selector);
|
||||
if (method)
|
||||
return_type = method->type->t.func.type;
|
||||
|
||||
for (m = message; m; m = m->next) {
|
||||
*a = m->expr;
|
||||
while ((*a)) {
|
||||
expr_file_line (selector, *a);
|
||||
a = &(*a)->next;
|
||||
}
|
||||
}
|
||||
*a = selector;
|
||||
a = &(*a)->next;
|
||||
*a = receiver;
|
||||
|
||||
send_msg = expr_file_line (send_message (super), receiver);
|
||||
if (method) {
|
||||
expr_t *err;
|
||||
if ((err = method_check_params (method, args)))
|
||||
return err;
|
||||
method_type = method->type;
|
||||
}
|
||||
call = build_function_call (send_msg, method_type, args);
|
||||
|
||||
if (call->type == ex_error)
|
||||
return receiver;
|
||||
|
||||
call->e.block.result = new_ret_expr (return_type);
|
||||
return call;
|
||||
}
|
Loading…
Reference in a new issue