1 /****************************************************************************
2  * Copyright (C) 2012 by Matteo Franchin                                    *
3  *                                                                          *
4  * This file is part of Box.                                                *
5  *                                                                          *
6  *   Box is free software: you can redistribute it and/or modify it         *
7  *   under the terms of the GNU Lesser General Public License as published  *
8  *   by the Free Software Foundation, either version 3 of the License, or   *
9  *   (at your option) any later version.                                    *
10  *                                                                          *
11  *   Box is distributed in the hope that it will be useful,                 *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
14  *   GNU Lesser General Public License for more details.                    *
15  *                                                                          *
16  *   You should have received a copy of the GNU Lesser General Public       *
17  *   License along with Box.  If not, see <http://www.gnu.org/licenses/>.   *
18  ****************************************************************************/
19 
20 /**
21  * @file combs.h
22  * @brief Module to add, find and manipulate type combinations.
23  *
24  * This header gives access to the part of the Box type system which allows
25  * creating and finding combinations. A type combination is a relation
26  * between two types.
27  */
28 
29 #ifndef _BOX_COMBS_H
30 #  define _BOX_COMBS_H
31 
32 #  include <box/types.h>
33 #  include <box/callable.h>
34 
35 /**
36  * @brief Define a combination and associate a callable to it.
37  *
38  * Define the combination of the given type between the child @p child and the
39  * parent @parent. The given callable is associated to the combination and the
40  * combination node is returned.
41  * @param parent The parent type.
42  * @param type The type of combination.
43  * @param child The child type.
44  * @param callable The callable to be associated to the combination.
45  * @return The combination node, if the operation succeed else MNUL
46  */
47 BOXEXPORT BoxType *
48 BoxType_Define_Combination(BoxType *parent, BoxCombType type, BoxType *child,
49                            BoxCallable *callable);
50 
51 /**
52  * @brief Register a combination with a #BoxCall2 implementation.
53  * @note Use of this function is discouraged outside the Box runtime
54  *    implementation.
55  *
56  * @param child Child type for the combination (the type on the left of @@).
57  * @param comb_type Type of combination. See #BoxCombType.
58  * @param parent Parent type for the combination (the type on the right of @@).
59  * @param uid A string used to identify the combination during linking.
60  * @param fn The C implementation of the combination.
61  * @return Whether the operation was successful.
62  */
63 BOXEXPORT BoxBool
64 BoxType_Define_CCall2_Combination(BoxType *child, BoxCombType comb_type,
65                                   BoxType *parent, const char *uid,
66                                   BoxCCall2 fn);
67 
68 /**
69  * @brief Convenience macro to for calling BoxType_Define_CCall2_Combination().
70  *
71  * This macro expands to a call to BoxType_Define_CCall2_Combination() where
72  * the @c uid parameter is stringified.
73  */
74 #define BOXTYPE_DEFINE_CCALL2_COMBINATION(child, comb_type, parent, fn) \
75   BoxType_Define_CCall2_Combination((child), (comb_type), (parent), #fn, (fn))
76 
77 /**
78  * @brief Undefine a combination defined with BoxType_Define_Combination().
79  *
80  * @param parent The parent in the combination to be removed.
81  * @param comb The combination node, as returned by BoxType_Find_Combination()
82  *  or BoxType_Define_Combination().
83  */
84 BOXEXPORT void
85 BoxType_Undefine_Combination(BoxType *parent, BoxType *comb);
86 
87 /**
88  * @brief Find a (possibly inherited) combination <tt>child@@parent</tt>
89  * of @c parent.
90  *
91  * The function returns:
92  * - @p child if the combination was found and the type @p child is equal to
93  *   the combination's child type;
94  * - the expansion type, if the combination was found but @p child must be
95  *   expanded;
96  * - @c NULL if the procedure was not found.
97  *
98  * @param parent The parent type.
99  * @param comb_type The combination type, see #BoxCombType.
100  * @param child The child type.
101  * @param expand How @p child compares with the found combination's child type.
102  * @return The type of the found combination's child type (@c NULL if the
103  *   combination was not found).
104  * @see BoxCombType
105  * @see BoxType_Find_Own_Combination
106  */
107 BOXEXPORT BoxType *
108 BoxType_Find_Combination(BoxType *parent, BoxCombType comb_type,
109                          BoxType *child, BoxTypeCmp *expand);
110 
111 /**
112  * Similar to #BoxType_Find_Combination, but restrict the search to the
113  * @p parent type, excluding the inherited combinations.
114  * @param parent The parent type.
115  * @param comb_type The combination type, see #BoxCombType.
116  * @param child The child type.
117  * @param expand How @p child compares with the found combination's child type.
118  * @return The type of the found combination's child type (@c NULL if the
119  *   combination was not found).
120  * @see BoxCombType
121  * @see BoxType_Find_Combination
122  */
123 BOXEXPORT BoxType *
124 BoxType_Find_Own_Combination(BoxType *parent, BoxCombType comb_type,
125                              BoxType *child, BoxTypeCmp *expand);
126 
127 /**
128  * Similar to BoxType_Find_Combination, but uses the type ID (BoxTypeId)
129  * instead of a BoxType * for the child.
130  */
131 BOXEXPORT BoxType *
132 BoxType_Find_Own_Combination_With_Id(BoxType *parent, BoxCombType type,
133                                      BoxTypeId child_id, BoxTypeCmp *expand);
134 
135 /**
136  * Get details about a combination found with BoxType_Find_Combination.
137  * @param comb The combination, as returned by #BoxType_Find_Combination.
138  * @param type Where to put the child type (if not NULL).
139  * @param cb Where to put the callable (if not NULL).
140  * @return BOXBOOL_TRUE if comb is a combination node, BOXBOOL_FALSE otherwise.
141  */
142 BOXEXPORT BoxBool
143 BoxType_Get_Combination_Info(BoxType *comb, BoxType **child, BoxCallable **cb);
144 
145 /**
146  * @brief Generate a call number for calling a combination from bytecode.
147  *
148  * Generate a call number for calling the combination @p comb from the virtual
149  * machine @p vm. If the operation succeed, the function returns
150  * @c BOXBOOL_TRUE and the call number is stored in <tt>*call_num</tt>.
151  * @param comb The combination, as returned by #BoxType_Find_Combination.
152  * @param vm The virtual machine for which a call number is generated.
153  * @param call_num Where to store the call number (ignored if @c NULL).
154  * @return A boolean which is true iff the operation succeeded.
155  * @remarks Note that - if necessary - the current callable for the combination
156  *   is replaced with a corresponding VM callable for @p vm.
157  */
158 BOXEXPORT BoxBool
159 BoxType_Generate_Combination_Call_Num(BoxType *comb, BoxVM *vm,
160                                      BoxVMCallNum *call_num);
161 
162 /**
163  * @brief Structure used with 'BoxCombDef_Define() and friends.
164  * @note Use the #BOXCOMBDEF_T_AT_T and friends to create values for initialize
165  *   a #BoxCombDef value.
166  */
167 typedef struct {
168   BoxType     *parent,   /**< Parent. If @c NULL, use @c parent_id instead. */
169               *child;    /**< Child. If @c NULL, use @c child_id instead. */
170   BoxTypeId   parent_id, /**< Parent-id, used when @c parent is @c NULL. */
171               child_id;  /**< Child-id, used when @c child is @c NULL. */
172   BoxCombType comb_type; /**< Combination type. */
173   const char  *name;     /**< Name used during linking. */
174   BoxCCall2   call2;     /**< C implementation. */
175 } BoxCombDef;
176 
177 /**
178  * @brief Convenience function used to define many combinations at once.
179  *
180  * @param defs An array of #BoxCombDef object. Each item in the array describe
181  *   one combination to define.
182  * @param num_defs Number of items in the #BoxCombDef array.
183  * @return The number of consecutive items in @p defs (starting from 0) which
184  *   could be successfully defined.
185  */
186 BOXEXPORT size_t
187 BoxCombDef_Define(BoxCombDef *defs, size_t num_defs);
188 
189 /**
190  * @brief Macro to generate a #BoxCombDef value from parent and child type.
191  *
192  * @param child type of the child.
193  * @param parent type of the parent.
194  * @param fn Pointer to the C implementation (a #BoxCCall2).
195  * @note The string identifying the combination (when linking) is obtained by
196  *   stringifying @p fn.
197  */
198 #define BOXCOMBDEF_T_AT_T(child, parent, fn)       \
199   {(parent), (child), BOXTYPEID_NONE, BOXTYPEID_NONE, \
200    BOXCOMBTYPE_AT, #fn, (fn)}
201 
202 /**
203  * @brief Macro to generate a #BoxCombDef value from parent type and child id.
204  *
205  * @param child type of the child.
206  * @param parent type-id of the parent.
207  * @param fn See #BOXCOMBDEF_T_AT_T.
208  */
209 #define BOXCOMBDEF_I_AT_T(child_id, parent, fn)            \
210   {(parent), NULL, BOXTYPEID_NONE, (child_id), BOXCOMBTYPE_AT, #fn, (fn)}
211 
212 /**
213  * @brief Macro to generate a #BoxCombDef value from parent type and child id.
214  *
215  * @param child type-id of the child.
216  * @param parent type of the parent.
217  * @param fn See #BOXCOMBDEF_T_AT_T.
218  */
219 #define BOXCOMBDEF_T_AT_I(child, parent_id, fn) \
220   {NULL, (child), (parent_id), BOXTYPEID_NONE, BOXCOMBTYPE_AT, #fn, (fn)}
221 
222 /**
223  * @brief Macro to generate a #BoxCombDef value from parent type and child id.
224  *
225  * @param child type-id of the child.
226  * @param parent type-id of the parent.
227  * @param fn See #BOXCOMBDEF_T_AT_T.
228  */
229 #define BOXCOMBDEF_I_AT_I(child_id, parent_id, fn) \
230   {NULL, NULL, (parent_id), (child_id), BOXCOMBTYPE_AT, #fn, (fn)}
231 
232 /**
233  * @brief Macro to generate a #BoxCombDef value from parent and child type.
234  *
235  * @param child type of the child.
236  * @param parent type of the parent.
237  * @param fn Pointer to the C implementation (a #BoxCCall2).
238  * @note The string identifying the combination (when linking) is obtained by
239  *   stringifying @p fn.
240  */
241 #define BOXCOMBDEF_T_TO_T(child, parent, fn)       \
242   {(parent), (child), BOXTYPEID_NONE, BOXTYPEID_NONE, \
243    BOXCOMBTYPE_COPY, #fn, (fn)}
244 
245 #endif /* _BOX_COMBS_H */
246