Example #1
0
/*! Returns a new SyxOop */
SyxOop
syx_memory_alloc (void)
{
  SyxOop oop;

  if (_syx_freed_memory_top == 0)
    {
      syx_memory_gc ();
      if (_syx_freed_memory_top == 0)
        syx_error ("object memory heap is really full\n");
    }

  oop = _syx_freed_memory[--_syx_freed_memory_top];

  /* Prevent the object from being collected */
  if (_syx_memory_gc_trans_running)
    {
      if (_syx_memory_gc_trans_top == 0x100)
        syx_error ("transactions can hold up to 256 objects\n");

      SYX_OBJECT_IS_MARKED(oop) = TRUE;
      _syx_memory_gc_trans[_syx_memory_gc_trans_top++] = oop;
    }
  else
    SYX_OBJECT_IS_MARKED(oop) = FALSE;

  return oop;
}
Example #2
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);
}
Example #3
0
/*!
  Parse a declaration file.

  \return TRUE if no error has occurred
*/
syx_bool
syx_cold_file_in (syx_symbol filename)
{
  SyxLexer *lexer;
  syx_string buffer;
  syx_int32 fd, count;
  syx_size size;
#ifdef HAVE_FSTAT
  struct stat statbuf;
#endif

  if ((fd = open (filename, O_RDONLY)) < 0)
     {
        syx_error ("can't open %s\n", filename);
        return FALSE;
     }
#ifdef HAVE_FSTAT
  if ((fstat (fd, &statbuf)) < 0)
     {
        syx_error ("can't obtain size of %s\n", filename);
        return FALSE;
     }
  size = statbuf.st_size;
#else
  size = 1000000;
#endif

  buffer = (syx_string) syx_malloc (size + 1);
  count = read (fd, buffer, size);
  buffer[count - 1] = '\0';
   
  close (fd);
   
  lexer = syx_lexer_new (buffer);
  if (!lexer)
    {
      syx_free (buffer);
      return FALSE;
    }

  if (!syx_cold_parse (lexer))
    {
      syx_lexer_free (lexer, TRUE);
      return FALSE;
    }

  syx_lexer_free (lexer, TRUE);
  return TRUE;
}
Example #4
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;
}
Example #5
0
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;
}
Example #6
0
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_error ("illegal text in literal array\n");
          break;
        }

      token = syx_lexer_next_token (self->lexer);
    }

  return syx_array_new_ref (top, elements);
}
Example #7
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;
}
Example #8
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;
}
Example #9
0
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;
}
Example #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;
}