[macruby-changes] [3962] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sun Apr 25 20:32:28 PDT 2010
Revision: 3962
http://trac.macosforge.org/projects/ruby/changeset/3962
Author: lsansonetti at apple.com
Date: 2010-04-25 20:32:23 -0700 (Sun, 25 Apr 2010)
Log Message:
-----------
added support for anonymous structs
Modified Paths:
--------------
MacRuby/trunk/bridgesupport.cpp
MacRuby/trunk/compiler.cpp
MacRuby/trunk/objc.h
MacRuby/trunk/spec/macruby/fixtures/method.m
MacRuby/trunk/spec/macruby/language/objc_method_spec.rb
MacRuby/trunk/vm.h
Modified: MacRuby/trunk/bridgesupport.cpp
===================================================================
--- MacRuby/trunk/bridgesupport.cpp 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/bridgesupport.cpp 2010-04-26 03:32:23 UTC (rev 3962)
@@ -526,6 +526,168 @@
return true;
}
+rb_vm_bs_boxed_t *
+RoxorCore::register_anonymous_bs_struct(const char *type)
+{
+ if (strlen(type) < 3 || type[0] != _C_STRUCT_B || type[1] != '?'
+ || type[2] != '=') {
+ // Does not look like an anonymous struct...
+ return NULL;
+ }
+
+ // Prepare the list of field types.
+ std::vector<std::string> s_types;
+ char buf[100];
+ const char *p = &type[3];
+ while (*p != _C_STRUCT_E) {
+ p = GetFirstType(p, buf, sizeof buf);
+ assert(*p != '\0');
+ s_types.push_back(buf);
+ }
+
+ // Prepare the BridgeSupport structure.
+ bs_element_struct_t *bs_struct = (bs_element_struct_t *)
+ malloc(sizeof(bs_element_struct_t));
+ bs_struct->name = (char *)"?";
+ bs_struct->type = strdup(type);
+ bs_struct->fields_count = s_types.size();
+ assert(bs_struct->fields_count > 0);
+ bs_struct->fields = (bs_element_struct_field_t *)
+ malloc(sizeof(bs_element_struct_field_t) * bs_struct->fields_count);
+ for (unsigned i = 0; i < bs_struct->fields_count; i++) {
+ bs_element_struct_field_t *field = &bs_struct->fields[i];
+ field->name = (char *)"?";
+ field->type = strdup(s_types.at(i).c_str());
+ }
+ bs_struct->opaque = true;
+
+ // Prepare the boxed structure.
+ rb_vm_bs_boxed_t *boxed = (rb_vm_bs_boxed_t *)
+ malloc(sizeof(rb_vm_bs_boxed_t));
+ boxed->bs_type = BS_ELEMENT_STRUCT;
+ boxed->as.s = bs_struct;
+ boxed->type = NULL; // Lazy
+ boxed->klass = rb_cBoxed; // This type has no class
+
+ // Register it to the runtime.
+ bs_boxed[type] = boxed;
+ return boxed;
+}
+
+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));
+ }
+
+ if (bs_boxed->klass == rb_cBoxed) {
+ // An anonymous type...
+ // Let's check that the given boxed object matches the types.
+ rb_vm_bs_boxed_t *rval_bs_boxed =
+ locate_bs_boxed(CLASS_OF(rval), true);
+ assert(rval_bs_boxed != NULL);
+
+ if (rval_bs_boxed->as.s->fields_count
+ != bs_boxed->as.s->fields_count) {
+ rb_raise(rb_eTypeError,
+ "expected instance of Boxed with %d fields, got %d",
+ bs_boxed->as.s->fields_count,
+ rval_bs_boxed->as.s->fields_count);
+ }
+
+ for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
+ if (strcmp(bs_boxed->as.s->fields[i].type,
+ rval_bs_boxed->as.s->fields[i].type) != 0) {
+ rb_raise(rb_eTypeError,
+ "field %d of given instance of `%s' does not match " \
+ "the type expected (%s, got %s)",
+ i,
+ rb_class2name(bs_boxed->klass),
+ bs_boxed->as.s->fields[i].type,
+ rval_bs_boxed->as.s->fields[i].type);
+ }
+ }
+ }
+
+ VALUE *data;
+ Data_Get_Struct(rval, VALUE, data);
+
+ for (unsigned i = 0; i < bs_boxed->as.s->fields_count; i++) {
+ buf[i] = data[i];
+ }
+ }
+}
+
static VALUE
rb_boxed_objc_type(VALUE rcv, SEL sel)
{
@@ -797,7 +959,16 @@
RoxorCore::find_bs_struct(std::string type)
{
rb_vm_bs_boxed_t *boxed = find_bs_boxed(type);
- return boxed == NULL ? NULL : boxed->is_struct() ? boxed : NULL;
+ if (boxed != NULL) {
+ if (boxed->is_struct()) {
+ return boxed;
+ }
+ return NULL;
+ }
+
+ // Given structure type does not exist... but it may be an anonymous
+ // type (like {?=qq}) which is sometimes present in BridgeSupport files...
+ return register_anonymous_bs_struct(type.c_str());
}
rb_vm_bs_boxed_t *
@@ -1079,7 +1250,6 @@
case BS_ELEMENT_CFTYPE:
{
-
bs_element_cftype_t *bs_cftype = (bs_element_cftype_t *)value;
std::map<std::string, bs_element_cftype_t *>::iterator
iter = bs_cftypes.find(bs_cftype->type);
@@ -1132,7 +1302,8 @@
char *error = NULL;
const bool ok = bs_parser_parse(bs_parser, path, framework_path,
- (bs_parse_options_t)options, __bs_parse_cb, rb_cObject_dict, &error);
+ (bs_parse_options_t)options, __bs_parse_cb, rb_cObject_dict,
+ &error);
if (!ok) {
rb_raise(rb_eRuntimeError, "%s", error);
}
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/compiler.cpp 2010-04-26 03:32:23 UTC (rev 3962)
@@ -6029,17 +6029,6 @@
return f;
}
-static inline const char *
-GetFirstType(const char *p, char *buf, size_t buflen)
-{
- const char *p2 = SkipFirstType(p);
- const size_t len = p2 - p;
- assert(len < buflen);
- strncpy(buf, p, len);
- buf[len] = '\0';
- return SkipStackSize(p2);
-}
-
static inline void
convert_error(const char type, VALUE val)
{
@@ -6248,92 +6237,7 @@
return *cptr;
}
-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];
- }
- }
-}
-
-void
RoxorCompiler::compile_get_struct_fields(Value *val, Value *buf,
rb_vm_bs_boxed_t *bs_boxed)
{
@@ -6530,8 +6434,10 @@
case _C_FPTR_B:
{
- GlobalVariable *proc_gvar = new GlobalVariable(*RoxorCompiler::module,
- RubyObjTy, false, GlobalValue::InternalLinkage, nilVal, "");
+ GlobalVariable *proc_gvar =
+ new GlobalVariable(*RoxorCompiler::module,
+ RubyObjTy, false, GlobalValue::InternalLinkage,
+ nilVal, "");
new StoreInst(val, proc_gvar, bb);
char buf[100];
@@ -6799,7 +6705,7 @@
Value *
RoxorCompiler::compile_conversion_to_ruby(const char *type,
- const Type *llvm_type, Value *val)
+ const Type *llvm_type, Value *val)
{
const char *func_name = NULL;
Modified: MacRuby/trunk/objc.h
===================================================================
--- MacRuby/trunk/objc.h 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/objc.h 2010-04-26 03:32:23 UTC (rev 3962)
@@ -151,6 +151,17 @@
}
}
+static inline const char *
+GetFirstType(const char *p, char *buf, size_t buflen)
+{
+ const char *p2 = SkipFirstType(p);
+ const size_t len = p2 - p;
+ assert(len < buflen);
+ strncpy(buf, p, len);
+ buf[len] = '\0';
+ return SkipStackSize(p2);
+}
+
static inline unsigned int
TypeArity(const char *type)
{
Modified: MacRuby/trunk/spec/macruby/fixtures/method.m
===================================================================
--- MacRuby/trunk/spec/macruby/fixtures/method.m 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/spec/macruby/fixtures/method.m 2010-04-26 03:32:23 UTC (rev 3962)
@@ -720,6 +720,16 @@
return ptr == NULL;
}
+typedef struct {
+ CGFloat f1;
+ CGFloat f2;
+} anon_struct;
+
+- (BOOL)methodAcceptingAnonymousStructure:(anon_struct)s
+{
+ return s.f1 == 42 && s.f2 == 4200;
+}
+
extern id objc_msgSend(id self, SEL op, ...);
- (void)methodAcceptingSEL:(SEL)sel target:(id)target
Modified: MacRuby/trunk/spec/macruby/language/objc_method_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/language/objc_method_spec.rb 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/spec/macruby/language/objc_method_spec.rb 2010-04-26 03:32:23 UTC (rev 3962)
@@ -426,6 +426,22 @@
end
@o.methodAcceptingSEL('foo:arg1:arg2:', target:o)
end
+
+ it "accepting an anonymous structure should be given a Boxed object that matches the types" do
+ @o.methodSignatureForSelector(:'methodAcceptingAnonymousStructure:').getArgumentTypeAtIndex(2).should == '{?=dd}'
+
+ @o.methodAcceptingAnonymousStructure(NSPoint.new(42, 4200)).should == 1
+ @o.methodAcceptingAnonymousStructure(NSSize.new(42, 4200)).should == 1
+ @o.methodAcceptingAnonymousStructure([42, 4200]).should == 1
+ @o.methodAcceptingAnonymousStructure(NSPoint.new(42, 4201)).should == 0
+ @o.methodAcceptingAnonymousStructure(NSSize.new(42, 4201)).should == 0
+ @o.methodAcceptingAnonymousStructure([42, 4201]).should == 0
+
+ lambda { @o.methodAcceptingAnonymousStructure([42]) }.should raise_error(ArgumentError)
+ lambda { @o.methodAcceptingAnonymousStructure([42, 4200, 42]) }.should raise_error(ArgumentError)
+ lambda { @o.methodAcceptingAnonymousStructure(nil) }.should raise_error(TypeError)
+ lambda { @o.methodAcceptingAnonymousStructure(NSRange.new(42, 4200)) }.should raise_error(TypeError)
+ end
end
describe "A pure MacRuby method" do
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2010-04-24 20:12:57 UTC (rev 3961)
+++ MacRuby/trunk/vm.h 2010-04-26 03:32:23 UTC (rev 3962)
@@ -847,6 +847,7 @@
private:
bool register_bs_boxed(bs_element_type_t type, void *value);
void register_bs_class(bs_element_class_t *bs_class);
+ rb_vm_bs_boxed_t *register_anonymous_bs_struct(const char *type);
};
#define GET_CORE() (RoxorCore::shared)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100425/5c765e8e/attachment-0001.html>
More information about the macruby-changes
mailing list