~jdpipe/ascend/trunk-old

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*	ASCEND modelling environment
	Copyright (C) 2006 Carnegie Mellon University
	Copyright 1997, Carnegie Mellon University.

	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, 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, see <http://www.gnu.org/licenses/>.
*//** @file
	'Anonymous type' classification functions.

	The idea of this module is to find and report groups of
	isomorphic instances (instances with the same Anonymous Type).
	We do not actually produce type definitions, or anything like them,
	but instead use various sorting techniques. Note that anonymous
	type is a dynamic quantity in the ascend language definition which
	allows deferred binding.
	This should be named something like isomorph.c, but half the compiler
	files start with i already.
	These functions are thread-safe, if the instance data
	structures are, as this module creates no global variables.
	At present, instance structures are not thread-safe unless the
	entire global simulations list is locked into one thread.

	Ultimately the user will be returned a gl_list of AnonType pointers,
	where each pointer knows how many occurrences of some identical AT
	there are and where those occurences are. This list will become
	invalid if any compiler actions anywhere in the simulation universe
	change any of the instances in such a way that any instance is
	MOVED (e.g. by realloc) or modified independently of all other
	instances in the same anonymous type group.

	The Instances are NOT left with a record of their anonymous type.
	Each AT has a unique index number, which is its position in the
	gl_list returned. There is no useful ordering of the gl_list returned.
	Each AT knows its formal family as a doubly linked list, and each
	AT has a counter, visited, that the user can do arbitrary things
	with. The doubly linked list is ordered in some way that is an
	artifact of the classification algorithm. The head and tail of
	the linked list are NULL.

	Special cases:

	-# Relations, logical relations, and when statements are always
	   anonymous in the following sense:

	   They are more like atomic types. Their true 'formal type',
	   if you like, is the statement defining them since their
	   basic DEFINITIONS are universal. If you accept this, then
	   you can easily see also that the 'anonymous type' (the
	   expanded token form) of a relation is entirely dependent
	   on the anonymous type of the relation's context. This also
	   holds for logical relations and when structures.

	   So, in the collected 'anonymous types', there will be only as
	   many AT's devoted to relations as there are formal definitions
	   present in the system for relation (normally just 1).
	   The AT for each formal relation definition present will have
	   an instance list of all relations from that definition.

	   To find cliques of relations, just look at cliques of models.
	   If this handling of relations is insufficient, then the
	   statement of the relation could be used in a secondary slot
	   of the AT. To find exact relation groups requires a two pass
	   algorithm.

	-# Arrays. ASCEND arrays just suck. The approach here is
	   conservative; there may be fewer array cliques than we can
	   compute with a single pass algorithm.

	-# Undefined constants. Constant reals/integers which are undefined
	   are sorted as if they have DBL_MAX/LONG_MAX for a value. We are
	   assuming there are no meaningful constants for modeling
	   which take on the maximum value of the machine representation.

	Requires
	#include <stdio.h>
	       #include "utilities/ascConfig.h"
	       #include "general/list.h"
	       #include "compiler/instance_enum.h"

*//*
	By Benjamin Andrew Allan
	Created August 30, 1997.
	Last in CVS: $Revision: 1.5 $ $Date: 1998/02/05 22:23:20 $ $Author: ballan $
*/

#ifndef ASC_ANONTYPE_H
#define ASC_ANONTYPE_H

/**	@addtogroup compiler_anon Compiler Anonymous Types
	@{
*/

/** For debugging set =1, for performance set = 0 */
#define ATDEBUG 0

/** abbreviated AT in comments */
struct AnonType {
   unsigned long index;           /**< index in the gllist of ATs
                                      0 -> not in list. -1 == freed. */
   struct gl_list_t *instances;   /**< list of this AT's instances */
   struct AnonType *prev, *next;  /**< other ATs related by
                                       all being the same formally. */
   int exactfamily;               /**< group id of anonymous types which are
                                       identical except for merged substructure. */
   int visited;                   /**< counter for arbitrary use. */
};

/**
 * The initial number of instances to expect for each AT.
 * Tuning this may be hard. E.g. relations and some atoms
 * will grow to a huge number, but many constant types will
 * only have 1-3 instances shared universally.
 * In a distillation MODEL there are ~400 anon types
 * and most of these fall in the constant types.
 */
#define INSTANCES_PER_AT 2

/**
 * Define the expected maximum number of anonymous types.
 * This should not be too low or the code will do memory
 * reallocation of gl_list, atl.
 */
#define ANONEXPECTED 200

/**
 * Define the size for the hash tables keyed by the
 * formal type name and secondarily keyed by type ptr.
 * The secondary key is required because mixed simulations
 * may be created by pathological users and we must not
 * get confused when classifying.
 * One such hash table is used while classifying an instance tree
 * into AT groups. The user never sees this table, however.
 * This size must be even power of 2 and shouldn't be messed with.
 */
#define ANONTABLESIZE 1024

/**
 * Return the nth element of anon type list n.
 * The return type is <code>AnonType*</code>.
 */
#define Asc_GetAnonType(atl,n) \
  ((struct AnonType *)gl_fetch((atl),(n)))

/**
 * Return the number of instances associated with the nth position
 * in anonymous type list n.  The return value is type
 * <code>unsigned long</code>.
 */
#define Asc_GetAnonCount(atl,n) \
  gl_length(Asc_GetAnonType((atl),(n))->instances)

/**
 * Returns the cth member of an anonymous type clique
 * represented by at.  The return value is type <code>Instance*</code>.
 * @param at  an AnonType*, such as returned by: at = Asc_GetAnonType(atl,n);
 * @param  c  index:  1 <= c <= Asc_GetAnonCount(atl,n)
 */
#define Asc_GetAnonTypeInstance(at,c) \
  (struct Instance *)gl_fetch((at)->instances,(c))

/**
 * Returns the first element of the instance list associated with the
 * AT given. Does not normally return unless there is such a creature.
 */
extern struct Instance *Asc_GetAnonPrototype(struct AnonType *at);

/**
 * Destroys the anonlist we returned from a call to classify.
 * Do not destroy this list any other way.
 */
ASC_DLLSPEC void Asc_DestroyAnonList(struct gl_list_t *atl);

/**
 * This function classifies an instance tree
 * and returns the list described above.
 * root may be at any place in an instance tree.
 * The list should be destroyed with Asc_DestroyAnonList.
 */
ASC_DLLSPEC struct gl_list_t *Asc_DeriveAnonList(struct Instance *root);

/**
 * Writes a list of anon type info in atl, mainly for debugging purposes,
 * to the file given. root is the instance that Asc_DeriveAnonList
 * was called with, for the proper writing of names.
 * If root is NULL, arbitrary names will be made up.
 * If mlists != 0 and merge info exists, merge info will be written
 * with the AT info.
 */
ASC_DLLSPEC void Asc_WriteAnonList(FILE *fp,
                              struct gl_list_t *atl,
                              struct Instance *root,
                              int mlists);

/* @} */

#endif  /* ASC_ANONTYPE_H */