call-by-reference handling with a true multidimensional map
This commit is contained in:
		
							
								
								
									
										141
									
								
								hawk/lib/run.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								hawk/lib/run.c
									
									
									
									
									
								
							| @ -184,7 +184,7 @@ static hawk_val_t* __eval_call ( | |||||||
| 	void* eharg); | 	void* eharg); | ||||||
|  |  | ||||||
| static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref); | static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref); | ||||||
| static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, hawk_val_t** val); | static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var); | ||||||
|  |  | ||||||
| static hawk_val_t* eval_int (hawk_rtx_t* rtx, hawk_nde_t* nde); | static hawk_val_t* eval_int (hawk_rtx_t* rtx, hawk_nde_t* nde); | ||||||
| static hawk_val_t* eval_flt (hawk_rtx_t* rtx, hawk_nde_t* nde); | static hawk_val_t* eval_flt (hawk_rtx_t* rtx, hawk_nde_t* nde); | ||||||
| @ -3604,7 +3604,7 @@ static hawk_val_t* eval_expression0 (hawk_rtx_t* rtx, hawk_nde_t* nde) | |||||||
|  |  | ||||||
| 	v = __evaluator[nde->type-HAWK_NDE_GRP](rtx, nde); | 	v = __evaluator[nde->type-HAWK_NDE_GRP](rtx, nde); | ||||||
|  |  | ||||||
| 	if (v != HAWK_NULL && rtx->exit_level >= EXIT_GLOBAL) | 	if (HAWK_UNLIKELY(v && rtx->exit_level >= EXIT_GLOBAL)) | ||||||
| 	{ | 	{ | ||||||
| 		hawk_rtx_refupval (rtx, v); | 		hawk_rtx_refupval (rtx, v); | ||||||
| 		hawk_rtx_refdownval (rtx, v); | 		hawk_rtx_refdownval (rtx, v); | ||||||
| @ -3649,7 +3649,7 @@ static hawk_val_t* eval_group (hawk_rtx_t* rtx, hawk_nde_t* nde) | |||||||
|  |  | ||||||
| loop: | loop: | ||||||
| 	val = eval_expression (rtx, np); | 	val = eval_expression (rtx, np); | ||||||
| 	if (val == HAWK_NULL) return HAWK_NULL; | 	if (HAWK_UNLIKELY(!val)) return HAWK_NULL; | ||||||
|  |  | ||||||
| 	np = np->next; | 	np = np->next; | ||||||
| 	if (np) | 	if (np) | ||||||
| @ -6267,12 +6267,7 @@ static hawk_val_t* __eval_call ( | |||||||
| 		if (call->u.fnc.spec.impl) | 		if (call->u.fnc.spec.impl) | ||||||
| 		{ | 		{ | ||||||
| 			n = call->u.fnc.spec.impl(rtx, &call->u.fnc.info); | 			n = call->u.fnc.spec.impl(rtx, &call->u.fnc.info); | ||||||
| 			if (n <= -1) | 			if (HAWK_UNLIKELY(n <= -1)) ADJERR_LOC (rtx, &nde->loc); | ||||||
| 			{ |  | ||||||
| 				ADJERR_LOC (rtx, &nde->loc); |  | ||||||
| 				/* correct the return code just in case */ |  | ||||||
| 				if (n < -1) n = -1; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -6300,7 +6295,7 @@ static hawk_val_t* __eval_call ( | |||||||
| 		hawk_nde_t* p = call->args; | 		hawk_nde_t* p = call->args; | ||||||
| 		for (i = 0; i < call->nargs; i++) | 		for (i = 0; i < call->nargs; i++) | ||||||
| 		{ | 		{ | ||||||
| 			if (fun->argspec[i] == HAWK_T('r')) | 			if (n >= 0 && fun->argspec[i] == HAWK_T('r')) | ||||||
| 			{ | 			{ | ||||||
| 				hawk_val_t** ref; | 				hawk_val_t** ref; | ||||||
| 				hawk_val_ref_t refv; | 				hawk_val_ref_t refv; | ||||||
| @ -6316,7 +6311,11 @@ static hawk_val_t* __eval_call ( | |||||||
| 				rtx->stack_base = cur_stack_base; /* UGLY */ | 				rtx->stack_base = cur_stack_base; /* UGLY */ | ||||||
|  |  | ||||||
| 				HAWK_RTX_INIT_REF_VAL (&refv, p->type - HAWK_NDE_NAMED, ref, 9); /* initialize a fake reference variable. 9 chosen randomly */ | 				HAWK_RTX_INIT_REF_VAL (&refv, p->type - HAWK_NDE_NAMED, ref, 9); /* initialize a fake reference variable. 9 chosen randomly */ | ||||||
| 				hawk_rtx_setrefval (rtx, &refv, HAWK_RTX_STACK_ARG(rtx, i)); | 				if (HAWK_UNLIKELY(hawk_rtx_setrefval(rtx, &refv, HAWK_RTX_STACK_ARG(rtx, i)) <= -1))  | ||||||
|  | 				{ | ||||||
|  | 					n = -1; | ||||||
|  | 					ADJERR_LOC (rtx, &nde->loc); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i)); | 			hawk_rtx_refdownval (rtx, HAWK_RTX_STACK_ARG(rtx,i)); | ||||||
| @ -6341,7 +6340,7 @@ static hawk_val_t* __eval_call ( | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	v = HAWK_RTX_STACK_RETVAL(rtx); | 	v = HAWK_RTX_STACK_RETVAL(rtx); | ||||||
| 	if (n == -1) | 	if (HAWK_UNLIKELY(n <= -1)) | ||||||
| 	{ | 	{ | ||||||
| 		if (hawk_rtx_geterrnum(rtx) == HAWK_ENOERR && errhandler != HAWK_NULL)  | 		if (hawk_rtx_geterrnum(rtx) == HAWK_ENOERR && errhandler != HAWK_NULL)  | ||||||
| 		{ | 		{ | ||||||
| @ -6394,7 +6393,7 @@ static hawk_val_t* __eval_call ( | |||||||
| #if defined(DEBUG_RUN) | #if defined(DEBUG_RUN) | ||||||
| 	hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("returning from function top=%zd, base=%zd\n"), (hawk_oow_t)rtx->stack_top, (hawk_oow_t)rtx->stack_base);  | 	hawk_logfmt (hawk_rtx_gethawk(rtx), HAWK_T("returning from function top=%zd, base=%zd\n"), (hawk_oow_t)rtx->stack_top, (hawk_oow_t)rtx->stack_base);  | ||||||
| #endif | #endif | ||||||
| 	return (n == -1)? HAWK_NULL: v; | 	return (n <= -1)? HAWK_NULL: v; | ||||||
| } | } | ||||||
|  |  | ||||||
| static hawk_oow_t push_arg_from_vals (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, void* data) | static hawk_oow_t push_arg_from_vals (hawk_rtx_t* rtx, hawk_nde_fncall_t* call, void* data) | ||||||
| @ -6577,41 +6576,11 @@ static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref) | |||||||
| 			return 0; | 			return 0; | ||||||
|  |  | ||||||
| 		case HAWK_NDE_NAMEDIDX: | 		case HAWK_NDE_NAMEDIDX: | ||||||
| 		{ |  | ||||||
| 			hawk_htb_pair_t* pair; |  | ||||||
|  |  | ||||||
| 			pair = hawk_htb_search(rtx->named, tgt->id.name.ptr, tgt->id.name.len); |  | ||||||
| 			if (pair == HAWK_NULL) |  | ||||||
| 			{ |  | ||||||
| 				pair = hawk_htb_upsert(rtx->named, tgt->id.name.ptr, tgt->id.name.len, hawk_val_nil, 0); |  | ||||||
| 				if (pair == HAWK_NULL)  |  | ||||||
| 				{ |  | ||||||
| 					ADJERR_LOC (rtx, &nde->loc); |  | ||||||
| 					return -1; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_HTB_VPTR(pair)); |  | ||||||
| 			if (tmp == HAWK_NULL) return -1; |  | ||||||
| 			*ref = tmp; |  | ||||||
| 			return 0; |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		case HAWK_NDE_GBLIDX: | 		case HAWK_NDE_GBLIDX: | ||||||
| 			tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_GBL(rtx,tgt->id.idxa)); |  | ||||||
| 			if (tmp == HAWK_NULL) return -1; |  | ||||||
| 			*ref = tmp; |  | ||||||
| 			return 0; |  | ||||||
|  |  | ||||||
| 		case HAWK_NDE_LCLIDX: | 		case HAWK_NDE_LCLIDX: | ||||||
| 			tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_LCL(rtx,tgt->id.idxa)); |  | ||||||
| 			if (tmp == HAWK_NULL) return -1; |  | ||||||
| 			*ref = tmp; |  | ||||||
| 			return 0; |  | ||||||
|  |  | ||||||
| 		case HAWK_NDE_ARGIDX: | 		case HAWK_NDE_ARGIDX: | ||||||
| 			tmp = get_reference_indexed(rtx, tgt, (hawk_val_t**)&HAWK_RTX_STACK_ARG(rtx,tgt->id.idxa)); | 			tmp = get_reference_indexed(rtx, tgt); | ||||||
| 			if (tmp == HAWK_NULL) return -1; | 			if (HAWK_UNLIKELY(!tmp)) return -1; | ||||||
| 			*ref = tmp; | 			*ref = tmp; | ||||||
| 			return 0; | 			return 0; | ||||||
|  |  | ||||||
| @ -6624,13 +6593,13 @@ static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref) | |||||||
| 			/* the position number is returned for the positional  | 			/* the position number is returned for the positional  | ||||||
| 			 * variable unlike other reference types. */ | 			 * variable unlike other reference types. */ | ||||||
| 			v = eval_expression(rtx, ((hawk_nde_pos_t*)nde)->val); | 			v = eval_expression(rtx, ((hawk_nde_pos_t*)nde)->val); | ||||||
| 			if (v == HAWK_NULL) return -1; | 			if (HAWK_UNLIKELY(!v)) return -1; | ||||||
|  |  | ||||||
| 			hawk_rtx_refupval (rtx, v); | 			hawk_rtx_refupval (rtx, v); | ||||||
| 			n = hawk_rtx_valtoint(rtx, v, &lv); | 			n = hawk_rtx_valtoint(rtx, v, &lv); | ||||||
| 			hawk_rtx_refdownval (rtx, v); | 			hawk_rtx_refdownval (rtx, v); | ||||||
|  |  | ||||||
| 			if (n <= -1)  | 			if (HAWK_UNLIKELY(n <= -1)) | ||||||
| 			{ | 			{ | ||||||
| 				hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_EPOSIDX); | 				hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_EPOSIDX); | ||||||
| 				return -1; | 				return -1; | ||||||
| @ -6652,51 +6621,83 @@ static int get_reference (hawk_rtx_t* rtx, hawk_nde_t* nde, hawk_val_t*** ref) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, hawk_val_t** val) | static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* var) | ||||||
| { | { | ||||||
|  | 	hawk_map_t* map; | ||||||
| 	hawk_map_pair_t* pair; | 	hawk_map_pair_t* pair; | ||||||
| 	hawk_ooch_t* str = HAWK_NULL; | 	hawk_ooch_t* str = HAWK_NULL; | ||||||
| 	hawk_oow_t len; | 	hawk_oow_t len; | ||||||
| 	hawk_ooch_t idxbuf[IDXBUFSIZE]; | 	hawk_ooch_t idxbuf[IDXBUFSIZE]; | ||||||
|  | 	hawk_val_t* v; | ||||||
| 	hawk_val_type_t vtype; | 	hawk_val_type_t vtype; | ||||||
| 	hawk_nde_t* remidx; | 	hawk_nde_t* remidx; | ||||||
|  |  | ||||||
| 	HAWK_ASSERT (val != HAWK_NULL); | 	HAWK_ASSERT (var->idx != HAWK_NULL); | ||||||
|  |  | ||||||
| 	vtype = HAWK_RTX_GETVALTYPE(rtx, *val); | 	v = fetch_topval_from_var(rtx, var); | ||||||
| 	if (vtype == HAWK_VAL_NIL) | 	vtype = HAWK_RTX_GETVALTYPE(rtx, v); | ||||||
|  |  | ||||||
|  | 	switch (vtype) | ||||||
| 	{ | 	{ | ||||||
| 		hawk_val_t* tmp; | 		case HAWK_VAL_NIL: | ||||||
|  | 			v = assign_newmapval_to_var(rtx, var); | ||||||
|  | 			if (HAWK_UNLIKELY(!v)) goto oops; | ||||||
|  | 			break; | ||||||
| 		 | 		 | ||||||
| 		tmp = hawk_rtx_makemapval(rtx); | 		case HAWK_VAL_MAP: | ||||||
| 		if (HAWK_UNLIKELY(!tmp)) goto oops; | 			/* do nothing */ | ||||||
|  | 			break; | ||||||
|  |  | ||||||
| 		hawk_rtx_refdownval (rtx, *val); | 		default: | ||||||
| 		*val = tmp; | 			hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP); | ||||||
| 		hawk_rtx_refupval (rtx, (hawk_val_t*)*val); | 			goto oops; | ||||||
| 	} | 	} | ||||||
| 	else if (vtype != HAWK_VAL_MAP)  |  | ||||||
| 	{ |  | ||||||
| 		hawk_rtx_seterrnum (rtx, &nde->loc, HAWK_ENOTMAP); |  | ||||||
| 		goto oops; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	HAWK_ASSERT (nde->idx != HAWK_NULL); |  | ||||||
|  |  | ||||||
| 	len = HAWK_COUNTOF(idxbuf); | 	len = HAWK_COUNTOF(idxbuf); | ||||||
| 	str = idxnde_to_str(rtx, nde->idx, idxbuf, &len, &remidx); | 	str = idxnde_to_str(rtx, var->idx, idxbuf, &len, &remidx); | ||||||
| 	if (HAWK_UNLIKELY(!str)) goto oops; | 	if (HAWK_UNLIKELY(!str)) goto oops; | ||||||
|  |  | ||||||
|  | 	map = ((hawk_val_map_t*)v)->map; | ||||||
|  |  | ||||||
| #if defined(HAWK_ENABLE_GC) | #if defined(HAWK_ENABLE_GC) | ||||||
| /* TODO: true-multidimensional map support  */ | 	while (remidx) | ||||||
|  | 	{ | ||||||
|  | 		pair = hawk_map_search(map, str, len); | ||||||
|  | 		v = pair? (hawk_val_t*)HAWK_HTB_VPTR(pair): hawk_val_nil; | ||||||
|  | 		vtype = HAWK_RTX_GETVALTYPE(rtx, v); | ||||||
|  |  | ||||||
|  | 		switch (vtype) | ||||||
|  | 		{ | ||||||
|  | 			case HAWK_VAL_NIL: | ||||||
|  | 				v = assign_newmapval_in_map(rtx, map, str, len); | ||||||
|  | 				if (HAWK_UNLIKELY(!v)) goto oops; | ||||||
|  | 				map = ((hawk_val_map_t*)v)->map; | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			case HAWK_VAL_MAP: | ||||||
|  | 				map = ((hawk_val_map_t*)v)->map; | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			default: | ||||||
|  | 				hawk_rtx_seterrnum (rtx, &var->loc, HAWK_ENOTMAP); | ||||||
|  | 				goto oops; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (str != idxbuf) hawk_rtx_freemem (rtx, str); | ||||||
|  | 		len = HAWK_COUNTOF(idxbuf); | ||||||
|  | 		str = idxnde_to_str(rtx, remidx, idxbuf, &len, &remidx); | ||||||
|  | 		if (HAWK_UNLIKELY(!str)) goto oops; | ||||||
|  | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	pair = hawk_map_search((*(hawk_val_map_t**)val)->map, str, len); | 	pair = hawk_map_search(map, str, len); | ||||||
| 	if (!pair) | 	if (!pair) | ||||||
| 	{ | 	{ | ||||||
| 		pair = hawk_map_upsert((*(hawk_val_map_t**)val)->map, str, len, hawk_val_nil, 0); | 		pair = hawk_map_upsert(map, str, len, hawk_val_nil, 0); | ||||||
| 		if (HAWK_UNLIKELY(!pair)) goto oops; | 		if (HAWK_UNLIKELY(!pair)) goto oops; | ||||||
| 		hawk_rtx_refupval (rtx, HAWK_HTB_VPTR(pair)); | 		HAWK_ASSERT (HAWK_HTB_VPTR(pair) == hawk_val_nil); | ||||||
|  | 		/* no reference count increment as hawk_val_nil is upserted | ||||||
|  | 		hawk_rtx_refupval (rtx, HAWK_HTB_VPTR(pair)); */ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (str != idxbuf) hawk_rtx_freemem (rtx, str); | 	if (str != idxbuf) hawk_rtx_freemem (rtx, str); | ||||||
| @ -6704,7 +6705,7 @@ static hawk_val_t** get_reference_indexed (hawk_rtx_t* rtx, hawk_nde_var_t* nde, | |||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); | 	if (str && str != idxbuf) hawk_rtx_freemem (rtx, str); | ||||||
| 	ADJERR_LOC (rtx, &nde->loc); | 	ADJERR_LOC (rtx, &var->loc); | ||||||
| 	return HAWK_NULL; | 	return HAWK_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -2503,6 +2503,7 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) | |||||||
| 		case HAWK_VAL_REF_GBLIDX: | 		case HAWK_VAL_REF_GBLIDX: | ||||||
| 		case HAWK_VAL_REF_LCLIDX: | 		case HAWK_VAL_REF_LCLIDX: | ||||||
| 		case HAWK_VAL_REF_ARGIDX: | 		case HAWK_VAL_REF_ARGIDX: | ||||||
|  | 		#if !defined(HAWK_ENABLE_GC) | ||||||
| 			if (vtype == HAWK_VAL_MAP) | 			if (vtype == HAWK_VAL_MAP) | ||||||
| 			{ | 			{ | ||||||
| 				/* an indexed variable cannot be assigned a map.  | 				/* an indexed variable cannot be assigned a map.  | ||||||
| @ -2510,6 +2511,7 @@ int hawk_rtx_setrefval (hawk_rtx_t* rtx, hawk_val_ref_t* ref, hawk_val_t* val) | |||||||
| 				hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOIDX); | 				hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_EMAPTOIDX); | ||||||
| 				return -1; | 				return -1; | ||||||
| 			} | 			} | ||||||
|  | 		#endif | ||||||
| 			/* fall through */ | 			/* fall through */ | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user