mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Retabbed things
This commit is contained in:
		
							
								
								
									
										306
									
								
								dict.c
									
									
									
									
									
								
							
							
						
						
									
										306
									
								
								dict.c
									
									
									
									
									
								
							| @@ -11,25 +11,25 @@ | |||||||
| static GstValue *gst_object_bag_find(GstDict *obj, GstValue key) { | static GstValue *gst_object_bag_find(GstDict *obj, GstValue key) { | ||||||
|     GstValue *start = obj->data; |     GstValue *start = obj->data; | ||||||
|     GstValue *end = obj->data + obj->count * 2; |     GstValue *end = obj->data + obj->count * 2; | ||||||
| 	while (start < end) { |     while (start < end) { | ||||||
|     	if (gst_equals(*start, key)) |         if (gst_equals(*start, key)) | ||||||
|         	return start; |             return start; | ||||||
| 		start += 2; |         start += 2; | ||||||
| 	} |     } | ||||||
| 	return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Check for string equality */ | /* Check for string equality */ | ||||||
| static int str_equal_value(GstValue v, const char *str, uint32_t len, uint32_t hash) { | static int str_equal_value(GstValue v, const char *str, uint32_t len, uint32_t hash) { | ||||||
| 	uint32_t i; |     uint32_t i; | ||||||
|     if (v.type != GST_STRING) return 0; |     if (v.type != GST_STRING) return 0; | ||||||
| 	if (gst_string_length(str) != len) return 0; |     if (gst_string_length(str) != len) return 0; | ||||||
| 	if (!gst_string_hash(str)) |     if (!gst_string_hash(str)) | ||||||
| 		gst_string_hash(str) = gst_string_calchash((uint8_t *)str); |         gst_string_hash(str) = gst_string_calchash((uint8_t *)str); | ||||||
| 	if (gst_string_hash(str) != hash) return 0; |     if (gst_string_hash(str) != hash) return 0; | ||||||
| 	for (i = 0; i < len; ++i) |     for (i = 0; i < len; ++i) | ||||||
| 		if (str[1] != v.data.string[i]) return 0; |         if (str[1] != v.data.string[i]) return 0; | ||||||
| 	return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Find key value pair with c string key */ | /* Find key value pair with c string key */ | ||||||
| @@ -39,53 +39,53 @@ static GstValue *gst_object_bag_findcstring(GstDict *obj, const char *key) { | |||||||
|     hash = gst_cstring_calchash((uint8_t *)key, len); |     hash = gst_cstring_calchash((uint8_t *)key, len); | ||||||
|     GstValue *start = obj->data; |     GstValue *start = obj->data; | ||||||
|     GstValue *end = obj->data + obj->count * 2; |     GstValue *end = obj->data + obj->count * 2; | ||||||
| 	while (start < end) { |     while (start < end) { | ||||||
|     	if (start->type == GST_STRING) { |         if (start->type == GST_STRING) { | ||||||
| 			uint8_t *str = start->data.string; |             uint8_t *str = start->data.string; | ||||||
| 			if (gst_string_length(str) == len) { |             if (gst_string_length(str) == len) { | ||||||
| 				if (!gst_string_hash(str)) |                 if (!gst_string_hash(str)) | ||||||
|     				gst_string_hash(str) = gst_string_calchash(str); |                     gst_string_hash(str) = gst_string_calchash(str); | ||||||
|     			if (gst_string_hash(str) == hash) { |                 if (gst_string_hash(str) == hash) { | ||||||
| 					return start |                     return start | ||||||
|     			} |                 } | ||||||
| 			} |             } | ||||||
|     	} |         } | ||||||
| 		start += 2; |         start += 2; | ||||||
| 	} |     } | ||||||
| 	return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a key from a bag */ | /* Remove a key from a bag */ | ||||||
| static void gst_object_bag_remove(GstDict *obj, GstValue key) { | static void gst_object_bag_remove(GstDict *obj, GstValue key) { | ||||||
| 	GstValue *kv = gst_object_bag_find(obj, key); |     GstValue *kv = gst_object_bag_find(obj, key); | ||||||
| 	if (kv != NULL) { |     if (kv != NULL) { | ||||||
|     	GstValue *lastKv = obj->data + --obj->count * 2; |         GstValue *lastKv = obj->data + --obj->count * 2; | ||||||
| 		kv[0] = lastKv[0]; |         kv[0] = lastKv[0]; | ||||||
| 		kv[1] = lastKv[1]; |         kv[1] = lastKv[1]; | ||||||
| 	} |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Add a key to a bag */ | /* Add a key to a bag */ | ||||||
| static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) { | static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) { | ||||||
| 	GstValue *kv = gst_object_bag_find(obj, key); |     GstValue *kv = gst_object_bag_find(obj, key); | ||||||
| 	if (kv != NULL) { |     if (kv != NULL) { | ||||||
|     	/* Replace value */ |         /* Replace value */ | ||||||
|     	kv[1] = value; |         kv[1] = value; | ||||||
| 	} else { |     } else { | ||||||
| 		/* Check for need to resize */ |         /* Check for need to resize */ | ||||||
| 		if (obj->count + 1 > obj->capacity) { |         if (obj->count + 1 > obj->capacity) { | ||||||
|     		uint32_t newCap = 2 * obj->count + 2; |             uint32_t newCap = 2 * obj->count + 2; | ||||||
|     		GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap); |             GstValue *newData = gst_alloc(vm, sizeof(GstValue) * 2 * newCap); | ||||||
| 			gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue)); |             gst_memcpy(newData, obj->data, obj->count * 2 * sizeof(GstValue)); | ||||||
| 			obj->data = newData; |             obj->data = newData; | ||||||
| 			obj->capacity = newCap; |             obj->capacity = newCap; | ||||||
| 		} |         } | ||||||
| 		/* Push to end */ |         /* Push to end */ | ||||||
| 		kv = obj->data + obj->count * 2; |         kv = obj->data + obj->count * 2; | ||||||
| 		kv[0] = key; |         kv[0] = key; | ||||||
| 		kv[1] = value; |         kv[1] = value; | ||||||
| 		++obj->count; |         ++obj->count; | ||||||
| 	} |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /****/ | /****/ | ||||||
| @@ -94,58 +94,58 @@ static void gst_object_bag_put(Gst *vm, GstDict *obj, GstValue key, GstValue val | |||||||
|  |  | ||||||
| /* Add a key value pair to a given array. Returns if key successfully added. */  | /* Add a key value pair to a given array. Returns if key successfully added. */  | ||||||
| static void hash_putkv(GstValue *data, uint32_t cap, GstValue key, GstValue value) { | static void hash_putkv(GstValue *data, uint32_t cap, GstValue key, GstValue value) { | ||||||
| 	GstValue *end = data + 2 * cap; |     GstValue *end = data + 2 * cap; | ||||||
| 	GstValue *start = data + (gst_hash(key) % cap) * 2; |     GstValue *start = data + (gst_hash(key) % cap) * 2; | ||||||
| 	GstValue *bucket; |     GstValue *bucket; | ||||||
| 	/* Check second half of array */ |     /* Check second half of array */ | ||||||
| 	for (bucket = start; bucket < end; bucket += 2) { |     for (bucket = start; bucket < end; bucket += 2) { | ||||||
| 		if (bucket[0].type == GST_NIL) { |         if (bucket[0].type == GST_NIL) { | ||||||
| 			bucket[0] = key; |             bucket[0] = key; | ||||||
| 			bucket[1] = value; |             bucket[1] = value; | ||||||
| 			return; |             return; | ||||||
| 		} |         } | ||||||
| 	} |     } | ||||||
| 	/* Check first half of array */ |     /* Check first half of array */ | ||||||
| 	for (bucket = data; bucket < start; bucket += 2) { |     for (bucket = data; bucket < start; bucket += 2) { | ||||||
| 		if (bucket[0].type == GST_NIL) { |         if (bucket[0].type == GST_NIL) { | ||||||
|     		bucket[0] = key; |             bucket[0] = key; | ||||||
|     		bucket[1] = value; |             bucket[1] = value; | ||||||
|     		return; |             return; | ||||||
| 		} |         } | ||||||
| 	} |     } | ||||||
| 	/* Should never reach here - data would be full */ |     /* Should never reach here - data would be full */ | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Find a bucket in the hastable */ | /* Find a bucket in the hastable */ | ||||||
| static GstValue *hash_findkv(GstValue *data, uint32_t cap, GstValue key, GstValue **out) { | static GstValue *hash_findkv(GstValue *data, uint32_t cap, GstValue key, GstValue **out) { | ||||||
| 	GstValue *end = data + 2 * cap; |     GstValue *end = data + 2 * cap; | ||||||
| 	GstValue *start = data + (gst_hash(key) % cap) * 2; |     GstValue *start = data + (gst_hash(key) % cap) * 2; | ||||||
| 	GstValue *bucket; |     GstValue *bucket; | ||||||
| 	/* Check second half of array */ |     /* Check second half of array */ | ||||||
| 	for (bucket = start; bucket < end; bucket += 2) |     for (bucket = start; bucket < end; bucket += 2) | ||||||
| 		if (bucket[0].type == GST_NIL) |         if (bucket[0].type == GST_NIL) | ||||||
|     		if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ |             if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ | ||||||
| 				continue; |                 continue; | ||||||
| 			else { |             else { | ||||||
|     			*out = bucket; |                 *out = bucket; | ||||||
| 				return NULL; |                 return NULL; | ||||||
| 			} |             } | ||||||
| 		else if (gst_equals(bucket[0], key)) |         else if (gst_equals(bucket[0], key)) | ||||||
|     		return bucket; |             return bucket; | ||||||
| 	/* Check first half of array */ |     /* Check first half of array */ | ||||||
| 	for (bucket = data; bucket < start; bucket += 2) |     for (bucket = data; bucket < start; bucket += 2) | ||||||
|     	if (bucket[0].type == GST_NIL) |         if (bucket[0].type == GST_NIL) | ||||||
|     		if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ |             if (bucket[1].type == GST_BOOLEAN) /* Check if just marked deleted */ | ||||||
| 				continue; |                 continue; | ||||||
| 			else { |             else { | ||||||
|     			*out = bucket; |                 *out = bucket; | ||||||
| 				return NULL; |                 return NULL; | ||||||
| 			} |             } | ||||||
| 		else if (gst_equals(bucket[0], key)) |         else if (gst_equals(bucket[0], key)) | ||||||
|     		return bucket; |             return bucket; | ||||||
| 	/* Should never reach here - data would be full */ |     /* Should never reach here - data would be full */ | ||||||
| 	*out = bucket; |     *out = bucket; | ||||||
| 	return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Resize internal hashtable. Also works if currently a bag. */ | /* Resize internal hashtable. Also works if currently a bag. */ | ||||||
| @@ -155,32 +155,32 @@ static void gst_object_rehash(Gst *vm, GstDict *obj, uint32_t capacity) { | |||||||
|     toEnd = toData + 2 * capacity; |     toEnd = toData + 2 * capacity; | ||||||
|     fromBucket = obj->data; |     fromBucket = obj->data; | ||||||
|     fromEnd = fromBucket + obj->count * 2; |     fromEnd = fromBucket + obj->count * 2; | ||||||
| 	for (; fromBucket < fromEnd; fromBucket += 2) {	 |     for (; fromBucket < fromEnd; fromBucket += 2) {  | ||||||
| 		if (fromBucket[0].type == GST_NIL) continue; |         if (fromBucket[0].type == GST_NIL) continue; | ||||||
| 		toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2; |         toStart = toData + (gst_hash(fromBucket[0]) % capacity) * 2; | ||||||
| 		/* Check second half of array */ |         /* Check second half of array */ | ||||||
|     	for (toBucket = toStart; toBucket < toEnd; toBucket += 2) { |         for (toBucket = toStart; toBucket < toEnd; toBucket += 2) { | ||||||
|     		if (toBucket[0].type == GST_NIL) { |             if (toBucket[0].type == GST_NIL) { | ||||||
|     			toBucket[0] = fromBucket[0]; |                 toBucket[0] = fromBucket[0]; | ||||||
|     			toBucket[1] = fromBucket[1]; |                 toBucket[1] = fromBucket[1]; | ||||||
|     			goto finish_put; |                 goto finish_put; | ||||||
|     		} |             } | ||||||
|     	} |         } | ||||||
|     	/* Check first half of array */ |         /* Check first half of array */ | ||||||
|     	for (toBucket = toData; toBucket < toStart; toBucket += 2) { |         for (toBucket = toData; toBucket < toStart; toBucket += 2) { | ||||||
|     		if (toBucket[0].type == GST_NIL) { |             if (toBucket[0].type == GST_NIL) { | ||||||
|     			toBucket[0] = fromBucket[0]; |                 toBucket[0] = fromBucket[0]; | ||||||
|     			toBucket[1] = fromBucket[1]; |                 toBucket[1] = fromBucket[1]; | ||||||
|     			goto finish_put; |                 goto finish_put; | ||||||
|     		} |             } | ||||||
|     	} |         } | ||||||
|     	/* Error if we got here - backing array to small. */ |         /* Error if we got here - backing array to small. */ | ||||||
|     	; |         ; | ||||||
|     	/* Continue. */ |         /* Continue. */ | ||||||
|     	finish_put: continue; |         finish_put: continue; | ||||||
| 	} |     } | ||||||
| 	obj->capacity = capacity; |     obj->capacity = capacity; | ||||||
| 	obj->data = toData; |     obj->data = toData; | ||||||
| } | } | ||||||
|  |  | ||||||
| /****/ | /****/ | ||||||
| @@ -202,16 +202,16 @@ GstDict *gst_dict(Gst *vm, uint32_t capacity) { | |||||||
| GstValue gst_dict_get(GstDict *dict, GstValue key) { | GstValue gst_dict_get(GstDict *dict, GstValue key) { | ||||||
|     GstValue *bucket *notused; |     GstValue *bucket *notused; | ||||||
|     if (dict->flags & GST_OBJECT_FLAG_ISBAG) { |     if (dict->flags & GST_OBJECT_FLAG_ISBAG) { | ||||||
| 		bucket = gst_object_bag_find(dict, key); |         bucket = gst_object_bag_find(dict, key); | ||||||
|     } else { |     } else { | ||||||
|         bucket = hash_findkv(obj->data, obj->capacity, key, ¬used); |         bucket = hash_findkv(obj->data, obj->capacity, key, ¬used); | ||||||
|     } |     } | ||||||
|     if (bucket != NULL) { |     if (bucket != NULL) { | ||||||
| 		return bucket[1]; |         return bucket[1]; | ||||||
|     } else { |     } else { | ||||||
|         GstValue ret; |         GstValue ret; | ||||||
| 		ret.type = GST_NIL; |         ret.type = GST_NIL; | ||||||
| 		return ret; |         return ret; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -223,42 +223,42 @@ void gst_dict_put(Gst *vm, GstDict *obj, GstValue key, GstValue value) { | |||||||
|     if (obj->flags & GST_OBJECT_FLAG_ISBAG) { |     if (obj->flags & GST_OBJECT_FLAG_ISBAG) { | ||||||
|         if (obj->count > GST_OBJECT_BAG_THRESHOLD) { |         if (obj->count > GST_OBJECT_BAG_THRESHOLD) { | ||||||
|             /* Change to hashtable */ |             /* Change to hashtable */ | ||||||
| 			obj->flags |= GST_OBJECT_FLAG_ISBAG; |             obj->flags |= GST_OBJECT_FLAG_ISBAG; | ||||||
| 			gst_object_rehash(vm, obj, 4 * obj->count); |             gst_object_rehash(vm, obj, 4 * obj->count); | ||||||
| 			goto put_hash; |             goto put_hash; | ||||||
|         } |         } | ||||||
| 		gst_object_bag_put(vm, obj, key, value); |         gst_object_bag_put(vm, obj, key, value); | ||||||
|     } else { |     } else { | ||||||
|         GstValue *bucket, *out; |         GstValue *bucket, *out; | ||||||
| 		put_hash: |         put_hash: | ||||||
|         bucket = hash_findkv(obj->data, obj->capacity, key, &out); |         bucket = hash_findkv(obj->data, obj->capacity, key, &out); | ||||||
| 		if (bucket != NULL) { |         if (bucket != NULL) { | ||||||
| 			bucket[1] = value; |             bucket[1] = value; | ||||||
| 		} else { |         } else { | ||||||
| 			/* Check for resize */ |             /* Check for resize */ | ||||||
| 			if (obj->count + 1 > obj->capacity) { |             if (obj->count + 1 > obj->capacity) { | ||||||
|     			gst_object_rehash(vm, obj, 2 * (obj->count + 1)); |                 gst_object_rehash(vm, obj, 2 * (obj->count + 1)); | ||||||
|                 bucket = hash_findkv(obj->data, obj->capacity, key, &out); |                 bucket = hash_findkv(obj->data, obj->capacity, key, &out); | ||||||
| 			} |             } | ||||||
| 			out[0] = key; |             out[0] = key; | ||||||
| 			out[1] = value; |             out[1] = value; | ||||||
| 			++obj->count; |             ++obj->count; | ||||||
| 		} |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove item from dictionary */ | /* Remove item from dictionary */ | ||||||
| void gst_dict_remove(GstDict *obj, GstValue key) { | void gst_dict_remove(GstDict *obj, GstValue key) { | ||||||
|     if (obj->flags & GST_OBJECT_FLAG_ISBAG) { |     if (obj->flags & GST_OBJECT_FLAG_ISBAG) { | ||||||
| 		gst_object_bag_remove(obj, key); |         gst_object_bag_remove(obj, key); | ||||||
|     } else { |     } else { | ||||||
|         GstValue *bucket, *out; |         GstValue *bucket, *out; | ||||||
|         bucket = hash_findkv(obj->data, obj->capacity, key, &out); |         bucket = hash_findkv(obj->data, obj->capacity, key, &out); | ||||||
| 		if (bucket != NULL) { |         if (bucket != NULL) { | ||||||
| 			--obj->count; |             --obj->count; | ||||||
| 			bucket[0].type = GST_NIL; |             bucket[0].type = GST_NIL; | ||||||
| 			bucket[1].type = GST_BOOLEAN; |             bucket[1].type = GST_BOOLEAN; | ||||||
| 		} |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								ds.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								ds.c
									
									
									
									
									
								
							| @@ -229,7 +229,7 @@ GstValue gst_object_get(GstObject *o, GstValue key) { | |||||||
| /* Get a value of the object with a cstring key */ | /* Get a value of the object with a cstring key */ | ||||||
| GstValue gst_object_get_cstring(GstObject *obj, const char *key) { | GstValue gst_object_get_cstring(GstObject *obj, const char *key) { | ||||||
|     uint32_t len; |     uint32_t len; | ||||||
| 	for (len = 0; key[len]; ++len); |     for (len = 0; key[len]; ++len); | ||||||
|     uint32_t hash = gst_cstring_calchash((uint8_t *)key, len); |     uint32_t hash = gst_cstring_calchash((uint8_t *)key, len); | ||||||
|     uint32_t index = hash % obj->capacity; |     uint32_t index = hash % obj->capacity; | ||||||
|     GstBucket *bucket = obj->buckets[index]; |     GstBucket *bucket = obj->buckets[index]; | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								gc.c
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								gc.c
									
									
									
									
									
								
							| @@ -45,11 +45,11 @@ static void gst_mark_funcdef(Gst *vm, GstFuncDef *def) { | |||||||
|             for (i = 0; i < count; ++i) { |             for (i = 0; i < count; ++i) { | ||||||
|                 /* If the literal is a NIL type, it actually |                 /* If the literal is a NIL type, it actually | ||||||
|                  * contains a FuncDef */ |                  * contains a FuncDef */ | ||||||
|                	if (def->literals[i].type == GST_NIL) { |                 if (def->literals[i].type == GST_NIL) { | ||||||
| 					gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); |                     gst_mark_funcdef(vm, (GstFuncDef *) def->literals[i].data.pointer); | ||||||
|                	} else { |                 } else { | ||||||
|                     gst_mark(vm, def->literals + i); |                     gst_mark(vm, def->literals + i); | ||||||
|                	} |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -141,31 +141,31 @@ void gst_mark(Gst *vm, GstValue *x) { | |||||||
|                 gc_header(x->data.object)->color = vm->black; |                 gc_header(x->data.object)->color = vm->black; | ||||||
|                 gc_header(x->data.object->buckets)->color = vm->black; |                 gc_header(x->data.object->buckets)->color = vm->black; | ||||||
|                 for (i = 0; i < x->data.object->capacity; ++i) { |                 for (i = 0; i < x->data.object->capacity; ++i) { | ||||||
| 					bucket = x->data.object->buckets[i]; |                     bucket = x->data.object->buckets[i]; | ||||||
| 					while (bucket) { |                     while (bucket) { | ||||||
|     					gc_header(bucket)->color = vm->black; |                         gc_header(bucket)->color = vm->black; | ||||||
| 						gst_mark(vm, &bucket->key); |                         gst_mark(vm, &bucket->key); | ||||||
| 						gst_mark(vm, &bucket->value); |                         gst_mark(vm, &bucket->value); | ||||||
| 						bucket = bucket->next; |                         bucket = bucket->next; | ||||||
| 					} |                     } | ||||||
|                 } |                 } | ||||||
|                 if (x->data.object->meta != NULL) { |                 if (x->data.object->meta != NULL) { | ||||||
|                     GstValue temp; |                     GstValue temp; | ||||||
|                     temp.type = GST_OBJECT; |                     temp.type = GST_OBJECT; | ||||||
|                     temp.data.object = x->data.object->meta; |                     temp.data.object = x->data.object->meta; | ||||||
| 					gst_mark(vm, &temp); |                     gst_mark(vm, &temp); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         case GST_USERDATA: |         case GST_USERDATA: | ||||||
|             if (gc_header(x->data.string - sizeof(GstUserdataHeader))->color != vm->black) { |             if (gc_header(x->data.string - sizeof(GstUserdataHeader))->color != vm->black) { | ||||||
| 				GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1; |                 GstUserdataHeader *userHeader = (GstUserdataHeader *)x->data.string - 1; | ||||||
| 				gc_header(userHeader)->color = vm->black; |                 gc_header(userHeader)->color = vm->black; | ||||||
| 				GstValue temp; |                 GstValue temp; | ||||||
| 				temp.type = GST_OBJECT; |                 temp.type = GST_OBJECT; | ||||||
| 				temp.data.object = userHeader->meta; |                 temp.data.object = userHeader->meta; | ||||||
| 				gst_mark(vm, &temp); |                 gst_mark(vm, &temp); | ||||||
|             } |             } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -254,20 +254,20 @@ void gst_clear_memory(Gst *vm) { | |||||||
|  |  | ||||||
| /* Header for managed memory blocks */ | /* Header for managed memory blocks */ | ||||||
| struct MMHeader { | struct MMHeader { | ||||||
| 	struct MMHeader *next; |     struct MMHeader *next; | ||||||
| 	struct MMHeader *previous; |     struct MMHeader *previous; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Initialize managed memory */ | /* Initialize managed memory */ | ||||||
| void gst_mm_init(GstManagedMemory *mm) { | void gst_mm_init(GstManagedMemory *mm) { | ||||||
| 	*mm = NULL; |     *mm = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Allocate some managed memory */ | /* Allocate some managed memory */ | ||||||
| void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { | void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { | ||||||
| 	struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader)); |     struct MMHeader *mem = gst_raw_alloc(size + sizeof(struct MMHeader)); | ||||||
| 	if (mem == NULL) |     if (mem == NULL) | ||||||
|     	return NULL; |         return NULL; | ||||||
|     mem->next = *mm; |     mem->next = *mm; | ||||||
|     mem->previous = NULL; |     mem->previous = NULL; | ||||||
|     *mm = mem; |     *mm = mem; | ||||||
| @@ -276,9 +276,9 @@ void *gst_mm_alloc(GstManagedMemory *mm, uint32_t size) { | |||||||
|  |  | ||||||
| /* Intialize zeroed managed memory */ | /* Intialize zeroed managed memory */ | ||||||
| void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { | void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { | ||||||
| 	struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader)); |     struct MMHeader *mem = gst_raw_calloc(1, size + sizeof(struct MMHeader)); | ||||||
| 	if (mem == NULL) |     if (mem == NULL) | ||||||
|     	return NULL; |         return NULL; | ||||||
|     mem->next = *mm; |     mem->next = *mm; | ||||||
|     mem->previous = NULL; |     mem->previous = NULL; | ||||||
|     *mm = mem; |     *mm = mem; | ||||||
| @@ -287,32 +287,32 @@ void *gst_mm_zalloc(GstManagedMemory *mm, uint32_t size) { | |||||||
|  |  | ||||||
| /* Free a memory block used in managed memory */ | /* Free a memory block used in managed memory */ | ||||||
| void gst_mm_free(GstManagedMemory *mm, void *block) { | void gst_mm_free(GstManagedMemory *mm, void *block) { | ||||||
| 	struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader)); |     struct MMHeader *mem = (struct MMHeader *)(((char *)block) - sizeof(struct MMHeader)); | ||||||
| 	if (mem->previous != NULL) { |     if (mem->previous != NULL) { | ||||||
| 		mem->previous->next = mem->next; |         mem->previous->next = mem->next; | ||||||
| 	} else { |     } else { | ||||||
| 		*mm = mem->next; |         *mm = mem->next; | ||||||
| 	} |     } | ||||||
| 	gst_raw_free(mem); |     gst_raw_free(mem); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Free all memory in managed memory */ | /* Free all memory in managed memory */ | ||||||
| void gst_mm_clear(GstManagedMemory *mm) { | void gst_mm_clear(GstManagedMemory *mm) { | ||||||
| 	struct MMHeader *block = (struct MMHeader *)(*mm); |     struct MMHeader *block = (struct MMHeader *)(*mm); | ||||||
| 	struct MMHeader *next; |     struct MMHeader *next; | ||||||
| 	while (block != NULL) { |     while (block != NULL) { | ||||||
|     	next = block->next; |         next = block->next; | ||||||
| 		free(block); |         free(block); | ||||||
| 		block = next; |         block = next; | ||||||
| 	}; |     }; | ||||||
| 	*mm = NULL; |     *mm = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Analog to realloc */ | /* Analog to realloc */ | ||||||
| void *gst_mm_realloc(GstManagedMemory *mm, void *block, uint32_t nsize) { | void *gst_mm_realloc(GstManagedMemory *mm, void *block, uint32_t nsize) { | ||||||
| 	struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader)); |     struct MMHeader *mem = gst_raw_realloc(block, nsize + sizeof(struct MMHeader)); | ||||||
| 	if (mem == NULL) |     if (mem == NULL) | ||||||
|     	return NULL; |         return NULL; | ||||||
|     mem->next = *mm; |     mem->next = *mm; | ||||||
|     mem->previous = NULL; |     mem->previous = NULL; | ||||||
|     *mm = mem; |     *mm = mem; | ||||||
|   | |||||||
							
								
								
									
										216
									
								
								thread.c
									
									
									
									
									
								
							
							
						
						
									
										216
									
								
								thread.c
									
									
									
									
									
								
							| @@ -7,80 +7,80 @@ | |||||||
| /* Create a new thread */ | /* Create a new thread */ | ||||||
| GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { | GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { | ||||||
|     GstThread *thread = gst_alloc(vm, sizeof(GstThread)); |     GstThread *thread = gst_alloc(vm, sizeof(GstThread)); | ||||||
| 	GstValue *data, *stack; |     GstValue *data, *stack; | ||||||
| 	if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; |     if (capacity < GST_FRAME_SIZE) capacity = GST_FRAME_SIZE; | ||||||
| 	data = gst_alloc(vm, sizeof(GstValue) * capacity); |     data = gst_alloc(vm, sizeof(GstValue) * capacity); | ||||||
| 	thread->capacity = capacity; |     thread->capacity = capacity; | ||||||
| 	thread->count = GST_FRAME_SIZE; |     thread->count = GST_FRAME_SIZE; | ||||||
| 	thread->data = data; |     thread->data = data; | ||||||
| 	thread->status = GST_THREAD_PENDING; |     thread->status = GST_THREAD_PENDING; | ||||||
| 	stack = data + GST_FRAME_SIZE; |     stack = data + GST_FRAME_SIZE; | ||||||
| 	gst_frame_size(stack) = 0; |     gst_frame_size(stack) = 0; | ||||||
| 	gst_frame_prevsize(stack) = 0; |     gst_frame_prevsize(stack) = 0; | ||||||
| 	gst_frame_ret(stack) = 0; |     gst_frame_ret(stack) = 0; | ||||||
| 	gst_frame_errloc(stack) = 0; |     gst_frame_errloc(stack) = 0; | ||||||
| 	gst_frame_pc(stack) = NULL; |     gst_frame_pc(stack) = NULL; | ||||||
| 	gst_frame_env(stack) = NULL; |     gst_frame_env(stack) = NULL; | ||||||
| 	gst_frame_errjmp(stack) = NULL; |     gst_frame_errjmp(stack) = NULL; | ||||||
|     gst_thread_expand_callable(vm, thread, callee); |     gst_thread_expand_callable(vm, thread, callee); | ||||||
| 	gst_thread_endframe(vm, thread); |     gst_thread_endframe(vm, thread); | ||||||
|     return thread; |     return thread; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Ensure that the thread has enough EXTRA capacity */ | /* Ensure that the thread has enough EXTRA capacity */ | ||||||
| void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra) { | void gst_thread_ensure_extra(Gst *vm, GstThread *thread, uint32_t extra) { | ||||||
|    	GstValue *newData, *stack; |     GstValue *newData, *stack; | ||||||
|    	uint32_t usedCapacity, neededCapacity, newCapacity; |     uint32_t usedCapacity, neededCapacity, newCapacity; | ||||||
|    	stack = thread->data + thread->count; |     stack = thread->data + thread->count; | ||||||
|    	usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE; |     usedCapacity = thread->count + gst_frame_size(stack) + GST_FRAME_SIZE; | ||||||
|    	neededCapacity = usedCapacity + extra; |     neededCapacity = usedCapacity + extra; | ||||||
| 	if (thread->capacity >= neededCapacity) return; |     if (thread->capacity >= neededCapacity) return; | ||||||
| 	newCapacity = 2 * neededCapacity; |     newCapacity = 2 * neededCapacity; | ||||||
| 	newData = gst_alloc(vm, sizeof(GstValue) * newCapacity); |     newData = gst_alloc(vm, sizeof(GstValue) * newCapacity); | ||||||
| 	gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity); |     gst_memcpy(newData, thread->data, sizeof(GstValue) * usedCapacity); | ||||||
| 	thread->data = newData; |     thread->data = newData; | ||||||
| 	thread->capacity = newCapacity; |     thread->capacity = newCapacity; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Push a value on the current stack frame*/ | /* Push a value on the current stack frame*/ | ||||||
| void gst_thread_push(Gst *vm, GstThread *thread, GstValue x) { | void gst_thread_push(Gst *vm, GstThread *thread, GstValue x) { | ||||||
|     GstValue *stack; |     GstValue *stack; | ||||||
| 	gst_thread_ensure_extra(vm, thread, 1); |     gst_thread_ensure_extra(vm, thread, 1); | ||||||
| 	stack = thread->data + thread->count; |     stack = thread->data + thread->count; | ||||||
| 	stack[gst_frame_size(stack)++] = x; |     stack[gst_frame_size(stack)++] = x; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Push n nils onto the stack */ | /* Push n nils onto the stack */ | ||||||
| void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) { | void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n) { | ||||||
|     GstValue *stack, *current, *end; |     GstValue *stack, *current, *end; | ||||||
| 	gst_thread_ensure_extra(vm, thread, n); |     gst_thread_ensure_extra(vm, thread, n); | ||||||
| 	stack = thread->data + thread->count; |     stack = thread->data + thread->count; | ||||||
| 	current = stack + gst_frame_size(stack); |     current = stack + gst_frame_size(stack); | ||||||
| 	end = current + n; |     end = current + n; | ||||||
| 	for (; current < end; ++current) { |     for (; current < end; ++current) { | ||||||
| 		current->type = GST_NIL; |         current->type = GST_NIL; | ||||||
| 	} |     } | ||||||
| 	gst_frame_size(stack) += n; |     gst_frame_size(stack) += n; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Package up extra args after and including n into tuple at n*/ | /* Package up extra args after and including n into tuple at n*/ | ||||||
| void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { | void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { | ||||||
| 	GstValue *stack = thread->data + thread->count; |     GstValue *stack = thread->data + thread->count; | ||||||
| 	uint32_t size = gst_frame_size(stack); |     uint32_t size = gst_frame_size(stack); | ||||||
| 	if (n >= size) { |     if (n >= size) { | ||||||
| 		gst_thread_pushnil(vm, thread, n - size + 1); |         gst_thread_pushnil(vm, thread, n - size + 1); | ||||||
|     	stack = thread->data + thread->count; |         stack = thread->data + thread->count; | ||||||
| 		stack[n].type = GST_TUPLE; |         stack[n].type = GST_TUPLE; | ||||||
| 		stack[n].data.tuple = gst_tuple(vm, 0); |         stack[n].data.tuple = gst_tuple(vm, 0); | ||||||
| 	} else { |     } else { | ||||||
|     	uint32_t i; |         uint32_t i; | ||||||
| 		GstValue *tuple = gst_tuple(vm, size - n); |         GstValue *tuple = gst_tuple(vm, size - n); | ||||||
| 		for (i = n; i < size; ++i) |         for (i = n; i < size; ++i) | ||||||
|     		tuple[i - n] = stack[i]; |             tuple[i - n] = stack[i]; | ||||||
|     	stack[n].type = GST_TUPLE; |         stack[n].type = GST_TUPLE; | ||||||
|     	stack[n].data.tuple = tuple; |         stack[n].data.tuple = tuple; | ||||||
|     	gst_frame_size(stack) = n + 1; |         gst_frame_size(stack) = n + 1; | ||||||
| 	} |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Expand a callee on the stack frame to its delegate function. This means that | /* Expand a callee on the stack frame to its delegate function. This means that | ||||||
| @@ -128,70 +128,70 @@ GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uin | |||||||
|     uint32_t frameOffset; |     uint32_t frameOffset; | ||||||
|     GstValue *oldStack, *newStack; |     GstValue *oldStack, *newStack; | ||||||
|  |  | ||||||
| 	/* Push the frame */ |     /* Push the frame */ | ||||||
| 	gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4); |     gst_thread_ensure_extra(vm, thread, GST_FRAME_SIZE + arity + 4); | ||||||
| 	oldStack = thread->data + thread->count; |     oldStack = thread->data + thread->count; | ||||||
| 	frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE; |     frameOffset = gst_frame_size(oldStack) + GST_FRAME_SIZE; | ||||||
| 	newStack = oldStack + frameOffset; |     newStack = oldStack + frameOffset; | ||||||
| 	gst_frame_prevsize(newStack) = gst_frame_size(oldStack); |     gst_frame_prevsize(newStack) = gst_frame_size(oldStack); | ||||||
| 	gst_frame_env(newStack) = NULL; |     gst_frame_env(newStack) = NULL; | ||||||
| 	gst_frame_errjmp(newStack) = NULL; |     gst_frame_errjmp(newStack) = NULL; | ||||||
| 	gst_frame_size(newStack) = 0; |     gst_frame_size(newStack) = 0; | ||||||
| 	thread->count += frameOffset;  |     thread->count += frameOffset;  | ||||||
|  |  | ||||||
|     /* Get real callable */ |     /* Get real callable */ | ||||||
|     if (gst_thread_expand_callable(vm, thread, callee) == NULL) |     if (gst_thread_expand_callable(vm, thread, callee) == NULL) | ||||||
|         return NULL; |         return NULL; | ||||||
|      |      | ||||||
| 	/* Ensure the extra space and initialize to nil */ |     /* Ensure the extra space and initialize to nil */ | ||||||
|     gst_thread_pushnil(vm, thread, arity); |     gst_thread_pushnil(vm, thread, arity); | ||||||
|  |  | ||||||
| 	/* Return ok */ |     /* Return ok */ | ||||||
|     return thread->data + thread->count; |     return thread->data + thread->count; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* After pushing arguments to a stack frame created with gst_thread_beginframe, call this | /* After pushing arguments to a stack frame created with gst_thread_beginframe, call this | ||||||
|  * to finalize the frame before starting a function call. */ |  * to finalize the frame before starting a function call. */ | ||||||
| void gst_thread_endframe(Gst *vm, GstThread *thread) { | void gst_thread_endframe(Gst *vm, GstThread *thread) { | ||||||
| 	GstValue *stack = thread->data + thread->count; |     GstValue *stack = thread->data + thread->count; | ||||||
| 	GstValue callee = gst_frame_callee(stack); |     GstValue callee = gst_frame_callee(stack); | ||||||
| 	if (callee.type == GST_FUNCTION) { |     if (callee.type == GST_FUNCTION) { | ||||||
|     	GstFunction *fn = callee.data.function; |         GstFunction *fn = callee.data.function; | ||||||
|     	gst_frame_pc(stack) = fn->def->byteCode; |         gst_frame_pc(stack) = fn->def->byteCode; | ||||||
| 		if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) { |         if (fn->def->flags & GST_FUNCDEF_FLAG_VARARG) { | ||||||
|         	uint32_t arity = fn->def->arity; |             uint32_t arity = fn->def->arity; | ||||||
|         	gst_thread_tuplepack(vm, thread, arity); |             gst_thread_tuplepack(vm, thread, arity); | ||||||
| 		} else { |         } else { | ||||||
|         	uint32_t locals = fn->def->locals; |             uint32_t locals = fn->def->locals; | ||||||
|         	if (gst_frame_size(stack) < locals) { |             if (gst_frame_size(stack) < locals) { | ||||||
| 				gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack)); |                 gst_thread_pushnil(vm, thread, locals - gst_frame_size(stack)); | ||||||
|         	} |             } | ||||||
| 		} |         } | ||||||
| 	} |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Pop a stack frame from the thread. Returns the new stack frame, or | /* Pop a stack frame from the thread. Returns the new stack frame, or | ||||||
|  * NULL if there are no more frames */ |  * NULL if there are no more frames */ | ||||||
| GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { | GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { | ||||||
| 	GstValue *stack = thread->data + thread->count; |     GstValue *stack = thread->data + thread->count; | ||||||
| 	uint32_t prevsize = gst_frame_prevsize(stack); |     uint32_t prevsize = gst_frame_prevsize(stack); | ||||||
| 	GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize; |     GstValue *nextstack = stack - GST_FRAME_SIZE - prevsize; | ||||||
| 	GstFuncEnv *env = gst_frame_env(stack); |     GstFuncEnv *env = gst_frame_env(stack); | ||||||
|  |  | ||||||
| 	/* Check for closures */ |     /* Check for closures */ | ||||||
|     if (env != NULL) { |     if (env != NULL) { | ||||||
|         uint32_t size = gst_frame_size(stack); |         uint32_t size = gst_frame_size(stack); | ||||||
|         env->thread = NULL; |         env->thread = NULL; | ||||||
|         env->stackOffset = size; |         env->stackOffset = size; | ||||||
|        	env->values = gst_alloc(vm, sizeof(GstValue) * size); |         env->values = gst_alloc(vm, sizeof(GstValue) * size); | ||||||
|         gst_memcpy(env->values, stack, sizeof(GstValue) * size); |         gst_memcpy(env->values, stack, sizeof(GstValue) * size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Shrink stack */ |     /* Shrink stack */ | ||||||
|     thread->count -= GST_FRAME_SIZE + prevsize; |     thread->count -= GST_FRAME_SIZE + prevsize; | ||||||
|  |  | ||||||
| 	/* Check if the stack is empty, and if so, return null */ |     /* Check if the stack is empty, and if so, return null */ | ||||||
| 	if (thread->count) |     if (thread->count) | ||||||
|         return nextstack; |         return nextstack; | ||||||
|     else |     else | ||||||
|         return NULL; |         return NULL; | ||||||
| @@ -201,39 +201,39 @@ GstValue *gst_thread_popframe(Gst *vm, GstThread *thread) { | |||||||
|  * for primitive tail calls. */ |  * for primitive tail calls. */ | ||||||
| GstValue *gst_thread_tail(Gst *vm, GstThread *thread) { | GstValue *gst_thread_tail(Gst *vm, GstThread *thread) { | ||||||
|     GstFuncEnv *env; |     GstFuncEnv *env; | ||||||
| 	GstValue *stack = thread->data + thread->count; |     GstValue *stack = thread->data + thread->count; | ||||||
| 	GstValue *nextStack = gst_thread_popframe(vm, thread); |     GstValue *nextStack = gst_thread_popframe(vm, thread); | ||||||
| 	uint32_t i; |     uint32_t i; | ||||||
|  |  | ||||||
| 	if (nextStack == NULL) return NULL; |     if (nextStack == NULL) return NULL; | ||||||
| 	env = gst_frame_env(nextStack); |     env = gst_frame_env(nextStack); | ||||||
|  |  | ||||||
| 	/* Check for old closures */ |     /* Check for old closures */ | ||||||
|     if (env != NULL) { |     if (env != NULL) { | ||||||
|         uint32_t size = gst_frame_size(stack); |         uint32_t size = gst_frame_size(stack); | ||||||
|         env->thread = NULL; |         env->thread = NULL; | ||||||
|         env->stackOffset = size; |         env->stackOffset = size; | ||||||
|        	env->values = gst_alloc(vm, sizeof(GstValue) * size); |         env->values = gst_alloc(vm, sizeof(GstValue) * size); | ||||||
|         gst_memcpy(env->values, stack, sizeof(GstValue) * size); |         gst_memcpy(env->values, stack, sizeof(GstValue) * size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Modify new closure */ |     /* Modify new closure */ | ||||||
|     env = gst_frame_env(stack); |     env = gst_frame_env(stack); | ||||||
|     if (env != NULL) { |     if (env != NULL) { | ||||||
| 		env->stackOffset = thread->count; |         env->stackOffset = thread->count; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| 	/* Copy over (some of) stack frame. Leave ret and prevsize untouched. */ |     /* Copy over (some of) stack frame. Leave ret and prevsize untouched. */ | ||||||
| 	gst_frame_env(nextStack) = env; |     gst_frame_env(nextStack) = env; | ||||||
| 	gst_frame_size(nextStack) = gst_frame_size(stack); |     gst_frame_size(nextStack) = gst_frame_size(stack); | ||||||
| 	gst_frame_pc(nextStack) = gst_frame_pc(stack); |     gst_frame_pc(nextStack) = gst_frame_pc(stack); | ||||||
| 	gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack); |     gst_frame_errjmp(nextStack) = gst_frame_errjmp(stack); | ||||||
| 	gst_frame_errloc(nextStack) = gst_frame_errloc(stack); |     gst_frame_errloc(nextStack) = gst_frame_errloc(stack); | ||||||
| 	gst_frame_callee(nextStack) = gst_frame_callee(stack); |     gst_frame_callee(nextStack) = gst_frame_callee(stack); | ||||||
|  |  | ||||||
| 	/* Copy stack arguments */ |     /* Copy stack arguments */ | ||||||
| 	for (i = 0; i < gst_frame_size(nextStack); ++i) |     for (i = 0; i < gst_frame_size(nextStack); ++i) | ||||||
|     	nextStack[i] = stack[i]; |         nextStack[i] = stack[i]; | ||||||
|  |  | ||||||
| 	return nextStack; |     return nextStack; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								vm.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								vm.c
									
									
									
									
									
								
							| @@ -349,7 +349,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             continue; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_RET: /* Return */ |         case GST_OP_RET: /* Return */ | ||||||
|         	temp = stack[pc[1]]; |             temp = stack[pc[1]]; | ||||||
|             stack = gst_thread_popframe(vm, &thread); |             stack = gst_thread_popframe(vm, &thread); | ||||||
|             if (thread.count < stackBase) { |             if (thread.count < stackBase) { | ||||||
|                 vm->ret = temp; |                 vm->ret = temp; | ||||||
| @@ -362,59 +362,59 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|  |  | ||||||
|         case GST_OP_CAL: /* Call */ |         case GST_OP_CAL: /* Call */ | ||||||
|         case GST_OP_TCL: /* Tail call */ |         case GST_OP_TCL: /* Tail call */ | ||||||
|         	{ |             { | ||||||
|             	GstValue *oldStack; |                 GstValue *oldStack; | ||||||
|             	temp = stack[pc[1]]; |                 temp = stack[pc[1]]; | ||||||
|                 int isTCall = *pc == GST_OP_TCL; |                 int isTCall = *pc == GST_OP_TCL; | ||||||
|             	uint32_t i, arity, offset, size; |                 uint32_t i, arity, offset, size; | ||||||
|             	uint16_t ret = pc[2]; |                 uint16_t ret = pc[2]; | ||||||
|             	offset = isTCall ? 3 : 4; |                 offset = isTCall ? 3 : 4; | ||||||
| 				arity = pc[offset - 1]; |                 arity = pc[offset - 1]; | ||||||
| 				/* Push new frame */ |                 /* Push new frame */ | ||||||
| 				stack = gst_thread_beginframe(vm, &thread, temp, arity); |                 stack = gst_thread_beginframe(vm, &thread, temp, arity); | ||||||
| 				oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack); |                 oldStack = stack - GST_FRAME_SIZE - gst_frame_prevsize(stack); | ||||||
| 				/* Write arguments */ |                 /* Write arguments */ | ||||||
| 				size = gst_frame_size(stack); |                 size = gst_frame_size(stack); | ||||||
| 				for (i = 0; i < arity; ++i) |                 for (i = 0; i < arity; ++i) | ||||||
|     				stack[i + size - arity] = oldStack[pc[offset + i]]; |                     stack[i + size - arity] = oldStack[pc[offset + i]]; | ||||||
|     			/* Finish new frame */ |                 /* Finish new frame */ | ||||||
| 				gst_thread_endframe(vm, &thread); |                 gst_thread_endframe(vm, &thread); | ||||||
| 				/* Check tail call - if so, replace frame. */ |                 /* Check tail call - if so, replace frame. */ | ||||||
| 				if (isTCall) { |                 if (isTCall) { | ||||||
| 					stack = gst_thread_tail(vm, &thread); |                     stack = gst_thread_tail(vm, &thread); | ||||||
| 				} else { |                 } else { | ||||||
| 					gst_frame_ret(oldStack) = ret; |                     gst_frame_ret(oldStack) = ret; | ||||||
| 				} |                 } | ||||||
| 				/* Call function */ |                 /* Call function */ | ||||||
| 				temp = gst_frame_callee(stack); |                 temp = gst_frame_callee(stack); | ||||||
| 				if (temp.type == GST_FUNCTION) { |                 if (temp.type == GST_FUNCTION) { | ||||||
|     				/* Save pc and set new pc */ |                     /* Save pc and set new pc */ | ||||||
|                     if (!isTCall) |                     if (!isTCall) | ||||||
|                         gst_frame_pc(oldStack) = pc + offset + arity; |                         gst_frame_pc(oldStack) = pc + offset + arity; | ||||||
|     				pc = temp.data.function->def->byteCode; |                     pc = temp.data.function->def->byteCode; | ||||||
| 				} else { |                 } else { | ||||||
| 					int status; |                     int status; | ||||||
| 					GST_STATE_WRITE(); |                     GST_STATE_WRITE(); | ||||||
| 					vm->ret.type = GST_NIL; |                     vm->ret.type = GST_NIL; | ||||||
| 					status = temp.data.cfunction(vm); |                     status = temp.data.cfunction(vm); | ||||||
| 					GST_STATE_SYNC(); |                     GST_STATE_SYNC(); | ||||||
| 					stack = gst_thread_popframe(vm, &thread); |                     stack = gst_thread_popframe(vm, &thread); | ||||||
| 					if (status == GST_RETURN_OK) |                     if (status == GST_RETURN_OK) | ||||||
|     					if (thread.count < stackBase) { |                         if (thread.count < stackBase) { | ||||||
|                             GST_STATE_WRITE(); |                             GST_STATE_WRITE(); | ||||||
|         					return status; |                             return status; | ||||||
|                         } else {  |                         } else {  | ||||||
|         					stack[gst_frame_ret(stack)] = vm->ret; |                             stack[gst_frame_ret(stack)] = vm->ret; | ||||||
|                             if (isTCall) |                             if (isTCall) | ||||||
|                                 pc = gst_frame_pc(stack); |                                 pc = gst_frame_pc(stack); | ||||||
|                             else |                             else | ||||||
|                                 pc += offset + arity; |                                 pc += offset + arity; | ||||||
|                         } |                         } | ||||||
| 					else |                     else | ||||||
|     					goto vm_error; |                         goto vm_error; | ||||||
| 				} |                 } | ||||||
|         	} |             } | ||||||
|         	break; |             break; | ||||||
|  |  | ||||||
|         /* Handle errors from c functions and vm opcodes */ |         /* Handle errors from c functions and vm opcodes */ | ||||||
|         vm_error: |         vm_error: | ||||||
| @@ -453,11 +453,11 @@ int gst_run(Gst *vm, GstValue callee) { | |||||||
|     /* If callee was not actually a function, get the delegate function */ |     /* If callee was not actually a function, get the delegate function */ | ||||||
|     callee = gst_frame_callee(stack); |     callee = gst_frame_callee(stack); | ||||||
|     if (callee.type == GST_CFUNCTION) { |     if (callee.type == GST_CFUNCTION) { | ||||||
| 		int status; |         int status; | ||||||
| 		vm->ret.type = GST_NIL; |         vm->ret.type = GST_NIL; | ||||||
| 		status = callee.data.cfunction(vm); |         status = callee.data.cfunction(vm); | ||||||
| 		gst_thread_popframe(vm, vm->thread); |         gst_thread_popframe(vm, vm->thread); | ||||||
| 		return status; |         return status; | ||||||
|     } else { |     } else { | ||||||
|         return gst_continue(vm); |         return gst_continue(vm); | ||||||
|     } |     } | ||||||
| @@ -484,15 +484,15 @@ int gst_call(Gst *vm, GstValue callee, uint32_t arity, GstValue *args) { | |||||||
|     gst_thread_endframe(vm, vm->thread); |     gst_thread_endframe(vm, vm->thread); | ||||||
|  |  | ||||||
|     /* Call function */ |     /* Call function */ | ||||||
| 	callee = gst_frame_callee(stack); |     callee = gst_frame_callee(stack); | ||||||
| 	if (callee.type == GST_FUNCTION) { |     if (callee.type == GST_FUNCTION) { | ||||||
|         gst_frame_pc(stack) = callee.data.function->def->byteCode; |         gst_frame_pc(stack) = callee.data.function->def->byteCode; | ||||||
|     	status = gst_continue(vm); |         status = gst_continue(vm); | ||||||
| 	} else { |     } else { | ||||||
| 		vm->ret.type = GST_NIL; |         vm->ret.type = GST_NIL; | ||||||
| 		status = callee.data.cfunction(vm); |         status = callee.data.cfunction(vm); | ||||||
| 		gst_thread_popframe(vm, vm->thread); |         gst_thread_popframe(vm, vm->thread); | ||||||
| 	} |     } | ||||||
|  |  | ||||||
|     /* Pop the extra nil */ |     /* Pop the extra nil */ | ||||||
|     --gst_frame_size(gst_thread_stack(vm->thread)); |     --gst_frame_size(gst_thread_stack(vm->thread)); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose