Permalink
Browse files

added support for @@foo||=42, a lot of changes for a very stupid func…

…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...
1 parent 64899b9 commit eeb7a106544e363c5e911d10bce92431d54f7b76 @lrz lrz committed Aug 3, 2009
Showing with 53 additions and 25 deletions.
  1. +35 −20 compiler.cpp
  2. +1 −0 compiler.h
  3. +1 −0 include/ruby/intern.h
  4. +14 −3 variable.c
  5. +2 −2 vm.cpp
View
@@ -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)
{
@@ -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);
@@ -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);
View
@@ -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);
View
@@ -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);
View
@@ -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;
@@ -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;
@@ -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)
{
View
4 vm.cpp
@@ -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"

0 comments on commit eeb7a10

Please sign in to comment.