[macruby-changes] [2226] MacRuby/branches/experimental/ext/libyaml

source_changes at macosforge.org source_changes at macosforge.org
Wed Aug 5 13:20:52 PDT 2009


Revision: 2226
          http://trac.macosforge.org/projects/ruby/changeset/2226
Author:   pthomson at apple.com
Date:     2009-08-05 13:20:52 -0700 (Wed, 05 Aug 2009)
Log Message:
-----------
Okay, event-based parsing works much better. Now to figure out how to do aliases.

Modified Paths:
--------------
    MacRuby/branches/experimental/ext/libyaml/emitter.c
    MacRuby/branches/experimental/ext/libyaml/rubyext.c

Modified: MacRuby/branches/experimental/ext/libyaml/emitter.c
===================================================================
--- MacRuby/branches/experimental/ext/libyaml/emitter.c	2009-08-05 20:20:51 UTC (rev 2225)
+++ MacRuby/branches/experimental/ext/libyaml/emitter.c	2009-08-05 20:20:52 UTC (rev 2226)
@@ -654,8 +654,11 @@
     {
         if (emitter->open_ended)
         {
+			// MacRuby change: since the emitter ignores this parameter, disable it.
+			#if 0
             if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
                 return 0;
+			#endif
             if (!yaml_emitter_write_indent(emitter))
                 return 0;
         }

Modified: MacRuby/branches/experimental/ext/libyaml/rubyext.c
===================================================================
--- MacRuby/branches/experimental/ext/libyaml/rubyext.c	2009-08-05 20:20:51 UTC (rev 2225)
+++ MacRuby/branches/experimental/ext/libyaml/rubyext.c	2009-08-05 20:20:52 UTC (rev 2226)
@@ -18,18 +18,15 @@
 // Ideas to speed this up:
 // embed the yaml_parser_t and yaml_emitter_t into the parser/emitter structs
 // rather than just keep pointers to them; this means fewer mallocs
+// have the resolver be an opaque CFMutableDictionary mapping C strings to VALUES
+// store that dictionary in the parser, fewer ivar accesses
 
 typedef struct rb_yaml_parser_s {
 	struct RBasic basic;		// holds the class information
 	yaml_parser_t *parser;		// the parser object.
 	
 	VALUE input;				// a reference to the object that's providing input
-	
-	VALUE *stack;				// the current object hierarchy that is being parsed.
-								// the root element is at stack[0].
-	int32_t stack_index;		// what element are we currently adding to?
-	int32_t stack_size;			// how big can the stack become?
-	
+
 	VALUE resolver;				// used to determine how to unserialize objects.
 	
 	yaml_event_t event;			// the event that is currently being parsed.
@@ -58,10 +55,14 @@
 static ID id_quote2;
 
 static SEL sel_to_yaml;
+static SEL sel_call;
+static SEL sel_yaml_new;
 
 static VALUE rb_oDefaultResolver;
 
 static struct mcache *to_yaml_cache = NULL;
+static struct mcache *call_cache = NULL;
+static struct mcache *yaml_new_cache = NULL;
 
 static const int DEFAULT_STACK_SIZE = 8;
 
@@ -71,11 +72,6 @@
 	NEWOBJ(parser, struct rb_yaml_parser_s);
 	OBJSETUP(parser, klass, T_OBJECT);
 	
-	GC_WB(&parser->stack, ALLOC_N(VALUE, DEFAULT_STACK_SIZE));	
-	parser->stack_size = DEFAULT_STACK_SIZE;
-	parser->stack_index = -1;
-	parser->stack[0] = Qnil;
-	
 	parser->resolver = rb_oDefaultResolver;
 	
 	parser->event_valid = false;
@@ -207,27 +203,44 @@
 	return rb_yaml_parser_generate_error(RYAMLParser(self)->parser);
 }
 
+static bool
+yaml_next_event(rb_yaml_parser_t *parser)
+{
+	if (parser->event_valid)
+	{
+		yaml_event_delete(&parser->event);
+		parser->event_valid = false;
+	}
+	if (yaml_parser_parse(parser->parser, &parser->event) == -1)
+	{
+		rb_exc_raise(rb_yaml_parser_generate_error(parser->parser));
+		parser->event_valid = false;
+	} else
+	{
+		parser->event_valid = true;
+	}
+	return parser->event_valid;
+}
 
-static void push(rb_yaml_parser_t *parser, VALUE val) __attribute__ ((noinline));
+#define NEXT_EVENT() yaml_next_event(parser)
+static VALUE get_node(rb_yaml_parser_t *parser);
 
-static void
-push(rb_yaml_parser_t *parser, VALUE val)
+static VALUE interpret_value(rb_yaml_parser_t *parser, VALUE result, VALUE tag)
 {
-	parser->stack_index++;
-	if(parser->stack_index >= (parser->stack_size - 1))
+	VALUE handler = rb_hash_lookup(rb_ivar_get(parser->resolver, id_tags_ivar), tag);
+	if (rb_vm_respond_to(handler, sel_call, 0))
 	{
-		printf("Currently at index %d out of size %d\n", parser->stack_index, parser->stack_size);
-		parser->stack_size *= 2;
-		GC_WB(&parser->stack, xrealloc2(parser->stack, parser->stack_size, sizeof(VALUE)));
-		printf("Reallocated to size %d\n", parser->stack_size);
+		return rb_vm_call_with_cache(call_cache, handler, sel_call, 1, &result);
 	}
-	parser->stack[parser->stack_index] = val;
+	else if (rb_vm_respond_to(handler, sel_yaml_new, 0))
+	{
+		return rb_vm_call_with_cache(yaml_new_cache, handler, sel_yaml_new, 1, &result);
+	}
+	return result;
 }
 
-static VALUE rb_yaml_get_and_interpret_scalar(rb_yaml_parser_t *parser) __attribute__ ((noinline));
-
 static VALUE 
-rb_yaml_get_and_interpret_scalar(rb_yaml_parser_t *parser)
+handle_scalar(rb_yaml_parser_t *parser)
 {
 	char *val = (char*)parser->event.data.scalar.value;
 	char *tag = (char*)parser->event.data.scalar.tag;
@@ -256,125 +269,99 @@
 		tag = "tag:yaml.org,2002:str";
 	}
 	VALUE scalarval = rb_str_new(val, parser->event.data.scalar.length);
-	VALUE tags = rb_ivar_get(parser->resolver, id_tags_ivar);
-	VALUE handler = rb_hash_lookup(tags, rb_str_new2(tag));
-	if (rb_respond_to(handler, rb_intern("call")))
+	return interpret_value(parser, scalarval, rb_str_new2(tag));
+}
+
+static VALUE handle_sequence(rb_yaml_parser_t *parser)
+{
+	VALUE node;
+	VALUE tag = (parser->event.data.sequence_start.tag == NULL) ? Qnil :
+					rb_str_new2(parser->event.data.sequence_start.tag);
+	VALUE arr = rb_ary_new();
+	while(node = get_node(parser))
 	{
-		return rb_funcall(handler, rb_intern("call"), 1, scalarval);
+		rb_ary_push(arr, node);
 	}
-	else if (rb_respond_to(handler, rb_intern("yaml_new")))
-	{
-		return rb_funcall(handler, rb_intern("yaml_new"), 1, scalarval);
-	}
-	return scalarval;
+	return interpret_value(parser, arr, tag);
 }
 
