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 core.h
22  * @brief Definition of core types and objects.
23  *
24  * This module defines Box core types and objects.
25  */
26 
27 #ifndef _BOX_CORE_H
28 #  define _BOX_CORE_H
29 
30 #  include <float.h>
31 #  include <stdlib.h>
32 
33 /* Detect whether we are being compiled on MS Windows platforms */
34 #  ifndef __WINDOWS__
35 #    if defined(WIN32) || defined(_WIN32)
36 #      define __WINDOWS__
37 #    endif
38 #  endif
39 
40 #  ifdef __WINDOWS__
41 /**
42  * Macro to use as a prefix when declaring functions in a shared library that
43  * are meant to be used from outside callers.
44  */
45 #    define BOXEXPORT extern __declspec(dllexport)
46 #  else
47 #    define BOXEXPORT extern
48 #  endif
49 
50 /**
51  * @brief Integers associated to the fundamental types. These constant values
52  *   are used internally for caching combinations and - in general - for
53  *   speeding up the type system (or at least speeding up usage of fundamental
54  *   types).
55  */
56 typedef enum {
57   BOXTYPEID_NONE  =-1,
58   BOXTYPEID_MIN_VAL=0,
59   BOXTYPEID_FAST_LOWER = 0,
60   BOXTYPEID_CHAR  = 0,
61   BOXTYPEID_INT   = 1,
62   BOXTYPEID_REAL  = 2,
63   BOXTYPEID_POINT = 3,
64   BOXTYPEID_PTR   = 4,
65   BOXTYPEID_FAST_UPPER = 4,
66   BOXTYPEID_OBJ   = 5,
67   BOXTYPEID_VOID,
68   BOXTYPEID_INIT,
69   BOXTYPEID_FINISH,
70   BOXTYPEID_COPY,
71   BOXTYPEID_BEGIN,
72   BOXTYPEID_END,
73   BOXTYPEID_PAUSE,
74   BOXTYPEID_CPTR,
75   BOXTYPEID_TYPE,
76   BOXTYPEID_ANY,
77   BOXTYPEID_SINT,
78   BOXTYPEID_SREAL,
79   BOXTYPEID_SPOINT,
80   BOXTYPEID_REAL_COUPLE,
81   BOXTYPEID_IF,
82   BOXTYPEID_ELSE,
83   BOXTYPEID_ELIF,
84   BOXTYPEID_FOR,
85   BOXTYPEID_NUM,
86   BOXTYPEID_STR,
87   BOXTYPEID_REPR,
88   BOXTYPEID_PRINT,
89   BOXTYPEID_COMPARE,
90   BOXTYPEID_Get,
91   BOXTYPEID_Getter,
92   BOXTYPEID_Set,
93   BOXTYPEID_ARRAY,
94   BOXTYPEID_Array,
95   BOXTYPEID_MAX_VAL
96 } BoxTypeId;
97 
98 /**
99  * @brief A type in the Box type system. This is currently implemented as a
100  *   pointer to an opaque structure.
101  */
102 typedef struct BoxType_struct BoxType;
103 
104 /**
105  * The BoxChar type, the smallest integer in terms of size.
106  */
107 typedef unsigned char BoxChar;
108 
109 /**
110  * The integer type of Box numbers and the integer type we will try
111  * to use whenever possible: this corresponds to the C long int.
112  */
113 typedef long BoxInt;
114 
115 /**
116  * The unsigned integer type that we will try to use whenever possible.
117  * Same size of Int.
118  */
119 typedef unsigned long BoxUInt;
120 
121 /**
122  * Fundamental boolean type used in the Box compiler API.
123  */
124 typedef int BoxBool;
125 
126 enum {
127   BOXBOOL_FALSE=0,
128   BOXBOOL_TRUE=1
129 };
130 
131 /**
132  * Here is the definition of the floating point type used by Box.
133  */
134 typedef double BoxReal;
135 
136 /**
137  * Conversion string --> Int
138  */
139 #  define BoxInt_Of_Str strtol
140 
141 /**
142  * Conversion string --> Real
143  */
144 #  define BoxReal_Of_Str strtod
145 
146 #  define BOXREAL_MAX DBL_MAX
147 #  define BOXREAL_MIN (-DBL_MAX)
148 
149 /**
150  * The 2D point type.
151  */
152 typedef struct BoxPoint_struct {
153   BoxReal x, y;
154 } BoxPoint;
155 
156 /**
157  * We need more than just a pointer when referring to Box objects.
158  */
159 typedef struct BoxPtr_struct {
160   void *ptr,   /**< Pointer to the data inside this block */
161        *block; /**< Pointer to the allocated memory block */
162 } BoxPtr;
163 
164 /** Reset an extended BoxPtr pointer to NULL (point to nothing) */
165 #  define BoxPtr_Init(p) \
166   do {(p)->block = (p)->ptr = NULL;} while(0)
167 
168 #  define BoxPtr_Nullify BoxPtr_Init
169 
170 /** Detach a pointer so that it does not reference its source */
171 #  define BoxPtr_Detach(p) \
172   do {(p)->block = NULL;} while(0)
173 
174 /** Whether a BoxPtr pointer is NULL */
175 #  define BoxPtr_Is_Null(p) ((p)->ptr == NULL)
176 
177 /** Whether a BoxPtr pointer is detached (not bound to a memory block) */
178 #  define BoxPtr_Is_Detached(p) ((p)->block == NULL)
179 
180 /** Get the target pointer associated to the given BoxPtr extended pointer. */
181 #  define BoxPtr_Get_Target(p) ((p)->ptr)
182 
183 /** Get the block of the given BoxPtr extended pointer. */
184 #  define BoxPtr_Get_Block(p) ((p)->block)
185 
186 /**
187  * This macro expands to nothing. It is used in function prototypes to indicate
188  * that the declared function steals a reference to the passed object. This
189  * macro has hence a purely aesthetical/declarative purpose.
190  */
191 #  define BOXIN
192 
193 /**
194  * This macro expands to nothing. It is used in function prototypes to indicate
195  * that the declared function provides a newly created or existing object. This
196  * macro has hence a purely aesthetical/declarative purpose.
197  */
198 #  define BOXOUT
199 
200 /** Type representing C pointers from Box */
201 typedef void *BoxCPtr;
202 
203 /**
204  * A subtype is simply a structure containing two pointers: one points
205  * to the parent, one to the child.
206  */
207 typedef struct {
208   BoxPtr child, parent;
209 } BoxSubtype;
210 
211 #  define BoxSubtype_Get_Parent_Target(subtype_ptr) \
212   ((subtype_ptr)->parent.ptr)
213 
214 #  define BoxSubtype_Get_Child_Target(subtype_ptr) \
215   ((subtype_ptr)->child.ptr)
216 
217 #  define SUBTYPE_PARENT_PTR(subtype_ptr, parent_type) \
218   ((parent_type *) (subtype_ptr)->parent.ptr)
219 
220 #  define SUBTYPE_CHILD_PTR(subtype_ptr, child_type) \
221   (( child_type *) (subtype_ptr)->child.ptr)
222 
223 
224 /**
225  * Union of all the intrinsic Box types.
226  */
227 typedef union {
228   BoxChar  box_char;
229   BoxInt   box_int;
230   BoxReal  box_real;
231   BoxPoint box_point;
232   BoxPtr   box_obj;
233 } BoxImmValue;
234 
235 /* Strings containing the printf formats for the various types */
236 #  define BoxChar_Fmt "%c"
237 #  define BoxUInt_Fmt "%lu"
238 #  define BoxInt_Fmt "%ld"
239 #  define BoxReal_Fmt "%g"
240 #  define BoxPoint_Fmt "(%g, %g)"
241 
242 /**
243  * @brief Type used from functions to communicate whether an operation
244  *   succeeded or failed.
245  */
246 typedef enum {
247   BOXTASK_OK      = 0, /**< Function succeeded */
248   BOXTASK_FAILURE = 1, /**< Function failed: caller needs to report error */
249   BOXTASK_ERROR   = 2  /**< Function failed: error already reported */
250 } BoxTask;
251 
252 /*****************************************************************************/
253 /* Obsolete stuff below. */
254 
255 typedef struct {
256   BoxInt length;
257   char *text;
258 } BoxName;
259 
260 #  define BOXNAME(str) ((BoxName) {sizeof(str)-1, str})
261 
262 typedef BoxName BoxData;
263 
264 /* Questa macro permette di usare una indicizzazione "circolare", secondo cui,
265  * data una lista di num_items elementi, l'indice 1 si riferisce al primo
266  * elemento, 2 al secondo, ..., num_items all'ultimo, num_items+1 al primo,
267  * num_items+2 al secondo, ...  Inoltre l'indice 0 si riferisce all'ultimo
268  * elemento, -1 al pen'ultimo, ...
269  */
270 #define BOX_CIRCULAR_INDEX(num_items, index)            \
271   ((index) > 0 ? ((index) - 1) % (num_items)            \
272    : (num_items) - 1 - ((-(index)) % (num_items)))
273 
274 /* Shorthands. */
275 #    define SUInt BoxUInt_Fmt
276 #    define SChar BoxChar_Fmt
277 #    define SInt BoxInt_Fmt
278 #    define SReal BoxReal_Fmt
279 #    define SPoint BoxPoint_Fmt
280 #    define CIRCULAR_INDEX BOX_CIRCULAR_INDEX
281 
282 /*****************************************************************************/
283 
284 /**
285  * @brief Macro to call a function returning #BoxTask from a function returning
286  *   #BoxTask.
287  */
288 #  define BOXTASK(x) \
289   do {if (x) return BOXTASK_FAILURE;} while(0)
290 
291 /**
292  * @brief This macro should be used to check - via an assert - that a function
293  *   returning #BoxTask succeeded.
294  *
295  * @note This should be used with functions that are expected to succeed.
296  */
297 #  define ASSERT_TASK(x) \
298   do {BoxTask t = (x); assert(t == BOXTASK_OK);} while(0)
299 
300 typedef struct BoxCoreTypes_struct BoxCoreTypes;
301 
302 /**
303  * @brief Initialize the core types of Box.
304  */
305 BOXEXPORT BoxBool
306 BoxCoreTypes_Init(BoxCoreTypes *core_types);
307 
308 /**
309  * @brief Finalize the core type of Box.
310  */
311 BOXEXPORT void
312 BoxCoreTypes_Finish(BoxCoreTypes *core_types);
313 
314 /**
315  * @brief Initialize the type system.
316  */
317 BOXEXPORT BoxBool
318 Box_Initialize_Type_System(void);
319 
320 /**
321  * @brief Initialize the type system.
322  */
323 BOXEXPORT void
324 Box_Finalize_Type_System(void);
325 
326 /**
327  * @brief Get the core type corresponding to the given type identifier.
328  *
329  * @param ct The set of core types from which the type is to be extracted.
330  * @param id The type identifier for the type to extract.
331  * @return The type corresponding to @p id, extracted from @p ct, or @c NULL
332  *   if the operation failed.
333  * @note @p ct is initialized if it is not. In other words @p ct can be a
334  *   pointer to a zeroed region of memory which can contain
335  *   <tt>sizeof(BoxCoreTypes)</tt> bytes.
336  */
337 BOXEXPORT BoxType *
338 BoxCoreTypes_Get_Type(BoxCoreTypes *ct, BoxTypeId id);
339 
340 /**
341  * @brief Similar to BoxCoreTypes_Get_Type() but uses the global core type
342  *   set.
343  *
344  * @see BoxCoreTypes_Get_Type().
345  */
346 BOXEXPORT BoxType *
347 Box_Get_Core_Type(BoxTypeId id);
348 
349 #  define BOX_FATAL_ERROR() Box_Fatal_Error(__FILE__, __LINE__)
350 
351 /**
352  * @brief Install a core type (internal function).
353  *
354  * @param ct The set of core types.
355  * @param id Core type id.
356  * @param t The type to be associated to @p id.
357  * @note Aborts on failure.
358  */
359 BOXEXPORT void
360 BoxCoreTypes_Install_Type(BoxCoreTypes *ct, BoxTypeId id, BoxType *t);
361 
362 #endif /* _BOX_CORE_H */
363