Exemple #1
0
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;
}
Exemple #2
0
/*!
  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;
}
Exemple #3
0
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);
}
Exemple #4
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;
}
Exemple #5
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);
}
Exemple #6
0
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);
}
Exemple #7
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;
}
Exemple #8
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_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);
}
Exemple #9
0
/*!
  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;
}
Exemple #11
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;
}
Exemple #12
0
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;
}
Exemple #13
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;
}