[macruby-changes] [1429] MacRuby/branches/experimental/roxor.cpp
source_changes at macosforge.org
source_changes at macosforge.org
Sat Apr 18 19:47:21 PDT 2009
Revision: 1429
http://trac.macosforge.org/projects/ruby/changeset/1429
Author: vincent.isambart at gmail.com
Date: 2009-04-18 19:47:20 -0700 (Sat, 18 Apr 2009)
Log Message:
-----------
continued improving multiple assignment
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-19 01:53:34 UTC (rev 1428)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-19 02:47:20 UTC (rev 1429)
@@ -312,6 +312,7 @@
Value *compile_ivar_assignment(ID vid, Value *val);
Value *compile_cvar_assignment(ID vid, Value *val);
Value *compile_multiple_assignment(NODE *node, Value *val);
+ void compile_multiple_assignment_element(NODE *node, Value *val);
Value *compile_current_class(void);
Value *compile_class_path(NODE *node);
Value *compile_const(ID id, Value *outer);
@@ -974,65 +975,109 @@
return compile_dispatch_call(params);
}
+void
+RoxorCompiler::compile_multiple_assignment_element(NODE *node, Value *val)
+{
+ switch (nd_type(node)) {
+ case NODE_LASGN:
+ case NODE_DASGN:
+ case NODE_DASGN_CURR:
+ {
+ Value *slot = compile_lvar_slot(node->nd_vid);
+ new StoreInst(val, slot, bb);
+ }
+ break;
+
+ case NODE_IASGN:
+ case NODE_IASGN2:
+ compile_ivar_assignment(node->nd_vid, val);
+ break;
+
+ case NODE_CVASGN:
+ compile_cvar_assignment(node->nd_vid, val);
+ break;
+
+ case NODE_ATTRASGN:
+ compile_attribute_assign(node, val);
+ break;
+
+ case NODE_MASGN:
+ compile_multiple_assignment(node, val);
+ break;
+
+ default:
+ compile_node_error("unimplemented MASGN subnode",
+ node);
+ }
+}
+
Value *
RoxorCompiler::compile_multiple_assignment(NODE *node, Value *val)
{
assert(nd_type(node) == NODE_MASGN);
if (rhsnGetFunc == NULL) {
- // VALUE rb_vm_rhsn_get(VALUE ary, int offset);
+ // VALUE rb_vm_rhsn_get(VALUE obj, int offset, int min_offset, unsigned char is_first);
rhsnGetFunc = cast<Function>(module->getOrInsertFunction(
- "rb_vm_rhsn_get",
- RubyObjTy, RubyObjTy, Type::Int32Ty, NULL));
+ "rb_vm_rhsn_get",
+ RubyObjTy, RubyObjTy, Type::Int32Ty, Type::Int32Ty, Type::Int8Ty, NULL));
}
- NODE *lhsn = node->nd_head;
- assert((lhsn == NULL) || (nd_type(lhsn) == NODE_ARRAY));
- NODE *l = lhsn;
+ NODE *before_splat = node->nd_head, *after_splat = NULL, *splat = NULL;
+
+ assert((before_splat == NULL) || (nd_type(before_splat) == NODE_ARRAY));
+
+ // if the splat has no name (a, *, b = 1, 2, 3), its node value is -1
+ if ((node->nd_next == (NODE *)-1) || (node->nd_next == NULL) || (nd_type(node->nd_next) != NODE_POSTARG)) {
+ splat = node->nd_next;
+ }
+ else {
+ NODE *post_arg = node->nd_next;
+ splat = post_arg->nd_1st;
+ after_splat = post_arg->nd_2nd;
+ }
+
+ assert((after_splat == NULL) || (nd_type(after_splat) == NODE_ARRAY));
+
+ int before_splat_count = 0, after_splat_count = 0;
+ for (NODE *l = before_splat; l != NULL; l = l->nd_next) {
+ ++before_splat_count;
+ }
+ for (NODE *l = after_splat; l != NULL; l = l->nd_next) {
+ ++after_splat_count;
+ }
+
+ NODE *l = before_splat;
for (int i = 0; l != NULL; ++i) {
- NODE *ln = l->nd_head;
-
std::vector<Value *> params;
params.push_back(val);
params.push_back(ConstantInt::get(Type::Int32Ty, i));
+ params.push_back(ConstantInt::get(Type::Int32Ty, 0));
+ params.push_back(ConstantInt::get(Type::Int8Ty, i == 0 ? TRUE : FALSE));
Value *elt = CallInst::Create(rhsnGetFunc, params.begin(),
params.end(), "", bb);
- switch (nd_type(ln)) {
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_DASGN_CURR:
- {
- Value *slot = compile_lvar_slot(ln->nd_vid);
- new StoreInst(elt, slot, bb);
- }
- break;
+ compile_multiple_assignment_element(l->nd_head, elt);
- case NODE_IASGN:
- case NODE_IASGN2:
- compile_ivar_assignment(ln->nd_vid, elt);
- break;
+ l = l->nd_next;
+ }
- case NODE_CVASGN:
- compile_cvar_assignment(ln->nd_vid, elt);
- break;
+ // TODO: splat
- case NODE_ATTRASGN:
- compile_attribute_assign(ln, elt);
- break;
+ l = after_splat;
+ for (int i = 0; l != NULL; ++i) {
+ std::vector<Value *> params;
+ params.push_back(val);
+ params.push_back(ConstantInt::get(Type::Int32Ty, -(after_splat_count - i)));
+ params.push_back(ConstantInt::get(Type::Int32Ty, before_splat_count + i));
+ params.push_back(ConstantInt::get(Type::Int8Ty, (before_splat_count == 0 && i == 0) ? TRUE : FALSE));
+ Value *elt = CallInst::Create(rhsnGetFunc, params.begin(),
+ params.end(), "", bb);
- case NODE_MASGN:
- compile_multiple_assignment(ln, elt);
- break;
+ compile_multiple_assignment_element(l->nd_head, elt);
- default:
- compile_node_error("unimplemented MASGN subnode",
- ln);
- }
l = l->nd_next;
}
- // TODO: splat and what's after the splat
-
return val;
}
@@ -5897,14 +5942,22 @@
extern "C"
VALUE
-rb_vm_rhsn_get(VALUE obj, int offset)
+rb_vm_rhsn_get(VALUE obj, int offset, int min_offset, unsigned char is_first)
{
if (TYPE(obj) == T_ARRAY) {
- if (offset < RARRAY_LEN(obj)) {
- return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)obj, offset));
+ if (offset >= 0) {
+ if (offset < RARRAY_LEN(obj)) {
+ return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)obj, offset));
+ }
}
+ else {
+ offset += RARRAY_LEN(obj);
+ if (offset >= min_offset && offset < RARRAY_LEN(obj)) {
+ return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)obj, offset));
+ }
+ }
}
- else if (offset == 0) {
+ else if (is_first) {
return obj;
}
return Qnil;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090418/d1b222d3/attachment-0001.html>
More information about the macruby-changes
mailing list