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
27 #include "st-object.h"
28 #include "st-behavior.h"
30 #include "st-association.h"
31 #include "st-method.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"
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"
52 st_oop st_specials
[ST_NUM_SPECIALS
];
56 st_global_get (const char *name
)
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
);
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,
79 class_new (st_format format
, st_uint instance_size
)
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
;
103 add_global (const char *name
, st_oop object
)
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
);
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
);
126 initialize_class (const char *name
,
127 const char *super_name
,
130 st_oop metaclass
, class, superclass
;
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"));
151 superclass
= st_global_get (super_name
);
152 if (superclass
== st_nil
)
153 st_assert (superclass
!= st_nil
);
155 class = st_global_get (name
);
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
)));
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);
193 parse_variable_names (st_lexer
*lexer
, st_list
**varnames
)
199 token
= st_lexer_next_token (lexer
);
201 if (st_token_get_type (token
) != ST_TOKEN_STRING_CONST
)
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
);
224 parse_class (st_lexer
*lexer
, st_token
*token
)
226 char *class_name
= NULL
;
227 char *superclass_name
= NULL
;
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
);
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
);
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
));
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
);
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
));
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
);
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
);
287 parse_classes (const char *filename
)
293 if (!st_file_get_contents (filename
, &contents
)) {
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
);
312 file_in_classes (void)
316 parse_classes ("../st/class-defs.st");
318 static const char * files
[] =
321 "PositionableStream.st",
324 "SequenceableCollection.st",
325 "ArrayedCollection.st",
326 "HashedCollection.st",
342 "UndefinedObject.st",
357 "OrderedCollection.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
);
370 #define NIL_SIZE_OOPS (sizeof (struct st_header) / sizeof (st_oop))
373 create_nil_object (void)
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);
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");
427 st_bootstrap_universe (void)
430 st_oop st_object_class_
, st_class_class_
;
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
);
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
;
523 st_set_verbosity (bool verbose
)
529 st_verbose_mode (void)