Преглед изворни кода

entirely reviewed dynamic calls and function wrappers

Nicolas Cannasse пре 9 година
родитељ
комит
c8b35a8596
3 измењених фајлова са 151 додато и 183 уклоњено
  1. 8 2
      src/hl.h
  2. 0 121
      src/std/cast.c
  3. 143 60
      src/std/fun.c

+ 8 - 2
src/hl.h

@@ -308,13 +308,18 @@ typedef struct {
 	int __pad; // force align on 16 bytes for double
 } varray;
 
-typedef struct {
+typedef struct _vclosure {
 	hl_type *t;
 	void *fun;
 	int hasValue;
 	void *value;
 } vclosure;
 
+typedef struct {
+	struct _vclosure;
+	vclosure *wrappedFun;
+} vclosure_wrapper;
+
 typedef struct {
 	hl_type *t;
 	int hashed_name;
@@ -415,7 +420,8 @@ void hl_dyn_setd( vdynamic *d, int hfield, double v );
 
 vclosure *hl_alloc_closure_void( hl_type *t, void *fvalue );
 vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *ptr );
-vclosure *hl_alloc_closure_wrapper( hl_type *t, void *fvalue, void *ptr );
+vclosure *hl_make_fun_wrapper( vclosure *c, hl_type *to );
+void *hl_wrapper_call( void *value, void **args, vdynamic *ret );
 
 // ----------------------- ALLOC --------------------------------------------------
 

+ 0 - 121
src/std/cast.c

@@ -89,127 +89,6 @@ int hl_dyn_casti( void *data, hl_type *t, hl_type *to ) {
 	return 0;
 }
 
-
-#define HL_MAX_ARGS 7
-
-void *hlc_dyn_call( void *fun, hl_type *t, vdynamic **args );
-
-static void *hl_wrap0( vclosure *c ) {
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,(vdynamic**)&c->value) : hlc_dyn_call(c->fun,c->t,NULL);
-}
-
-static void *hl_wrap1( vclosure *c, vdynamic *p1 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap2( vclosure *c, vdynamic *p1, vdynamic *p2 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap3( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap4( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap5( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap6( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5, vdynamic *p6 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5, p6 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static void *hl_wrap7( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5, vdynamic *p6, vdynamic *p7 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5, p6, p7 };
-	return c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args + 1);
-}
-
-static int hl_wrap0i( vclosure *c ) {
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,(vdynamic**)&c->value) : hlc_dyn_call(c->fun,c->t,NULL);
-	return hl_dyn_casti(&v,c->t->fun->ret,&hlt_i32);
-}
-
-static int hl_wrap1i( vclosure *c, vdynamic *p1 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap2i( vclosure *c, vdynamic *p1, vdynamic *p2 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap3i( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap4i( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap5i( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap6i( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5, vdynamic *p6 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5, p6 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-static int hl_wrap7i( vclosure *c, vdynamic *p1, vdynamic *p2, vdynamic *p3, vdynamic *p4, vdynamic *p5, vdynamic *p6, vdynamic *p7 ) {
-	vdynamic *args[] = { (vdynamic*)c->value, p1, p2, p3, p4, p5, p6, p7 };
-	void *v = c->hasValue ? hlc_dyn_call(c->fun,c->t->fun->parent,args) : hlc_dyn_call(c->fun,c->t,args+1);
-	return hl_dyn_casti(&v,&hlt_dyn,c->t->fun->ret);
-}
-
-vclosure *hl_make_fun_wrapper( vclosure *c, hl_type *to ) {
-	static void *fptr_p[HL_MAX_ARGS+1] = { hl_wrap0, hl_wrap1, hl_wrap2, hl_wrap3, hl_wrap4, hl_wrap5, hl_wrap6, hl_wrap7 };
-	static void *fptr_i[HL_MAX_ARGS+1] = { hl_wrap0i, hl_wrap1i, hl_wrap2i, hl_wrap3i, hl_wrap4i, hl_wrap5i, hl_wrap6i, hl_wrap7i };
-	hl_type_fun *ct = c->t->fun;
-	int i;
-	if( ct->nargs != to->fun->nargs )
-		return NULL;
-	for(i=0;i<to->fun->nargs;i++)
-		if( !hl_is_ptr(to->fun->args[i]) )
-			return NULL;
-	if( to->fun->nargs > HL_MAX_ARGS )
-		return NULL;
-	if( hl_is_ptr(to->fun->ret) )
-		return hl_alloc_closure_wrapper(to,fptr_p[to->fun->nargs],c);
-	switch( to->fun->ret->kind ) {
-	case HI8:
-	case HI16:
-	case HI32:
-	case HBOOL:
-		return hl_alloc_closure_wrapper(to,fptr_i[to->fun->nargs],c);
-	case HF64:
-		hl_fatal("TODO");
-	case HF32:
-		hl_fatal("TODO");
-	default:
-		break;
-	}
-	return NULL;
-}
-
 void *hl_dyn_castp( void *data, hl_type *t, hl_type *to ) {
 	if( t->kind == HDYN ) {
 		vdynamic *v = *(vdynamic**)data;

+ 143 - 60
src/std/fun.c

@@ -31,15 +31,6 @@ vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v ) {
 	return c;
 }
 
-vclosure *hl_alloc_closure_wrapper( hl_type *t, void *fvalue, void *v ) {
-	vclosure *c = (vclosure*)hl_gc_alloc(sizeof(vclosure));
-	c->t = t;
-	c->fun = fvalue;
-	c->hasValue = 2;
-	c->value = v;
-	return c;
-}
-
 HL_PRIM vdynamic *hl_make_var_args( vclosure *c ) {
 	hl_fatal("TODO");
 	return NULL;
@@ -48,82 +39,174 @@ HL_PRIM vdynamic *hl_make_var_args( vclosure *c ) {
 HL_PRIM vdynamic *hl_no_closure( vdynamic *c ) {
 	vclosure *cl = (vclosure*)c;
 	if( !cl->hasValue ) return c;
-	if( cl->hasValue == 2 ) hl_fatal("TODO"); // wrapper
+	if( cl->hasValue == 2 )
+		return hl_no_closure((vdynamic*)((vclosure_wrapper*)c)->wrappedFun);
 	return (vdynamic*)hl_alloc_closure_void(cl->t->fun->parent,cl->fun);
 }
 
 HL_PRIM vdynamic* hl_get_closure_value( vdynamic *c ) {
 	vclosure *cl = (vclosure*)c;
 	if( cl->hasValue == 2 )
-		return hl_get_closure_value((vdynamic*)cl->value);
+		return hl_get_closure_value((vdynamic*)((vclosure_wrapper*)c)->wrappedFun);
 	return (vdynamic*)cl->value;
 }
 
-void *hlc_dyn_call( void *fun, hl_type *t, vdynamic **args );
+bool hl_fun_compare( vdynamic *a, vdynamic *b ) {
+	vclosure *ca, *cb;
+	if( a == b )
+		return true;
+	if( !a || !b )
+		return false;
+	if( a->t->kind != b->t->kind || a->t->kind != HFUN )
+		return false;
+	ca = (vclosure*)a;
+	cb = (vclosure*)b;
+	if( ca->fun != cb->fun )
+		return false;
+	if( ca->hasValue && ca->value != cb->value )
+		return false;
+	return true;
+}
+
+
+// ------------ DYNAMIC CALLS
+
+extern void *hlc_static_call( void *fun, hl_type *t, void **args, vdynamic *out );
+extern void *hlc_get_wrapper( hl_type *t );
+
+#define HL_MAX_ARGS 5
 
 HL_PRIM vdynamic* hl_call_method( vdynamic *c, varray *args ) {
 	vclosure *cl = (vclosure*)c;
-	int i;
 	vdynamic **vargs = (vdynamic**)(args + 1);
+	void *pargs[HL_MAX_ARGS];
 	void *ret;
+	union { double d; int i; float f; } tmp[HL_MAX_ARGS];
 	hl_type *tret;
-	vdynamic *tmp;
+	vdynamic *dret;
+	vdynamic out;
+	int i;
 	if( cl->hasValue ) hl_error("Can't call closure with value");
-	if( args->size != cl->t->fun->nargs || args->at->kind != HDYN ) hl_error("Invalid args");
+	if( args->size != cl->t->fun->nargs || args->at->kind != HDYN )
+		hl_error("Invalid args");
 	for(i=0;i<args->size;i++) {
 		vdynamic *v = vargs[i];
 		hl_type *t = cl->t->fun->args[i];
+		void *p;
 		if( v == NULL ) {
 			if( hl_is_ptr(t) )
-				continue;
-			v = hl_alloc_dynamic(t);
-			v->v.d = 0;
-			vargs[i] = v;
-		} else if( hl_is_ptr(t) )
-			vargs[i] = (vdynamic*)hl_dyn_castp(vargs + i,&hlt_dyn,t);
-		else {
-			vdynamic *v = hl_alloc_dynamic(t);
-			switch( t->kind ) {
-			case HBOOL:
-			case HI8:
-			case HI16:
-			case HI32:
-				v->v.i = hl_dyn_casti(vargs +i, &hlt_dyn,t);
-				break;
-			case HF32:
-				v->v.f = hl_dyn_castf(vargs +i, &hlt_dyn);
-				break;
-			case HF64:
-				v->v.d = hl_dyn_castd(vargs +i, &hlt_dyn);
-				break;
-			default:
-				hl_fatal("assert");
+				p = NULL;
+			else {
+				tmp[i].d = 0;
+				p = &tmp[i].d;
 			}
-			vargs[i] = v;
+		} else switch( t->kind ) {
+		case HBOOL:
+		case HI8:
+		case HI16:
+		case HI32:
+			tmp[i].i = hl_dyn_casti(vargs +i, &hlt_dyn,t);
+			p = &tmp[i].i;
+			break;
+		case HF32:
+			tmp[i].f = hl_dyn_castf(vargs +i, &hlt_dyn);
+			p = &tmp[i].f;
+			break;
+		case HF64:
+			tmp[i].d = hl_dyn_castd(vargs +i, &hlt_dyn);
+			p = &tmp[i].d;
+			break;
+		default:
+			p = hl_dyn_castp(vargs + i,&hlt_dyn,t);
+			break;
 		}
+		pargs[i] = p;
 	}
-	ret = hlc_dyn_call(cl->fun,cl->t,vargs);
+	ret = hlc_static_call(cl->fun,cl->t,pargs,&out);
 	tret = cl->t->fun->ret;
-	if( ret == NULL || !hl_is_ptr(tret) || hl_is_dynamic(tret) )
+	if( !hl_is_ptr(tret) ) {
+		vdynamic *r = hl_alloc_dynamic(tret);
+		r->t = tret;
+		r->v.d = out.v.d; // copy
+		return r;
+	}
+	if( ret == NULL || hl_is_dynamic(tret) )
 		return (vdynamic*)ret;
-	tmp = hl_alloc_dynamic(tret);
-	tmp->v.ptr = ret;
-	return tmp;
+	dret = hl_alloc_dynamic(tret);
+	dret->v.ptr = ret;
+	return dret;
 }
 
-bool hl_fun_compare( vdynamic *a, vdynamic *b ) {
-	vclosure *ca, *cb;
-	if( a == b )
-		return true;
-	if( !a || !b )
-		return false;
-	if( a->t->kind != b->t->kind || a->t->kind != HFUN )
-		return false;
-	ca = (vclosure*)a;
-	cb = (vclosure*)b;
-	if( ca->fun != cb->fun )
-		return false;
-	if( ca->hasValue && ca->value != cb->value )
-		return false;
-	return true;
-}
+void *hl_wrapper_call( void *_c, void **args, vdynamic *ret ) {
+	vclosure_wrapper *c = (vclosure_wrapper*)_c;
+	union { double d; int i; float f; } tmp[HL_MAX_ARGS];
+	void *vargs[HL_MAX_ARGS+1];
+	vdynamic out;
+	vclosure *w = c->wrappedFun;
+	int i;
+	int p = 0;
+	void *pret, *aret;
+	if( ret == NULL )
+		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;
+		}
+		vargs[p++] = v;
+	}
+	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;
+	switch( c->t->fun->ret->kind ) {
+	case HI8:
+	case HI16:
+	case HI32:
+		ret->v.i = hl_dyn_casti(aret,w->t->fun->ret,c->t->fun->ret);
+		break;
+	case HF32:
+		ret->v.f = hl_dyn_castf(aret,w->t->fun->ret);
+		break;
+	case HF64:
+		ret->v.d = hl_dyn_castd(aret,w->t->fun->ret);
+		break;
+	default:
+		pret = hl_dyn_castp(aret,w->t->fun->ret,c->t->fun->ret);
+		break;
+	}
+	return pret;
+}
+
+vclosure *hl_make_fun_wrapper( vclosure *v, hl_type *to ) {
+	vclosure_wrapper *c;
+	void *wrap = hlc_get_wrapper(to);
+	if( wrap == NULL ) return NULL;
+	if( v->t->fun->nargs != to->fun->nargs )
+		return NULL;
+	c = (vclosure_wrapper*)hl_gc_alloc(sizeof(vclosure_wrapper));
+	c->t = to;
+	c->fun = wrap;
+	c->hasValue = 2;
+	c->value = c;
+	c->wrappedFun = v; 
+	return (vclosure*)c;
+}