getting closer to emiting ObjQC code

This commit is contained in:
Bill Currie 2002-05-08 21:24:24 +00:00
parent de86019d4b
commit 7f47447492
12 changed files with 461 additions and 43 deletions

View file

@ -0,0 +1,60 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2001 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
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
$Id$
*/
#ifndef __class_h
#define __class_h
#include "method.h"
typedef struct class_s {
const char *name;
struct class_s *base;
methodlist_t methods;
} class_t;
typedef struct protocol_s {
const char *name;
methodlist_t methods;
} protocol_t;
typedef struct category_s {
const char *name;
class_t *klass;
methodlist_t methods;
} category_t;
class_t *new_class (const char *name, class_t *base);
protocol_t *new_protocol (const char *name);
category_t *new_category (const char *name, class_t *klass);
class_t *find_class (const char *name);
protocol_t *find_protocol (const char *name);
#endif//__class_h

View file

@ -40,9 +40,8 @@ typedef struct param_s {
} param_t;
param_t *new_param (const char *selector, type_t *type, const char *name);
param_t *_reverse_params (param_t *params, param_t *next);
param_t *reverse_params (param_t *params);
type_t *parse_params (type_t *type, param_t *params);
void build_scope (function_t *f, def_t *func, param_t *params);
function_t *new_function (void);

View file

@ -0,0 +1,57 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2001 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
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
$Id$
*/
#ifndef __method_h
#define __method_h
#include "function.h"
typedef struct method_s {
struct method_s *next;
int instance;
param_t *selector;
param_t *params;
type_t *type;
def_t *def;
} method_t;
typedef struct {
method_t *head;
method_t **tail;
} methodlist_t;
struct class_s;
method_t *new_method (type_t *ret_type, param_t *selector, param_t *opt_parms);
void add_method (methodlist_t *methodlist, method_t *method);
def_t *method_def (struct class_s *klass, method_t *method);
#endif//__method_h

View file

