summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c72
1 files changed, 65 insertions, 7 deletions
diff --git a/vm_eval.c b/vm_eval.c
index a8c12707ec..74dfd40907 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1692,12 +1692,24 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
iseq = parent;
rb_encoding *encoding = rb_enc_get(src);
+#define FORWARDING_POSITIONALS_CHR '*'
+#define FORWARDING_POSITIONALS_STR "*"
+#define FORWARDING_KEYWORDS_CHR ':'
+#define FORWARDING_KEYWORDS_STR ":"
+#define FORWARDING_BLOCK_CHR '&'
+#define FORWARDING_BLOCK_STR "&"
+#define FORWARDING_ALL_CHR '.'
+#define FORWARDING_ALL_STR "."
+
for (int scopes_index = 0; scopes_index < scopes_count; scopes_index++) {
VALUE iseq_value = (VALUE)iseq;
int locals_count = ISEQ_BODY(iseq)->local_table_size;
+
pm_options_scope_t *options_scope = &result.options.scopes[scopes_count - scopes_index - 1];
pm_options_scope_init(options_scope, locals_count);
+ uint8_t forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
+
for (int local_index = 0; local_index < locals_count; local_index++) {
pm_string_t *scope_local = &options_scope->locals[local_index];
ID local = ISEQ_BODY(iseq)->local_table[local_index];
@@ -1729,10 +1741,23 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
RB_GC_GUARD(name_obj);
- pm_string_owned_init(scope_local, (uint8_t *)name_dup, length);
+ pm_string_owned_init(scope_local, (uint8_t *) name_dup, length);
+ } else if (local == idMULT) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS;
+ pm_string_constant_init(scope_local, FORWARDING_POSITIONALS_STR, 1);
+ } else if (local == idPow) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS;
+ pm_string_constant_init(scope_local, FORWARDING_KEYWORDS_STR, 1);
+ } else if (local == idAnd) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_BLOCK;
+ pm_string_constant_init(scope_local, FORWARDING_BLOCK_STR, 1);
+ } else if (local == idDot3) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_ALL;
+ pm_string_constant_init(scope_local, FORWARDING_ALL_STR, 1);
}
}
+ pm_options_scope_forwarding_set(options_scope, forwarding);
iseq = ISEQ_BODY(iseq)->parent_iseq;
/* We need to GC guard the iseq because the code above malloc memory
@@ -1775,14 +1800,38 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
for (int local_index = 0; local_index < locals_count; local_index++) {
const pm_string_t *scope_local = &options_scope->locals[local_index];
-
pm_constant_id_t constant_id = 0;
- if (pm_string_length(scope_local) > 0) {
- constant_id = pm_constant_pool_insert_constant(
- &result.parser.constant_pool, pm_string_source(scope_local),
- pm_string_length(scope_local));
- st_insert(parent_scope->index_lookup_table, (st_data_t)constant_id, (st_data_t)local_index);
+
+ const uint8_t *source = pm_string_source(scope_local);
+ size_t length = pm_string_length(scope_local);
+
+ if (length > 0) {
+ if (length == 1) {
+ switch (*source) {
+ case FORWARDING_POSITIONALS_CHR:
+ constant_id = PM_CONSTANT_MULT;
+ break;
+ case FORWARDING_KEYWORDS_CHR:
+ constant_id = PM_CONSTANT_POW;
+ break;
+ case FORWARDING_BLOCK_CHR:
+ constant_id = PM_CONSTANT_AND;
+ break;
+ case FORWARDING_ALL_CHR:
+ constant_id = PM_CONSTANT_DOT3;
+ break;
+ default:
+ constant_id = pm_constant_pool_insert_constant(&result.parser.constant_pool, source, length);
+ break;
+ }
+ }
+ else {
+ constant_id = pm_constant_pool_insert_constant(&result.parser.constant_pool, source, length);
+ }
+
+ st_insert(parent_scope->index_lookup_table, (st_data_t) constant_id, (st_data_t) local_index);
}
+
pm_constant_id_list_append(&parent_scope->locals, constant_id);
}
@@ -1791,6 +1840,15 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
iseq = ISEQ_BODY(iseq)->parent_iseq;
}
+#undef FORWARDING_POSITIONALS_CHR
+#undef FORWARDING_POSITIONALS_STR
+#undef FORWARDING_KEYWORDS_CHR
+#undef FORWARDING_KEYWORDS_STR
+#undef FORWARDING_BLOCK_CHR
+#undef FORWARDING_BLOCK_STR
+#undef FORWARDING_ALL_CHR
+#undef FORWARDING_ALL_STR
+
int error_state;
iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, 0, &error_state);