Example #1
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;
}
Example #2
0
static void
_syx_parser_parse_statement (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "^"))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      _syx_parser_parse_expression (self);
      syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_STACK_RETURN);
    }
  else
    _syx_parser_parse_expression (self);
}
Example #3
0
static syx_varsize
_syx_parser_parse_optimized_block (SyxParser *self, SyxBytecodeSpecial branch_type, syx_bool do_pop)
{
  syx_int8 scope_top;
  syx_uint16 jump;
  syx_bool block_state;
  SyxToken token;
  syx_int32 i;

  syx_bytecode_do_special (self->bytecode, branch_type);
  syx_bytecode_gen_code (self->bytecode, 0);
  jump = self->bytecode->code_top - 1;

  if (do_pop)
    syx_bytecode_pop_top (self->bytecode);
  
  block_state = self->_in_block;
  self->_in_block = TRUE;

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "["))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      /* we need to restore the current scope after the optimized block has been parsed */
      scope_top = self->_temporary_scopes[self->_temporary_scopes_top].top;
      _syx_parser_parse_temporaries (self);
      _syx_parser_parse_body (self);
      for (i=scope_top; i < self->_temporary_scopes[self->_temporary_scopes_top].top; i++)
        syx_free (self->_temporary_scopes[self->_temporary_scopes_top].stack[i]);
      self->_temporary_scopes[self->_temporary_scopes_top].top = scope_top;
      token = syx_lexer_next_token (self->lexer);
    }
  else
    {
      /* a variable or such has been used, like ifTrue: trueBlock */
      _syx_parser_do_binary_continuation (self, _syx_parser_parse_term (self), FALSE);
      syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
    }

  self->_in_block = block_state;
  self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
  return jump;
}
Example #4
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;
}
Example #5
0
static syx_varsize
_syx_parser_parse_optimized_block (SyxParser *self, SyxBytecodeSpecial branch_type, syx_bool do_pop)
{
  syx_uint16 jump;
  syx_bool block_state;
  SyxToken token;

  syx_bytecode_do_special (self->bytecode, branch_type);
  syx_bytecode_gen_code (self->bytecode, 0);
  jump = self->bytecode->code_top - 1;

  if (do_pop)
    syx_bytecode_pop_top (self->bytecode);
  
  block_state = self->_in_block;
  self->_in_block = TRUE;

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "["))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      _syx_parser_parse_temporaries (self);
      _syx_parser_parse_body (self);
      self->_temporary_scopes.top--;
      token = syx_lexer_next_token (self->lexer);
    }
  else
    {
      _syx_parser_do_binary_continuation (self, _syx_parser_parse_term (self), FALSE);
      syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
    }

  self->_in_block = block_state;
  self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
  return jump;
}
Example #6
0
static syx_bool
_syx_parser_do_key_continuation (SyxParser *self, syx_bool super_receiver)
{
  SyxToken token;
  syx_char selector[256] = {0};
  syx_int8 num_args;
  syx_bool super_term;
  syx_uint16 jump, conditionJump, loopJump;
  SyxBytecodeSpecial branchType;

  super_receiver = _syx_parser_do_binary_continuation (self, super_receiver, TRUE);

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_NAME_COLON)
    {
      self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top;
      
      if (!strcmp (token.value.string, "ifTrue:"))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH_IF_TRUE, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
          if (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "ifFalse:"))
            {
              syx_token_free (token);
              token = syx_lexer_next_token (self->lexer);
              
              /* skip ifFalse: block if condition is true */
              syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
              syx_bytecode_gen_code (self->bytecode, 0);
              conditionJump = self->bytecode->code_top - 1;

              /* jump here if condition is false */
              self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
              jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH, TRUE);
              /* We don't need any jump after ifFalse: */
              self->bytecode->code[jump] = 0;

              /* jump here if condition was true */
              self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
            }

          return FALSE;
        }
      else if (!strcmp (token.value.string, "ifFalse:"))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH_IF_FALSE, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
          if (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "ifTrue:"))
            {
              syx_token_free (token);
              token = syx_lexer_next_token (self->lexer);

              /* skip ifTrue: block if condition is false */
              syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
              syx_bytecode_gen_code (self->bytecode, 0);
              conditionJump = self->bytecode->code_top - 1;

              /* jump here if condition is true */
              self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
              jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH, TRUE);
              /* We don't need any jump after ifFalse: */
              self->bytecode->code[jump] = 0;

              /* jump here if condition was false */
              self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
            }

          return FALSE;
        }
      else if (!strcmp (token.value.string, "whileTrue:") || !strcmp (token.value.string, "whileFalse:"))
        {
          if (!strcmp (token.value.string, "whileTrue:"))
            branchType = SYX_BYTECODE_BRANCH_IF_TRUE;
          else
            branchType = SYX_BYTECODE_BRANCH_IF_FALSE;

          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          loopJump = self->bytecode->code_top;
          syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_DUPLICATE);
          syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
          conditionJump = _syx_parser_parse_optimized_block (self, branchType, FALSE);
          syx_bytecode_pop_top (self->bytecode);
          syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
          syx_bytecode_gen_code (self->bytecode, loopJump);
          self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
          syx_bytecode_pop_top (self->bytecode);

          return FALSE;
        }

      num_args = 0;
      while (token.type == SYX_TOKEN_NAME_COLON)
        {
          strcat (selector, token.value.string);
          num_args++;
          syx_token_free (token);
          syx_lexer_next_token (self->lexer);

          super_term = _syx_parser_parse_term (self);
          _syx_parser_do_binary_continuation (self, super_term, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
        }

      syx_bytecode_gen_message (self->bytecode, super_receiver, num_args, selector);

      return FALSE;
    }
  return super_receiver;
}