@ -369,6 +369,7 @@ extern type_t type_integer;
extern type_t type_uinteger;
extern type_t type_short;
extern type_t type_struct;
extern type_t type_id;
extern def_t def_void;
extern def_t def_string;
@ -383,6 +384,7 @@ extern def_t def_integer;
extern def_t def_uinteger;
extern def_t def_short;
extern def_t def_struct;
extern def_t def_id;
struct function_s
{

View file

@ -37,7 +37,7 @@ YFLAGS = -d
bin_PROGRAMS= qfcc
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c function.c struct.c switch.c type.c
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l class.c emit.c expr.c function.c method.c struct.c switch.c type.c
qfcc_LDADD= $(QFCC_LIBS)
qfcc_DEPENDENCIES= $(QFCC_DEPS)
EXTRA_DIST= qc-parse.h

85
tools/qfcc/source/class.c Normal file
View file

@ -0,0 +1,85 @@
/*
function.c
QC function support code
Copyright (C) 2001 Bill Currie
Author: Bill Currie <bill@taniwha.org>
Date: 2002/5/7
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
*/
static const char rcsid[] =
"$Id$";
#include "QF/dstring.h"
#include "qfcc.h"
#include "class.h"
#include "type.h"
class_t *
new_class (const char *name, class_t *base)
{
class_t *c = malloc (sizeof (class_t));
c->name = name;
c->base = base;
c->methods.head = 0;
c->methods.tail = &c->methods.head;
return c;
}
protocol_t *
new_protocol (const char *name)
{
protocol_t *p = malloc (sizeof (protocol_t));
p->name = name;
p->methods.head = 0;
p->methods.tail = &p->methods.head;
return p;
}
category_t *
new_category (const char *name, class_t *klass)
{
category_t *c = malloc (sizeof (category_t));
c->name = name;
c->klass = klass;
c->methods.head = 0;
c->methods.tail = &c->methods.head;
return c;
}
class_t *
find_class (const char *name)
{
return 0;
}
protocol_t *
find_protocol (const char *name)
{
return 0;
}

View file

@ -30,6 +30,8 @@
static const char rcsid[] =
"$Id$";
#include "QF/dstring.h"
#include "qfcc.h"
#include "function.h"
@ -48,7 +50,7 @@ new_param (const char *selector, type_t *type, const char *name)
return param;
}
static param_t *
param_t *
_reverse_params (param_t *params, param_t *next)
{
param_t *p = params;

View file

@ -0,0 +1,91 @@
/*
method.c
QC method support code
Copyright (C) 2001 Bill Currie
Author: Bill Currie <bill@taniwha.org>
Date: 2002/5/7
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
*/
static const char rcsid[] =
"$Id$";
#include "QF/dstring.h"
#include "qfcc.h"
#include "class.h"
#include "method.h"
#include "type.h"
method_t *
new_method (type_t *ret_type, param_t *selector, param_t *opt_parms)
{
method_t *meth = malloc (sizeof (method_t));
param_t *cmd = new_param (0, &type_pointer, "_cmd");
param_t *self = new_param (0, &type_id, "self");
opt_parms = reverse_params (opt_parms);
selector = _reverse_params (selector, opt_parms);
cmd->next = selector;
self->next = cmd;
meth->next = 0;
meth->instance = 0;
meth->selector = selector;
meth->params = self;
meth->type = parse_params (ret_type, meth->params);
//print_type (meth->type); puts ("");
meth->def = 0;
return meth;
}
void
add_method (methodlist_t *methodlist, method_t *method)
{
if (method->next) {
error (0, "add_method: method loop detected");
abort ();
}
*methodlist->tail = method;
methodlist->tail = &method->next;
}
def_t *
method_def (class_t *klass, method_t *method)
{
dstring_t *str = dstring_newstr ();
dstring_t *sel = dstring_newstr ();
param_t *p;
dsprintf (str, "_%c_%s", method->instance ? 'i' : 'c', klass->name);
for (p = method->selector; p && p->selector; p = p->next) {
dstring_clearstr (sel);
dsprintf (sel, "_%s", p->selector);
dstring_appendstr (str, sel->str);
}
//printf ("%s\n", str->str);
// FIXME need a file scope
return PR_GetDef (method->type, str->str, 0, &numpr_globals);
}

View file

@ -68,6 +68,7 @@ type_t type_integer = { ev_integer, &def_integer };
type_t type_uinteger = { ev_uinteger, &def_uinteger };
type_t type_short = { ev_short, &def_short };
type_t type_struct = { ev_struct, &def_struct };
type_t type_id = {ev_pointer, &def_id };
type_t type_floatfield = { ev_field, &def_field, NULL, &type_float };
@ -84,6 +85,7 @@ def_t def_integer = { &type_integer, "temp" };
def_t def_uinteger = { &type_uinteger, "temp" };
def_t def_short = { &type_short, "temp" };
def_t def_struct = { &type_struct, "temp" };
def_t def_id = { &type_id, "temp" };
def_t def_ret, def_parms[MAX_PARMS];

View file

@ -31,11 +31,13 @@
static const char rcsid[] =
"$Id$";
#include "qfcc.h"
#include <QF/hash.h>
#include <QF/sys.h>
#include "qfcc.h"
#include "function.h"
#include "method.h"
#include "class.h"
#include "struct.h"
#include "switch.h"
#include "type.h"
@ -85,6 +87,10 @@ typedef struct {
function_t *function;
struct switch_block_s *switch_block;
struct param_s *param;
struct method_s *method;
struct class_s *klass;
struct protocol_s *protocol;
struct category_s *category;
}
%right <op> '=' ASX PAS /* pointer assign */
@ -128,9 +134,11 @@ typedef struct {
%type <scope> param_scope
%type <string_val> selector
%type <param> keyworddecl keywordselector
%type <param> optparmlist unaryselector keyworddecl keywordselector
%type <method> methodproto methoddecl
%type <expr> identifier_list
%expect 1
%expect 2 // statement : if | if else, defs : defs def ';' | defs obj_def
%{
@ -138,12 +146,14 @@ type_t *current_type;
def_t *current_def;
function_t *current_func;
param_t *current_params;
expr_t *current_init;
class_t *current_class;
methodlist_t *current_methodlist;
expr_t *local_expr;
expr_t *break_label;
expr_t *continue_label;
switch_block_t *switch_block;
type_t *struct_type;
expr_t *current_init;
def_t *pr_scope; // the function being parsed, or NULL
string_t s_file; // filename for function definition
@ -157,6 +167,7 @@ int element_flag;
defs
: /* empty */
| defs def ';'
| defs obj_def
;
def
@ -172,7 +183,6 @@ def
process_enum ($4);
new_typedef ($7, &type_integer);
}
| obj_def
;
struct_defs
@ -854,7 +864,7 @@ string_val
}
;
obj_def /* XXX */
obj_def
: classdef
| classdecl
| protocoldef
@ -862,50 +872,116 @@ obj_def /* XXX */
| END
;
identifier_list /* XXX */
: NAME {}
identifier_list
: NAME
{
$$ = new_block_expr ();
append_expr ($$, new_name_expr ($1));
}
| identifier_list ',' NAME
{
append_expr ($1, new_name_expr ($3));
$$ = $1;
}
;
classdecl /* XXX */
: CLASS identifier_list
{
expr_t *e;
for (e = $2->e.block.head; e; e = e->next)
new_class (e->e.string_val, 0);
}
;
classdef /* XXX */
: INTERFACE NAME protocolrefs '{'
ivar_decl_list '}'
: INTERFACE NAME
protocolrefs
{
$<klass>$ = new_class ($2, 0);
current_methodlist = &$<klass>$->methods;
}
'{' ivar_decl_list '}'
methodprotolist
END
| INTERFACE NAME protocolrefs
| INTERFACE NAME
protocolrefs
{
$<klass>$ = new_class ($2, 0);
current_methodlist = &$<klass>$->methods;
}
methodprotolist
END
| INTERFACE NAME ':' NAME protocolrefs '{'
ivar_decl_list '}'
| INTERFACE NAME ':' NAME
protocolrefs
{
class_t *base = find_class ($4);
$<klass>$ = new_class ($2, base);
current_methodlist = &$<klass>$->methods;
}
'{' ivar_decl_list '}'
methodprotolist
END
| INTERFACE NAME ':' NAME protocolrefs
| INTERFACE NAME ':' NAME
protocolrefs
{
class_t *base = find_class ($4);
$<klass>$ = new_class ($2, base);
current_methodlist = &$<klass>$->methods;
}
methodprotolist
END
| INTERFACE NAME '(' NAME ')' protocolrefs
| INTERFACE NAME '(' NAME ')'
{
class_t *klass = find_class ($4);
$<category>$ = new_category ($2, klass);
current_methodlist = &$<category>$->methods;
}
protocolrefs
methodprotolist
END
| IMPLEMENTATION NAME '{'
ivar_decl_list '}'
| IMPLEMENTATION NAME
| IMPLEMENTATION NAME ':' NAME '{'
ivar_decl_list '}'
{
current_class = new_class ($2, 0);
}
'{' ivar_decl_list '}'
| IMPLEMENTATION NAME
{
current_class = new_class ($2, 0);
}
| IMPLEMENTATION NAME ':' NAME
{
class_t *base = find_class ($4);
current_class = new_class ($2, base);
}
'{' ivar_decl_list '}'
| IMPLEMENTATION NAME ':' NAME
{
class_t *base = find_class ($4);
current_class = new_class ($2, base);
}
| IMPLEMENTATION NAME '(' NAME ')'
;
protocoldef /* XXX */
: PROTOCOL NAME protocolrefs
: PROTOCOL NAME
{
$<protocol>$ = new_protocol ($2);
current_methodlist = &$<protocol>$->methods;
}
protocolrefs
methodprotolist END
;
protocolrefs /* XXX */
: /* emtpy */
| '<' identifier_list '>'
| LT identifier_list GT
{
expr_t *e;
for (e = $2->e.block.head; e; e = e->next) {
//puts (e->e.string_val);
}
}
;
ivar_decl_list /* XXX */
@ -937,44 +1013,88 @@ ivar_declarator /* XXX */
: NAME {}
;
methoddef /* XXX */
methoddef
: '+'
methoddecl opt_state_expr
{
$2->instance = 0;
current_def = $2->def = method_def (current_class, $2);
current_params = $2->params;
}
begin_function statement_block end_function
{
build_function ($5);
if ($3) {
$3->next = $6;
emit_function ($5, $3);
} else {
emit_function ($5, $6);
}
finish_function ($5);
}
| '-'
methoddecl opt_state_expr
{
$2->instance = 1;
current_def = $2->def = method_def (current_class, $2);
current_params = $2->params;
}
begin_function statement_block end_function
{
build_function ($5);
if ($3) {
$3->next = $6;
emit_function ($5, $3);
} else {
emit_function ($5, $6);
}
finish_function ($5);
}
;
methodprotolist /* XXX */
methodprotolist
: /* emtpy */
| methodprotolist2
;
methodprotolist2 /* XXX */
: methodproto
| methodprotolist2 methodproto
methodprotolist2
: methodproto { add_method (current_methodlist, $1); }
| methodprotolist2 methodproto { add_method (current_methodlist, $2); }
;
methodproto /* XXX */
methodproto
: '+' methoddecl ';'
{
$2->instance = 0;
$$ = $2;
}
| '-' methoddecl ';'
{
$2->instance = 1;
$$ = $2;
}
;
methoddecl /* XXX */
methoddecl
: '(' type ')' unaryselector
{ $$ = new_method ($2, $4, 0); }
| unaryselector
| '(' type ')' keywordselector optparmlist {}
| keywordselector optparmlist {}
{ $$ = new_method (&type_id, $1, 0); }
| '(' type ')' keywordselector optparmlist
{ $$ = new_method ($2, $4, $5); }
| keywordselector optparmlist
{ $$ = new_method (&type_id, $1, $2); }
;
optparmlist /* XXX */
optparmlist
: /* empty */
{ $$ = 0; }
| ',' ELLIPSIS
{ $$ = new_param (0, 0, 0); }
;
unaryselector /* XXX */
: selector {}
unaryselector
: selector { $$ = new_param ($1, 0, 0); }
;
keywordselector
@ -990,11 +1110,11 @@ keyworddecl
: selector ':' '(' type ')' NAME
{ $$ = new_param ($1, $4, $6); }
| selector ':' NAME
{ $$ = new_param ($1, 0/*&type_id*/, $3); }
{ $$ = new_param ($1, &type_id, $3); }
| ':' '(' type ')' NAME
{ $$ = new_param (0, $3, $5); }
{ $$ = new_param ("", $3, $5); }
| ':' NAME
{ $$ = new_param (0, 0/*&type_id*/, $2); }
{ $$ = new_param ("", &type_id, $2); }
;
messageargs /* XXX */

View file

@ -1221,8 +1221,8 @@ main (int argc, char **argv)
int yyparse (void);
extern void clear_frame_macros (void);
// extern int yydebug;
// yydebug = 1;
//extern int yydebug;
//yydebug = 1;
if (*sourcedir)
snprintf (filename, sizeof (filename), "%s%c%s", sourcedir,

View file

@ -107,7 +107,7 @@ print_type (type_t *type)
break;
case ev_func:
print_type (type->aux_type);
if (type->num_parms < 0) {
if (type->num_parms == -1) {
printf ("(...)");
} else {
int c, i;