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