static void _syx_parser_parse_block_message_pattern (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); SyxParserScope *scope = self->_argument_scopes + self->_argument_scopes_top; if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":"))) { SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (0); return; } while (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); assert (token.type == SYX_TOKEN_NAME_CONST); scope->stack[scope->top++] = syx_strdup (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 | after block message pattern\n")); syx_token_free (token); syx_lexer_next_token (self->lexer); SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (scope->top); return; }
/*! Do parse. \return TRUE if parsing was successful, otherwise FALSE */ syx_bool syx_parser_parse (SyxParser *self, syx_bool skip_message_pattern) { SyxToken token; SyxParserScope scope; token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_END) return TRUE; if (skip_message_pattern) { scope.start = self->_argument_names_top; scope.end = self->_argument_names_top; self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope; } else _syx_parser_parse_message_pattern (self); if (!self->_in_block) _syx_parser_parse_primitive (self); _syx_parser_parse_temporaries (self); if (self->_in_block) syx_bytecode_push_constant (self->bytecode, SYX_BYTECODE_CONST_NIL); _syx_parser_parse_body (self); syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_SELF_RETURN); SYX_CODE_BYTECODES(self->method) = syx_byte_array_new_ref (self->bytecode->code_top * sizeof (syx_uint16), (syx_uint8 *)self->bytecode->code); SYX_CODE_LITERALS(self->method) = syx_array_new_ref (self->bytecode->literals_top, self->bytecode->literals); if (self->_in_block) SYX_BLOCK_ARGUMENT_STACK_TOP(self->method) = syx_small_integer_new (self->_argument_scopes.stack[self->_argument_scopes.top-1].start); else { SYX_METHOD_ARGUMENT_STACK_SIZE(self->method) = syx_small_integer_new (self->_argument_names_top); SYX_METHOD_TEMPORARY_STACK_SIZE(self->method) = syx_small_integer_new (self->_temporary_names_top); } SYX_CODE_STACK_SIZE(self->method) = syx_small_integer_new (self->bytecode->stack_size + 1); SYX_CODE_TEXT(self->method) = syx_string_new (self->lexer->text + syx_find_first_non_whitespace (self->lexer->text)); SYX_CODE_CLASS(self->method) = self->klass; return TRUE; }
static void _syx_parser_parse_temporaries (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); SyxParserScope *scope = self->_temporary_scopes + self->_temporary_scopes_top; if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); while (token.type == SYX_TOKEN_NAME_CONST) { scope->stack[scope->top++] = syx_strdup (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 ("Temporary list not terminated by bar")); syx_token_free (token); syx_lexer_next_token (self->lexer); } /* we choose the maximum number so we can hold all the temporaries without forgetting previous parsed optimized blocks. */ if (SYX_IS_NIL (SYX_CODE_TEMPORARIES_COUNT (self->method)) || scope->top > SYX_SMALL_INTEGER (SYX_CODE_TEMPORARIES_COUNT (self->method))) SYX_CODE_TEMPORARIES_COUNT(self->method) = syx_small_integer_new (scope->top); }
int main (int argc, char *argv[]) { SyxOop instance; SyxOop context; SyxOop process; SyxOop result; /* initialize Syx */ syx_init (argc, argv, NULL); /* load the default image */ syx_memory_load_image (NULL); /* now file in class and method declarations from our ST file */ syx_file_in_blocking ("add.st"); /* create a Sum instance */ instance = syx_object_new (syx_globals_at ("Sum")); /* create a Process */ process = syx_process_new (); /* create a MethodContext which sends the #with:and: message */ context = syx_send_message (instance, // the receiver "with:and:", // the selector 2, // the number of arguments syx_small_integer_new (41), // first argument syx_small_integer_new (22)); /* enter the context in the created process */ syx_interp_enter_context (process, context); /* execute the process in blocking mode */ syx_process_execute_blocking (process); /* fetch the last returned object (an instance variable of Process) */ result = SYX_PROCESS_RETURNED_OBJECT (process); printf ("The result is %d\n", SYX_SMALL_INTEGER (result)); /* cleanup Syx */ syx_quit (); return 0; }
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 void _syx_parser_parse_block_message_pattern (SyxParser *self) { SyxToken token = syx_lexer_get_last_token (self->lexer); SyxParserScope scope; scope.start = self->_argument_names_top; scope.end = self->_argument_names_top; if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":"))) { self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope; SYX_CODE_ARGUMENT_COUNT(self->method) = syx_small_integer_new (0); return; } while (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":")) { syx_token_free (token); token = syx_lexer_next_token (self->lexer); assert (token.type == SYX_TOKEN_NAME_CONST); self->_argument_names[self->_argument_names_top++] = token.value.string; scope.end++; token = syx_lexer_next_token (self->lexer); } if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|"))) syx_error ("Expected | after block message pattern\n"); syx_token_free (token); syx_lexer_next_token (self->lexer); 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); return; }
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); }
/*! Do parse. \return TRUE if parsing was successful, otherwise FALSE */ syx_bool syx_parser_parse (SyxParser *self, syx_bool skip_message_pattern) { SyxToken token; token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_END) return TRUE; self->_temporary_scopes[self->_temporary_scopes_top].top = 0; self->_argument_scopes[self->_argument_scopes_top].top = 0; if (!skip_message_pattern) _syx_parser_parse_message_pattern (self); if (!self->_in_block) _syx_parser_parse_primitive (self); _syx_parser_parse_temporaries (self); if (self->_in_block) syx_bytecode_push_constant (self->bytecode, SYX_BYTECODE_CONST_NIL); _syx_parser_parse_body (self); syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_SELF_RETURN); SYX_CODE_BYTECODES(self->method) = syx_byte_array_new_ref (self->bytecode->code_top * sizeof (syx_uint16), (syx_uint8 *)self->bytecode->code); SYX_CODE_LITERALS(self->method) = syx_array_new_ref (self->bytecode->literals_top, self->bytecode->literals); SYX_CODE_STACK_SIZE(self->method) = syx_small_integer_new (self->bytecode->stack_size + 1); SYX_CODE_TEXT(self->method) = syx_string_new (self->lexer->text + syx_find_first_non_whitespace (self->lexer->text)); SYX_CODE_CLASS(self->method) = self->klass; /* Free arguments and temporaries of this scope */ _syx_parser_free_arguments (self); _syx_parser_free_temporaries (self); return TRUE; }
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; }