2
0
Эх сурвалжийг харах

implemented make_var_args

Nicolas Cannasse 9 жил өмнө
parent
commit
8884e70111
1 өөрчлөгдсөн 53 нэмэгдсэн , 31 устгасан
  1. 53 31
      src/std/fun.c

+ 53 - 31
src/std/fun.c

@@ -31,11 +31,6 @@ vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v ) {
 	return c;
 	return c;
 }
 }
 
 
-HL_PRIM vdynamic *hl_make_var_args( vclosure *c ) {
-	hl_fatal("TODO");
-	return NULL;
-}
-
 HL_PRIM vdynamic *hl_no_closure( vdynamic *c ) {
 HL_PRIM vdynamic *hl_no_closure( vdynamic *c ) {
 	vclosure *cl = (vclosure*)c;
 	vclosure *cl = (vclosure*)c;
 	if( !cl->hasValue ) return c;
 	if( !cl->hasValue ) return c;
@@ -137,6 +132,10 @@ HL_PRIM vdynamic* hl_call_method( vdynamic *c, varray *args ) {
 	return dret;
 	return dret;
 }
 }
 
 
+static void fun_var_args() {
+	hl_fatal("assert");
+}
+
 void *hl_wrapper_call( void *_c, void **args, vdynamic *ret ) {
 void *hl_wrapper_call( void *_c, void **args, vdynamic *ret ) {
 	vclosure_wrapper *c = (vclosure_wrapper*)_c;
 	vclosure_wrapper *c = (vclosure_wrapper*)_c;
 	union { double d; int i; float f; } tmp[HL_MAX_ARGS];
 	union { double d; int i; float f; } tmp[HL_MAX_ARGS];
@@ -148,32 +147,46 @@ void *hl_wrapper_call( void *_c, void **args, vdynamic *ret ) {
 	void *pret, *aret;
 	void *pret, *aret;
 	if( ret == NULL )
 	if( ret == NULL )
 		ret = &out;
 		ret = &out;
-	if( w->hasValue )
-		vargs[p++] = (vdynamic*)w->value;
-	for(i=0;i<w->t->fun->nargs;i++) {
-		hl_type *t = c->t->fun->args[i];
-		hl_type *to = w->t->fun->args[i];
-		void *v = hl_is_ptr(t) ? args + i : args[i];
-		switch( to->kind ) {
-		case HI8:
-		case HI16:
-		case HI32:
-			tmp[i].i = hl_dyn_casti(v,t,to);
-			v = &tmp[i].i;
-			break;
-		case HF32:
-			tmp[i].f = hl_dyn_castf(v,t);
-			v = &tmp[i].f;
-			break;
-		case HF64:
-			tmp[i].d = hl_dyn_castd(v,t);
-			v = &tmp[i].d;
-			break;
-		default:
-			v = hl_dyn_castp(v,t,to);
-			break;
+	if( w->fun == fun_var_args ) {
+		varray *a;
+		w = (vclosure*)w->value; // the real callback
+		a = hl_aalloc(&hlt_dyn,c->t->fun->nargs);
+		for(i=0;i<c->t->fun->nargs;i++) {
+			hl_type *t = c->t->fun->args[i];
+			void *v = hl_is_ptr(t) ? args + i : args[i];
+			*(void**)(a + 1) = hl_make_dyn(v,t);
+		}
+		if( w->hasValue )
+			vargs[p++] = (vdynamic*)w->value;
+		vargs[p++] = (vdynamic*)a;
+	} else {
+		if( w->hasValue )
+			vargs[p++] = (vdynamic*)w->value;
+		for(i=0;i<w->t->fun->nargs;i++) {
+			hl_type *t = c->t->fun->args[i];
+			hl_type *to = w->t->fun->args[i];
+			void *v = hl_is_ptr(t) ? args + i : args[i];
+			switch( to->kind ) {
+			case HI8:
+			case HI16:
+			case HI32:
+				tmp[i].i = hl_dyn_casti(v,t,to);
+				v = &tmp[i].i;
+				break;
+			case HF32:
+				tmp[i].f = hl_dyn_castf(v,t);
+				v = &tmp[i].f;
+				break;
+			case HF64:
+				tmp[i].d = hl_dyn_castd(v,t);
+				v = &tmp[i].d;
+				break;
+			default:
+				v = hl_dyn_castp(v,t,to);
+				break;
+			}
+			vargs[p++] = v;
 		}
 		}
-		vargs[p++] = v;
 	}
 	}
 	pret = hlc_static_call(w->fun,w->hasValue ? w->t->fun->parent : w->t,vargs,ret);
 	pret = hlc_static_call(w->fun,w->hasValue ? w->t->fun->parent : w->t,vargs,ret);
 	aret = hl_is_ptr(w->t->fun->ret) ? &pret : pret;
 	aret = hl_is_ptr(w->t->fun->ret) ? &pret : pret;
@@ -200,7 +213,7 @@ vclosure *hl_make_fun_wrapper( vclosure *v, hl_type *to ) {
 	vclosure_wrapper *c;
 	vclosure_wrapper *c;
 	void *wrap = hlc_get_wrapper(to);
 	void *wrap = hlc_get_wrapper(to);
 	if( wrap == NULL ) return NULL;
 	if( wrap == NULL ) return NULL;
-	if( v->t->fun->nargs != to->fun->nargs )
+	if( v->fun != fun_var_args && v->t->fun->nargs != to->fun->nargs )
 		return NULL;
 		return NULL;
 	c = (vclosure_wrapper*)hl_gc_alloc(sizeof(vclosure_wrapper));
 	c = (vclosure_wrapper*)hl_gc_alloc(sizeof(vclosure_wrapper));
 	c->t = to;
 	c->t = to;
@@ -210,3 +223,12 @@ vclosure *hl_make_fun_wrapper( vclosure *v, hl_type *to ) {
 	c->wrappedFun = v; 
 	c->wrappedFun = v; 
 	return (vclosure*)c;
 	return (vclosure*)c;
 }
 }
+
+static hl_type hlt_var_args = { HFUN };
+static hl_type_fun hlt_var_fun = { NULL, &hlt_void, -1, &hlt_var_args, { HFUN, NULL }, { NULL, &hlt_void, -1, &hlt_var_args} };
+
+HL_PRIM vdynamic *hl_make_var_args( vclosure *c ) {
+	hlt_var_args.fun = &hlt_var_fun;
+	hlt_var_fun.closure_type.p = &hlt_var_fun;
+	return (vdynamic*)hl_alloc_closure_ptr(&hlt_var_args,fun_var_args,c);
+}