Skip to content

Commit

Permalink
added support for @@foo||=42, a lot of changes for a very stupid func…
Browse files Browse the repository at this point in the history
…tionality, unfortunately used in crap projects such as minitest

git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/branches/experimental@2154 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Aug 3, 2009
1 parent 64899b9 commit eeb7a10
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 25 deletions.
55 changes: 35 additions & 20 deletions compiler.cpp
Expand Up @@ -1071,6 +1071,25 @@ RoxorCompiler::compile_ivar_assignment(ID vid, Value *val)
return val;
}

Value *
RoxorCompiler::compile_cvar_get(ID id, bool check)
{
if (cvarGetFunc == NULL) {
// VALUE rb_vm_cvar_get(VALUE klass, ID id, unsigned char check);
cvarGetFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_cvar_get",
RubyObjTy, RubyObjTy, IntTy, Type::Int8Ty, NULL));
}

std::vector<Value *> params;

params.push_back(compile_current_class());
params.push_back(compile_id(id));
params.push_back(ConstantInt::get(Type::Int8Ty, check ? 1 : 0));

return compile_protected_call(cvarGetFunc, params);
}

Value *
RoxorCompiler::compile_cvar_assignment(ID name, Value *val)
{
Expand Down Expand Up @@ -3054,24 +3073,8 @@ RoxorCompiler::compile_node(NODE *node)
break;

case NODE_CVAR:
{
assert(node->nd_vid > 0);

if (cvarGetFunc == NULL) {
// VALUE rb_vm_cvar_get(VALUE klass, ID id);
cvarGetFunc = cast<Function>(module->getOrInsertFunction(
"rb_vm_cvar_get",
RubyObjTy, RubyObjTy, IntTy, NULL));
}

std::vector<Value *> params;

params.push_back(compile_current_class());
params.push_back(compile_id(node->nd_vid));

return compile_protected_call(cvarGetFunc, params);
}
break;
assert(node->nd_vid > 0);
return compile_cvar_get(node->nd_vid, true);

case NODE_CVASGN:
assert(node->nd_vid > 0);
Expand Down Expand Up @@ -3108,8 +3111,20 @@ RoxorCompiler::compile_node(NODE *node)
{
assert(node->nd_recv != NULL);
assert(node->nd_value != NULL);

Value *recvVal = compile_node(node->nd_recv);

Value *recvVal;
if (nd_type(node->nd_recv) == NODE_CVAR) {
// @@foo ||= 42
// We need to compile the class variable retrieve to not
// raise an exception in case the variable has never been
// defined yet.
assert(node->nd_recv->nd_vid > 0);
recvVal = compile_cvar_get(node->nd_recv->nd_vid, false);
}
else {
recvVal = compile_node(node->nd_recv);
}


Value *falseCond = new ICmpInst(ICmpInst::ICMP_EQ, recvVal, falseVal, "", bb);

Expand Down
1 change: 1 addition & 0 deletions compiler.h
Expand Up @@ -224,6 +224,7 @@ class RoxorCompiler {
Value *compile_ivar_read(ID vid);
Value *compile_ivar_assignment(ID vid, Value *val);
Value *compile_cvar_assignment(ID vid, Value *val);
Value *compile_cvar_get(ID vid, bool check);
Value *compile_gvar_assignment(NODE *node, Value *val);
Value *compile_constant_declaration(NODE *node, Value *val);
Value *compile_multiple_assignment(NODE *node, Value *val);
Expand Down
1 change: 1 addition & 0 deletions include/ruby/intern.h
Expand Up @@ -652,6 +652,7 @@ void rb_const_set(VALUE, ID, VALUE);
VALUE rb_cvar_defined(VALUE, ID);
void rb_cvar_set(VALUE, ID, VALUE);
VALUE rb_cvar_get(VALUE, ID);
VALUE rb_cvar_get2(VALUE klass, ID id, bool check);
void rb_cv_set(VALUE, const char*, VALUE);
VALUE rb_cv_get(VALUE, const char*);
void rb_define_class_variable(VALUE, const char*, VALUE);
Expand Down
17 changes: 14 additions & 3 deletions variable.c
Expand Up @@ -1945,7 +1945,7 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
}

VALUE
rb_cvar_get(VALUE klass, ID id)
rb_cvar_get2(VALUE klass, ID id, bool check)
{
VALUE value, tmp, front = 0, target = 0;
CFMutableDictionaryRef iv_dict;
Expand All @@ -1956,8 +1956,13 @@ rb_cvar_get(VALUE klass, ID id)
}
CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
if (!target) {
rb_name_error(id,"uninitialized class variable %s in %s",
rb_id2name(id), rb_class2name(tmp));
if (check) {
rb_name_error(id,"uninitialized class variable %s in %s",
rb_id2name(id), rb_class2name(tmp));
}
else {
return Qnil;
}
}
if (front && target != front) {
ID did = id;
Expand All @@ -1974,6 +1979,12 @@ rb_cvar_get(VALUE klass, ID id)
return value;
}

VALUE
rb_cvar_get(VALUE klass, ID id)
{
return rb_cvar_get2(klass, id, true);
}

VALUE
rb_cvar_defined(VALUE klass, ID id)
{
Expand Down
4 changes: 2 additions & 2 deletions vm.cpp
Expand Up @@ -1006,13 +1006,13 @@ rb_vm_ivar_set(VALUE obj, ID name, VALUE val, int *slot_cache)

extern "C"
VALUE
rb_vm_cvar_get(VALUE klass, ID id)
rb_vm_cvar_get(VALUE klass, ID id, unsigned char check)
{
Class k = GET_VM()->get_current_class();
if (k != NULL) {
klass = (VALUE)k;
}
return rb_cvar_get(klass, id);
return rb_cvar_get2(klass, id, check);
}

extern "C"
Expand Down

0 comments on commit eeb7a10

Please sign in to comment.