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"
50 st_global_get (const char *name
)
54 sym
= st_symbol_new (name
);
56 return st_dictionary_at (ST_GLOBALS
, sym
);
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,
71 class_new (st_format format
, st_uint instance_size
)
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
;
95 add_global (const char *name
, st_oop object
)
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
);
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
);
118 initialize_class (const char *name
,
119 const char *super_name
,
122 st_oop metaclass
, class, superclass
;
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"));
142 superclass
= st_global_get (super_name
);
143 if (superclass
== ST_NIL
)
144 st_assert (superclass
!= ST_NIL
);
146 class = st_global_get (name
);
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
)));
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);
184 parse_variable_names (st_lexer
*lexer
, st_list
**varnames
)
190 token
= st_lexer_next_token (lexer
);
192 if (st_token_get_type (token
) != ST_TOKEN_STRING_CONST
)
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
);
215 parse_class (st_lexer
*lexer
, st_token
*token
)
217 char *class_name
= NULL
;
218 char *superclass_name
= NULL
;
219 st_list
*ivarnames
= NULL
;
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
);
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
);
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
));
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
);
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
));
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
);
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
);
274 parse_classes (const char *filename
)
280 if (!st_file_get_contents (filename
, &contents
)) {
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
);
299 file_in_classes (void)
303 parse_classes ("../st/class-defs.st");
305 static const char * files
[] =
308 "PositionableStream.st",
311 "SequenceableCollection.st",
312 "ArrayedCollection.st",
313 "HashedCollection.st",
317 "IdentityDictionary.st",
332 "UndefinedObject.st",
347 "OrderedCollection.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
);
361 #define NIL_SIZE_OOPS (sizeof (struct st_header) / sizeof (st_oop))
364 create_nil_object (void)
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);
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");
418 st_bootstrap_universe (void)
421 st_oop st_object_class_
, st_class_class_
;
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
);
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
;
504 st_set_verbosity (bool verbose
)
510 st_verbose_mode (void)