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 #include <assert.h>
21 
22 #include <box/callable.h>
23 #include <box/obj.h>
24 #include <box/core.h>
25 #include <box/coremath.h>
26 #include <box/str.h>
27 #include <box/bltinarray.h>
28 
29 #include <box/types_priv.h>
30 #include <box/bltinarray_priv.h>
31 #include <box/core_priv.h>
32 
33 /**
34  * Structure collection all Box core types.
35  */
36 static BoxCoreTypes box_core_types;
37 
38 
39 static void
My_Set_Type(BoxCoreTypes * ct,BoxTypeId t_id,BoxType * t,BoxBool * success)40 My_Set_Type(BoxCoreTypes *ct, BoxTypeId t_id, BoxType *t, BoxBool *success) {
41   assert(t_id >= BOXTYPEID_MIN_VAL && t_id < BOXTYPEID_MAX_VAL);
42   ct->types[t_id] = t;
43   if (!t) {
44     *success = BOXBOOL_FALSE;
45     BoxSPtr_Unlink(t);
46   }
47 }
48 
49 static void
My_Create_Type(BoxCoreTypes * core_types,const char * name,BoxTypeId id,size_t sz,size_t algn,BoxBool * success)50 My_Create_Type(BoxCoreTypes *core_types, const char *name,
51                BoxTypeId id, size_t sz, size_t algn, BoxBool *success) {
52   BoxType *t;
53 
54   if (id != BOXTYPEID_NONE)
55     t = BoxType_Create_Primary(id, sz, algn);
56   else
57     t = BoxType_Create_Intrinsic(sz, algn);
58 
59   My_Set_Type(core_types, id, BoxType_Create_Ident(t, name), success);
60 }
61 
62 /* Create primary and intrinsic types. */
63 static void
My_Init_Basic_Types(BoxCoreTypes * core_types,BoxBool * success)64 My_Init_Basic_Types(BoxCoreTypes *core_types, BoxBool *success) {
65   int idx;
66 
67   struct {
68     const char *name;
69     BoxTypeId id;
70     size_t size;
71     size_t alignment;
72   } *row, table[] = {
73     {"Type", BOXTYPEID_TYPE, sizeof(BoxTypeBundle), __alignof__(BoxTypeBundle)},
74     {"(.[)", BOXTYPEID_INIT, (size_t) 0, (size_t) 0},
75     {"(].)", BOXTYPEID_FINISH, (size_t) 0, (size_t) 0},
76     {"Char", BOXTYPEID_CHAR, sizeof(BoxChar), __alignof__(BoxChar)},
77     {"INT", BOXTYPEID_INT, sizeof(BoxInt), __alignof__(BoxInt)},
78     {"REAL", BOXTYPEID_REAL, sizeof(BoxReal), __alignof__(BoxReal)},
79     {"POINT", BOXTYPEID_POINT, sizeof(BoxPoint), __alignof__(BoxPoint)},
80     {"PTR", BOXTYPEID_PTR, sizeof(BoxPtr), __alignof__(BoxPtr)},
81     {"Obj", BOXTYPEID_OBJ, sizeof(BoxPtr), __alignof__(BoxPtr)},
82     {"Void", BOXTYPEID_VOID, (size_t) 0,  (size_t) 0},
83     {"(=)", BOXTYPEID_COPY, (size_t) 0,  (size_t) 0},
84     {"([)", BOXTYPEID_BEGIN, (size_t) 0, (size_t) 0},
85     {"(])", BOXTYPEID_END, (size_t) 0, (size_t) 0},
86     {"(;)", BOXTYPEID_PAUSE, (size_t) 0, (size_t) 0},
87     {"CPtr", BOXTYPEID_CPTR, sizeof(BoxCPtr), __alignof__(BoxCPtr)},
88     {"Str", BOXTYPEID_STR, sizeof(BoxStr), __alignof__(BoxStr)},
89     {(const char *) NULL, BOXTYPEID_NONE, (size_t) 0, (size_t) 0}
90 
91 #if 0
92     {& core_types->root_type, "/", BOXTYPEID_NONE,
93      (size_t) 0, (size_t) 0},
94     {& core_types->REFERENCES_type, "REFERENCES", BOXTYPEID_NONE,
95      0, 0},
96 #endif
97   };
98 
99   /* Set all the entries in the table to NULL. */
100   for (idx = BOXTYPEID_MIN_VAL; idx < BOXTYPEID_MAX_VAL; idx++)
101     core_types->types[idx] = NULL;
102 
103   /* Populate the table. */
104   for (row = & table[0]; row->name; row++)
105     My_Create_Type(core_types, row->name,
106                    row->id, row->size, row->alignment, success);
107 
108   My_Set_Type(core_types, BOXTYPEID_ANY, BoxType_Create_Any(), success);
109 
110   /* Register combinations for core_types->type_type. */
111   if (!Box_Register_Type_Combs(core_types))
112     *success = BOXBOOL_FALSE;
113 }
114 
115 /* Create species. */
My_Init_Composite_Types(BoxCoreTypes * ct,BoxBool * success)116 static void My_Init_Composite_Types(BoxCoreTypes *ct, BoxBool *success) {
117   BoxType *t_Any = ct->types[BOXTYPEID_ANY];
118   BoxType *t, *t_Set;
119   BoxType *real_couple;
120 
121   /* Int = (CHAR => INT) */
122   t = BoxType_Create_Species();
123   if (t) {
124     BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_CHAR]);
125     BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_INT]);
126     t = BoxType_Create_Ident(t, "Int");
127   }
128   My_Set_Type(ct, BOXTYPEID_SINT, t, success);
129 
130   /* Real = (CHAR => INT => REAL) */
131   t = BoxType_Create_Species();
132   if (t) {
133     BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_CHAR]);
134     BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_INT]);
135     BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_REAL]);
136     t = BoxType_Create_Ident(t, "Real");
137   }
138   My_Set_Type(ct, BOXTYPEID_SREAL, t, success);
139 
140   /* Point = ((Real x, y) => POINT) */
141   t = BoxType_Create_Species();
142   real_couple = BoxType_Create_Structure();
143   if (t) {
144     BoxType *real_type = ct->types[BOXTYPEID_SREAL];
145     if (real_type && real_couple) {
146       BoxType_Add_Member_To_Structure(real_couple, real_type, "x");
147       BoxType_Add_Member_To_Structure(real_couple, real_type, "y");
148       BoxType_Add_Member_To_Species(t, real_couple);
149       BoxType_Add_Member_To_Species(t, ct->types[BOXTYPEID_POINT]);
150       t = BoxType_Create_Ident(t, "Point");
151     } else {
152       (void) BoxType_Unlink(t);
153       t = NULL;
154     }
155   }
156   My_Set_Type(ct, BOXTYPEID_REAL_COUPLE, real_couple, success);
157   My_Set_Type(ct, BOXTYPEID_SPOINT, t, success);
158 
159   /* Print = Void */
160   t = BoxType_Create_Ident(BoxType_Link(ct->types[BOXTYPEID_VOID]), "Print");
161   My_Set_Type(ct, BOXTYPEID_PRINT, t, success);
162 
163   /* Repr = Str */
164   t = BoxType_Create_Ident(BoxType_Link(ct->types[BOXTYPEID_STR]), "Repr");
165   My_Set_Type(ct, BOXTYPEID_REPR, t, success);
166 
167   /* Num = Int */
168   t = BoxType_Create_Ident(BoxType_Link(ct->types[BOXTYPEID_SINT]), "Num");
169   My_Set_Type(ct, BOXTYPEID_NUM, t, success);
170 
171   /* Compare = Int */
172   t = BoxType_Create_Ident(BoxType_Link(ct->types[BOXTYPEID_INT]), "Compare");
173   My_Set_Type(ct, BOXTYPEID_COMPARE, t, success);
174 
175   /* If = Int */
176   t = BoxType_Create_Raised(BoxType_Link(ct->types[BOXTYPEID_INT]));
177   t = BoxType_Create_Ident(t, "If");
178   My_Set_Type(ct, BOXTYPEID_IF, t, success);
179 
180   /* Else = Void */
181   t = BoxType_Create_Raised(BoxType_Link(ct->types[BOXTYPEID_VOID]));
182   t = BoxType_Create_Ident(t, "Else");
183   My_Set_Type(ct, BOXTYPEID_ELSE, t, success);
184 
185   /* Elif = Int */
186   t = BoxType_Create_Raised(BoxType_Link(ct->types[BOXTYPEID_INT]));
187   t = BoxType_Create_Ident(t, "Elif");
188   My_Set_Type(ct, BOXTYPEID_ELIF, t, success);
189 
190   /* For = Int */
191   t = BoxType_Create_Raised(BoxType_Link(ct->types[BOXTYPEID_INT]));
192   t = BoxType_Create_Ident(t, "For");
193   My_Set_Type(ct, BOXTYPEID_FOR, t, success);
194 
195   /* Get = Any */
196   t = BoxType_Create_Ident(BoxType_Link(ct->types[BOXTYPEID_ANY]), "Get");
197   My_Set_Type(ct, BOXTYPEID_Get, t, success);
198 
199   /* Set = ^(Any index, value) */
200   t_Set = BoxType_Create_Structure();
201   if (t_Set) {
202     BoxType_Add_Member_To_Structure(t_Set, t_Any, "index");
203     BoxType_Add_Member_To_Structure(t_Set, t_Any, "value");
204     t_Set = BoxType_Create_Ident(BoxType_Create_Raised(t_Set), "Set");
205   }
206   My_Set_Type(ct, BOXTYPEID_Set, t_Set, success);
207 }
208 
209 /* Initialize the core types of Box. */
BoxCoreTypes_Init(BoxCoreTypes * core_types)210 BoxBool BoxCoreTypes_Init(BoxCoreTypes *core_types) {
211   BoxBool success = BOXBOOL_TRUE;
212 
213   core_types->initialized = BOXBOOL_TRUE;
214   My_Init_Basic_Types(core_types, & success);
215   My_Init_Composite_Types(core_types, & success);
216   BoxCoreTypes_Register_Array(core_types);
217 
218 #if 0
219   /* Register math core functions. */
220   if (success)
221     success = BoxCoreTypes_Init_Math(core_types);
222 #endif
223 
224   return success;
225 }
226 
227 /* Finalize the core type of Box. */
BoxCoreTypes_Finish(BoxCoreTypes * core_types)228 void BoxCoreTypes_Finish(BoxCoreTypes *core_types) {
229   int idx;
230 
231   /* Set all the entries in the table to NULL. */
232   for (idx = BOXTYPEID_MIN_VAL; idx < BOXTYPEID_MAX_VAL; idx++)
233     BoxSPtr_Unlink(core_types->types[idx]);
234 
235   core_types->initialized = BOXBOOL_FALSE;
236 }
237 
238 /* Initialize the type system. */
Box_Initialize_Type_System(void)239 BoxBool Box_Initialize_Type_System(void) {
240   return BoxCoreTypes_Init(& box_core_types);
241 }
242 
243 /* Finalize the type system. */
Box_Finalize_Type_System(void)244 void Box_Finalize_Type_System(void) {
245   BoxCoreTypes_Finish(& box_core_types);
246 }
247 
248 /* Get the core type corresponding to the given type identifier. */
249 BoxType *
BoxCoreTypes_Get_Type(BoxCoreTypes * ct,BoxTypeId id)250 BoxCoreTypes_Get_Type(BoxCoreTypes *ct, BoxTypeId id) {
251   unsigned int idx = (unsigned int) id;
252 
253   if (idx >= BOXTYPEID_MIN_VAL && idx < BOXTYPEID_MAX_VAL) {
254     if (ct->initialized)
255       return ct->types[idx];
256     else if (BoxCoreTypes_Init(ct))
257       return ct->types[idx];
258   }
259 
260   return NULL;
261 }
262 
263 /* Similar to BoxCoreTypes_Get_Type() but uses the global core type set. */
264 BoxType *
Box_Get_Core_Type(BoxTypeId id)265 Box_Get_Core_Type(BoxTypeId id) {
266   return BoxCoreTypes_Get_Type(& box_core_types, id);
267 }
268 
269 /* Install a core type (internal function). */
270 void
BoxCoreTypes_Install_Type(BoxCoreTypes * ct,BoxTypeId id,BoxType * t)271 BoxCoreTypes_Install_Type(BoxCoreTypes *ct, BoxTypeId id, BoxType *t) {
272   assert(ct && id >= BOXTYPEID_MIN_VAL && id < BOXTYPEID_MAX_VAL);
273   ct->types[id] = t;
274 }
275