made global variable names uppercase
[panda.git] / src / st-universe.c
blob4f1faf99cf80452a1c5e48f6e4ca40ce478bcdc9
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-compiler.h"
41 #include "st-memory.h"
42 #include "st-context.h"
43 #include "st-cpu.h"
45 #include <stdlib.h>
46 #include <string.h>
47 #include <stdio.h>
49 st_oop
50 st_global_get (const char *name)
52 st_oop sym;
54 sym = st_symbol_new (name);
56 return st_dictionary_at (ST_GLOBALS, sym);
59 enum
61 INSTANCE_SIZE_UNDEFINED = 0,
62 INSTANCE_SIZE_CLASS = 6,
63 INSTANCE_SIZE_METACLASS = 6,
64 INSTANCE_SIZE_DICTIONARY = 3,
65 INSTANCE_SIZE_SET = 3,
66 INSTANCE_SIZE_ASSOCIATION = 2,
67 INSTANCE_SIZE_SYSTEM = 2,
70 static st_oop
71 class_new (st_format format, st_uint instance_size)
73 st_oop class;
75 class = st_memory_allocate (ST_SIZE_OOPS (struct st_class));
77 ST_OBJECT_MARK (class) = 0 | ST_MARK_TAG;
78 ST_OBJECT_HASH (class) = st_smi_new (st_current_hash++);
79 ST_OBJECT_CLASS (class) = ST_NIL;
80 st_object_set_format (class, ST_FORMAT_OBJECT);
81 st_object_set_instance_size (class, INSTANCE_SIZE_CLASS);
83 ST_BEHAVIOR_FORMAT (class) = st_smi_new (format);
84 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (instance_size);
85 ST_BEHAVIOR_SUPERCLASS (class) = ST_NIL;
86 ST_BEHAVIOR_METHOD_DICTIONARY (class) = ST_NIL;
87 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = ST_NIL;
89 ST_CLASS (class)->name = ST_NIL;
91 return class;
94 static void
95 add_global (const char *name, st_oop object)
97 st_oop symbol;
99 // sanity check for symbol interning
100 st_assert (st_symbol_new (name) == st_symbol_new (name));
102 symbol = st_symbol_new (name);
103 st_dictionary_at_put (ST_GLOBALS, symbol, object);
105 // sanity check for dictionary
106 st_assert (st_dictionary_at (ST_GLOBALS, symbol) == object);
109 static void
110 parse_error (char *message, st_token *token)
112 fprintf (stderr, "error: %i: %i: %s",
113 st_token_get_line (token), st_token_get_column (token), message);
114 exit (1);
117 static void
118 initialize_class (const char *name,
119 const char *super_name,
120 st_list *ivarnames)
122 st_oop metaclass, class, superclass;
123 st_oop names;
124 st_uint i = 1;
126 if (streq (name, "Object") && streq (super_name, "nil")) {
128 class = st_dictionary_at (ST_GLOBALS, st_symbol_new ("Object"));
129 st_assert (class != ST_NIL);
131 metaclass = st_object_class (class);
132 if (metaclass == ST_NIL) {
133 metaclass = st_object_new (ST_METACLASS_CLASS);
134 ST_OBJECT_CLASS (class) = metaclass;
137 ST_BEHAVIOR_SUPERCLASS (class) = ST_NIL;
138 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (0);
139 ST_BEHAVIOR_SUPERCLASS (metaclass) = st_dictionary_at (ST_GLOBALS, st_symbol_new ("Class"));
141 } else {
142 superclass = st_global_get (super_name);
143 if (superclass == ST_NIL)
144 st_assert (superclass != ST_NIL);
146 class = st_global_get (name);
147 if (class == ST_NIL)
148 class = class_new (st_smi_value (ST_BEHAVIOR_FORMAT (superclass)), 0);
150 metaclass = ST_HEADER (class)->class;
151 if (metaclass == ST_NIL) {
152 metaclass = st_object_new (ST_METACLASS_CLASS);
153 ST_OBJECT_CLASS (class) = metaclass;
156 ST_BEHAVIOR_SUPERCLASS (class) = superclass;
157 ST_BEHAVIOR_SUPERCLASS (metaclass) = ST_HEADER (superclass)->class;
158 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (st_list_length (ivarnames) +
159 st_smi_value (ST_BEHAVIOR_INSTANCE_SIZE (superclass)));
162 names = ST_NIL;
163 if (st_list_length (ivarnames) != 0) {
164 names = st_object_new_arrayed (ST_ARRAY_CLASS, st_list_length (ivarnames));
165 for (st_list *l = ivarnames; l; l = l->next)
166 st_array_at_put (names, i++, st_symbol_new (l->data));
167 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names;
170 ST_BEHAVIOR_FORMAT (metaclass) = st_smi_new (ST_FORMAT_OBJECT);
171 ST_BEHAVIOR_METHOD_DICTIONARY (metaclass) = st_dictionary_new ();
172 ST_BEHAVIOR_INSTANCE_VARIABLES (metaclass) = ST_NIL;
173 ST_BEHAVIOR_INSTANCE_SIZE (metaclass) = st_smi_new (INSTANCE_SIZE_CLASS);
174 ST_METACLASS_INSTANCE_CLASS (metaclass) = class;
175 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names;
176 ST_BEHAVIOR_METHOD_DICTIONARY (class) = st_dictionary_new ();
177 ST_CLASS_NAME (class) = st_symbol_new (name);
179 st_dictionary_at_put (ST_GLOBALS, st_symbol_new (name), class);
183 static bool
184 parse_variable_names (st_lexer *lexer, st_list **varnames)
186 st_lexer *ivarlexer;
187 st_token *token;
188 char *names;
190 token = st_lexer_next_token (lexer);
192 if (st_token_get_type (token) != ST_TOKEN_STRING_CONST)
193 return false;
195 names = st_strdup (st_token_get_text (token));
196 ivarlexer = st_lexer_new (names); /* input valid at this stage */
197 token = st_lexer_next_token (ivarlexer);
199 while (st_token_get_type (token) != ST_TOKEN_EOF) {
201 if (st_token_get_type (token) != ST_TOKEN_IDENTIFIER)
202 parse_error (NULL, token);
204 *varnames = st_list_append (*varnames, st_strdup (st_token_get_text (token)));
205 token = st_lexer_next_token (ivarlexer);
208 st_lexer_destroy (ivarlexer);
210 return true;
214 static void
215 parse_class (st_lexer *lexer, st_token *token)
217 char *class_name = NULL;
218 char *superclass_name = NULL;
219 st_list *ivarnames = NULL;
221 // 'Class' token
222 if (st_token_get_type (token) != ST_TOKEN_IDENTIFIER
223 || !streq (st_token_get_text (token), "Class"))
224 parse_error ("expected class definition", token);
226 // `named:' token
227 token = st_lexer_next_token (lexer);
228 if (st_token_get_type (token) != ST_TOKEN_KEYWORD_SELECTOR
229 || !streq (st_token_get_text (token), "named:"))
230 parse_error ("expected 'name:'", token);
232 // class name
233 token = st_lexer_next_token (lexer);
234 if (st_token_get_type (token) == ST_TOKEN_STRING_CONST) {
235 class_name = st_strdup (st_token_get_text (token));
236 } else {
237 parse_error ("expected string literal", token);
240 // `superclass:' token
241 token = st_lexer_next_token (lexer);
242 if (st_token_get_type (token) != ST_TOKEN_KEYWORD_SELECTOR
243 || !streq (st_token_get_text (token), "superclass:"))
244 parse_error ("expected 'superclass:'", token);
246 // superclass name
247 token = st_lexer_next_token (lexer);
248 if (st_token_get_type (token) == ST_TOKEN_STRING_CONST) {
250 superclass_name = st_strdup (st_token_get_text (token));
252 } else {
253 parse_error ("expected string literal", token);
256 // 'instanceVariableNames:' keyword selector
257 token = st_lexer_next_token (lexer);
258 if (st_token_get_type (token) == ST_TOKEN_KEYWORD_SELECTOR &&
259 streq (st_token_get_text (token), "instanceVariableNames:")) {
261 parse_variable_names (lexer, &ivarnames);
262 } else {
263 parse_error (NULL, token);
266 token = st_lexer_next_token (lexer);
267 initialize_class (class_name, superclass_name, ivarnames);
268 st_list_destroy (ivarnames);
270 return;
273 static void
274 parse_classes (const char *filename)
276 char *contents;
277 st_lexer *lexer;
278 st_token *token;
280 if (!st_file_get_contents (filename, &contents)) {
281 exit (1);
284 lexer = st_lexer_new (contents);
285 st_assert (lexer != NULL);
286 token = st_lexer_next_token (lexer);
288 while (st_token_get_type (token) != ST_TOKEN_EOF) {
290 while (st_token_get_type (token) == ST_TOKEN_COMMENT)
291 token = st_lexer_next_token (lexer);
293 parse_class (lexer, token);
294 token = st_lexer_next_token (lexer);
298 static void
299 file_in_classes (void)
301 char *filename;
303 parse_classes ("../st/class-defs.st");
305 static const char * files[] =
307 "Stream.st",
308 "PositionableStream.st",
309 "WriteStream.st",
310 "Collection.st",
311 "SequenceableCollection.st",
312 "ArrayedCollection.st",
313 "HashedCollection.st",
314 "Set.st",
315 "Dictionary.st",
316 "IdentitySet.st",
317 "IdentityDictionary.st",
318 "Bag.st",
319 "Array.st",
320 "ByteArray.st",
321 "WordArray.st",
322 "FloatArray.st",
323 "Association.st",
324 "Magnitude.st",
325 "Number.st",
326 "Integer.st",
327 "SmallInteger.st",
328 "LargeInteger.st",
329 "Fraction.st",
330 "Float.st",
331 "Object.st",
332 "UndefinedObject.st",
333 "String.st",
334 "Symbol.st",
335 "ByteString.st",
336 "WideString.st",
337 "Character.st",
338 "UnicodeTables.st",
339 "Behavior.st",
340 "Boolean.st",
341 "True.st",
342 "False.st",
343 "Behavior.st",
344 "ContextPart.st",
345 "BlockContext.st",
346 "Message.st",
347 "OrderedCollection.st",
348 "FileStream.st",
349 "List.st",
350 "System.st",
351 "CompiledMethod.st"
354 for (st_uint i = 0; i < ST_N_ELEMENTS (files); i++) {
355 filename = st_strconcat ("..", ST_DIR_SEPARATOR_S, "st", ST_DIR_SEPARATOR_S, files[i], NULL);
356 st_compile_file_in (filename);
357 st_free (filename);
361 #define NIL_SIZE_OOPS (sizeof (struct st_header) / sizeof (st_oop))
363 static st_oop
364 create_nil_object (void)
366 st_oop nil;
368 nil = st_memory_allocate (NIL_SIZE_OOPS);
370 ST_OBJECT_MARK (nil) = 0 | ST_MARK_TAG;
371 ST_OBJECT_HASH (nil) = st_smi_new (st_current_hash++);
372 ST_OBJECT_CLASS (nil) = nil;
373 st_object_set_format (nil, ST_FORMAT_OBJECT);
374 st_object_set_instance_size (nil, 0);
376 return nil;
379 static void
380 init_specials (void)
382 ST_SELECTOR_PLUS = st_symbol_new ("+");
383 ST_SELECTOR_MINUS = st_symbol_new ("-");
384 ST_SELECTOR_LT = st_symbol_new ("<");
385 ST_SELECTOR_GT = st_symbol_new (">");
386 ST_SELECTOR_LE = st_symbol_new ("<=");
387 ST_SELECTOR_GE = st_symbol_new (">=");
388 ST_SELECTOR_EQ = st_symbol_new ("=");
389 ST_SELECTOR_NE = st_symbol_new ("~=");
390 ST_SELECTOR_MUL = st_symbol_new ("*");
391 ST_SELECTOR_DIV = st_symbol_new ("/");
392 ST_SELECTOR_MOD = st_symbol_new ("\\");
393 ST_SELECTOR_BITSHIFT = st_symbol_new ("bitShift:");
394 ST_SELECTOR_BITAND = st_symbol_new ("bitAnd:");
395 ST_SELECTOR_BITOR = st_symbol_new ("bitOr:");
396 ST_SELECTOR_BITXOR = st_symbol_new ("bitXor:");
398 ST_SELECTOR_AT = st_symbol_new ("at:");
399 ST_SELECTOR_ATPUT = st_symbol_new ("at:put:");
400 ST_SELECTOR_SIZE = st_symbol_new ("size");
401 ST_SELECTOR_VALUE = st_symbol_new ("value");
402 ST_SELECTOR_VALUE_ARG = st_symbol_new ("value:");
403 ST_SELECTOR_IDEQ = st_symbol_new ("==");
404 ST_SELECTOR_CLASS = st_symbol_new ("class");
405 ST_SELECTOR_NEW = st_symbol_new ("new");
406 ST_SELECTOR_NEW_ARG = st_symbol_new ("new:");
408 ST_SELECTOR_DOESNOTUNDERSTAND = st_symbol_new ("doesNotUnderstand:");
409 ST_SELECTOR_MUSTBEBOOLEAN = st_symbol_new ("mustBeBoolean");
410 ST_SELECTOR_STARTUPSYSTEM = st_symbol_new ("startupSystem");
411 ST_SELECTOR_CANNOTRETURN = st_symbol_new ("cannotReturn");
412 ST_SELECTOR_OUTOFMEMORY = st_symbol_new ("outOfMemory");
415 st_memory *memory;
417 void
418 st_bootstrap_universe (void)
420 st_oop smalltalk;
421 st_oop st_object_class_, st_class_class_;
423 st_memory_new ();
425 ST_NIL = create_nil_object ();
427 st_object_class_ = class_new (ST_FORMAT_OBJECT, 0);
428 ST_UNDEFINED_OBJECT_CLASS = class_new (ST_FORMAT_OBJECT, 0);
429 ST_METACLASS_CLASS = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_METACLASS);
430 ST_BEHAVIOR_CLASS = class_new (ST_FORMAT_OBJECT, 0);
431 st_class_class_ = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_CLASS);
432 ST_SMI_CLASS = class_new (ST_FORMAT_OBJECT, 0);
433 ST_LARGE_INTEGER_CLASS = class_new (ST_FORMAT_LARGE_INTEGER, 0);
434 ST_CHARACTER_CLASS = class_new (ST_FORMAT_OBJECT, 0);
435 ST_TRUE_CLASS = class_new (ST_FORMAT_OBJECT, 0);
436 ST_FALSE_CLASS = class_new (ST_FORMAT_OBJECT, 0);
437 ST_FLOAT_CLASS = class_new (ST_FORMAT_FLOAT, 0);
438 ST_ARRAY_CLASS = class_new (ST_FORMAT_ARRAY, 0);
439 ST_WORD_ARRAY_CLASS = class_new (ST_FORMAT_WORD_ARRAY, 0);
440 ST_FLOAT_ARRAY_CLASS = class_new (ST_FORMAT_FLOAT_ARRAY, 0);
441 ST_DICTIONARY_CLASS = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_DICTIONARY);
442 ST_SET_CLASS = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_SET);
443 ST_BYTE_ARRAY_CLASS = class_new (ST_FORMAT_BYTE_ARRAY, 0);
444 ST_SYMBOL_CLASS = class_new (ST_FORMAT_BYTE_ARRAY, 0);
445 ST_STRING_CLASS = class_new (ST_FORMAT_BYTE_ARRAY, 0);
446 ST_WIDE_STRING_CLASS = class_new (ST_FORMAT_WORD_ARRAY, 0);
447 ST_ASSOCIATION_CLASS = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_ASSOCIATION);
448 ST_COMPILED_METHOD_CLASS = class_new (ST_FORMAT_OBJECT, 0);
449 ST_METHOD_CONTEXT_CLASS = class_new (ST_FORMAT_CONTEXT, 5);
450 ST_BLOCK_CONTEXT_CLASS = class_new (ST_FORMAT_CONTEXT, 7);
451 ST_SYSTEM_CLASS = class_new (ST_FORMAT_OBJECT, INSTANCE_SIZE_SYSTEM);
453 ST_OBJECT_CLASS (ST_NIL) = ST_UNDEFINED_OBJECT_CLASS;
455 /* special objects */
456 ST_TRUE = st_object_new (ST_TRUE_CLASS);
457 ST_FALSE = st_object_new (ST_FALSE_CLASS);
458 ST_SYMBOLS = st_set_new_with_capacity (256);
459 ST_GLOBALS = st_dictionary_new_with_capacity (256);
460 ST_SMALLTALK = st_object_new (ST_SYSTEM_CLASS);
461 ST_OBJECT_FIELDS (ST_SMALLTALK)[0] = ST_GLOBALS;
462 ST_OBJECT_FIELDS (ST_SMALLTALK)[1] = ST_SYMBOLS;
464 /* add class names to symbol table */
465 add_global ("Object", st_object_class_);
466 add_global ("UndefinedObject", ST_UNDEFINED_OBJECT_CLASS);
467 add_global ("Behavior", ST_BEHAVIOR_CLASS);
468 add_global ("Class", st_class_class_);
469 add_global ("Metaclass", ST_METACLASS_CLASS);
470 add_global ("SmallInteger", ST_SMI_CLASS);
471 add_global ("LargeInteger", ST_LARGE_INTEGER_CLASS);
472 add_global ("Character", ST_CHARACTER_CLASS);
473 add_global ("True", ST_TRUE_CLASS);
474 add_global ("False", ST_FALSE_CLASS);
475 add_global ("Float", ST_FLOAT_CLASS);
476 add_global ("Array", ST_ARRAY_CLASS);
477 add_global ("ByteArray", ST_BYTE_ARRAY_CLASS);
478 add_global ("WordArray", ST_WORD_ARRAY_CLASS);
479 add_global ("FloatArray", ST_FLOAT_ARRAY_CLASS);
480 add_global ("ByteString", ST_STRING_CLASS);
481 add_global ("ByteSymbol", ST_SYMBOL_CLASS);
482 add_global ("WideString", ST_WIDE_STRING_CLASS);
483 add_global ("IdentitySet", ST_SET_CLASS);
484 add_global ("IdentityDictionary", ST_DICTIONARY_CLASS);
485 add_global ("Association", ST_ASSOCIATION_CLASS);
486 add_global ("CompiledMethod", ST_COMPILED_METHOD_CLASS);
487 add_global ("MethodContext", ST_METHOD_CONTEXT_CLASS);
488 add_global ("BlockContext", ST_BLOCK_CONTEXT_CLASS);
489 add_global ("System", ST_SYSTEM_CLASS);
490 add_global ("Smalltalk", ST_SMALLTALK);
492 init_specials ();
493 file_in_classes ();
495 st_memory_add_root (ST_NIL);
496 st_memory_add_root (ST_TRUE);
497 st_memory_add_root (ST_FALSE);
498 st_memory_add_root (ST_SMALLTALK);
501 static bool verbosity;
503 void
504 st_set_verbosity (bool verbose)
506 verbosity = verbose;
509 bool
510 st_verbose_mode (void)
512 return verbosity;