Added more protocol for Behavior. Fleshed out HashedCollection classes.
[panda.git] / src / st-universe.c
blob7535f4d3037f7df89e81618c43a2e6d033a39c95
1 /*
2 * st-universe.c
4 * Copyright (C) 2008 Vincent Geddes
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "st-types.h"
26 #include "st-utils.h"
27 #include "st-object.h"
28 #include "st-behavior.h"
29 #include "st-float.h"
30 #include "st-association.h"
31 #include "st-method.h"
32 #include "st-array.h"
33 #include "st-small-integer.h"
34 #include "st-dictionary.h"
35 #include "st-large-integer.h"
36 #include "st-symbol.h"
37 #include "st-universe.h"
38 #include "st-object.h"
39 #include "st-lexer.h"
40 #include "st-descriptor.h"
41 #include "st-compiler.h"
42 #include "st-memory.h"
43 #include "st-context.h"
44 #include "st-processor.h"
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdio.h>
50 st_oop globals[34];
52 st_oop st_specials[ST_NUM_SPECIALS];
55 st_oop
56 st_global_get (const char *name)
58 st_oop sym;
60 st_assert (st_symbol_new (name) == st_symbol_new (name));
62 sym = st_symbol_new (name);
64 return st_dictionary_at (st_globals, sym);
67 enum
69 INSTANCE_SIZE_UNDEFINED = 0,
70 INSTANCE_SIZE_CLASS = 6,
71 INSTANCE_SIZE_METACLASS = 6,
72 INSTANCE_SIZE_DICTIONARY = 3,
73 INSTANCE_SIZE_SET = 3,
74 INSTANCE_SIZE_ASSOCIATION = 2,
75 INSTANCE_SIZE_SYSTEM = 2,
78 static st_oop
79 class_new (st_format format, st_uint instance_size)
81 st_oop class;
83 class = st_memory_allocate (ST_SIZE_OOPS (struct st_class));
85 ST_HEADER (class)->mark = 0 | ST_MARK_TAG;
86 ST_HEADER (class)->hash = st_smi_new (st_current_hash++);
87 ST_HEADER (class)->class = st_nil;
88 st_object_set_format (class, ST_FORMAT_OBJECT);
89 st_object_set_instance_size (class, INSTANCE_SIZE_CLASS);
91 ST_BEHAVIOR (class)->format = st_smi_new (format);
92 ST_BEHAVIOR (class)->instance_size = st_smi_new (instance_size);
93 ST_BEHAVIOR (class)->superclass = st_nil;
94 ST_BEHAVIOR (class)->method_dictionary = st_nil;
95 ST_BEHAVIOR (class)->instance_variables = st_nil;
97 ST_CLASS (class)->name = st_nil;
99 return class;
102 static void
103 add_global (const char *name, st_oop object)
105 st_oop symbol;
107 // sanity check for symbol interning
108 st_assert (st_symbol_new (name) == st_symbol_new (name));
110 symbol = st_symbol_new (name);
111 st_dictionary_at_put (st_globals, symbol, object);
113 // sanity check for dictionary
114 st_assert (st_dictionary_at (st_globals, symbol) == object);
117 static void
118 parse_error (char *message, st_token *token)
120 fprintf (stderr, "error: %i: %i: %s",
121 st_token_get_line (token), st_token_get_column (token), message);
122 exit (1);
125 static void
126 initialize_class (const char *name,
127 const char *super_name,
128 st_list *ivarnames)
130 st_oop metaclass, class, superclass;
131 st_oop names;
132 st_uint i = 1;
134 if (streq (name, "Object") && streq (super_name, "nil")) {
136 class = st_dictionary_at (st_globals, st_symbol_new ("Object"));
137 st_assert (class != st_nil);
139 metaclass = st_object_class (class);
140 if (metaclass == st_nil) {
141 metaclass = st_object_new (st_metaclass_class);
142 ST_HEADER (class)->class = metaclass;
145 ST_BEHAVIOR_SUPERCLASS (class) = st_nil;
146 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (0);
147 ST_BEHAVIOR_SUPERCLASS (metaclass) = st_dictionary_at (st_globals, st_symbol_new ("Class"));
149 } else {
151 superclass = st_global_get (super_name);
152 if (superclass == st_nil)
153 st_assert (superclass != st_nil);
155 class = st_global_get (name);
156 if (class == st_nil)
157 class = class_new (st_smi_value (ST_BEHAVIOR_FORMAT (superclass)), 0);
159 metaclass = ST_HEADER (class)->class;
160 if (metaclass == st_nil) {
161 metaclass = st_object_new (st_metaclass_class);
162 ST_HEADER (class)->class = metaclass;
165 ST_BEHAVIOR_SUPERCLASS (class) = superclass;
166 ST_BEHAVIOR_SUPERCLASS (metaclass) = ST_HEADER (superclass)->class;
167 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (st_list_length (ivarnames) +
168 st_smi_value (ST_BEHAVIOR_INSTANCE_SIZE (superclass)));
171 names = st_nil;
172 if (st_list_length (ivarnames) != 0) {
173 names = st_object_new_arrayed (st_array_class, st_list_length (ivarnames));
174 for (st_list *l = ivarnames; l; l = l->next)
175 st_array_at_put (names, i++, st_symbol_new (l->data));
176 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names;
179 ST_BEHAVIOR_FORMAT (metaclass) = st_smi_new (ST_FORMAT_OBJECT);
180 ST_BEHAVIOR_METHOD_DICTIONARY (metaclass) = st_dictionary_new ();
181 ST_BEHAVIOR_INSTANCE_VARIABLES (metaclass) = st_nil;
182 ST_BEHAVIOR_INSTANCE_SIZE (metaclass) = st_smi_new (INSTANCE_SIZE_CLASS);
183 ST_METACLASS_INSTANCE_CLASS (metaclass) = class;
184 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names;
185 ST_BEHAVIOR_METHOD_DICTIONARY (class) = st_dictionary_new ();
186 ST_CLASS_NAME (class) = st_symbol_new (name);
188 st_dictionary_at_put (st_globals, st_symbol_new (name), class);
192 static bool
193 parse_variable_names (st_lexer *lexer, st_list **varnames)
195 st_lexer *ivarlexer;
196 st_token *token;
197 char *names;
199 token = st_lexer_next_token (lexer);
201 if (st_token_get_type (token) != ST_TOKEN_STRING_CONST)
202 return false;
204 names = st_strdup (st_token_get_text (token));
205 ivarlexer = st_lexer_new (names); /* input valid at this stage */
206 token = st_lexer_next_token (ivarlexer);
208 while (st_token_get_type (token) != ST_TOKEN_EOF) {
210 if (st_token_get_type (token) != ST_TOKEN_IDENTIFIER)
211 parse_error (NULL, token);
213 *varnames = st_list_append (*varnames, st_strdup (st_token_get_text (token)));
214 token = st_lexer_next_token (ivarlexer);
217 st_lexer_destroy (ivarlexer);
219 return true;
223 static void
224 parse_class (st_lexer *lexer, st_token *token)
226 char *class_name = NULL;
227 char *superclass_name = NULL;
229 // 'Class' token
230 if (st_token_get_type (token) != ST_TOKEN_IDENTIFIER
231 || !streq (st_token_get_text (token), "Class"))
232 parse_error ("expected class definition", token);
234 // `named:' token
235 token = st_lexer_next_token (lexer);
236 if (st_token_get_type (token) != ST_TOKEN_KEYWORD_SELECTOR
237 || !streq (st_token_get_text (token), "named:"))
238 parse_error ("expected 'name:'", token);
240 // class name
241 token = st_lexer_next_token (lexer);
242 if (st_token_get_type (token) == ST_TOKEN_STRING_CONST) {
243 class_name = st_strdup (st_token_get_text (token));
244 } else {
245 parse_error ("expected string literal", token);
248 // `superclass:' token
249 token = st_lexer_next_token (lexer);
250 if (st_token_get_type (token) != ST_TOKEN_KEYWORD_SELECTOR
251 || !streq (st_token_get_text (token), "superclass:"))
252 parse_error ("expected 'superclass:'", token);
254 // superclass name
255 token = st_lexer_next_token (lexer);
256 if (st_token_get_type (token) == ST_TOKEN_STRING_CONST) {
258 superclass_name = st_strdup (st_token_get_text (token));
260 } else {
261 parse_error ("expected string literal", token);
264 st_list *ivarnames = NULL;
266 // 'instanceVariableNames:' keyword selector
267 token = st_lexer_next_token (lexer);
268 if (st_token_get_type (token) == ST_TOKEN_KEYWORD_SELECTOR &&
269 streq (st_token_get_text (token), "instanceVariableNames:")) {
271 parse_variable_names (lexer, &ivarnames);
273 } else {
274 parse_error (NULL, token);
277 token = st_lexer_next_token (lexer);
279 initialize_class (class_name, superclass_name, ivarnames);
281 st_list_destroy (ivarnames);
283 return;
286 static void
287 parse_classes (const char *filename)
289 char *contents;
290 st_lexer *lexer;
291 st_token *token;
293 if (!st_file_get_contents (filename, &contents)) {
294 exit (1);
297 lexer = st_lexer_new (contents);
298 st_assert (lexer != NULL);
299 token = st_lexer_next_token (lexer);
301 while (st_token_get_type (token) != ST_TOKEN_EOF) {
303 while (st_token_get_type (token) == ST_TOKEN_COMMENT)
304 token = st_lexer_next_token (lexer);
306 parse_class (lexer, token);
307 token = st_lexer_next_token (lexer);
311 static void
312 file_in_classes (void)
314 char *filename;
316 parse_classes ("../st/class-defs.st");
318 static const char * files[] =
320 "Stream.st",
321 "PositionableStream.st",
322 "WriteStream.st",
323 "Collection.st",
324 "SequenceableCollection.st",
325 "ArrayedCollection.st",
326 "HashedCollection.st",
327 "Set.st",
328 "Dictionary.st",
329 "Array.st",
330 "ByteArray.st",
331 "WordArray.st",
332 "FloatArray.st",
333 "Association.st",
334 "Magnitude.st",
335 "Number.st",
336 "Integer.st",
337 "SmallInteger.st",
338 "LargeInteger.st",
339 "Fraction.st",
340 "Float.st",
341 "Object.st",
342 "UndefinedObject.st",
343 "String.st",
344 "Symbol.st",
345 "ByteString.st",
346 "WideString.st",
347 "Character.st",
348 "UnicodeTables.st",
349 "Behavior.st",
350 "Boolean.st",
351 "True.st",
352 "False.st",
353 "Behavior.st",
354 "ContextPart.st",
355 "BlockContext.st",
356 "Message.st",
357 "OrderedCollection.st",
358 "FileStream.st",
359 "List.st",
360 "System.st"
363 for (st_uint i = 0; i < ST_N_ELEMENTS (files); i++) {
364 filename = st_strconcat("..", ST_DIR_SEPARATOR_S, "st", ST_DIR_SEPARATOR_S, files[i], NULL);
365 st_compile_file_in (filename);
366 st_free (filename);
370 #define NIL_SIZE_OOPS (sizeof (struct st_header) / sizeof (st_oop))
372 static st_oop
373 create_nil_object (void)
375 st_oop nil;
377 nil = st_memory_allocate (NIL_SIZE_OOPS);
379 ST_HEADER (nil)->mark = 0 | ST_MARK_TAG;
380 ST_HEADER (nil)->hash = st_smi_new (st_current_hash++);
381 ST_HEADER (nil)->class = nil;
382 st_object_set_format (nil, ST_FORMAT_OBJECT);
383 st_object_set_instance_size (nil, 0);
385 return nil;
388 static void
389 init_specials (void)
391 st_specials[ST_SPECIAL_PLUS] = st_symbol_new ("+");
392 st_specials[ST_SPECIAL_MINUS] = st_symbol_new ("-");
393 st_specials[ST_SPECIAL_LT] = st_symbol_new ("<");
394 st_specials[ST_SPECIAL_GT] = st_symbol_new (">");
395 st_specials[ST_SPECIAL_LE] = st_symbol_new ("<=");
396 st_specials[ST_SPECIAL_GE] = st_symbol_new (">=");
397 st_specials[ST_SPECIAL_EQ] = st_symbol_new ("=");
398 st_specials[ST_SPECIAL_NE] = st_symbol_new ("~=");
399 st_specials[ST_SPECIAL_MUL] = st_symbol_new ("*");
400 st_specials[ST_SPECIAL_DIV] = st_symbol_new ("/");
401 st_specials[ST_SPECIAL_MOD] = st_symbol_new ("\\");
402 st_specials[ST_SPECIAL_BITSHIFT] = st_symbol_new ("bitShift:");
403 st_specials[ST_SPECIAL_BITAND] = st_symbol_new ("bitAnd:");
404 st_specials[ST_SPECIAL_BITOR] = st_symbol_new ("bitOr:");
405 st_specials[ST_SPECIAL_BITXOR] = st_symbol_new ("bitXor:");
407 st_specials[ST_SPECIAL_AT] = st_symbol_new ("at:");
408 st_specials[ST_SPECIAL_ATPUT] = st_symbol_new ("at:put:");
409 st_specials[ST_SPECIAL_SIZE] = st_symbol_new ("size");
410 st_specials[ST_SPECIAL_VALUE] = st_symbol_new ("value");
411 st_specials[ST_SPECIAL_VALUE_ARG] = st_symbol_new ("value:");
412 st_specials[ST_SPECIAL_IDEQ] = st_symbol_new ("==");
413 st_specials[ST_SPECIAL_CLASS] = st_symbol_new ("class");
414 st_specials[ST_SPECIAL_NEW] = st_symbol_new ("new");
415 st_specials[ST_SPECIAL_NEW_ARG] = st_symbol_new ("new:");
417 st_selector_doesNotUnderstand = st_symbol_new ("doesNotUnderstand:");
418 st_selector_mustBeBoolean = st_symbol_new ("mustBeBoolean");
419 st_selector_startupSystem = st_symbol_new ("startupSystem");
420 st_selector_cannotReturn = st_symbol_new ("cannotReturn");
421 st_selector_outOfMemory = st_symbol_new ("outOfMemory");
424 st_memory *memory;
426 void
427 st_bootstrap_universe (void)
429 st_oop smalltalk;
430 st_oop st_object_class_, st_class_class_;
432 st_memory_new ();
434 /* setup format descriptors */
435 st_descriptors[ST_FORMAT_OBJECT] = st_object_descriptor ();
436 st_descriptors[ST_FORMAT_ARRAY] = st_array_descriptor ();
437 st_descriptors[ST_FORMAT_BYTE_ARRAY] = st_byte_array_descriptor ();
438 st_descriptors[ST_FORMAT_WORD_ARRAY] = st_word_array_descriptor ();
439 st_descriptors[ST_FORMAT_FLOAT_ARRAY] = st_float_array_descriptor ();
440 st_descriptors[ST_FORMAT_FLOAT] = st_float_descriptor ();
441 st_descriptors[ST_FORMAT_LARGE_INTEGER] = st_large_integer_descriptor ();
442 st_descriptors[ST_FORMAT_CONTEXT] = st_context_descriptor ();
444 st_nil = create_nil_object ();
446 st_object_class_ = class_new (ST_FORMAT_OBJECT, 0);
447 st_undefined_object_class = class_new (ST_FORMAT_OBJECT, 0);
448 st_metaclass_class = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_METACLASS);
449 st_behavior_class = class_new (ST_FORMAT_OBJECT, 0);
450 st_class_class_ = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_CLASS);
451 st_smi_class = class_new (ST_FORMAT_OBJECT, 0);
452 st_large_integer_class = class_new (ST_FORMAT_LARGE_INTEGER, 0);
453 st_character_class = class_new (ST_FORMAT_OBJECT, 0);
454 st_true_class = class_new (ST_FORMAT_OBJECT, 0);
455 st_false_class = class_new (ST_FORMAT_OBJECT, 0);
456 st_float_class = class_new (ST_FORMAT_FLOAT, 0);
457 st_array_class = class_new (ST_FORMAT_ARRAY, 0);
458 st_word_array_class = class_new (ST_FORMAT_WORD_ARRAY, 0);
459 st_float_array_class = class_new (ST_FORMAT_FLOAT_ARRAY, 0);
460 st_dictionary_class = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_DICTIONARY);
461 st_set_class = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_SET);
462 st_byte_array_class = class_new (ST_FORMAT_BYTE_ARRAY, 0);
463 st_symbol_class = class_new (ST_FORMAT_BYTE_ARRAY, 0);
464 st_string_class = class_new (ST_FORMAT_BYTE_ARRAY, 0);
465 st_wide_string_class = class_new (ST_FORMAT_WORD_ARRAY, 0);
466 st_association_class = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_ASSOCIATION);
467 st_compiled_method_class = class_new (ST_FORMAT_OBJECT, 0);
468 st_method_context_class = class_new (ST_FORMAT_CONTEXT, 5);
469 st_block_context_class = class_new (ST_FORMAT_CONTEXT, 7);
470 st_system_class = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_SYSTEM);
472 ST_HEADER (st_nil)->class = st_undefined_object_class;
474 /* special objects */
475 st_true = st_object_new (st_true_class);
476 st_false = st_object_new (st_false_class);
477 st_symbols = st_set_new_with_capacity (256);
478 st_globals = st_dictionary_new_with_capacity (256);
479 st_smalltalk = st_object_new (st_system_class);
480 ST_HEADER (st_smalltalk)->fields[0] = st_globals;
481 ST_HEADER (st_smalltalk)->fields[1] = st_symbols;
483 /* add class names to symbol table */
484 add_global ("Object", st_object_class_);
485 add_global ("UndefinedObject", st_undefined_object_class);
486 add_global ("Behavior", st_behavior_class);
487 add_global ("Class", st_class_class_);
488 add_global ("Metaclass", st_metaclass_class);
489 add_global ("SmallInteger", st_smi_class);
490 add_global ("LargeInteger", st_large_integer_class);
491 add_global ("Character", st_character_class);
492 add_global ("True", st_true_class);
493 add_global ("False", st_false_class);
494 add_global ("Float", st_float_class);
495 add_global ("Array", st_array_class);
496 add_global ("ByteArray", st_byte_array_class);
497 add_global ("WordArray", st_word_array_class);
498 add_global ("FloatArray", st_float_array_class);
499 add_global ("ByteString", st_string_class);
500 add_global ("ByteSymbol", st_symbol_class);
501 add_global ("WideString", st_wide_string_class);
502 add_global ("IdentitySet", st_set_class);
503 add_global ("IdentityDictionary", st_dictionary_class);
504 add_global ("Association", st_association_class);
505 add_global ("CompiledMethod", st_compiled_method_class);
506 add_global ("MethodContext", st_method_context_class);
507 add_global ("BlockContext", st_block_context_class);
508 add_global ("System", st_system_class);
509 add_global ("Smalltalk", st_smalltalk);
511 init_specials ();
512 file_in_classes ();
514 st_memory_add_root (st_nil);
515 st_memory_add_root (st_true);
516 st_memory_add_root (st_false);
517 st_memory_add_root (st_smalltalk);
520 static bool verbosity;
522 void
523 st_set_verbosity (bool verbose)
525 verbosity = verbose;
528 bool
529 st_verbose_mode (void)
531 return verbosity;