[macruby-changes] [1439] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 21 19:29:56 PDT 2009
Revision: 1439
http://trac.macosforge.org/projects/ruby/changeset/1439
Author: lsansonetti at apple.com
Date: 2009-04-21 19:29:55 -0700 (Tue, 21 Apr 2009)
Log Message:
-----------
some work on incoming C structs
Modified Paths:
--------------
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m
MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-22 00:06:53 UTC (rev 1438)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-22 02:29:55 UTC (rev 1439)
@@ -172,6 +172,18 @@
}
};
+typedef struct {
+ bs_element_type_t bs_type;
+ bool is_struct(void) { return bs_type == BS_ELEMENT_STRUCT; }
+ union {
+ bs_element_struct_t *s;
+ bs_element_opaque_t *o;
+ void *v;
+ } as;
+ Type *type;
+ VALUE klass;
+} rb_vm_bs_boxed_t;
+
#define SPLAT_ARG_FOLLOWS 0xdeadbeef
class RoxorCompiler
@@ -251,6 +263,7 @@
Function *dupArrayFunc;
Function *newArrayFunc;
Function *newStructFunc;
+ Function *getStructFieldsFunc;
Function *newRangeFunc;
Function *newRegexpFunc;
Function *strInternFunc;
@@ -333,6 +346,8 @@
void compile_rethrow_exception(void);
Value *compile_lvar_slot(ID name);
Value *compile_new_struct(VALUE klass, std::vector<Value *> &fields);
+ void compile_get_struct_fields(Value *val, Value *buf,
+ rb_vm_bs_boxed_t *bs_boxed);
Value *compile_conversion_to_c(const char *type, Value *val,
Value *slot);
@@ -426,18 +441,6 @@
NODE *node;
} rb_vm_method_source_t;
-typedef struct {
- bs_element_type_t bs_type;
- bool is_struct(void) { return bs_type == BS_ELEMENT_STRUCT; }
- union {
- bs_element_struct_t *s;
- bs_element_opaque_t *o;
- void *v;
- } as;
- Type *type;
- VALUE klass;
-} rb_vm_bs_boxed_t;
-
class RoxorVM
{
private:
@@ -648,6 +651,7 @@
dupArrayFunc = NULL;
newArrayFunc = NULL;
newStructFunc = NULL;
+ getStructFieldsFunc = NULL;
newRangeFunc = NULL;
newRegexpFunc = NULL;
strInternFunc = NULL;
@@ -5010,6 +5014,110 @@
*ocval = (float)rval_to_double(rval);
}
+static inline long
+rebuild_new_struct_ary(const StructType *type, VALUE orig, VALUE new_ary)
+{
+ long n = 0;
+
+ for (StructType::element_iterator iter = type->element_begin();
+ iter != type->element_end();
+ ++iter) {
+
+ const Type *ftype = *iter;
+
+ if (ftype->getTypeID() == Type::StructTyID) {
+ long i, n2;
+ VALUE tmp;
+
+ n2 = rebuild_new_struct_ary(cast<StructType>(ftype), orig, new_ary);
+ tmp = rb_ary_new();
+ for (i = 0; i < n2; i++) {
+ if (RARRAY_LEN(orig) == 0) {
+ return 0;
+ }
+ rb_ary_push(tmp, rb_ary_shift(orig));
+ }
+ rb_ary_push(new_ary, tmp);
+ }
+ n++;
+ }
+
+ return n;
+}
+
+extern "C"
+void
+rb_vm_get_struct_fields(VALUE rval, VALUE *buf, rb_vm_bs_boxed_t *bs_boxed)
+{
+ if (TYPE(rval) == T_ARRAY) {
+ unsigned n = RARRAY_LEN(rval);
+ if (n < bs_boxed->as.s->fields_count) {
+ rb_raise(rb_eArgError,
+ "not enough elements in array `%s' to create " \
+ "structure `%s' (%d for %d)",
+ RSTRING_PTR(rb_inspect(rval)), bs_boxed->as.s->name, n,
+ bs_boxed->as.s->fields_count);
+ }
+
+ if (n > bs_boxed->as.s->fields_count) {
+ VALUE new_rval = rb_ary_new();
+ VALUE orig = rval;
+ rval = rb_ary_dup(rval);
+ rebuild_new_struct_ary(cast<StructType>(bs_boxed->type), rval,
+ new_rval);
+ n = RARRAY_LEN(new_rval);
+ if (RARRAY_LEN(rval) != 0 || n != bs_boxed->as.s->fields_count) {
+ rb_raise(rb_eArgError,
+ "too much elements in array `%s' to create " \
+ "structure `%s' (%ld for %d)",
+ RSTRING_PTR(rb_inspect(orig)),
+ bs_boxed->as.s->name, RARRAY_LEN(orig),
+ bs_boxed->as.s->fields_count);
+ }
+ rval = new_rval;
+ }
+
+ for (unsigned i = 0; i < n; i++) {
+ buf[i] = RARRAY_AT(rval, i);
+ }
+ }
+ else {
+ if (!rb_obj_is_kind_of(rval, bs_boxed->klass)) {
+ rb_raise(rb_eTypeError,
+ "expected instance of `%s', got `%s' (%s)",
+ rb_class2name(bs_boxed->klass),
+ RSTRING_PTR(rb_inspect(rval)),
+ rb_obj_classname(rval));
+ }
+
+ VALUE *data;
+ Data_Get_Struct(rval, VALUE, data);
+
+ for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
+ buf[i] = data[i];
+printf("buf[%d] = %p\n", i, (void *)data[i]);
+ }
+ }
+}
+
+void
+RoxorCompiler::compile_get_struct_fields(Value *val, Value *buf,
+ rb_vm_bs_boxed_t *bs_boxed)
+{
+ if (getStructFieldsFunc == NULL) {
+ getStructFieldsFunc = cast<Function>(module->getOrInsertFunction(
+ "rb_vm_get_struct_fields",
+ Type::VoidTy, RubyObjTy, RubyObjPtrTy, PtrTy, NULL));
+ }
+
+ std::vector<Value *> params;
+ params.push_back(val);
+ params.push_back(buf);
+ params.push_back(compile_const_pointer(bs_boxed));
+
+ CallInst::Create(getStructFieldsFunc, params.begin(), params.end(), "", bb);
+}
+
Value *
RoxorCompiler::compile_conversion_to_c(const char *type, Value *val,
Value *slot)
@@ -5078,17 +5186,58 @@
func_name = "rb_vm_rval_to_ocsel";
break;
- default:
- printf("unrecognized compile type `%s' to C - aborting\n", type);
- abort();
+ case _C_STRUCT_B:
+ {
+ rb_vm_bs_boxed_t *bs_boxed = GET_VM()->find_bs_struct(type);
+ if (bs_boxed != NULL) {
+ Value *fields = new AllocaInst(RubyObjTy,
+ ConstantInt::get(Type::Int32Ty,
+ bs_boxed->as.s->fields_count), "", bb);
+
+ compile_get_struct_fields(val, fields, bs_boxed);
+
+ //Value *struct_val = new LoadInst(slot, "", bb);
+
+ for (unsigned i = 0; i < bs_boxed->as.s->fields_count;
+ i++) {
+
+ const char *ftype = bs_boxed->as.s->fields[i].type;
+ //const Type *llvm_ftype = convert_type(ftype);
+
+ Value *fval = GetElementPtrInst::Create(fields,
+ ConstantInt::get(Type::Int32Ty, i), "", bb);
+ fval = new LoadInst(fval, "", bb);
+
+ //Value *fslot = new AllocaInst(llvm_ftype, "", bb);
+
+ Value *fslot = GetElementPtrInst::Create(slot,
+ ConstantInt::get(Type::Int32Ty, i), "", bb);
+
+ /*Value *fcval =*/ RoxorCompiler::compile_conversion_to_c(
+ ftype, fval, fslot);
+
+ //InsertValueInst::Create(struct_val, fcval, i, "", bb);
+ }
+
+ return new LoadInst(slot, "", bb);
+ //return struct_val;
+ }
+ }
+ break;
}
+
+ if (func_name == NULL) {
+ printf("unrecognized compile type `%s' to C - aborting\n", type);
+ abort();
+ }
std::vector<Value *> params;
params.push_back(val);
- params.push_back(new BitCastInst(slot, PtrTy, "", bb));
+ params.push_back(slot);
Function *func = cast<Function>(module->getOrInsertFunction(
- func_name, Type::VoidTy, RubyObjTy, PtrTy, NULL));
+ func_name, Type::VoidTy, RubyObjTy,
+ PointerType::getUnqual(convert_type(type)), NULL));
CallInst::Create(func, params.begin(), params.end(), "", bb);
return new LoadInst(slot, "", bb);
Modified: MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m 2009-04-22 00:06:53 UTC (rev 1438)
+++ MacRuby/branches/experimental/spec/frozen/macruby/fixtures/method.m 2009-04-22 02:29:55 UTC (rev 1439)
@@ -271,6 +271,28 @@
return d > 3.1414 && d < 3.1416;
}
+- (BOOL)methodAcceptingNSPoint:(NSPoint)p
+{
+NSLog(@" -> %@", NSStringFromPoint(p));
+ return p.x == 1 && p.y == 2;
+}
+
+- (BOOL)methodAcceptingNSSize:(NSSize)s
+{
+ return s.width == 3 && s.height == 4;
+}
+
+- (BOOL)methodAcceptingNSRect:(NSRect)r
+{
+ return r.origin.x == 1 && r.origin.y == 2 && r.size.width == 3
+ && r.size.height == 4;
+}
+
+- (BOOL)methodAcceptingNSRange:(NSRange)r
+{
+ return r.location == 0 && r.length == 42;
+}
+
@end
void
Modified: MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb 2009-04-22 00:06:53 UTC (rev 1438)
+++ MacRuby/branches/experimental/spec/frozen/macruby/method_spec.rb 2009-04-22 02:29:55 UTC (rev 1439)
@@ -410,4 +410,35 @@
lambda { o.methodAcceptingFloat(Object.new) }.should raise_error(TypeError)
lambda { o.methodAcceptingDouble(Object.new) }.should raise_error(TypeError)
end
+
+=begin
+ it "accepting an NSPoint, NSSize, NSRange or NSRect object as 'NSPoint', 'NSSize', 'NSRange' or 'NSRect' should receive the C structure" do
+ o = TestMethod.new
+ p = o.methodReturningNSPoint
+ o.methodAcceptingNSPoint(p).should == 1
+ p = o.methodReturningNSSize
+ o.methodAcceptingNSSize(p).should == 1
+ p = o.methodReturningNSRect
+ o.methodAcceptingNSRect(p).should == 1
+ p = o.methodReturningNSRange
+ o.methodAcceptingNSRange(p).should == 1
+
+ lambda { o.methodAcceptingNSPoint(nil) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSPoint(123) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSPoint(Object.new) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSPoint(o.methodAcceptingNSSize) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSSize(nil) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSSize(123) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSSize(Object.new) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSSize(o.methodAcceptingNSPoint) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRect(nil) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRect(123) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRect(Object.new) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRect(o.methodAcceptingNSPoint) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRange(nil) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRange(123) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRange(Object.new) }.should raise_error(TypeError)
+ lambda { o.methodAcceptingNSRange(o.methodAcceptingNSPoint) }.should raise_error(TypeError)
+ end
+=end
end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090421/a45da7a6/attachment.html>
More information about the macruby-changes
mailing list