-
-static bool
-yaml_next_event(rb_yaml_parser_t *parser)
+static VALUE handle_mapping(rb_yaml_parser_t *parser)
 {
-	if (parser->event_valid)
+	VALUE key_node, value_node;
+	VALUE tag = (parser->event.data.mapping_start.tag == NULL) ? Qnil :
+					rb_str_new2(parser->event.data.mapping_start.tag);
+	VALUE hash = rb_hash_new();
+	while(key_node = get_node(parser))
 	{
-		yaml_event_delete(&parser->event);
-		parser->event_valid = false;
+		value_node = get_node(parser);
+		rb_hash_aset(hash, key_node, value_node);
 	}
-	if (yaml_parser_parse(parser->parser, &parser->event) == -1)
-	{
-		rb_exc_raise(rb_yaml_parser_generate_error(parser->parser));
-		parser->event_valid = false;
-	} else
-	{
-		parser->event_valid = true;
-	}
-	return parser->event_valid;
+	return interpret_value(parser, hash, tag);
 }
 
-#define NEXT_EVENT() yaml_next_event(parser)
-#define CURRENT_ITEM(p) p->stack[p->stack_index]
-
-static VALUE
-rb_yaml_parser_slurp(rb_yaml_parser_t *parser)
+static VALUE get_node(rb_yaml_parser_t *parser)
 {
-	int current_depth = parser->stack_index;
+	VALUE node;
 	NEXT_EVENT();
-	switch(parser->event.type)
-	{
-		case YAML_MAPPING_START_EVENT:;
-		push(parser, rb_hash_new());
-		assert(current_depth+1 == parser->stack_index);
-		for(;;)
-		{
-			VALUE key = rb_yaml_parser_slurp(parser);
-			if(parser->event.type == YAML_MAPPING_END_EVENT)
-			{
-				parser->stack_index--;
-				break;
-			}
-			VALUE val = rb_yaml_parser_slurp(parser);
-			assert(TYPE(CURRENT_ITEM(parser)) == T_HASH);
-			rb_hash_aset(CURRENT_ITEM(parser), key, val);
-		}
+	
+	switch(parser->event.type) {
+		case YAML_DOCUMENT_END_EVENT:
+		case YAML_MAPPING_END_EVENT:
+		case YAML_SEQUENCE_END_EVENT:
+		case YAML_STREAM_END_EVENT:
+		return 0ull;
 		
+		case YAML_MAPPING_START_EVENT:
+		node = handle_mapping(parser);
 		break;
-
+		
 		case YAML_SEQUENCE_START_EVENT:
-		push(parser, rb_ary_new());
-		assert(current_depth+1 == parser->stack_index);
-		for(;;)
-		{
-			VALUE item = rb_yaml_parser_slurp(parser);
-			if(parser->event.type == YAML_SEQUENCE_END_EVENT) 
-			{
-				parser->stack_index--;
-				break;
-			}
-			assert(TYPE(parser->stack[parser->stack_index]) == T_ARRAY);
-			rb_ary_push(parser->stack[parser->stack_index], item);
-		}
+		node = handle_sequence(parser);
 		break;
-
+		
 		case YAML_SCALAR_EVENT:
-		push(parser, rb_yaml_get_and_interpret_scalar(parser));
-		assert(current_depth+1 == parser->stack_index);
-		parser->stack_index--;
+		node = handle_scalar(parser);
 		break;
-
-		case YAML_ALIAS_EVENT:
-		printf("oh god an alias i don't even know how to do this\n");
-		break;
-			
-		case YAML_MAPPING_END_EVENT:
-		case YAML_SEQUENCE_END_EVENT:
-		return Qnil;
-		break;
-
-		case YAML_STREAM_END_EVENT:
-		case YAML_DOCUMENT_END_EVENT:
-		break;
 		
 		default:
-		break;
-		
+		rb_raise(rb_eArgError, "Invalid event %d at top level", (int)parser->event.type);
 	}
-	return parser->stack[parser->stack_index+1];
+	return node;
 }
 
+
 static VALUE
 rb_yaml_parser_load(VALUE self, SEL sel)
 {
 	rb_yaml_parser_t *parser = RYAMLParser(self);
+	VALUE root;
 	NEXT_EVENT();
-	if(parser->event.type != YAML_STREAM_START_EVENT)
+	if (parser->event.type != YAML_STREAM_START_EVENT)
 	{
 		rb_raise(rb_eRuntimeError, "expected STREAM_START event");
 	}
+	
 	NEXT_EVENT();
-	if(parser->event.type != YAML_DOCUMENT_START_EVENT)
+	if (parser->event.type != YAML_DOCUMENT_START_EVENT)
 	{
 		rb_raise(rb_eRuntimeError, "expected DOCUMENT_START event");
 	}
+
+	root = (get_node(parser) || Qnil);
+
+	NEXT_EVENT();
+	if (parser->event.type != YAML_DOCUMENT_END_EVENT)
+	{
+		rb_raise(rb_eRuntimeError, "expected DOCUMENT_END event");
+	}
 	
-	return rb_yaml_parser_slurp(parser);
+	NEXT_EVENT();
+	if (parser->event.type != YAML_STREAM_END_EVENT)
+	{
+		rb_raise(rb_eRuntimeError, "expected STREAM_END event");
+	}
+	
+	return root;
 }
 
 static IMP rb_yaml_parser_finalize_super = NULL; 
@@ -389,10 +376,6 @@
 		yaml_parser_delete(rbparser->parser);
 		rbparser->parser = NULL;
 	}
