Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Introduce rb_literal_t struct for purge literal generation in parse.y #33

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
180 changes: 177 additions & 3 deletions compile.c
Expand Up @@ -9390,6 +9390,166 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
return COMPILE_OK;
}

static VALUE
compile_negative_numeric(VALUE val)
{
if (FIXNUM_P(val)) {
return LONG2FIX(-FIX2LONG(val));
}
if (SPECIAL_CONST_P(val)) {
#if USE_FLONUM
if (FLONUM_P(val)) {
return DBL2NUM(-RFLOAT_VALUE(val));
}
#endif
}
switch (OBJ_BUILTIN_TYPE(val))
{
case T_BIGNUM:
BIGNUM_NEGATE(val);
val = rb_big_norm(val);
break;
case T_RATIONAL:
RATIONAL_SET_NUM(val, compile_negative_numeric(RRATIONAL(val)->num));
break;
case T_COMPLEX:
RCOMPLEX_SET_REAL(val, compile_negative_numeric(RCOMPLEX(val)->real));
RCOMPLEX_SET_IMAG(val, compile_negative_numeric(RCOMPLEX(val)->imag));
break;
case T_FLOAT:
val = DBL2NUM(-RFLOAT_VALUE(val));
break;
default:
val = LONG2FIX(-FIX2LONG(val));
break;
}
return val;
}

static VALUE
compile_numeric_literal(rb_literal_t *literal, VALUE val)
{
if (literal->numeric_literal_info.tminus) {
val = compile_negative_numeric(val);
}
if (literal->numeric_literal_info.is_imaginary) {
val = rb_complex_raw(INT2FIX(0), val);
}
return val;
}

static VALUE
rb_compile_integer_literal(rb_literal_t *literal)
{
VALUE lit = rb_cstr_to_inum(literal->val, literal->numeric_literal_info.base, FALSE);
return compile_numeric_literal(literal, lit);
}

static VALUE
rb_compile_float_literal(rb_literal_t *literal)
{
double d = strtod(literal->val, 0);
VALUE lit = DBL2NUM(d);
return compile_numeric_literal(literal, lit);
}

static VALUE
rb_compile_rational_literal(rb_literal_t *literal)
{
VALUE lit;
char *val = strdup(literal->val);
int base = literal->numeric_literal_info.base;
if (literal->numeric_literal_info.seen_point > 0) {
int len = (int)(strlen(val));
int seen_point = literal->numeric_literal_info.seen_point;
char *point = &val[seen_point];
size_t fraclen = len-seen_point-1;
memmove(point, point+1, fraclen+1);

lit = rb_rational_new(rb_cstr_to_inum(val, base, FALSE), rb_int_positive_pow(10, fraclen));
} else {
lit = rb_rational_raw1(rb_cstr_to_inum(literal->val, base, FALSE));
}
return compile_numeric_literal(literal, lit);
}

VALUE
rb_compile_numeric_literal(rb_literal_t *literal)
{
if (literal->type == integer_literal) {
if (literal->numeric_literal_info.is_tokenline == TRUE) {
return INT2FIX(literal->numeric_literal_info.tokenline);
}
return rb_compile_integer_literal(literal);
} else if (literal->type == float_literal) {
return rb_compile_float_literal(literal);
} else if (literal->type == rational_literal) {
return rb_compile_rational_literal(literal);
}
return 0;
}

VALUE
rb_compile_symbol_literal(rb_literal_t *literal)
{
return ID2SYM(literal->symbol_literal_info.symbol_id);
}

VALUE
rb_compile_empty_hash_literal(void)
{
static VALUE empty_hash;
if (!empty_hash) {
empty_hash = rb_obj_freeze(rb_hash_new());
rb_gc_register_mark_object(empty_hash);
}
return empty_hash;
}

VALUE
rb_compile_empty_array_literal(void)
{
VALUE lit = rb_ary_new();
OBJ_FREEZE_RAW(lit);
return lit;
}

VALUE
rb_compile_ruby_vm_core_literal(void)
{
return rb_mRubyVMFrozenCore;
}

VALUE
rb_compile_string_literal(rb_literal_t *literal)
{
return rb_enc_str_new(literal->val, literal->string_literal_info.length, literal->string_literal_info.encoding);
}

char *
rb_generate_const_decl_cstr_path(NODE *n)
{
VALUE path = rb_ary_new();
for (; n && nd_type_p(n, NODE_COLON2); n = RNODE_COLON2(n)->nd_head) {
rb_ary_push(path, rb_id2str(RNODE_COLON2(n)->nd_mid));
}
if (n && nd_type_p(n, NODE_CONST)) {
// Const::Name
rb_ary_push(path, rb_id2str(RNODE_CONST(n)->nd_vid));
}
else if (n && nd_type_p(n, NODE_COLON3)) {
// ::Const::Name
rb_ary_push(path, rb_str_new(0, 0));
}
else {
// expression::Name
rb_ary_push(path, rb_str_new_cstr("..."));
}
path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::"));
path = rb_fstring(path);
return RSTRING_PTR(path);
}

static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped);
/**
compile each node
Expand Down Expand Up @@ -9755,10 +9915,24 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
CHECK(compile_match(iseq, ret, node, popped, type));
break;
case NODE_LIT:{
debugp_param("lit", RNODE_LIT(node)->nd_lit);
VALUE lit = RNODE_LIT(node)->nd_lit;
debugp_param("lit", lit);
if (!popped) {
ADD_INSN1(ret, node, putobject, RNODE_LIT(node)->nd_lit);
RB_OBJ_WRITTEN(iseq, Qundef, RNODE_LIT(node)->nd_lit);
if (RB_TYPE_P(lit, T_REGEXP) || RB_TYPE_P(lit, T_STRING) || SYMBOL_P(lit)) {
// nothing to do.
} else if (RNODE_LIT(node)->literal != NULL) {
if (RNODE_LIT(node)->literal->type == integer_literal || RNODE_LIT(node)->literal->type == float_literal || RNODE_LIT(node)->literal->type == rational_literal) {
lit = rb_compile_numeric_literal(RNODE_LIT(node)->literal);
} else if (RNODE_LIT(node)->literal->type == symbol_literal) {
lit =rb_compile_symbol_literal(RNODE_LIT(node)->literal);
} else if (RNODE_LIT(node)->literal->type == encoding_literal) {
lit = rb_enc_from_encoding(RNODE_LIT(node)->literal->encoding_literal_info.encoding);
} else if (RNODE_LIT(node)->literal->type == ruby_vm_frozen_liteal) {
lit = rb_compile_ruby_vm_core_literal();
}
}
ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
break;
}
Expand Down
7 changes: 7 additions & 0 deletions node.h
Expand Up @@ -124,4 +124,11 @@ nd_type_p(const NODE *n, enum node_type t)
return (enum node_type)nd_type(n) == t;
}

VALUE rb_compile_numeric_literal(rb_literal_t *literal);
VALUE rb_compile_symbol_literal(rb_literal_t *literal);
VALUE rb_compile_empty_hash_literal(void);
VALUE rb_compile_empty_array_literal(void);
VALUE rb_compile_ruby_vm_core_literal(void);
char *rb_generate_const_decl_cstr_path(NODE *n);
VALUE rb_compile_string_literal(rb_literal_t *literal);
#endif /* RUBY_NODE_H */