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-compiler.h"
41 #include "st-memory.h"
42 #include "st-context.h"
43 #include "st-processor.h"
51 st_oop st_specials
[ST_NUM_SPECIALS
];
55 st_global_get (const char *name
)
59 st_assert (st_symbol_new (name
) == st_symbol_new (name
));
61 sym
= st_symbol_new (name
);
63 return st_dictionary_at (st_globals
, sym
);
68 INSTANCE_SIZE_UNDEFINED
= 0,
69 INSTANCE_SIZE_CLASS
= 6,
70 INSTANCE_SIZE_METACLASS
= 6,
71 INSTANCE_SIZE_DICTIONARY
= 3,
72 INSTANCE_SIZE_SET
= 3,
73 INSTANCE_SIZE_ASSOCIATION
= 2,
74 INSTANCE_SIZE_SYSTEM
= 2,
78 class_new (st_format format
, st_uint instance_size
)
82 class = st_memory_allocate (ST_SIZE_OOPS (struct st_class
));
84 ST_OBJECT_MARK (class) = 0 | ST_MARK_TAG
;
85 ST_OBJECT_HASH (class) = st_smi_new (st_current_hash
++);
86 ST_OBJECT_CLASS (class) = st_nil
;
87 st_object_set_format (class, ST_FORMAT_OBJECT
);
88 st_object_set_instance_size (class, INSTANCE_SIZE_CLASS
);
90 ST_BEHAVIOR_FORMAT (class) = st_smi_new (format
);
91 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (instance_size
);
92 ST_BEHAVIOR_SUPERCLASS (class) = st_nil
;
93 ST_BEHAVIOR_METHOD_DICTIONARY (class) = st_nil
;
94 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = st_nil
;
96 ST_CLASS (class)->name
= st_nil
;
102 add_global (const char *name
, st_oop object
)
106 // sanity check for symbol interning
107 st_assert (st_symbol_new (name
) == st_symbol_new (name
));
109 symbol
= st_symbol_new (name
);
110 st_dictionary_at_put (st_globals
, symbol
, object
);
112 // sanity check for dictionary
113 st_assert (st_dictionary_at (st_globals
, symbol
) == object
);
117 parse_error (char *message
, st_token
*token
)
119 fprintf (stderr
, "error: %i: %i: %s",
120 st_token_get_line (token
), st_token_get_column (token
), message
);
125 initialize_class (const char *name
,
126 const char *super_name
,
129 st_oop metaclass
, class, superclass
;
133 if (streq (name
, "Object") && streq (super_name
, "nil")) {
135 class = st_dictionary_at (st_globals
, st_symbol_new ("Object"));
136 st_assert (class != st_nil
);
138 metaclass
= st_object_class (class);
139 if (metaclass
== st_nil
) {
140 metaclass
= st_object_new (st_metaclass_class
);
141 ST_OBJECT_CLASS (class) = metaclass
;
144 ST_BEHAVIOR_SUPERCLASS (class) = st_nil
;
145 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (0);
146 ST_BEHAVIOR_SUPERCLASS (metaclass
) = st_dictionary_at (st_globals
, st_symbol_new ("Class"));
149 superclass
= st_global_get (super_name
);
150 if (superclass
== st_nil
)
151 st_assert (superclass
!= st_nil
);
153 class = st_global_get (name
);
155 class = class_new (st_smi_value (ST_BEHAVIOR_FORMAT (superclass
)), 0);
157 metaclass
= ST_HEADER (class)->class;
158 if (metaclass
== st_nil
) {
159 metaclass
= st_object_new (st_metaclass_class
);
160 ST_OBJECT_CLASS (class) = metaclass
;
163 ST_BEHAVIOR_SUPERCLASS (class) = superclass
;
164 ST_BEHAVIOR_SUPERCLASS (metaclass
) = ST_HEADER (superclass
)->class;
165 ST_BEHAVIOR_INSTANCE_SIZE (class) = st_smi_new (st_list_length (ivarnames
) +
166 st_smi_value (ST_BEHAVIOR_INSTANCE_SIZE (superclass
)));
170 if (st_list_length (ivarnames
) != 0) {
171 names
= st_object_new_arrayed (st_array_class
, st_list_length (ivarnames
));
172 for (st_list
*l
= ivarnames
; l
; l
= l
->next
)
173 st_array_at_put (names
, i
++, st_symbol_new (l
->data
));
174 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names
;
177 ST_BEHAVIOR_FORMAT (metaclass
) = st_smi_new (ST_FORMAT_OBJECT
);
178 ST_BEHAVIOR_METHOD_DICTIONARY (metaclass
) = st_dictionary_new ();
179 ST_BEHAVIOR_INSTANCE_VARIABLES (metaclass
) = st_nil
;
180 ST_BEHAVIOR_INSTANCE_SIZE (metaclass
) = st_smi_new (INSTANCE_SIZE_CLASS
);
181 ST_METACLASS_INSTANCE_CLASS (metaclass
) = class;
182 ST_BEHAVIOR_INSTANCE_VARIABLES (class) = names
;
183 ST_BEHAVIOR_METHOD_DICTIONARY (class) = st_dictionary_new ();
184 ST_CLASS_NAME (class) = st_symbol_new (name
);
186 st_dictionary_at_put (st_globals
, st_symbol_new (name
), class);
191 parse_variable_names (st_lexer
*lexer
, st_list
**varnames
)
197 token
= st_lexer_next_token (lexer
);
199 if (st_token_get_type (token
) != ST_TOKEN_STRING_CONST
)
202 names
= st_strdup (st_token_get_text (token
));
203 ivarlexer
= st_lexer_new (names
); /* input valid at this stage */
204 token
= st_lexer_next_token (ivarlexer
);
206 while (st_token_get_type (token
) != ST_TOKEN_EOF
) {
208 if (st_token_get_type (token
) != ST_TOKEN_IDENTIFIER
)
209 parse_error (NULL
, token
);
211 *varnames
= st_list_append (*varnames
, st_strdup (st_token_get_text (token
)));
212 token
= st_lexer_next_token (ivarlexer
);
215 st_lexer_destroy (ivarlexer
);
222 parse_class (st_lexer
*lexer
, st_token
*token
)
224 char *class_name
= NULL
;
225 char *superclass_name
= NULL
;
226 st_list
*ivarnames
= NULL
;
229 if (st_token_get_type (token
) != ST_TOKEN_IDENTIFIER
230 || !streq (st_token_get_text (token
), "Class"))
231 parse_error ("expected class definition", token
);
234 token
= st_lexer_next_token (lexer
);
235 if (st_token_get_type (token
) != ST_TOKEN_KEYWORD_SELECTOR
236 || !streq (st_token_get_text (token
), "named:"))
237 parse_error ("expected 'name:'", token
);
240 token
= st_lexer_next_token (lexer
);
241 if (st_token_get_type (token
) == ST_TOKEN_STRING_CONST
) {
242 class_name
= st_strdup (st_token_get_text (token
));
244 parse_error ("expected string literal", token
);
247 // `superclass:' token
248 token
= st_lexer_next_token (lexer
);
249 if (st_token_get_type (token
) != ST_TOKEN_KEYWORD_SELECTOR
250 || !streq (st_token_get_text (token
), "superclass:"))
251 parse_error ("expected 'superclass:'", token
);
254 token
= st_lexer_next_token (lexer
);
255 if (st_token_get_type (token
) == ST_TOKEN_STRING_CONST
) {
257 superclass_name
= st_strdup (st_token_get_text (token
));
260 parse_error ("expected string literal", token
);
263 // 'instanceVariableNames:' keyword selector
264 token
= st_lexer_next_token (lexer
);
265 if (st_token_get_type (token
) == ST_TOKEN_KEYWORD_SELECTOR
&&
266 streq (st_token_get_text (token
), "instanceVariableNames:")) {
268 parse_variable_names (lexer
, &ivarnames
);
270 parse_error (NULL
, token
);
273 token
= st_lexer_next_token (lexer
);
274 initialize_class (class_name
, superclass_name
, ivarnames
);
275 st_list_destroy (ivarnames
);
281 parse_classes (const char *filename
)
287 if (!st_file_get_contents (filename
, &contents
)) {
291 lexer
= st_lexer_new (contents
);
292 st_assert (lexer
!= NULL
);
293 token
= st_lexer_next_token (lexer
);
295 while (st_token_get_type (token
) != ST_TOKEN_EOF
) {
297 while (st_token_get_type (token
) == ST_TOKEN_COMMENT
)
298 token
= st_lexer_next_token (lexer
);
300 parse_class (lexer
, token
);
301 token
= st_lexer_next_token (lexer
);
306 file_in_classes (void)
310 parse_classes ("../st/class-defs.st");
312 static const char * files
[] =
315 "PositionableStream.st",
318 "SequenceableCollection.st",
319 "ArrayedCollection.st",
320 "HashedCollection.st",
324 "IdentityDictionary.st",
339 "UndefinedObject.st",
354 "OrderedCollection.st",
361 for (st_uint i
= 0; i
< ST_N_ELEMENTS (files
); i
++) {
362 filename
= st_strconcat ("..", ST_DIR_SEPARATOR_S
, "st", ST_DIR_SEPARATOR_S
, files
[i
], NULL
);
363 st_compile_file_in (filename
);
368 #define NIL_SIZE_OOPS (sizeof (struct st_header) / sizeof (st_oop))
371 create_nil_object (void)
375 nil
= st_memory_allocate (NIL_SIZE_OOPS
);
377 ST_OBJECT_MARK (nil
) = 0 | ST_MARK_TAG
;
378 ST_OBJECT_HASH (nil
) = st_smi_new (st_current_hash
++);
379 ST_OBJECT_CLASS (nil
) = nil
;
380 st_object_set_format (nil
, ST_FORMAT_OBJECT
);
381 st_object_set_instance_size (nil
, 0);
389 st_specials
[ST_SPECIAL_PLUS
] = st_symbol_new ("+");
390 st_specials
[ST_SPECIAL_MINUS
] = st_symbol_new ("-");
391 st_specials
[ST_SPECIAL_LT
] = st_symbol_new ("<");
392 st_specials
[ST_SPECIAL_GT
] = st_symbol_new (">");
393 st_specials
[ST_SPECIAL_LE
] = st_symbol_new ("<=");
394 st_specials
[ST_SPECIAL_GE
] = st_symbol_new (">=");
395 st_specials
[ST_SPECIAL_EQ
] = st_symbol_new ("=");
396 st_specials
[ST_SPECIAL_NE
] = st_symbol_new ("~=");
397 st_specials
[ST_SPECIAL_MUL
] = st_symbol_new ("*");
398 st_specials
[ST_SPECIAL_DIV
] = st_symbol_new ("/");
399 st_specials
[ST_SPECIAL_MOD
] = st_symbol_new ("\\");
400 st_specials
[ST_SPECIAL_BITSHIFT
] = st_symbol_new ("bitShift:");
401 st_specials
[ST_SPECIAL_BITAND
] = st_symbol_new ("bitAnd:");
402 st_specials
[ST_SPECIAL_BITOR
] = st_symbol_new ("bitOr:");
403 st_specials
[ST_SPECIAL_BITXOR
] = st_symbol_new ("bitXor:");
405 st_specials
[ST_SPECIAL_AT
] = st_symbol_new ("at:");
406 st_specials
[ST_SPECIAL_ATPUT
] = st_symbol_new ("at:put:");
407 st_specials
[ST_SPECIAL_SIZE
] = st_symbol_new ("size");
408 st_specials
[ST_SPECIAL_VALUE
] = st_symbol_new ("value");
409 st_specials
[ST_SPECIAL_VALUE_ARG
] = st_symbol_new ("value:");
410 st_specials
[ST_SPECIAL_IDEQ
] = st_symbol_new ("==");
411 st_specials
[ST_SPECIAL_CLASS
] = st_symbol_new ("class");
412 st_specials
[ST_SPECIAL_NEW
] = st_symbol_new ("new");
413 st_specials
[ST_SPECIAL_NEW_ARG
] = st_symbol_new ("new:");
415 st_selector_doesNotUnderstand
= st_symbol_new ("doesNotUnderstand:");
416 st_selector_mustBeBoolean
= st_symbol_new ("mustBeBoolean");
417 st_selector_startupSystem
= st_symbol_new ("startupSystem");
418 st_selector_cannotReturn
= st_symbol_new ("cannotReturn");
419 st_selector_outOfMemory
= st_symbol_new ("outOfMemory");
425 st_bootstrap_universe (void)
428 st_oop st_object_class_
, st_class_class_
;
432 st_nil
= create_nil_object ();
434 st_object_class_
= class_new (ST_FORMAT_OBJECT
, 0);
435 st_undefined_object_class
= class_new (ST_FORMAT_OBJECT
, 0);
436 st_metaclass_class
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_METACLASS
);
437 st_behavior_class
= class_new (ST_FORMAT_OBJECT
, 0);
438 st_class_class_
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_CLASS
);
439 st_smi_class
= class_new (ST_FORMAT_OBJECT
, 0);
440 st_large_integer_class
= class_new (ST_FORMAT_LARGE_INTEGER
, 0);
441 st_character_class
= class_new (ST_FORMAT_OBJECT
, 0);
442 st_true_class
= class_new (ST_FORMAT_OBJECT
, 0);
443 st_false_class
= class_new (ST_FORMAT_OBJECT
, 0);
444 st_float_class
= class_new (ST_FORMAT_FLOAT
, 0);
445 st_array_class
= class_new (ST_FORMAT_ARRAY
, 0);
446 st_word_array_class
= class_new (ST_FORMAT_WORD_ARRAY
, 0);
447 st_float_array_class
= class_new (ST_FORMAT_FLOAT_ARRAY
, 0);
448 st_dictionary_class
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_DICTIONARY
);
449 st_set_class
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_SET
);
450 st_byte_array_class
= class_new (ST_FORMAT_BYTE_ARRAY
, 0);
451 st_symbol_class
= class_new (ST_FORMAT_BYTE_ARRAY
, 0);
452 st_string_class
= class_new (ST_FORMAT_BYTE_ARRAY
, 0);
453 st_wide_string_class
= class_new (ST_FORMAT_WORD_ARRAY
, 0);
454 st_association_class
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_ASSOCIATION
);
455 st_compiled_method_class
= class_new (ST_FORMAT_OBJECT
, 0);
456 st_method_context_class
= class_new (ST_FORMAT_CONTEXT
, 5);
457 st_block_context_class
= class_new (ST_FORMAT_CONTEXT
, 7);
458 st_system_class
= class_new (ST_FORMAT_OBJECT
, INSTANCE_SIZE_SYSTEM
);
460 ST_OBJECT_CLASS (st_nil
) = st_undefined_object_class
;
462 /* special objects */
463 st_true
= st_object_new (st_true_class
);
464 st_false
= st_object_new (st_false_class
);
465 st_symbols
= st_set_new_with_capacity (256);
466 st_globals
= st_dictionary_new_with_capacity (256);
467 st_smalltalk
= st_object_new (st_system_class
);
468 ST_OBJECT_FIELDS (st_smalltalk
)[0] = st_globals
;
469 ST_OBJECT_FIELDS (st_smalltalk
)[1] = st_symbols
;
471 /* add class names to symbol table */
472 add_global ("Object", st_object_class_
);
473 add_global ("UndefinedObject", st_undefined_object_class
);
474 add_global ("Behavior", st_behavior_class
);
475 add_global ("Class", st_class_class_
);
476 add_global ("Metaclass", st_metaclass_class
);
477 add_global ("SmallInteger", st_smi_class
);
478 add_global ("LargeInteger", st_large_integer_class
);
479 add_global ("Character", st_character_class
);
480 add_global ("True", st_true_class
);
481 add_global ("False", st_false_class
);
482 add_global ("Float", st_float_class
);
483 add_global ("Array", st_array_class
);
484 add_global ("ByteArray", st_byte_array_class
);
485 add_global ("WordArray", st_word_array_class
);
486 add_global ("FloatArray", st_float_array_class
);
487 add_global ("ByteString", st_string_class
);
488 add_global ("ByteSymbol", st_symbol_class
);
489 add_global ("WideString", st_wide_string_class
);
490 add_global ("IdentitySet", st_set_class
);
491 add_global ("IdentityDictionary", st_dictionary_class
);
492 add_global ("Association", st_association_class
);
493 add_global ("CompiledMethod", st_compiled_method_class
);
494 add_global ("MethodContext", st_method_context_class
);
495 add_global ("BlockContext", st_block_context_class
);
496 add_global ("System", st_system_class
);
497 add_global ("Smalltalk", st_smalltalk
);
502 st_memory_add_root (st_nil
);
503 st_memory_add_root (st_true
);
504 st_memory_add_root (st_false
);
505 st_memory_add_root (st_smalltalk
);
508 static bool verbosity
;
511 st_set_verbosity (bool verbose
)
517 st_verbose_mode (void)