예제 #1
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);
}
예제 #2
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);
}
예제 #3
0
static void
_syx_parser_parse_assignment (SyxParser *self, syx_symbol assign_name)
{
  syx_varsize pos;
  SyxOop binding;

  pos = _syx_parser_find_temporary_name (self, assign_name);
  if (pos >= 0)
    {
      _syx_parser_parse_expression (self);
      syx_bytecode_assign_temporary (self->bytecode, pos);
      return;
    }

  pos = _syx_parser_find_instance_name (self, assign_name);
  if (pos >= 0)
    {
      _syx_parser_parse_expression (self);
      syx_bytecode_assign_instance (self->bytecode, pos);
      return;
    }

  binding = _syx_parser_find_class_variable_name (self, assign_name);
  if (!SYX_IS_NIL (binding))
    {
      _syx_parser_parse_expression (self);
      syx_bytecode_assign_binding_variable (self->bytecode, binding);
      return;
    }
  
  syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unassignable variable named: %s\n", assign_name));
}
예제 #4
0
static void
_syx_parser_parse_body (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  while (TRUE)
    {
      while (token.type == SYX_TOKEN_CLOSING)
        {
          if (self->_in_block && token.value.character == ']')
            return;
          
          if (token.value.character == '.')
            {
              token = syx_lexer_next_token (self->lexer);
              /* Do not pop from the stack multiple times */
              if (token.type != SYX_TOKEN_CLOSING && token.type != SYX_TOKEN_END)
                syx_bytecode_pop_top (self->bytecode);
            }
          else
            token = syx_lexer_next_token (self->lexer);
        }

      if (token.type == SYX_TOKEN_END)
        break;

      _syx_parser_parse_statement (self);
      token = syx_lexer_get_last_token (self->lexer);
    }

  if (self->_in_block)
    syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected ] after block body"));
}
예제 #5
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);
}
예제 #6
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;
}
예제 #7
0
파일: syx-parser.c 프로젝트: chazu/syx
static void
_syx_parser_parse_temporaries (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  SyxParserScope scope;
  scope.start = self->_temporary_names_top;
  scope.end = self->_temporary_names_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)
        {
          self->_temporary_names[self->_temporary_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_signal (SYX_ERROR_INTERP, syx_string_new ("Temporary list not terminated by bar"));
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
    }

  self->_temporary_scopes.stack[(syx_int32) self->_temporary_scopes.top++] = scope;
}
예제 #8
0
/*!
  Do it in blocking mode. This function send a message to String>>#doIt.

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

  process = syx_process_new ();
  context = syx_send_unary_message (syx_string_new (code), "doIt");
  syx_interp_enter_context (process, context);
  syx_process_execute_blocking (process);
  return SYX_PROCESS_RETURNED_OBJECT (process);
}
예제 #9
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);
}
예제 #10
0
파일: syx-parser.c 프로젝트: chazu/syx
/*!
  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;
}
예제 #11
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;
}
예제 #12
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;
}
예제 #13
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;
}
예제 #14
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;
}