Пример #1
0
INLINE void
_syx_memory_gc_mark (SyxOop object)
{
  syx_varsize i;

  if (!SYX_IS_OBJECT (object) || SYX_OBJECT_IS_MARKED(object) || SYX_IS_NIL(syx_object_get_class (object)))
    return;

  SYX_OBJECT_IS_MARKED(object) = TRUE;

  _syx_memory_gc_mark (SYX_OBJECT(object)->klass);

  /* Only the used stack part of the process must be marked */
  if (SYX_OOP_EQ (syx_object_get_class (object), syx_process_class))
    {
      SyxOop stack = SYX_PROCESS_STACK (object);
      SyxInterpFrame *frame = SYX_OOP_CAST_POINTER (SYX_PROCESS_FRAME_POINTER (object));
      syx_int32 offset = SYX_POINTERS_OFFSET (frame->stack,
                                              SYX_OBJECT_DATA (stack));

      SYX_OBJECT_IS_MARKED(stack) = TRUE;

      /* First mark variables except the process stack */
      for (i=0; i < SYX_VARS_PROCESS_STACK; i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

      /* Mark detached frames */
      while (frame)
        {
          _syx_memory_gc_mark (frame->detached_frame);
          frame = frame->parent_frame;
        }

      /* Now mark the stack */
      for (i=0; i < offset; i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(stack)[i]);

      /* Mark variables after the process stack */
      for (i=SYX_VARS_PROCESS_STACK+1; i < syx_object_vars_size (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

      /* Process has no data */
      return;
    }
  else
    {
      for (i=0; i < syx_object_vars_size (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);
    }

  if (SYX_OBJECT_HAS_REFS (object))
    {
      for (i=0; i < SYX_OBJECT_DATA_SIZE (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(object)[i]);
    }
}
Пример #2
0
/*!
  Create a MethodContext for an arbitrary message ready to enter a Process.

  \param num_args the number of arguments
  \param ap a va_list containing all SyxOops
*/
SyxOop
syx_vsend_message (SyxOop receiver, syx_symbol selector, syx_int32 num_args, va_list ap)
{
  syx_varsize i;
  SyxOop context;
  SyxOop klass;
  SyxOop method;
  SyxOop arguments;

  if (num_args == 0)
    return syx_send_unary_message (receiver, selector);

  klass = syx_object_get_class (receiver);
  method = syx_class_lookup_method (klass, selector);
  if (SYX_IS_NIL (method))
    syx_error ("Unable to lookup method #%s in class %p (%s)\n", selector,
               SYX_OOP_CAST_POINTER (klass),
               SYX_OBJECT_BYTE_ARRAY (SYX_CLASS_NAME(klass)));

  arguments = syx_array_new_size (num_args);
  for (i=0; i < num_args; i++)
    SYX_OBJECT_DATA(arguments)[i] = va_arg (ap, SyxOop);

  context = syx_method_context_new (method, receiver, arguments);

  return context;
}
Пример #3
0
/*!
  Enters a new MethodContext or BlockContext.

  \return FALSE if the context was syx_nil
*/
syx_bool
syx_interp_enter_context (SyxOop process, SyxOop context)
{
  SyxOop arguments;
  syx_bool reset_parent_frame = FALSE;
  SyxInterpState _state = SYX_INTERP_STATE_NEW;
  SyxInterpState *state;
  SyxInterpFrame *frame;

  if (SYX_IS_NIL (process) || SYX_IS_NIL (context))
    return FALSE;

  if (SYX_OOP_EQ (process, _syx_interp_state.process))
    state = &_syx_interp_state;
  else 
    {
      state = &_state;
      frame = SYX_OOP_CAST_POINTER (SYX_PROCESS_FRAME_POINTER (process));
      /* This is a new Process, reset the parent_frame once we created the frame */
      if (SYX_IS_NIL (frame->method))
        reset_parent_frame = TRUE;
      state->frame = frame;
      state->process = process;
    }

  arguments = SYX_CONTEXT_PART_ARGUMENTS (context);
  if (SYX_IS_NIL (arguments))
    state->message_arguments_count = 0;
  else
    {
      state->message_arguments_count = SYX_OBJECT_DATA_SIZE (arguments);
      memcpy (state->message_arguments, SYX_OBJECT_DATA (arguments), state->message_arguments_count * sizeof (SyxOop));
    }

  if (SYX_OOP_EQ (syx_object_get_class (context), syx_block_context_class))
    _syx_interp_frame_prepare_new_closure (state, SYX_BLOCK_CONTEXT_CLOSURE (context));
  else
    {
      state->message_receiver = SYX_METHOD_CONTEXT_RECEIVER (context);
      _syx_interp_frame_prepare_new (state, SYX_CONTEXT_PART_METHOD (context));
    }

  if (reset_parent_frame)
    state->frame->stack_return_frame = state->frame->parent_frame = NULL;

  state->frame->this_context = context;
  SYX_CONTEXT_PART_FRAME_POINTER (context) = SYX_POINTER_CAST_OOP (state->frame);
  _syx_interp_save_process_state (state);

  return TRUE;
}
Пример #4
0
static SyxOop
_syx_parser_find_class_variable_name (SyxParser *self, syx_symbol name)
{
  SyxOop klass = self->klass;
  SyxOop binding;

  if (syx_object_get_class (klass) == syx_metaclass_class)
    klass = SYX_METACLASS_INSTANCE_CLASS (klass);

  for (; !SYX_IS_NIL(klass); klass=SYX_CLASS_SUPERCLASS(klass))
    {
      binding = syx_dictionary_binding_at_symbol_if_absent (SYX_CLASS_CLASS_VARIABLES (klass), name, syx_nil);
      if (!SYX_IS_NIL (binding))
        return binding;
    }

  return syx_nil;
}
Пример #5
0
/*! Create a MethodContext for a unary message ready to enter a Process */
SyxOop
syx_send_unary_message (SyxOop receiver, syx_symbol selector)
{
  SyxOop context;
  SyxOop klass;
  SyxOop method;

  klass = syx_object_get_class (receiver);
  method = syx_class_lookup_method (klass, selector);
  if (SYX_IS_NIL (method))
    syx_error ("Unable to lookup method #%s in class %p (%s)\n", selector,
               SYX_OOP_CAST_POINTER (klass),
               SYX_IS_NIL (SYX_CLASS_NAME(klass))
               ? NULL
               : SYX_OBJECT_STRING (SYX_CLASS_NAME(klass)));

  context = syx_method_context_new (method, receiver, syx_nil);
  return context;
}
Пример #6
0
INLINE void
_syx_memory_gc_mark (SyxOop object)
{
  syx_varsize i;
  if (!SYX_IS_OBJECT (object) || SYX_OBJECT_IS_MARKED(object) || SYX_IS_NIL(syx_object_get_class (object)))
    return;

  SYX_OBJECT_IS_MARKED(object) = TRUE;

  _syx_memory_gc_mark (SYX_OBJECT(object)->klass);

  for (i=0; i < syx_object_vars_size (object); i++)
    _syx_memory_gc_mark (SYX_OBJECT_VARS(object)[i]);

  if (SYX_OBJECT_HAS_REFS (object))
    {
      for (i=0; i < SYX_OBJECT_DATA_SIZE (object); i++)
        _syx_memory_gc_mark (SYX_OBJECT_DATA(object)[i]);
    }
}
Пример #7
0
/*! Create a MethodContext for a binary message ready to enter a Process */
SyxOop
syx_send_binary_message (SyxOop receiver, syx_symbol selector, SyxOop argument)
{
  SyxOop context;
  SyxOop klass;
  SyxOop method;
  SyxOop arguments;

  klass = syx_object_get_class (receiver);
  method = syx_class_lookup_method (klass, selector);
  if (SYX_IS_NIL (method))
    syx_error ("Unable to lookup method #%s in class %p (%s)\n", selector,
               SYX_OOP_CAST_POINTER (klass),
               SYX_OBJECT_BYTE_ARRAY (SYX_CLASS_NAME(klass)));

  arguments = syx_array_new_size (1);
  SYX_OBJECT_DATA(arguments)[0] = argument;
  context = syx_method_context_new (method, receiver, arguments);

  return context;
}
Пример #8
0
/*! Print to stdout the current execution state of the interpreter and the Process traceback */
void
syx_show_traceback (void)
{
  SyxInterpState *es;
  SyxInterpFrame *frame, *homeframe;
  syx_symbol traceformat;
  SyxOop classname;
  syx_symbol extraclass;
  SyxOop receiver;

  if (!syx_memory)
    {
      puts ("Can't print the memory state");
      return;
    }

  es = &_syx_interp_state;
  frame = es->frame;

  puts ("Memory state:");
  printf("Memory size: %d\n", _syx_memory_size);
  printf("Freed memory top: %d\n", _syx_freed_memory_top);
  if (!_syx_memory_gc_trans_running)
    puts ("No GC transaction");
  else
    printf("GC transaction top: %d\n", _syx_memory_gc_trans_top);

  if (!es)
    {
      puts ("Can't print the execution state");
      return;
    }

  puts ("\nExecution state:");
  printf("Process: %p (memory index: %ld)\n",
         SYX_OOP_CAST_POINTER (syx_processor_active_process),
         SYX_MEMORY_INDEX_OF (syx_processor_active_process));
  printf("Frame: %p\n", (syx_pointer) frame);

  if (!frame)
    return;

  printf("Receiver: %p (memory index: %ld)\n",
         SYX_OOP_CAST_POINTER (frame->receiver),
         SYX_MEMORY_INDEX_OF (frame->receiver));
  printf("Arguments: %p\n", (syx_pointer) es->arguments);
  printf("Temporaries: %p\n", (syx_pointer) es->temporaries);
  printf("Stack: %p\n", (syx_pointer) frame->stack);
  printf("Literals: %p\n", (syx_pointer) es->method_literals);
  printf("Bytecodes: %p (size: %d)\n", (syx_pointer) es->method_bytecodes, es->method_bytecodes_count);
  printf("Byteslice: %d\n", es->byteslice);
  printf("Instruction pointer: %p\n", (syx_pointer) frame->next_instruction);
  printf("Stack pointer: %p\n", (syx_pointer) frame->stack);
  printf("Message receiver: %p (memory index: %ld)\n",
         SYX_OOP_CAST_POINTER (es->message_receiver),
         SYX_MEMORY_INDEX_OF (es->message_receiver));
  printf("Message arguments: %p (size: %d)\n",
         (syx_pointer) es->message_arguments,
         es->message_arguments_count);

  if (SYX_IS_NIL (frame->detached_frame))
    printf("Process offset: %d\n", SYX_POINTERS_OFFSET (frame, SYX_OBJECT_DATA (SYX_PROCESS_STACK (_syx_interp_state.process))));

  puts ("\nTraceback:");
  while (frame)
    {
      if (frame->outer_frame)
        {
          homeframe = frame->outer_frame;
          while (homeframe->outer_frame)
            homeframe = homeframe->outer_frame;
          traceformat = "%s%s>>%s[]\n";
        }
      else
        {
          homeframe = frame;
          traceformat = "%s%s>>%s\n";
        }

      receiver = frame->receiver;
      classname = SYX_CLASS_NAME(syx_object_get_class(receiver));
      if (SYX_IS_NIL (classname))
        {
          classname = SYX_CLASS_NAME(SYX_METACLASS_INSTANCE_CLASS(syx_object_get_class(receiver)));
          extraclass = " class";
        }
      else
        extraclass = "";

      printf (traceformat,
              SYX_OBJECT_SYMBOL(classname),
              extraclass,
              SYX_OBJECT_SYMBOL(SYX_METHOD_SELECTOR(homeframe->method)));

      frame = frame->parent_frame;
    }
}
Пример #9
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;
}
Пример #10
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;
}