static syx_bool _syx_parser_do_binary_continuation (SyxParser *self, syx_bool super_receiver, syx_bool do_cascade) { syx_string selector; SyxToken token; syx_bool super_term; super_receiver = _syx_parser_do_unary_continuation (self, super_receiver, do_cascade); token = syx_lexer_get_last_token (self->lexer); while (token.type == SYX_TOKEN_BINARY) { selector = syx_strdup (token.value.string); if (do_cascade) { self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top; do_cascade = FALSE; } syx_token_free (token); syx_lexer_next_token (self->lexer); super_term = _syx_parser_parse_term (self); _syx_parser_do_unary_continuation (self, super_term, FALSE); token = syx_lexer_get_last_token (self->lexer); syx_bytecode_gen_message (self->bytecode, super_receiver, 1, selector); syx_free (selector); } return super_receiver; }
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; }
static syx_bool _syx_parser_do_unary_continuation (SyxParser *self, syx_bool super_receiver, syx_bool do_cascade) { SyxToken token = syx_lexer_get_last_token (self->lexer); while (token.type == SYX_TOKEN_NAME_CONST) { if (do_cascade) self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top; syx_bytecode_gen_message (self->bytecode, super_receiver, 0, token.value.string); syx_token_free (token); token = syx_lexer_next_token (self->lexer); super_receiver = FALSE; } return super_receiver; }
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; }
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; }