Exemple #1
0
/*!
  Files in a file in blocking mode. This function send a message to FileStream>>#fileIn:.

  \return Return the last returned object from the process
*/
SyxOop
syx_file_in_blocking (syx_symbol file)
{
  SyxOop context;
  SyxOop process;

  process = syx_process_new ();
  context = syx_send_binary_message (syx_globals_at ("FileStream"),
                                     "fileIn:",
                                     syx_string_new (file));
  syx_interp_enter_context (process, context);
  syx_process_execute_blocking (process);
  return SYX_PROCESS_RETURNED_OBJECT (process);
}
Exemple #2
0
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;
}
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;
}
Exemple #4
0
/*!
  Loads the memory.

  \param path the file containing the data dumped by syx_memory_save_image
  \return FALSE if an error occurred
*/
syx_bool
syx_memory_load_image (syx_symbol path)
{
  SyxObject *object;
  FILE *image;
  syx_int32 data;
  syx_int32 i;
  SyxMemoryLazyPointer *lazy;
  
  SYX_START_PROFILE;

  if (!path)
    {
      if (SYX_IS_NIL (syx_globals))
        path = syx_get_image_path ();
      else
        path = SYX_OBJECT_SYMBOL (syx_globals_at ("ImageFileName"));
    }

  if (!path)
    return FALSE;

  image = fopen (path, "rb");
  if (!image)
    return FALSE;

  fread (&data, sizeof (syx_int32), 1, image);
  data = SYX_COMPAT_SWAP_32 (data);
  syx_memory_init (data);

  fread (&data, sizeof (syx_int32), 1, image);
  _syx_freed_memory_top = SYX_COMPAT_SWAP_32 (data);
  _syx_memory_read (_syx_freed_memory, FALSE, _syx_freed_memory_top, image);

  _syx_scheduler_load (image);

  _syx_memory_read (&syx_globals, FALSE, 1, image);
  _syx_memory_read (&syx_symbols, FALSE, 1, image);

  while (!feof (image))
    {
      if (!_syx_memory_read ((SyxOop *)&object, FALSE, 1, image))
        break;

      _syx_memory_read (&object->klass, FALSE, 1, image);
      object->has_refs = fgetc (image);
      object->is_constant = fgetc (image);

      /* fetch instance variables */
      fread (&data, sizeof (syx_varsize), 1, image);
      data = SYX_COMPAT_SWAP_32 (data);
      if (object->vars)
        syx_free (object->vars);
      object->vars = (SyxOop *) syx_calloc (data, sizeof (SyxOop));
      _syx_memory_read (object->vars, TRUE, data, image);

      /* fetch data */
      fread (&data, sizeof (syx_varsize), 1, image);
      object->data_size = SYX_COMPAT_SWAP_32 (data);
      if (object->data_size > 0)
        {
          if (object->data && object->data_size > 0)
            syx_free (object->data);
          
          if (object->has_refs)
            {
              object->data = (SyxOop *) syx_calloc (object->data_size, sizeof (SyxOop));
              _syx_memory_read (object->data, TRUE, object->data_size, image);
            }
          else
            {
              object->data = (SyxOop *) syx_calloc (object->data_size, sizeof (syx_int8));
              if (fgetc (image) == SYX_MEMORY_TYPE_LARGE_INTEGER)
                {
                  fread (&data, sizeof (syx_int32), 1, image);
                  data = SYX_COMPAT_SWAP_32 (data);
#ifdef HAVE_LIBGMP
                  mpz_init (SYX_OBJECT_LARGE_INTEGER ((SyxOop)object));
                  mpz_inp_raw (SYX_OBJECT_LARGE_INTEGER ((SyxOop)object), image);
#else
                  /* skip GMP data since we can't handle it */
                  fseek (image, data, SEEK_CUR);
#endif
                }
              else
                fread (object->data, sizeof (syx_int8), object->data_size, image);
            }
        }
    }
  
  fclose (image);
 
  /* Fix lazy pointers */
  for (i=0; i < _syx_memory_lazy_pointers_top; i++)
    {
      lazy = &_syx_memory_lazy_pointers[i];
      if (lazy->stack != 0)
        *lazy->entry = SYX_POINTER_CAST_OOP (SYX_OBJECT_DATA (lazy->stack) + lazy->offset);
      else
        *lazy->entry = SYX_POINTER_CAST_OOP (NULL);
    }
  syx_free (_syx_memory_lazy_pointers);
  _syx_memory_lazy_pointers_top = 0;

  syx_fetch_basic ();

  SYX_END_PROFILE(load_image);

  syx_initialize_system ();

  return TRUE;
}
Exemple #5
0
/*!
  Dumps all the memory.

  \param path the file path to put all inside
  \return FALSE if an error occurred
*/
syx_bool
syx_memory_save_image (syx_symbol path)
{
  SyxObject *object;
  FILE *image;
  syx_int32 data = 0;
  SyxObject *stack;
  SyxOop process;

  if (!path)
    path = SYX_OBJECT_SYMBOL (syx_globals_at ("ImageFileName"));

  if (!path)
    return FALSE;

  image = fopen (path, "wb");
  if (!image)
    return FALSE;

  syx_memory_gc ();

  data = SYX_COMPAT_SWAP_32 (_syx_memory_size);
  fwrite (&data, sizeof (syx_int32), 1, image);
  data = SYX_COMPAT_SWAP_32 (_syx_freed_memory_top);
  fwrite (&data, sizeof (syx_int32), 1, image);
  _syx_memory_write (_syx_freed_memory, FALSE, _syx_freed_memory_top, image);

  _syx_scheduler_save (image);

  _syx_memory_write (&syx_globals, FALSE, 1, image);
  _syx_memory_write (&syx_symbols, FALSE, 1, image);

  /* First store the processes */
  process = syx_processor_active_process;
  if (!SYX_IS_NIL (process))
    {
      do
        {
          _syx_memory_write_process_stack (SYX_OBJECT (process), image);
          process = SYX_PROCESS_NEXT (process);
        } while (SYX_OOP_NE (process, syx_processor_active_process));
    }

  for (object=syx_memory; object <= SYX_MEMORY_TOP; object++)
    {
      /* the mark check is not related to the GC but means the object has been already written */
      if (SYX_IS_NIL (object->klass) || object->is_marked)
        continue;

      _syx_memory_write_object_with_vars (object, image);

      /* store data */
      data = SYX_COMPAT_SWAP_32 (object->data_size);
      fwrite (&data, sizeof (syx_varsize), 1, image);
      if (object->data_size > 0)
        {
          if (object->has_refs)
            _syx_memory_write (object->data, TRUE, object->data_size, image);
          else
            {
#ifdef HAVE_LIBGMP
              if (SYX_OBJECT_IS_LARGE_INTEGER ((SyxOop)object))
                {
                  /* This algorithm is used to store large integers.
                     We need to specify how many bytes GMP wrote to the image,
                     for systems that don't support GMP */

                  syx_int32 offset = 0;
                  syx_nint start, end;
                  /* specify that's a large integer */
                  fputc (SYX_MEMORY_TYPE_LARGE_INTEGER, image);
                  /* make space to hold the offset */
                  fwrite (&offset, sizeof (syx_int32), 1, image);
                  start = ftell (image);
                  mpz_out_raw (image, SYX_OBJECT_LARGE_INTEGER ((SyxOop)object));
                  end = ftell (image);
                  offset = end - start;
                  /* go back to the offset */
                  fseek (image, - offset - sizeof (syx_int32), SEEK_CUR);
                  /* now write the length of the data written by mpz_out_raw () */
                  data = SYX_COMPAT_SWAP_32 (offset);
                  fwrite (&data, sizeof (syx_int32), 1, image);
                  /* return again to continue normal writing */
                  fseek (image, offset, SEEK_CUR);
                }
              else
#endif /* HAVE_LIBGMP */
                {
                  /* it's not a large integer */
                  fputc (SYX_MEMORY_TYPE_NORMAL, image);
                  fwrite (object->data, sizeof (syx_int8), object->data_size, image);
                }
            }
        }

      /* Check for block closures that are not attached to any process */
      if (SYX_OOP_EQ (object->klass, syx_block_closure_class))
        {
          stack = SYX_OBJECT (object->vars[SYX_VARS_BLOCK_CLOSURE_OUTER_FRAME]);
          /* Check if the stack has been collected or written to the image */
          if (SYX_IS_NIL (SYX_POINTER_CAST_OOP (stack)) || stack->is_marked)
            continue;

          _syx_memory_write_object_with_vars (stack, image);

          data = SYX_COMPAT_SWAP_32 (stack->data_size);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          /* Store the index of this frame */
          fputc (SYX_MEMORY_TYPE_BOF, image);
          data = SYX_COMPAT_SWAP_32 (0);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          /* Outer frames have only one frame */
          _syx_memory_write_frame (NULL, (SyxInterpFrame *)stack->data, NULL, image);
          fputc (SYX_MEMORY_TYPE_EOS, image);
          fwrite (&data, sizeof (syx_varsize), 1, image);
          
          stack->is_marked = TRUE;
        }
    }

  fclose (image);

  /* be sure all objects are unmarked */
  for (object=syx_memory; object <= SYX_MEMORY_TOP; object++)
    object->is_marked = FALSE;

  return TRUE;
}
Exemple #6
0
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
  static HWND hwndDoIt;
  static HWND hwndClear;
  static HWND hwndExit;
  
  switch (Msg) {
  case WM_CREATE:
    hwndEdit = CreateWindow(SYX_IFDEF_UNICODE ("EDIT"),
			    NULL,
			    WS_CHILD | WS_VISIBLE | WS_HSCROLL |
			    WS_VSCROLL | ES_LEFT | ES_MULTILINE |
			    ES_AUTOHSCROLL | ES_AUTOVSCROLL,
			    0, 0, 0, 0,
			    hWnd,
			    0,
			    hInstance,
			    NULL);
    if (!hwndEdit)
      {
	MessageBox(0, SYX_IFDEF_UNICODE ("Could not create workspace"),
		   SYX_IFDEF_UNICODE ("Error"), 0);
	exit(1);
      }
    Edit_SetText (hwndEdit, SYX_IFDEF_UNICODE ("'Hello PocketPC' printNl"));

    hwndDoIt = CreateWindow(SYX_IFDEF_UNICODE ("BUTTON"),
			    NULL,
			    WS_CHILD | WS_VISIBLE | ES_LEFT,
			    0, 0, 0, 0,
			    hWnd,
			    (HMENU) ID_BTN_DOIT,
			    hInstance,
			    NULL);
    if (!hwndDoIt)
      {
	MessageBox(0, SYX_IFDEF_UNICODE ("Could not create button"), SYX_IFDEF_UNICODE ("Error"), 0);
	exit(1);
      }
    Button_SetText (hwndDoIt, SYX_IFDEF_UNICODE ("&DoIt"));

    hwndClear = CreateWindow(SYX_IFDEF_UNICODE ("BUTTON"),
			     NULL,
			     WS_CHILD | WS_VISIBLE | ES_LEFT,
			     0, 0, 0, 0,
			     hWnd,
			     (HMENU) ID_BTN_CLEAR,
			     hInstance,
			     NULL);
    if (!hwndClear)
      {
	MessageBox(0, SYX_IFDEF_UNICODE ("Could not create button"), SYX_IFDEF_UNICODE ("Error"), 0);
	exit(1);
      }
    Button_SetText (hwndClear, SYX_IFDEF_UNICODE ("&Clear"));

    hwndExit = CreateWindow(SYX_IFDEF_UNICODE ("BUTTON"),
			    NULL,
			    WS_CHILD | WS_VISIBLE | ES_LEFT,
			    0, 0, 0, 0,
			    hWnd,
			    (HMENU) ID_BTN_EXIT,
			    hInstance,
			    NULL);
    if (!hwndExit)
      {
	MessageBox(0, SYX_IFDEF_UNICODE ("Could not create button"), SYX_IFDEF_UNICODE ("Error"), 0);
	exit(1);
      }
    Button_SetText (hwndExit, SYX_IFDEF_UNICODE ("E&xit"));
    break;
  case WM_SIZE:
    MoveWindow(hwndEdit, 1, 21, LOWORD(lParam)+1, HIWORD(lParam) - 21, TRUE);
    MoveWindow(hwndDoIt, 1, 0, 50, 20, TRUE);
    MoveWindow(hwndClear, 60, 0, 50, 20, TRUE);
    MoveWindow(hwndExit, LOWORD(lParam)-50, 0, 50, 20, TRUE);
    break;
  case WM_DESTROY:
    exit (0);
    break;
  case WM_COMMAND:
    switch (LOWORD(wParam))
      {
      case ID_BTN_DOIT:
	{
	  syx_size length = Edit_GetTextLength (hwndEdit) + 1;
	  SYX_IFDEF_CHAR_T *text = syx_calloc (length + 1, sizeof (SYX_IFDEF_CHAR_T));
	  Edit_GetText (hwndEdit, text, length);
	  text[length] = '\0';
	  SyxOop stext = syx_string_new (SYX_IFDEF_ANSI (text));
	  syx_free (text);
	  /* Pop out from the stack the true object previously pushed
	     by WinGui_IterateLoop. We'll enter another context, which will return
	     another object (push the object into the stack of this context).
	     The true object is in other words the default object returned by the
	     loop iteration, but now we let the new context push its object without growing
	     the stack versus infinite.
	  */
	  syx_interp_stack_pop ();
	  syx_interp_enter_context (syx_processor_active_process,
                                    syx_send_binary_message (syx_globals_at ("WinWorkspace"),
							     "doIt:",
							     stext));
	}
	break;
      case ID_BTN_CLEAR:
	Edit_SetText (hwndEdit, "");
	break;
      case ID_BTN_EXIT:
	exit (0);
	break;
      }
  default:
    return DefWindowProcW(hWnd, Msg, wParam, lParam);
  }
  return 0;
}
Exemple #7
0
syx_bool
syx_cold_parse_methods (SyxLexer *lexer)
{
  SyxToken token;
  SyxOop klass;
  SyxParser *parser;
  SyxLexer *method_lexer;
  /*syx_symbol category; */
  syx_string chunk;
  SyxLexer saved_lexer = *lexer;

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_CONST)
    {
      *lexer = saved_lexer;
      return FALSE;
    }

  klass = syx_globals_at (token.value.string);
  syx_token_free (token);

  if (SYX_IS_NIL (klass))
    return FALSE;

  token = syx_lexer_next_token (lexer);
  if (token.type == SYX_TOKEN_NAME_CONST && !strcmp (token.value.string, "class"))
    {
      klass = syx_object_get_class (klass);
      syx_token_free (token);
      token = syx_lexer_next_token (lexer);
    }

  if (! (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "methodsFor:")))
    {
      *lexer = saved_lexer;
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      *lexer = saved_lexer;
      return FALSE;
    }

  /*  category = syx_strdup (token.value.string); */
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (!_IS_EXL_MARK (token))
    {
      *lexer = saved_lexer;
      return FALSE;
    }
  syx_token_free (token);

  if (SYX_IS_NIL (SYX_CLASS_METHODS (klass)))
    {
      SYX_CLASS_METHODS(klass) = syx_dictionary_new (50);
    }

  while (TRUE)
    {
      chunk = syx_lexer_next_chunk (lexer);
      method_lexer = syx_lexer_new (chunk);
      if (!method_lexer)
        break;

      parser = syx_parser_new (method_lexer, syx_method_new (), klass);
      syx_parser_parse (parser, FALSE);

      syx_dictionary_at_symbol_put (SYX_CLASS_METHODS(klass),
                                    SYX_METHOD_SELECTOR(parser->method),
                                    parser->method);

      syx_parser_free (parser, TRUE);
    }
  
  return TRUE;
}
Exemple #8
0
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;
}
Exemple #9
0
/*!
  Dumps all the memory.

  \param path the file path to put all inside
  \return FALSE if an error occurred
*/
syx_bool
syx_memory_save_image (syx_symbol path)
{
  SyxObject *object;
  FILE *image;
  syx_int32 data;

  if (!path)
    path = SYX_OBJECT_SYMBOL (syx_globals_at ("ImageFileName"));

  if (!path)
    return FALSE;

  image = fopen (path, "wb");
  if (!image)
    return FALSE;

  syx_memory_gc ();

  data = SYX_COMPAT_SWAP_32 (_syx_memory_size);
  fwrite (&data, sizeof (syx_int32), 1, image);
  data = SYX_COMPAT_SWAP_32 (_syx_freed_memory_top);
  fwrite (&data, sizeof (syx_int32), 1, image);
  _syx_memory_write (_syx_freed_memory, FALSE, _syx_freed_memory_top, image);

  _syx_scheduler_save (image);

  _syx_memory_write (&syx_globals, FALSE, 1, image);
  _syx_memory_write (&syx_symbols, FALSE, 1, image);

  for (object=syx_memory; object <= SYX_MEMORY_TOP; object++)
    {
      if (SYX_IS_NIL (object->klass))
        continue;

      _syx_memory_write ((SyxOop *)&object, FALSE, 1, image);
      _syx_memory_write (&object->klass, FALSE, 1, image);
      fputc (object->has_refs, image);
      fputc (object->is_constant, image);

      /* store instance variables */
      data = syx_object_vars_size ((SyxOop)object);
      data = SYX_COMPAT_SWAP_32(data);
      fwrite (&data, sizeof (syx_varsize), 1, image);
      _syx_memory_write (object->vars, TRUE, SYX_COMPAT_SWAP_32(data), image);

      /* store data */
      data = SYX_COMPAT_SWAP_32 (object->data_size);
      fwrite (&data, sizeof (syx_varsize), 1, image);
      if (object->data_size > 0)
        {
          if (object->has_refs)
            _syx_memory_write (object->data, TRUE, object->data_size, image);
          else
            {
#ifdef HAVE_LIBGMP
              if (SYX_OBJECT_IS_LARGE_INTEGER ((SyxOop)object))
                {
                  /* This algorithm is used to store large integers.
                     We need to specify how many bytes GMP wrote to the image,
                     for systems that doesn't support GMP */

                  syx_int32 offset = 0;
                  syx_nint start, end;
                  /* specify that's a large integer */
                  fputc (1, image);
                  /* make space to hold the offset */
                  fwrite (&offset, sizeof (syx_int32), 1, image);
                  start = ftell (image);
                  mpz_out_raw (image, SYX_OBJECT_LARGE_INTEGER ((SyxOop)object));
                  end = ftell (image);
                  offset = end - start;
                  /* go back to the offset */
                  fseek (image, - offset - sizeof (syx_int32), SEEK_CUR);
                  data = SYX_COMPAT_SWAP_32 (offset);
                  fwrite (&data, sizeof (syx_int32), 1, image);
                  /* return again to continue normal writing */
                  fseek (image, offset, SEEK_CUR);
                }
              else
#endif
                {
                  /* it's not a large integer */
                  fputc (0, image);
                  fwrite (object->data, sizeof (syx_int8), object->data_size, image);
                }
            }
        }
    }

  fclose (image);

  return TRUE;
}