Prechádzať zdrojové kódy

work on virtuals, TestMisc passing

Nicolas Cannasse 9 rokov pred
rodič
commit
7f6de7e066
8 zmenil súbory, kde vykonal 286 pridanie a 49 odobranie
  1. 5 2
      src/hl.h
  2. 31 0
      src/hlc.h
  3. 19 1
      src/std/buffer.c
  4. 15 2
      src/std/cast.c
  5. 52 9
      src/std/date.c
  6. 129 34
      src/std/obj.c
  7. 7 0
      src/std/sys.c
  8. 28 1
      src/std/types.c

+ 5 - 2
src/hl.h

@@ -229,7 +229,7 @@ typedef struct {
 #	ifdef HL_64
 	int __pad;
 #	endif
-	hl_obj_field *fields; 
+	hl_obj_field *fields;
 } hl_type_virtual;
 
 typedef struct {
@@ -356,6 +356,7 @@ typedef struct _venum {
 
 extern hl_type hlt_void;
 extern hl_type hlt_i32;
+extern hl_type hlt_f64;
 extern hl_type hlt_dyn;
 extern hl_type hlt_array;
 extern hl_type hlt_bytes;
@@ -386,7 +387,8 @@ void hl_throw( vdynamic *v );
 void hl_rethrow( vdynamic *v );
 
 vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj );
-void *hl_fetch_virtual_method( vvirtual *v, int fid );
+void hl_init_virtual( hl_type *vt, hl_module_context *ctx );
+hl_field_lookup *hl_lookup_find( hl_field_lookup *l, int size, int hash );
 
 int hl_dyn_geti( vdynamic *d, int hfield, hl_type *t );
 void *hl_dyn_getp( vdynamic *d, int hfield, hl_type *t );
@@ -400,6 +402,7 @@ double hl_dyn_castd( void *data, hl_type *t );
 
 #define hl_invalid_comparison 0xAABBCCDD
 int hl_dyn_compare( vdynamic *a, vdynamic *b );
+vdynamic *hl_make_dyn( void *data, hl_type *t );
 
 void hl_dyn_seti( vdynamic *d, int hfield, hl_type *t, int value );
 void hl_dyn_setp( vdynamic *d, int hfield, hl_type *t, void *ptr );

+ 31 - 0
src/hlc.h

@@ -48,6 +48,37 @@ static vdynamic *hl_oalloc( hl_type *t ) {
 	return (vdynamic*)hl_alloc_obj(t);
 }
 
+extern vdynamic *hl_call_method( vdynamic *c, varray *args );
+
+#define HLC_DYN_MAX_ARGS 9
+static vdynamic *hlc_dyn_call_args( vclosure *c, vdynamic **args, int nargs ) {
+	struct {
+		varray a;
+		vdynamic *args[HLC_DYN_MAX_ARGS+1];
+	} tmp;
+	vclosure ctmp;
+	int i = 0;
+	if( nargs > HLC_DYN_MAX_ARGS ) hl_error("Too many arguments");
+	tmp.a.t = &hlt_array;
+	tmp.a.at = &hlt_dyn;
+	tmp.a.size = nargs;
+	if( c->hasValue ) {
+		if( c->hasValue == 2 ) hl_error("TODO");
+		ctmp.t = c->t->fun->parent;
+		ctmp.hasValue = 0;
+		ctmp.fun = c->fun;
+		c = &ctmp;
+		tmp.args[0] = hl_make_dyn(&c->value,ctmp.t->fun->args[0]);
+		tmp.a.size++;
+		for(i=0;i<nargs;i++)
+			tmp.args[i+1] = args[i];
+	} else {
+		for(i=0;i<nargs;i++)
+			tmp.args[i] = args[i];
+	}
+	return hl_call_method((vdynamic*)c,&tmp.a);
+}
+
 #include <setjmp.h>
 
 typedef struct _hl_trap_ctx hl_trap_ctx;

+ 19 - 1
src/std/buffer.c

@@ -113,11 +113,20 @@ static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack );
 static void hl_buffer_addr( hl_buffer *b, void *data, hl_type *t, vlist *stack ) {
 	uchar buf[32];
 	switch( t->kind ) {
+	case HI8:
+		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),*(char*)data));
+		break;
+	case HI16:
+		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),*(short*)data));
+		break;
 	case HI32:
 		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),*(int*)data));
 		break;
+	case HF32:
+		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.16f"),*(float*)data));
+		break;
 	case HF64:
