| 
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -355,11 +355,43 @@ struct context* ink_make_default_context(void) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static int ink_consume_one(int* end, struct context* pContext, char* r) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void new_protected_array(struct context* ctx); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static int ink_consume_one(int* end, struct context* pContext, char* r, int is_str) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int i; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int done; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				struct elem value; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int err; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if(is_str) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					struct ink_routine* routine = pContext->routines + pContext->routine_current; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					struct ink_array* ary; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					int it = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					new_protected_array(pContext); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					if(routine->top < 1) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						pContext->panic = -1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						return -8746; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					value = routine->stack[routine->top - 1]; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					ary = ink_get_value(pContext, value); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					if(ary == NULL) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						pContext->panic = -1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						return -8747; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					for(;it != *end;++it) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						struct elem character; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						character.type = INK_INTEGER; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						/* TODO: codepoint conversion and coalescence is required here */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						character.value = r[it]; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						array_push(pContext, routine, ary, character); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					*end = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					return 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				is_str = is_str; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if(*end == 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					return 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -460,9 +492,46 @@ static int ink_lex(struct context *pContext, const char* buffer) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				char r[128]; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int end; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int err; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int parses_string; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				end = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			restart_after_comment: | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				parses_string = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				while(*buffer != 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					if(parses_string) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						switch(*buffer) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							case '"': { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								if(*(buffer+1) == 0 || isspace(*(buffer+1))) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									err = ink_consume_one(&end, pContext, r, 1); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									if(err < 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
										pContext->panic = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
										return -995; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									parses_string = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								} else if(*(buffer+1) == '"') { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									r[end] = *buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									++end; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									++buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								} else if(*(buffer+1) == '/' && *(buffer+2) == '"') { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									r[end] = '\n'; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									++end; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									++buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									++buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								} else { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									pContext->panic = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
									return -994; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							}break; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							default: | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								r[end] = *buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								++end; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} else /* ... */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					if(isspace(*buffer)) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						if(end == 1 && r[0] == '#') { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							while(*buffer != '\n' && *buffer != 0) { | 
			
		
		
	
	
		
			
				| 
				
				
				
					
						
					
				
				 | 
			
			 | 
			
			@ -471,18 +540,24 @@ restart_after_comment: | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							end = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							goto restart_after_comment; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						err = ink_consume_one(&end, pContext, r); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						err = ink_consume_one(&end, pContext, r, 0); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						if(err < 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							pContext->panic = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							return -8; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} else { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} else /* ... */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					if(end == 0 && *buffer == '"' && !parses_string) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						parses_string = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} else /* ... */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						r[end] = *buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						++end; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					++buffer; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				err = ink_consume_one(&end, pContext, r); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				err = ink_consume_one(&end, pContext, r, 0); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if(err < 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					pContext->panic = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					return -9; | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -930,7 +1005,7 @@ void* ink_get_value(struct context* ctx, struct elem ref) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    return s->data; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			struct elem ink_make_native(struct context* ctx, int type, void* ptr) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			struct elem ink_make_native_unsafe(struct context* ctx, int type, void* ptr, int is_protected) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int type_id; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				struct elem ret; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int g, i; | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -982,7 +1057,8 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    for(i = 0; i < g; ++i) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        if(! ctx->types[type_id].elements[i].in_use) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            ctx->types[type_id].elements[i].in_use = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            ctx->types[type_id].elements[i].uses = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				        ctx->types[type_id].elements[i].uses = 1; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				        ctx->types[type_id].elements[i].is_protected = is_protected; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            if(ctx->types[type_id].element_size < 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			                ctx->types[type_id].elements[i].data = ptr; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            } else { | 
			
		
		
	
	
		
			
				| 
				
				
				
					
						
					
				
				 | 
			
			 | 
			
			@ -1006,6 +1082,10 @@ struct elem ink_make_native(struct context* ctx, int type, void* ptr) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    return ret; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			struct elem ink_make_native(struct context* ctx, int type, void* ptr) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				return ink_make_native_unsafe(ctx, type, ptr, 0); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			void ink_gc(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    int i, j, k; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int marked; | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -1041,7 +1121,7 @@ void ink_gc(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					for (i = 0; i < ctx->types_top; ++i) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
						for (j = 0; j < ctx->types[i].elements_top; ++j) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							/* Only mark from things that are active and detected as in use */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
							if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								struct ink_collection_list c; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
								for (k = 0; k < c.count; ++k) { | 
			
		
		
	
	
		
			
				| 
				
				
				
					
						
					
				
				 | 
			
			 | 
			
			@ -1061,7 +1141,7 @@ void ink_gc(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				/* Sweep phase: explore any allocated data and sweep the unused away */ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    for(i = 0; i < ctx->types_top; ++i) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        for(j = 0; j < ctx->types[i].elements_top; ++j) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected == 0) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			                ctx->collections++; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			                ctx->types[i].collect(ctx, ctx->types[i].elements[j].data); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			                if(ctx->types[i].element_size > 0) { | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -1598,6 +1678,20 @@ static void new_array(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				ink_push(ctx, e); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#ifndef NOSTRINGLITERALS | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void new_protected_array(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int tid; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				struct elem e; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				struct ink_array ary; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				tid =  get_type_by_name(ctx, "array"); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				ary.elements = NULL; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				ary.top = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				ary.capacity = 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				e = ink_make_native_unsafe(ctx, tid, &ary, 1); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				ink_push(ctx, e); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#endif | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void push_array_stack_delim(struct context* ctx) { | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				int tid; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				struct elem e; | 
			
		
		
	
	
		
			
				| 
				
					
						
					
				
				
				
				 | 
			
			 | 
			
			
 |