-	if((rbparser != NULL) && (rbparser->stack != NULL))
-	{
-		rbparser->stack = NULL;
-	}
 	if (rb_yaml_parser_finalize_super != NULL)
 	{
 		((void(*)(void *, SEL))rb_yaml_parser_finalize_super)(rcv, sel);
@@ -539,12 +522,12 @@
 	if(NIL_P(impl_beg)) { impl_beg = Qfalse; }
 	if(NIL_P(impl_end)) { impl_end = Qtrue; }
 	
-	yaml_document_start_event_initialize(&ev, NULL, NULL, NULL, RTEST(impl_beg));
+	yaml_document_start_event_initialize(&ev, NULL, NULL, NULL, 0);
 	yaml_emitter_emit(emitter, &ev);
 	
 	rb_yield(self);
 	
-	yaml_document_end_event_initialize(&ev, RTEST(impl_end));
+	yaml_document_end_event_initialize(&ev, 1);
 	yaml_emitter_emit(emitter, &ev);
 	yaml_emitter_flush(emitter);
 	return self;
@@ -632,7 +615,12 @@
 	id_tags_ivar = rb_intern("@tags");
 	
 	sel_to_yaml = sel_registerName("to_yaml:");
+	sel_call = sel_registerName("call:");
+	sel_yaml_new = sel_registerName("yaml_new:");
+	
 	to_yaml_cache = rb_vm_get_call_cache(sel_to_yaml);
+	call_cache = rb_vm_get_call_cache(sel_call);
+	yaml_new_cache = rb_vm_get_call_cache(sel_yaml_new);
 	
 	rb_mYAML = rb_define_module("YAML");
 	
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090805/86b5b897/attachment-0001.html>


More information about the macruby-changes mailing list