-		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),*(double*)data));
+		hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.19g"),*(double*)data));
 		break;
 	case HBYTES:
 		hl_buffer_str(b,*(uchar**)data);
@@ -224,6 +233,7 @@ static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack ) {
 			int i;
 			vlist l;
 			vlist *vtmp = stack;
+			hl_field_lookup *f;
 			while( vtmp != NULL ) {
 				if( vtmp->v == v ) {
 					hl_buffer_str_sub(b,USTR("..."),3);
@@ -233,6 +243,14 @@ static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack ) {
 			}
 			l.v = v;
 			l.next = stack;
+			f = hl_lookup_find(&o->dproto->fields,o->nfields,hl_hash_gen(USTR("__string"),false));
+			if( f && f->t->kind == HFUN && f->t->fun->nargs == 0 && f->t->fun->ret->kind == HBYTES ) {
+				vclosure *v = *(vclosure**)(o->fields_data + f->field_index);
+				if( v ) {
+					hl_buffer_str(b, v->hasValue ? ((uchar*(*)(void*))v->fun)(v->value) : ((uchar*(*)())v->fun)());
+					break;
+				}
+			}
 			hl_buffer_char(b, '{');
 			for(i=0;i<o->nfields;i++) {
 				hl_field_lookup *f = &o->dproto->fields + i;

+ 15 - 2
src/std/cast.c

@@ -64,6 +64,10 @@ int hl_dyn_casti( void *data, hl_type *t, hl_type *to ) {
 		return *(short*)data;
 	case TK2(HI32,HI32):
 		return *(int*)data;
+	case TK2(HF32,HI32):
+		return (int)*(float*)data;
+	case TK2(HF64,HI32):
+		return (int)*(double*)data;
 	case TK2(HBOOL,HBOOL):
 		return *(bool*)data;
 	default:
@@ -156,11 +160,20 @@ void *hl_dyn_castp( void *data, hl_type *t, hl_type *to ) {
 
 double hl_dyn_castd( void *data, hl_type *t ) {
 	switch( t->kind ) {
+	case HF32:
+		return *(float*)data;
+	case HI8:
+		return *(char*)data;
+	case HI16:
+		return *(short*)data;
+	case HI32:
+		return *(int*)data;
+	case HBOOL:
+		return *(bool*)data;
 	default:
-		hl_error_msg(USTR("Can't cast %s(%s) to double"),hl_to_string(hl_make_dyn(data,t)),hl_type_str(t));
 		break;
 	}
-	return 0;
+	return 0.;
 }
 
 static int fcompare( float d ) {

+ 52 - 9
src/std/date.c

@@ -1,20 +1,63 @@
 #include <hl.h>
+#include <time.h>
 
-HL_PRIM int hl_date_get_weekday( int date ) {
-	hl_fatal("TODO");
-	return 0;
+#ifdef HL_WIN
+
+static struct tm *localtime_r( time_t *t, struct tm *r ) {
+	struct tm *r2 = localtime(t);
+	if( r2 == NULL ) return NULL;
+	*r = *r2;
+	return r;
+}
+
+static struct tm *gmtime_r( time_t *t, struct tm *r ) {
+	struct tm *r2 = gmtime(t);
+	if( r2 == NULL ) return NULL;
+	*r = *r2;
+	return r;
 }
 
+#endif
+
 HL_PRIM vbyte *hl_date_to_string( int date, int *len ) {
-	hl_fatal("TODO");
-	return 0;
+	char buf[127];
+	struct tm t;
+	time_t d = (time_t)date;
+	int size;
+	uchar *out;
+	if( !localtime_r(&d,&t) )
+		hl_error("invalid date");
+	size = (int)strftime(buf,127,"%Y-%m-%d %H:%M:%S",&t);
+	out = (uchar*)hl_gc_alloc_noptr((size + 1) << 1);
+	strtou(out,size,buf);
+	out[size] = 0;
+	*len = size;
+	return (vbyte*)out;
 }
 
 HL_PRIM int hl_date_new( int y, int mo, int d, int h, int m, int s ) {
-	hl_fatal("TODO");
-	return 0;
+	struct tm t;
+	memset(&t,0,sizeof(struct tm));
+	t.tm_year = y - 1900;
+	t.tm_mon = mo;
+	t.tm_mday = d;
+	t.tm_hour = h;
+	t.tm_min = m;
+	t.tm_sec = s;
+	t.tm_isdst = -1;
+	return (int)mktime(&t);
 }
 
-HL_PRIM void hl_date_get_inf( int date, int *y, int *mo, int *d, int *h, int *m, int *s ) {
-	hl_fatal("TODO");
+HL_PRIM void hl_date_get_inf( int date, int *y, int *mo, int *day, int *h, int *m, int *s, int *wday ) {
+	struct tm t;
+	time_t d = (time_t)date;
+	if( !localtime_r(&d,&t) )
+		hl_error("invalid date");
+	if( y ) *y = t.tm_year + 1900;
+	if( mo ) *mo = t.tm_mon;
+	if( day ) *day = t.tm_mday;
+	if( h ) *h = t.tm_hour;
+	if( m ) *m = t.tm_min;
+	if( s ) *s = t.tm_sec;
+	if( wday ) *wday = t.tm_wday;
 }

+ 129 - 34
src/std/obj.c

@@ -17,7 +17,7 @@ static void hl_lookup_insert( hl_field_lookup *l, int size, int hash, hl_type *t
 	l[pos].t = t;
 }
 
-static hl_field_lookup *hl_lookup_find( hl_field_lookup *l, int size, int hash ) {
+hl_field_lookup *hl_lookup_find( hl_field_lookup *l, int size, int hash ) {
 	int min = 0;
 	int max = size;
 	while( min < max ) {
@@ -181,12 +181,25 @@ hl_runtime_obj *hl_get_obj_proto( hl_type *ot ) {
 	return t;
 }
 
+void hl_init_virtual( hl_type *vt, hl_module_context *ctx ) {
+	int i;
+	hl_field_lookup *l = (hl_field_lookup*)hl_malloc(&ctx->alloc,sizeof(hl_field_lookup)*vt->virt->nfields);
+	for(i=0;i<vt->virt->nfields;i++) {
+		hl_obj_field *f = vt->virt->fields + i;
+		hl_lookup_insert(l,i,f->hashed_name,f->t,i);
+	}
+	vt->vobj_proto = (void**)l;
+}
+
 /**
 	Allocate a virtual fields mapping to a given value.
 **/
 vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 	vvirtual *v;
 	if( obj == NULL ) return NULL;
+#ifdef _DEBUG
+	if( vt->vobj_proto == NULL ) hl_fatal("virtual not initialized");
+#endif
 	switch( obj->t->kind ) {
 	case HOBJ:
 		{ 
@@ -238,46 +251,24 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
 			v->value = obj;
 			for(i=0;i<vt->virt->nfields;i++) {
 				hl_field_lookup *f = hl_lookup_find(&o->dproto->fields,o->nfields,vt->virt->fields[i].hashed_name);
-				v->indexes[i] = f == NULL || f->t != vt->virt->fields[i].t ? 0 : f->field_index + sizeof(void*);
+				v->indexes[i] = f == NULL || !hl_same_type(f->t,vt->virt->fields[i].t) ? 0 : f->field_index + sizeof(void*);
 			}
 			// add it to the list
 			v->next = o->virtuals;
 			o->virtuals = v;
 		}
 		break;
+	case HVIRTUAL:
+		return hl_to_virtual(vt,((vvirtual*)obj)->value);
 	default:
 		hl_fatal_fmt("Don't know how to virtual %d",obj->t->kind);
 	}
 	return v;
 }
 
-/*
-void *hl_fetch_method( vvirtual *v, int fid ) {
-	hl_obj_field *f = v->t->virt->fields + fid;
-	switch( v->value->t->kind ) {
-	case HOBJ:
-		{
-			hl_type_obj *o = ((vobj*)v->value)->t->obj;
-			hl_module_context *m = o->m;
-			hl_runtime_obj *rt = o->rt;
-			while( rt ) {
-				hl_field_lookup *found = hl_lookup_find(rt->lookup,rt->nlookup,f->hashed_name);
-				if( found ) {
-					int fid;
-					if( found->field_index > 0 ) return NULL;
-					fid = rt->obj->proto[-found->field_index].findex;
-					return hl_alloc_closure_ptr(m->functions_types[fid], m->functions_ptrs[fid], o);
-				}
-				rt = rt->parent;
-			}
-		}
-		break;
-	}
-	return NULL;
-}*/
-
 #define B2(t1,t2) ((t1) + ((t2) * HLAST))
 #define fetch_i(data,src,dst) src == dst ? *(int*)(data) : hl_dyn_casti(data,src,dst)
+#define fetch_d(data,src) src->kind == HF64 ? *(double*)(data) : hl_dyn_castd(data,src)
 #define fetch_p(data,src,dst) src == dst ? *(void**)(data) : hl_dyn_castp(data,src,dst)
 
 static hl_field_lookup *hl_dyn_alloc_field( vdynobj *o, int hfield, hl_type *t ) {
@@ -304,16 +295,120 @@ static hl_field_lookup *hl_dyn_alloc_field( vdynobj *o, int hfield, hl_type *t )
 	memcpy(&proto->fields + (field_pos + 1),&o->dproto->fields + field_pos, (o->nfields - field_pos) * sizeof(hl_field_lookup));
 	o->nfields++;
 	o->dproto = proto;
+	// rebuild virtuals
+	{
+		vvirtual *v = o->virtuals;
+		while( v ) {
+			hl_field_lookup *vf = hl_lookup_find((hl_field_lookup*)v->t->vobj_proto,v->t->virt->nfields,hfield);
+			if( vf && hl_same_type(vf->t,t) )
+				v->indexes[vf->field_index] = f->field_index + sizeof(void*);
+			v->fields_data = newData - sizeof(void*);
+			v = v->next;
+		}
+	}
 	return f;
 }
 
+static void hl_dyn_change_field( vdynobj *o, hl_field_lookup *f, hl_type *t ) {
+	int i, index, total_size;
+	int size = hl_type_size(t);
+	int old_size = hl_type_size(f->t);
+	char *newData;
+	if( size <= old_size ) {
+		// don't remap, let's keep hole
+		f->t = t;
+	} else {
+		int wsize = 0;
+		index = hl_lookup_find_index(&o->dproto->fields,o->nfields,f->hashed_name);
+		total_size = f->field_index;
+		for(i=index+1;i<o->nfields;i++) {
+			hl_field_lookup *f = &o->dproto->fields + i;
+			int fsize = hl_type_size(f->t);
+			total_size += hl_pad_size(total_size,f->t);
+			memcpy(o->fields_data + total_size, o->fields_data + f->field_index, fsize);
+			f->field_index = total_size;
+			total_size += fsize;
+		}
+		wsize = total_size;
+		total_size += hl_pad_size(total_size,t);
+		f->field_index = total_size;
+		f->t = t;
+		total_size += size;
+		if( total_size > o->dataSize ) {
+			newData = (char*)hl_gc_alloc(total_size);
+			memcpy(newData,o->fields_data,wsize);
+			o->fields_data = newData;
+			o->dataSize = total_size;
+		}
+	}
+	// rebuild virtuals
+	{
+		vvirtual *v = o->virtuals;
+		while( v ) {
+			hl_field_lookup *vf = hl_lookup_find((hl_field_lookup*)v->t->vobj_proto,v->t->virt->nfields,f->hashed_name);
+			if( vf )
+				v->indexes[vf->field_index] = hl_same_type(vf->t,t) ? f->field_index + sizeof(void*) : 0;
+			v->fields_data = o->fields_data - sizeof(void*);
+			v = v->next;
+		}
+	}
+}
+
 double hl_dyn_getd( vdynamic *d, int hfield ) {
-	hl_fatal("TODO");
+	switch( d->t->kind ) {
+	case HDYNOBJ:
+		{
+			vdynobj *o = (vdynobj*)d;
+			hl_field_lookup *f = hl_lookup_find(&o->dproto->fields,o->nfields,hfield);
+			if( f == NULL ) return 0.;
+			return fetch_d(o->fields_data + f->field_index,f->t);
+		}
+		break;
+	case HOBJ:
+		{
+			hl_runtime_obj *rt = d->t->obj->rt;
+			hl_field_lookup *f = NULL;
+			do {
+				f = hl_lookup_find(rt->lookup,rt->nlookup,hfield);
+				if( f != NULL ) break;
+				rt = rt->parent;
+			} while( rt );
+			if( f == NULL ) return 0.;
+			return fetch_d((char*)d + f->field_index,f->t);
+		}
+		break;
+	case HVIRTUAL:
+		return hl_dyn_getd(((vvirtual*)d)->value, hfield);
+	default:
+		hl_error("Invalid field access");
+		break;
+	}
 	return 0.;
 }
 
-void hl_dyn_setd( vdynamic *d, int hfield, double v ) {
-	hl_fatal("TODO");
+void hl_dyn_setd( vdynamic *d, int hfield, double value ) {
+	if( d == NULL ) hl_error("Invalid field access");
+	switch( d->t->kind ) {
+	case HDYNOBJ:
+		{
+			vdynobj *o = (vdynobj*)d;
+			hl_field_lookup *f = hl_lookup_find(&o->dproto->fields,o->nfields,hfield);
+			if( f == NULL )
+				f = hl_dyn_alloc_field(o,hfield,&hlt_f64);
+			else if( f->t->kind != HF64 )
+				hl_dyn_change_field(o,f,&hlt_f64);
+			*(double*)(o->fields_data + f->field_index) = value;
+		}
+		break;
+	case HOBJ:
+		hl_error("TODO");
+		break;
+	case HVIRTUAL:
+		hl_dyn_setd(((vvirtual*)d)->value, hfield, value);
+		break;
+	default:
+		hl_error("Invalid field access");
+	}
 }
 
 int hl_dyn_geti( vdynamic *d, int hfield, hl_type *t ) {
@@ -392,8 +487,8 @@ void hl_dyn_seti( vdynamic *d, int hfield, hl_type *t, int value ) {
 			hl_field_lookup *f = hl_lookup_find(&o->dproto->fields,o->nfields,hfield);
 			if( f == NULL )
 				f = hl_dyn_alloc_field(o,hfield,t);
-			else if( f->t != t )
-				hl_error("Invalid dynset cast");
+			else if( f->t->kind != t->kind )
+				hl_dyn_change_field(o,f,t);
 			switch( t->kind ) {
 			case HI8:
 			case HBOOL:
@@ -428,8 +523,8 @@ void hl_dyn_setp( vdynamic *d, int hfield, hl_type *t, void *value ) {
 			hl_field_lookup *f = hl_lookup_find(&o->dproto->fields,o->nfields,hfield);
 			if( f == NULL )
 				f = hl_dyn_alloc_field(o,hfield,t);
-			else if( f->t != t )
-				hl_error("Invalid dynset cast");
+			else if( !hl_same_type(f->t,t) )
+				hl_dyn_change_field(o,f,t);
 			*(void**)(o->fields_data + f->field_index) = value;
 		}
 		break;

+ 7 - 0
src/std/sys.c

@@ -10,6 +10,7 @@ HL_PRIM void hl_sys_exit( int code ) {
 
 #ifndef HL_JIT
 
+#include <hlc.h>
 #if defined(HL_VCC) && defined(_DEBUG)
 #	include <crtdbg.h>
 #else
@@ -19,9 +20,15 @@ HL_PRIM void hl_sys_exit( int code ) {
 extern void hl_entry_point();
 
 int main() {
+	hl_trap_ctx ctx;
+	vdynamic *exc;
 	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/ );
+	hlc_trap(ctx,exc,on_exception);
 	hl_entry_point();
 	return 0;
+on_exception:
+	uprintf(USTR("Uncaught exception: %s\n"),hl_to_string(exc));
+	return 1;
 }
 
 #endif

+ 28 - 1
src/std/types.c

@@ -5,6 +5,7 @@ hl_type hlt_bytes = { HBYTES };
 hl_type hlt_dynobj = { HDYNOBJ };
 hl_type hlt_dyn = { HDYN };
 hl_type hlt_i32 = { HI32 };
+hl_type hlt_f64 = { HF64 };
 hl_type hlt_void = { HVOID };
 
 static const uchar *TSTR[] = {
@@ -299,11 +300,37 @@ HL_PRIM vdynamic *hl_type_get_global( hl_type *t ) {
 }
 
 bool hl_type_enum_eq( vdynamic *a, vdynamic *b ) {
+	int i;
+	venum *ea, *eb;
+	hl_enum_construct *c;
 	if( a == b )
 		return true;
 	if( !a || !b || a->t != b->t || a->t->kind != HENUM )
 		return false;
-	hl_fatal("TODO");
+	ea = (venum*)a->v.ptr;
+	eb = (venum*)b->v.ptr;
+	if( ea->index != eb->index )
+		return false;
+	c = a->t->tenum->constructs + ea->index;
+	for(i=0;i<c->nparams;i++) {
+		hl_type *t = c->params[i];
+		switch( t->kind ) {
+		case HENUM:
+			{
+				vdynamic pa, pb;
+				pa.t = pb.t = t;
+				pa.v.ptr = *(void**)((char*)ea + c->offsets[i]);
+				pb.v.ptr = *(void**)((char*)eb + c->offsets[i]);
+				if( !hl_type_enum_eq(&pa,&pb) )
+					return false;
+			}
+			break;
+		default:
+			if( hl_dyn_compare(hl_make_dyn((char*)ea + c->offsets[i],t),hl_make_dyn((char*)eb + c->offsets[i],t)) )
+				return false;
+			break;
+		}
+	}
 	return true;
 }