PIPS
genLisp.c
Go to the documentation of this file.
1 /*
2 
3  $Id: genLisp.c 1357 2016-03-02 08:18:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of NewGen.
8 
9  NewGen is free software: you can redistribute it and/or modify it under the
10  terms of the GNU General Public License as published by the Free Software
11  Foundation, either version 3 of the License, or any later version.
12 
13  NewGen is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16  License for more details.
17 
18  You should have received a copy of the GNU General Public License along with
19  NewGen. If not, see <http://www.gnu.org/licenses/>.
20 
21 */
22 /*
23 
24  This file includes the function used to implement user types
25  in (Common)Lisp.
26 
27  The implementation is based on CL structures. We could provide type
28  informations in order to (potentially) improve the efficiency.
29  The type information (i.e., the index in the Domains table) is put here
30  for compatibility with C only.
31 
32  . An inlined value is the value,
33  . A list is a Lisp list,
34  . An array is a Lisp array,
35  . An AND type is a DEFSTRUCT,
36  . An OR type is an OR structure with a tag (a keyword) and a value.
37 
38  Note that bool (which doesn't exist in Lisp) uses true and false, and
39  so (if (foo-bar x) ...) as to be written (if (true? (foo-bar x))
40  ...)
41 
42  */
43 
44 #ifdef HAVE_CONFIG_H
45  #include "config.h"
46 #endif
47 #include <stdio.h>
48 #include "newgen_include.h"
49 
50 #define TYPE(bp) (bp-Domains-Number_imports-Current_start)
51 #define NEWGEN_IMPL "#+akcl lisp:vector #-akcl (lisp:vector lisp:t)"
52 
53 /* The name of the variable from which to start counting domain numbers. */
54 
55 static char start[ 1024 ] ;
56 
57 /* The package name in which functions will be defined. */
58 
59 static char *package ;
60 
62 
63 int Read_spec_mode ; /* Unused in Lisp */
64 
65 #define OR_VALUE_INDEX 3
66 
67 static int or_counter ;
68 
69 /* INIT_MEMBER returns the initialization code for a value in the domain DP. */
70 
71 char *
73  union domain *dp ;
74 {
75  static char buffer[ 1024 ] ;
76 
77  switch( dp->ba.type ) {
78  case BASIS_DT: {
79  struct gen_binding *bp = dp->ba.constructand ;
80 
81  if( IS_INLINABLE( bp ))
82  sprintf( buffer, "%s", bp->inlined->Lisp_value ) ;
83  else if( IS_EXTERNAL( bp ))
84  sprintf( buffer, "`(:external ,(lisp:+ %s %d) %s)",
85  start, TYPE( bp ), ":external-undefined" ) ;
86  else sprintf( buffer, ":undefined", bp->name ) ;
87  break ;
88  }
89  case LIST_DT:
90  sprintf( buffer, ":list-undefined" ) ;
91  break ;
92  case ARRAY_DT: {
93  struct intlist *ilp ;
94 
95  sprintf( buffer, "(lisp:make-array '(" ) ;
96 
97  for( ilp = dp->ar.dimensions ; ilp != NULL ; ilp = ilp->cdr ) {
98  strcat( buffer, i2a( ilp->val )) ;
99  strcat( buffer, " " ) ;
100  }
101  strcat( buffer, ") :initial-element '--no-value--)" ) ;
102  break ;
103  }
104  case SET_DT:
105  sprintf( buffer, "(set:set-make)" ) ;
106  break ;
107  default:
108  fatal( "init_member: Unknown type %s\n", i2a( dp->ba.type )) ;
109  /*NOTREACHED*/
110  }
111  return( buffer ) ;
112 }
113 
114 /* GEN_EXTERNAL generates the type code for external type BP. */
115 
116 void
118 struct gen_binding *bp ;
119 {
120  printf( "(lisp:defvar %s (lisp:+ %s %d))\n", bp->name, start, TYPE( bp )) ;
121 }
122 
123 /* GEN_EXTERNAL_MEMBER generates the manipulation functions for a possible
124  external member (either and or or) in domain DP and OFFSET. It returns
125  whether some code has been generated or not.
126 
127  See INIT_MEMBER to understand mutation code. */
128 
129 int
131 union domain *dp ;
132 int offset ;
133 {
134  if( dp->ba.type == BASIS_DT ) {
135  struct gen_binding *bp = dp->ba.constructand ;
136 
137  if( !IS_INLINABLE( bp ) && IS_EXTERNAL( bp )) {
138  printf( "(lisp:defun %s-%s (and)\n", bp->name, dp->ba.constructor ) ;
139  printf( " (lisp:caddr (lisp:svref and %d)))\n", offset ) ;
140 
141  printf( "(lisp:defsetf %s-%s (and) (new-and)\n",
142  bp->name, dp->ba.constructor ) ;
143  printf( " `(lisp:setf (lisp:caddr (lisp:svref ,and %d)) ", offset ) ;
144  printf( ",new-and))\n" ) ;
145  return( 1 ) ;
146  }
147  }
148  return( 0 ) ;
149 }
150 
151 /* GEN_PRELUDE generates prelude declarations for potentially tabulated
152  domain BP. */
153 
154 static void
156 struct gen_binding *bp ;
157 {
158  printf( "(lisp:setf (lisp:aref newgen::*gen-tabulated-alloc*" ) ;
159  printf( " (lisp:+ %s %d)) %d)\n",
160  start, TYPE( bp ), (IS_TABULATED( bp )) ? 0 : -1 ) ;
161  printf( "(lisp:defvar %s::%s-domain (lisp:+ %s %d))\n",
162  package, bp->name, start, TYPE( bp )) ;
163 
164  if( IS_TABULATED( bp )) {
165  printf( "(lisp:setf (lisp:aref newgen::*gen-tabulated-index* " ) ;
166  printf( "%s::%s-domain) %d)\n", package, bp->name, bp->index ) ;
167  }
168 }
169 
170 /* GEN_POSTLUDE generates tabulation table updates. */
171 
172 static void
174 struct gen_binding *bp ;
175 {
176  if( IS_TABULATED( bp )) {
177  printf( "(lisp:defvar old-make-%s)\n", bp->name ) ;
178  printf( "(lisp:setf old-make-%s (lisp:symbol-function 'make-%s))\n",
179  bp->name, bp->name ) ;
180  printf( "(lisp:fmakunbound 'make-%s)\n", bp->name) ;
181  printf( "(lisp:setf (lisp:symbol-function 'make-%s)\n", bp->name ) ;
182  printf( " #'(lisp:lambda (lisp:&rest args)\n", bp->name ) ;
183  printf( " (lisp:let ((node (lisp:apply old-make-%s args)))\n", bp->name ) ;
184  printf( " (newgen::enter-tabulated-def\n" ) ;
185  printf( " (lisp:aref newgen::*gen-tabulated-index* %s-domain)\n",
186  bp->name ) ;
187  printf( " %s-domain\n", bp->name ) ;
188  printf( " (lisp:aref node %d)\n", HASH_OFFSET ) ;
189  printf( " node\n" ) ;
190  printf( " :allow-ref-p lisp:nil)\n" ) ;
191  printf( " node)))\n" ) ;
192  }
193 }
194 
195 /* GEN_TYPE generates the type member for potentially tabulated BP domain.
196  */
198 struct gen_binding *bp ;
199 {
200  printf( " (-type- `(:newgen ,(lisp:+ %s %d)))\n", start, TYPE( bp ) ) ;
201 
202  if( IS_TABULATED( bp )) {
203  printf( " (-tabular- (newgen::find-free-tabulated %d))\n",
204  TYPE( bp )) ;
205  }
206 }
207 
208 /* GEN_AND generates the manipulation functions for an AND type BP. */
209 
210 void
211 gen_and( bp )
212 struct gen_binding *bp ;
213 {
214  union domain *dom = bp->domain ;
215  struct domainlist *dlp = dom->co.components ;
216  int size ;
217 
218  gen_prelude( bp ) ;
219  printf( "(lisp:defstruct (%s (:type %s))\n", bp->name, NEWGEN_IMPL ) ;
220  generate_type_member( bp ) ;
221 
222  for( ; dlp != NULL ; dlp=dlp->cdr ) {
223  union domain *dp = dlp->domain ;
224 
225  printf( " (%s %s)\n", dp->ba.constructor, init_member( dp )) ;
226  }
227  printf( ")\n" ) ;
228 
229  for( size=2, dlp=dom->co.components; dlp != NULL ; dlp=dlp->cdr, size++ ) {
230  gen_external_member( dlp->domain, size ) ;
231  }
232  gen_postlude( bp ) ;
233 }
234 
235 /* GEN_OR generates the manipulation function for an OR_OP type BP. Note
236  that for a UNIT_TYPE_NAME, no access function is defined since the value is
237  meaningless. */
238 
239 void
240 gen_or( bp )
241  struct gen_binding *bp ;
242 {
243  char *name = bp->name ;
244  union domain *dom = bp->domain ;
245  struct domainlist *dlp ;
246  char *or_impl = (IS_TABULATED( bp )) ? "tabular-or" : "or" ;
247 
248  gen_prelude( bp ) ;
249  printf( "(lisp:defun make-%s ", name ) ;
250  printf( "(tag lisp:&optional (val :unit))\n" );
251  printf( " (lisp:let ((node (newgen::make-%s)))\n", or_impl) ;
252  printf( " (lisp:setf (newgen::%s-type node) `(:newgen ,(lisp:+ %s %d)))\n",
253  or_impl, start, TYPE( bp ) ) ;
254 
255  if( IS_TABULATED( bp )) {
256  printf( " (lisp:setf (newgen::%s-tabular node) ", or_impl ) ;
257  printf( "(newgen::find-free-tabulated (lisp:+ %s %d)))\n",
258  start, TYPE( bp )) ;
259  }
260  printf( " (lisp:setf (newgen::%s-tag node) tag)\n", or_impl ) ;
261  printf( " (lisp:setf (newgen::%s-val node) val)\n", or_impl ) ;
262  printf( " node))\n" ) ;
263  printf( "(lisp:defmacro %s-tag(node) `(newgen::%s-tag ,node))\n",
264  name, or_impl ) ;
265 
266  for( dlp=dom->co.components ; dlp != NULL ; dlp=dlp->cdr, or_counter++ ){
267  union domain *dp = dlp->domain ;
268 
269  printf( "(lisp:defconstant is-%s-%s %d)\n",
270  name, dp->ba.constructor, or_counter ) ;
271  printf( "(lisp:setf newgen::*tag-names* " ) ;
272  printf( "(lisp:acons %d 'is-%s-%s newgen::*tag-names*))\n",
273  or_counter, name, dp->ba.constructor ) ;
274  printf( "(lisp:defmacro %s-%s-p (or) ", name, dp->ba.constructor ) ;
275  printf( "`(lisp:= (%s-tag ,or) is-%s-%s))\n",
276  name, name, dp->ba.constructor ) ;
277 
278  if( dp->ba.type == BASIS &&
279  strcmp( dp->ba.constructand->name, UNIT_TYPE_NAME ) == 0 ||
281  continue ;
282 
283  printf( "(lisp:defmacro %s-%s (or) `(newgen::%s-val ,or))\n",
284  name, dp->ba.constructor, or_impl ) ;
285  }
286  gen_postlude( bp ) ;
287 }
288 
289 /* GEN_LIST defines the manipulation functions for a list type BP. */
290 
291 void
292 gen_list( bp )
293  struct gen_binding *bp ;
294 {
295  gen_prelude( bp ) ;
296  printf( "(lisp:defstruct (%s (:type %s))\n", bp->name, NEWGEN_IMPL ) ;
297  generate_type_member( bp ) ;
298  printf( " (%s '()))\n", bp->domain->li.constructor ) ;
299  gen_postlude( bp ) ;
300 }
301 
302 /* GEN_ARRAY defines the manipulation functions for an array type BP. */
303 
304 void
306  struct gen_binding *bp ;
307 {
308  union domain *dom = bp->domain ;
309 
310  gen_prelude( bp ) ;
311  printf( "(lisp:defstruct (%s (:type %s))\n", bp->name, NEWGEN_IMPL ) ;
312  generate_type_member( bp ) ;
313  printf( " (%s %))\n",
314  dom->ar.constructor, init_member( dom->ar.element->domain )) ;
315  gen_postlude( bp ) ;
316 }
317 
318 /* GEN_SET defines the manipulation functions for a set type BP. */
319 
320 void
321 gen_set( bp )
322  struct gen_binding *bp ;
323 {
324  union domain *dom = bp->domain ;
325 
326  gen_prelude( bp ) ;
327  printf( "(lisp:defstruct (%s (:type %s))\n", bp->name, NEWGEN_IMPL ) ;
328  generate_type_member( bp ) ;
329  printf( " (%s %))\n",
330  dom->se.constructor, init_member( dom->se.element->domain )) ;
331  gen_postlude( bp ) ;
332 }
333 
334 /* GEN_DOMAIN generates the manipulation functions for a type BP. This is
335  manily a dispatching function. */
336 
337 void
339  struct gen_binding *bp ;
340 {
341  union domain *dp = bp->domain ;
342 
343  if( !IS_INLINABLE( bp ) && !IS_EXTERNAL( bp )) {
344  printf( "(lisp:defmacro write-%s (fd obj) `(gen-write ,fd ,obj))\n",
345  bp->name, bp->name ) ;
346  printf("(lisp:defmacro read-%s (lisp:&optional (fd *standard-input*))\n",
347  bp->name ) ;
348  printf(" `(gen-read ,fd))\n");
349  }
350  switch( dp->ba.type ) {
351  case CONSTRUCTED_DT:
352  if( dp->co.op == AND_OP ) gen_and( bp ) ;
353  else if( dp->co.op == OR_OP ) gen_or( bp ) ;
354  else fatal( "gen_domain: Unknown constructed %s\n", i2a( dp->co.op )) ;
355  break ;
356  case LIST_DT:
357  gen_list( bp ) ;
358  break ;
359  case ARRAY_DT:
360  gen_array( bp ) ;
361  break ;
362  case SET_DT:
363  gen_set( bp ) ;
364  break ;
365  case EXTERNAL_DT:
366  gen_external( bp ) ;
367  break ;
368  default:
369  fatal( "gen_domain: Unknown type %s\n", i2a( dp->ba.type )) ;
370  }
371 }
372 
373 /* GENCODE generates the code necessary to manipulate every non-inlinable
374  type in the Domains table. */
375 
376 void
377 gencode( file )
378 char *file ;
379 {
380  struct gen_binding *bp ;
381  int domain_count = 0 ;
382 
383  or_counter = 0 ;
384  package = file ;
385  sprintf( start, "newgen::*gen-%s-start*", file ) ;
386 
387  for( bp = Domains ; bp < &Domains[ MAX_DOMAIN ] ; bp++ ) {
388  if( bp->name == NULL ||
389  IS_INLINABLE( bp ) || IS_IMPORT( bp ) || bp == Tabulated_bp )
390  continue ;
391 
392  gen_domain( bp ) ;
393  }
394 }
395 
static Value offset
Definition: translation.c:283
int gen_external_member(dp, offset)
GEN_EXTERNAL_MEMBER generates the manipulation functions for a possible external member (either and o...
Definition: genLisp.c:130
#define OR_VALUE_INDEX
Unused in Lisp.
Definition: genLisp.c:65
static char start[1024]
The name of the variable from which to start counting domain numbers.
Definition: genLisp.c:55
#define TYPE(bp)
Definition: genLisp.c:50
void gen_external(bp)
GEN_EXTERNAL generates the type code for external type BP.
Definition: genLisp.c:117
struct gen_binding * Tabulated_bp
Definition: genLisp.c:61
void gen_list(bp)
GEN_LIST defines the manipulation functions for a list type BP.
Definition: genLisp.c:292
static void gen_prelude(bp)
GEN_PRELUDE generates prelude declarations for potentially tabulated domain BP.
Definition: genLisp.c:155
void gen_or(bp)
GEN_OR generates the manipulation function for an OR_OP type BP.
Definition: genLisp.c:240
static generate_type_member(bp)
GEN_TYPE generates the type member for potentially tabulated BP domain.
Definition: genLisp.c:197
void gen_and(bp)
GEN_AND generates the manipulation functions for an AND type BP.
Definition: genLisp.c:211
static void gen_postlude(bp)
GEN_POSTLUDE generates tabulation table updates.
Definition: genLisp.c:173
void gen_array(bp)
GEN_ARRAY defines the manipulation functions for an array type BP.
Definition: genLisp.c:305
void gencode(file)
GENCODE generates the code necessary to manipulate every non-inlinable type in the Domains table.
Definition: genLisp.c:377
char * init_member(dp)
INIT_MEMBER returns the initialization code for a value in the domain DP.
Definition: genLisp.c:72
#define NEWGEN_IMPL
Definition: genLisp.c:51
static int or_counter
Definition: genLisp.c:67
void gen_set(bp)
GEN_SET defines the manipulation functions for a set type BP.
Definition: genLisp.c:321
int Read_spec_mode
extern int Current_first ;
Definition: genLisp.c:63
void gen_domain(bp)
GEN_DOMAIN generates the manipulation functions for a type BP.
Definition: genLisp.c:338
static char * package
The package name in which functions will be defined.
Definition: genLisp.c:59
struct gen_binding Domains[MAX_DOMAIN]
in build.c
Definition: genspec_yacc.c:114
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
@ OR_OP
@ AND_OP
#define IS_EXTERNAL(bp)
#define IS_INLINABLE(bp)
Different kinds of BINDING structure pointers.
@ EXTERNAL_DT
@ SET_DT
@ ARRAY_DT
@ LIST_DT
@ BASIS_DT
@ CONSTRUCTED_DT
#define HASH_OFFSET
For tabulated objects, the offset HASH_OFFSET of the hashed subdomain.
#define MAX_DOMAIN
MAX_DOMAIN is the maximum number of entries in the DOMAINS table.
void fatal(char *,...)
#define IS_IMPORT(bp)
#define IS_TABULATED(bp)
#define UNIT_TYPE_NAME
The UNIT_TYPE_NAME is the used to type expressions which only perform side-effects.
int printf()
static string buffer
Definition: string.c:113
union domain * domain
struct inlinable * inlined
string Lisp_value
Definition: build.c:49
A DOMAIN union describes the structure of a user type.
char * constructor
struct gen_binding * element
enum domain_operator op
struct domainlist * components
struct domain::@7 co
struct domain::@5 se
int type
EXTERNAL.
struct domain::@3 ba
struct intlist * dimensions
struct domain::@4 li
struct gen_binding * constructand
struct domain::@6 ar