static void _syx_parser_parse_method_message_pattern (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_char selector[256] = {0}; SyxParserScope scope; scope.start = self->_argument_names_top; scope.end = self->_argument_names_top; switch (token.type) { case SYX_TOKEN_NAME_CONST: /* Unary message pattern */ SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string); syx_token_free (token); syx_lexer_next_token (self->lexer); break; case SYX_TOKEN_BINARY: /* Binary message pattern */ SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_CONST) syx_error ("Expected name constant for argument name\n"); self->_argument_names[self->_argument_names_top++] = token.value.string; scope.end++; syx_lexer_next_token (self->lexer); break; case SYX_TOKEN_NAME_COLON: /* Keyword message pattern */ while (token.type == SYX_TOKEN_NAME_COLON) { strcat (selector, token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_CONST) syx_error ("Expected name constant for argument name\n"); self->_argument_names[self->_argument_names_top++] = token.value.string; scope.end++; token = syx_lexer_next_token (self->lexer); } SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (selector); break; default: syx_error ("Invalid message pattern\n"); } self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope; SYX_CODE_ARGUMENT_COUNT(self->method) = syx_small_integer_new (scope.end - scope.start); }
static void _syx_parser_parse_method_message_pattern (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_char selector[0xFF] = {0}; SyxParserScope *scope = self->_argument_scopes + self->_argument_scopes_top; switch (token.type) { case SYX_TOKEN_NAME_CONST: /* Unary message pattern */ SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string); syx_token_free (token); syx_lexer_next_token (self->lexer); break; case SYX_TOKEN_BINARY: /* Binary message pattern */ SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name constant for argument name\n")); scope->stack[scope->top++] = syx_strdup (token.value.string); syx_token_free (token); syx_lexer_next_token (self->lexer); break; case SYX_TOKEN_NAME_COLON: /* Keyword message pattern */ while (token.type == SYX_TOKEN_NAME_COLON) { strcat (selector, token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name constant for argument name\n")); scope->stack[scope->top++] = syx_strdup (token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); } SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (selector); break; default: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Invalid message pattern\n")); } SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (scope->top); }
static SyxOop _syx_parser_parse_literal_array (SyxParser *self) { SyxOop elements[256]; syx_varsize top = 0; SyxToken token; token = syx_lexer_next_token (self->lexer); while (! (token.type == SYX_TOKEN_END || (token.type == SYX_TOKEN_CLOSING && token.value.character == ')'))) { switch (token.type) { case SYX_TOKEN_ARRAY_BEGIN: elements[top++] = _syx_parser_parse_literal_array (self); break; case SYX_TOKEN_INT_CONST: elements[top++] = syx_small_integer_new (token.value.integer); break; case SYX_TOKEN_BINARY: if (!strcmp (token.value.string, "(")) { elements[top++] = _syx_parser_parse_literal_array (self); syx_token_free (token); break; } case SYX_TOKEN_NAME_CONST: case SYX_TOKEN_NAME_COLON: case SYX_TOKEN_SYM_CONST: elements[top++] = syx_symbol_new (token.value.string); syx_token_free (token); break; case SYX_TOKEN_STR_CONST: elements[top++] = syx_string_new (token.value.string); syx_token_free (token); break; case SYX_TOKEN_CHAR_CONST: elements[top++] = syx_character_new (token.value.character); break; default: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Illegal text in literal array\n")); break; } token = syx_lexer_next_token (self->lexer); } return syx_array_new_ref (top, elements); }
static SyxOop _syx_cold_parse_vars (SyxLexer *lexer, syx_bool capitalized) { SyxOop vars; SyxOop vars_raw[256]; syx_varsize vars_size; SyxToken token; /* Fetch variable names using the lexer */ token = syx_lexer_next_token (lexer); for (vars_size=0; token.type != SYX_TOKEN_END; vars_size++) { if (token.type != SYX_TOKEN_NAME_CONST) { syx_token_free (token); syx_error ("Expected names for variables\n"); } if (capitalized && !isupper (token.value.string[0])) { syx_token_free (token); syx_error ("First letter must be uppercase\n"); } vars_raw[vars_size] = syx_symbol_new (token.value.string); syx_token_free (token); token = syx_lexer_next_token (lexer); } /* Create the array */ vars = syx_array_new_size (vars_size); /* Copy out of the stack */ memcpy (SYX_OBJECT_DATA (vars), vars_raw, sizeof (SyxOop ) * vars_size); return vars; }
int SYX_CDECL main (int argc, char *argv[]) { SyxOop process, context; SyxOop arguments; SyxOop structTestClass; SyxOop structTest; syx_init (0, NULL, ".."); syx_memory_load_image ("test.sim"); syx_scheduler_init (); puts ("- Initializing test classes"); syx_cold_file_in ("stsupport/TestCStruct.st"); structTestClass = syx_globals_at ("TestCStruct"); syx_object_initialize (structTestClass); structTest = syx_object_new (structTestClass); puts ("- Test fields alignment 1"); arguments = syx_array_new_size (6); SYX_OBJECT_DATA(arguments)[0] = syx_small_integer_new ((syx_nint)&test1.f1 - (syx_nint)&test1); SYX_OBJECT_DATA(arguments)[1] = syx_small_integer_new ((syx_nint)&test1.f2 - (syx_nint)&test1); SYX_OBJECT_DATA(arguments)[2] = syx_small_integer_new ((syx_nint)&test1.f3 - (syx_nint)&test1); SYX_OBJECT_DATA(arguments)[3] = syx_small_integer_new ((syx_nint)&test1.f4 - (syx_nint)&test1); SYX_OBJECT_DATA(arguments)[4] = syx_small_integer_new ((syx_nint)&test1.f5 - (syx_nint)&test1); SYX_OBJECT_DATA(arguments)[5] = syx_small_integer_new ((syx_nint)&test1.f6 - (syx_nint)&test1); process = syx_process_new (); context = syx_send_message (structTest, "testOffsets:from:", 2, arguments, syx_symbol_new ("Test1Struct")); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); puts ("- Test fields alignment 2"); arguments = syx_array_new_size (14); SYX_OBJECT_DATA(arguments)[0] = syx_small_integer_new ((syx_nint)&test2.f1 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[1] = syx_small_integer_new ((syx_nint)&test2.f2 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[2] = syx_small_integer_new ((syx_nint)&test2.f3 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[3] = syx_small_integer_new ((syx_nint)&test2.f4 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[4] = syx_small_integer_new ((syx_nint)&test2.f5 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[5] = syx_small_integer_new ((syx_nint)&test2.f6 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[6] = syx_small_integer_new ((syx_nint)&test2.f7 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[7] = syx_small_integer_new ((syx_nint)&test2.f8 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[8] = syx_small_integer_new ((syx_nint)&test2.f9 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[9] = syx_small_integer_new ((syx_nint)&test2.f10 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[10] = syx_small_integer_new ((syx_nint)&test2.f11 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[11] = syx_small_integer_new ((syx_nint)&test2.f12 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[12] = syx_small_integer_new ((syx_nint)&test2.f13 - (syx_nint)&test2); SYX_OBJECT_DATA(arguments)[13] = syx_small_integer_new ((syx_nint)&test2.f14 - (syx_nint)&test2); process = syx_process_new (); context = syx_send_message (structTest, "testOffsets:from:", 2, arguments, syx_symbol_new ("Test2Struct")); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); puts ("- Test fields alignment 3"); arguments = syx_array_new_size (6); SYX_OBJECT_DATA(arguments)[0] = syx_small_integer_new ((syx_nint)&test3.f1 - (syx_nint)&test3); SYX_OBJECT_DATA(arguments)[1] = syx_small_integer_new ((syx_nint)&test3.f2 - (syx_nint)&test3); SYX_OBJECT_DATA(arguments)[2] = syx_small_integer_new ((syx_nint)&test3.f3 - (syx_nint)&test3); SYX_OBJECT_DATA(arguments)[3] = syx_small_integer_new ((syx_nint)&test3.f4 - (syx_nint)&test3); SYX_OBJECT_DATA(arguments)[4] = syx_small_integer_new ((syx_nint)&test3.f5 - (syx_nint)&test3); SYX_OBJECT_DATA(arguments)[5] = syx_small_integer_new ((syx_nint)&test3.f6 - (syx_nint)&test3); process = syx_process_new (); context = syx_send_message (structTest, "testOffsets:from:", 2, arguments, syx_symbol_new ("Test3Struct")); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); puts ("- Test reading"); test3.f1 = 240; test3.f2 = 7143; test3.f3 = 'R'; test3.f4 = 199.11822; test3.f5 = 23.5; /* won't read yet */ process = syx_process_new (); context = syx_send_binary_message (structTest, "testRead:", SYX_POINTER_CAST_OOP (&test3)); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); puts ("- Test writing"); process = syx_process_new (); context = syx_send_binary_message (structTest, "testWrite:", SYX_POINTER_CAST_OOP (&test3)); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); assert(test3.f1 == 320); assert(test3.f2 == 10293); assert(test3.f3 == ','); assert(test3.f4 == 291.4837); /* Double to float conversion assert(test3.f5 == 76.119); */ /* won't write longs yet */ puts ("- Test unions"); test4.f1 = 'S'; process = syx_process_new (); context = syx_send_binary_message (structTest, "testUnion:", SYX_POINTER_CAST_OOP (&test4)); syx_interp_enter_context (process, context); syx_process_execute_blocking (process); assert(test4.f1 == 'T'); syx_quit (); return 0; }
static void _syx_parser_parse_primitive (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_int32 prim_index; SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-1); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "<"))) return; syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_NAME_COLON) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name colon")); if (!strcmp (token.value.string, "primitive:")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called")); prim_index = syx_primitive_get_index (token.value.string); if (prim_index < 0) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unknown primitive named", token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >")); syx_token_free (token); SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (prim_index); syx_lexer_next_token (self->lexer); } else if (!strcmp (token.value.string, "cCall:")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called")); syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">")) { syx_token_free (token); syx_bytecode_gen_literal (self->bytecode, syx_nil); SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (-2); syx_lexer_next_token (self->lexer); return; } if (! (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "plugin:"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected plugin:")); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type != SYX_TOKEN_STR_CONST) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the plugin name")); syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">"))) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >")); syx_token_free (token); syx_lexer_next_token (self->lexer); SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-2); } else syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected primitive or cCall")); return; }
static syx_bool _syx_parser_parse_term (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); syx_bool super_term = FALSE; switch (token.type) { case SYX_TOKEN_NAME_CONST: super_term = _syx_parser_parse_name_term (self, token.value.string); syx_token_free (token); break; case SYX_TOKEN_STR_CONST: syx_bytecode_push_literal (self->bytecode, syx_string_new (token.value.string)); syx_token_free (token); break; case SYX_TOKEN_INT_CONST: syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (token.value.integer)); syx_token_free (token); break; #ifdef HAVE_LIBGMP case SYX_TOKEN_LARGE_INT_CONST: syx_bytecode_push_literal (self->bytecode, syx_large_integer_new_mpz (token.value.large_integer)); syx_token_free (token); break; #endif case SYX_TOKEN_FLOAT_CONST: syx_bytecode_push_literal (self->bytecode, syx_float_new (token.value.floating)); syx_token_free (token); break; case SYX_TOKEN_SYM_CONST: syx_bytecode_push_literal (self->bytecode, syx_symbol_new (token.value.string)); syx_token_free (token); break; case SYX_TOKEN_CHAR_CONST: syx_bytecode_push_literal (self->bytecode, syx_character_new (token.value.character)); syx_token_free (token); break; case SYX_TOKEN_ARRAY_BEGIN: syx_bytecode_push_literal (self->bytecode, _syx_parser_parse_literal_array (self)); syx_token_free (token); break; case SYX_TOKEN_BINARY: if (!strcmp (token.value.string, "(")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); _syx_parser_parse_expression (self); token = syx_lexer_get_last_token (self->lexer); if (! (token.type == SYX_TOKEN_CLOSING && token.value.character == ')')) syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected ) after sub expression")); break; } else if (!strcmp (token.value.string, "[")) { _syx_parser_parse_block (self); break; } else if (!strcmp (token.value.string, "{")) { _syx_parser_parse_array (self); break; } else if (!strcmp (token.value.string, "-")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_INT_CONST) syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (-token.value.integer)); #ifdef HAVE_LIBGMP else if (token.type == SYX_TOKEN_LARGE_INT_CONST) { mpz_neg (*token.value.large_integer, *token.value.large_integer); syx_bytecode_push_literal (self->bytecode, syx_large_integer_new_mpz (token.value.large_integer)); } #endif /* HAVE_LIBGMP */ else if (token.type == SYX_TOKEN_FLOAT_CONST) syx_bytecode_push_literal (self->bytecode, syx_float_new (-token.value.floating)); else syx_signal(SYX_ERROR_INTERP, syx_string_new ("Negation not followed by number")); syx_token_free (token); break; } /* We continue here because of weird binary token used as expression start */ default: switch (token.type) { case SYX_TOKEN_END: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected end of input")); break; case SYX_TOKEN_STRING_ENTRY: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Invalid expression start: %s", token.value.string)); syx_token_free (token); break; case SYX_TOKEN_CLOSING: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected closing: %c", token.value.character)); break; default: syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected expression")); break; } } syx_lexer_next_token (self->lexer); return super_term; }
static syx_bool _syx_cold_parse_class (SyxLexer *lexer) { SyxToken token = syx_lexer_get_last_token (lexer); SyxOop superclass, subclass; syx_string subclass_name; syx_bool existing_class = TRUE; SyxOop inst_vars, class_vars; SyxLexer *inst_vars_lexer, *class_vars_lexer; syx_varsize super_inst_vars_size; syx_int32 i; if (token.type != SYX_TOKEN_NAME_CONST) { syx_error ("Expected a name constant\n"); syx_token_free (token); return FALSE; } if (!strcmp (token.value.string, "nil")) superclass = syx_nil; else superclass = syx_globals_at (token.value.string); token = syx_lexer_next_token (lexer); if (!(token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "subclass:"))) { syx_token_free (token); syx_error ("Expected #subclass:\n"); return FALSE; } syx_token_free (token); token = syx_lexer_next_token (lexer); if (token.type != SYX_TOKEN_SYM_CONST) { syx_token_free (token); syx_error ("Expected a symbol constant\n"); return FALSE; } subclass_name = syx_strdup (token.value.string); syx_token_free (token); subclass = syx_globals_at_if_absent (subclass_name, syx_nil); if (strcmp (subclass_name, "Object")) { if (SYX_IS_NIL (subclass)) existing_class = FALSE; else { existing_class = TRUE; if (SYX_OOP_NE (SYX_CLASS_SUPERCLASS(subclass), superclass)) { syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS (subclass)), subclass); SYX_CLASS_SUPERCLASS(subclass) = superclass; syx_array_add (SYX_CLASS_SUBCLASSES (superclass), subclass, TRUE); syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass))), syx_object_get_class (subclass)); SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass)) = syx_object_get_class (superclass); syx_array_add (SYX_CLASS_SUBCLASSES (syx_object_get_class (superclass)), syx_object_get_class (subclass), TRUE); } } } token = syx_lexer_next_token (lexer); if (token.type != SYX_TOKEN_NAME_COLON) { syx_token_free (token); syx_error ("Expected #instanceVariableNames:\n"); return FALSE; } syx_token_free (token); token = syx_lexer_next_token (lexer); if (token.type != SYX_TOKEN_STR_CONST) { syx_token_free (token); syx_error ("Expected a string as argument for #instanceVariableNames:\n"); return FALSE; } inst_vars_lexer = syx_lexer_new (token.value.string); token = syx_lexer_next_token (lexer); if (token.type != SYX_TOKEN_NAME_COLON) { syx_token_free (token); syx_error ("Expected #classVariableNames:\n"); return FALSE; } syx_token_free (token); token = syx_lexer_next_token (lexer); if (token.type != SYX_TOKEN_STR_CONST) { syx_token_free (token); syx_error ("Expected a string as argument for #classVariableNames:\n"); return FALSE; } class_vars_lexer = syx_lexer_new (token.value.string); token = syx_lexer_next_token (lexer); if (!_IS_EXL_MARK (token)) { syx_token_free (token); syx_error ("Class definition must terminate with an exlamation mark\n"); return FALSE; } syx_token_free (token); if (!existing_class) { subclass = syx_class_new (superclass); SYX_CLASS_NAME(subclass) = syx_symbol_new (subclass_name); syx_globals_at_put (SYX_CLASS_NAME(subclass), subclass); } syx_free (subclass_name); /* Parse instance variables */ inst_vars = _syx_cold_parse_vars (inst_vars_lexer, FALSE); syx_lexer_free (inst_vars_lexer, TRUE); /* Fetch superclass instanceSize */ if (SYX_IS_NIL (superclass)) super_inst_vars_size = 0; else super_inst_vars_size = SYX_SMALL_INTEGER (SYX_CLASS_INSTANCE_SIZE (superclass)); SYX_CLASS_INSTANCE_VARIABLES(subclass) = inst_vars; SYX_CLASS_INSTANCE_SIZE(subclass) = syx_small_integer_new (super_inst_vars_size + SYX_OBJECT_DATA_SIZE (inst_vars)); /* Now parse class variables */ class_vars = _syx_cold_parse_vars (class_vars_lexer, TRUE); syx_lexer_free (class_vars_lexer, TRUE); SYX_CLASS_CLASS_VARIABLES(subclass) = syx_dictionary_new (SYX_OBJECT_DATA_SIZE (class_vars) + 10); /* translate from array to dictionary */ for (i=0; i < SYX_OBJECT_DATA_SIZE(class_vars); i++) syx_dictionary_at_symbol_put (SYX_CLASS_CLASS_VARIABLES(subclass), SYX_OBJECT_DATA(class_vars)[i], syx_nil); /* get rid of this */ syx_object_free (class_vars); return TRUE; }