fixed the reader and the compiler to process the a dic/array/byte-array item after a period in a data list properly
This commit is contained in:
		| @ -133,11 +133,19 @@ hcl_cnode_t* hcl_makecnodecons (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_cnode_t* | |||||||
| 	return c; | 	return c; | ||||||
| } | } | ||||||
|  |  | ||||||
| hcl_cnode_t* hcl_makecnodelist (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_concode_t type) | hcl_cnode_t* hcl_makecnodeelist (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_concode_t type) | ||||||
| { | { | ||||||
| 	hcl_cnode_t* c =  make_cnode(hcl, HCL_CNODE_LIST, loc, HCL_NULL); | 	hcl_cnode_t* c =  make_cnode(hcl, HCL_CNODE_ELIST, loc, HCL_NULL); | ||||||
| 	if (HCL_UNLIKELY(!c)) return HCL_NULL; | 	if (HCL_UNLIKELY(!c)) return HCL_NULL; | ||||||
| 	c->u.list.concode = type; | 	c->u.elist.concode = type; | ||||||
|  | 	return c; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | hcl_cnode_t* hcl_makecnodeshell (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_cnode_t* obj) | ||||||
|  | { | ||||||
|  | 	hcl_cnode_t* c =  make_cnode(hcl, HCL_CNODE_SHELL, loc, HCL_NULL); | ||||||
|  | 	if (HCL_UNLIKELY(!c)) return HCL_NULL; | ||||||
|  | 	c->u.shell.obj = obj; | ||||||
| 	return c; | 	return c; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -172,6 +180,23 @@ redo: | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		case HCL_CNODE_SHELL: | ||||||
|  | 		{ | ||||||
|  | 			hcl_cnode_t* tmp; | ||||||
|  |  | ||||||
|  | 			tmp = c->u.shell.obj; | ||||||
|  |  | ||||||
|  | 			hcl_freemem (hcl, c); | ||||||
|  |  | ||||||
|  | 			if (tmp) | ||||||
|  | 			{ | ||||||
|  | 				c = tmp; | ||||||
|  | 				goto redo; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			hcl_freemem (hcl, c); | 			hcl_freemem (hcl, c); | ||||||
| 			break; | 			break; | ||||||
|  | |||||||
| @ -1950,6 +1950,7 @@ static int compile_object (hcl_t* hcl) | |||||||
| 	HCL_ASSERT (hcl, cf->opcode == COP_COMPILE_OBJECT); | 	HCL_ASSERT (hcl, cf->opcode == COP_COMPILE_OBJECT); | ||||||
|  |  | ||||||
| 	oprnd = cf->operand; | 	oprnd = cf->operand; | ||||||
|  | redo: | ||||||
| 	switch (HCL_CNODE_GET_TYPE(oprnd)) | 	switch (HCL_CNODE_GET_TYPE(oprnd)) | ||||||
| 	{ | 	{ | ||||||
| 		case HCL_CNODE_NIL: | 		case HCL_CNODE_NIL: | ||||||
| @ -2040,10 +2041,10 @@ static int compile_object (hcl_t* hcl) | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		case HCL_CNODE_LIST: | 		case HCL_CNODE_ELIST: | ||||||
| 		{ | 		{ | ||||||
| 			/* empty list */ | 			/* empty list */ | ||||||
| 			switch (HCL_CNODE_LIST_CONCODE(oprnd)) | 			switch (HCL_CNODE_ELIST_CONCODE(oprnd)) | ||||||
| 			{ | 			{ | ||||||
| 				case HCL_CONCODE_XLIST: | 				case HCL_CONCODE_XLIST: | ||||||
| 					hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARDCLBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty executable list"); | 					hcl_setsynerrbfmt (hcl, HCL_SYNERR_VARDCLBANNED, HCL_CNODE_GET_LOC(oprnd), HCL_NULL, "empty executable list"); | ||||||
| @ -2077,6 +2078,11 @@ static int compile_object (hcl_t* hcl) | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		case HCL_CNODE_SHELL: | ||||||
|  | 			/* a shell node is just a wrapper of an actual node */ | ||||||
|  | 			oprnd = oprnd->u.shell.obj; | ||||||
|  | 			goto redo; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			hcl_setsynerrbfmt (hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "internal error - unexpected object type %d", HCL_CNODE_GET_TYPE(oprnd)); | 			hcl_setsynerrbfmt (hcl, HCL_SYNERR_INTERN, HCL_CNODE_GET_LOC(oprnd), HCL_CNODE_GET_TOK(oprnd), "internal error - unexpected object type %d", HCL_CNODE_GET_TYPE(oprnd)); | ||||||
| 			return -1; | 			return -1; | ||||||
|  | |||||||
| @ -197,7 +197,8 @@ enum hcl_cnode_type_t | |||||||
| 	HCL_CNODE_FALSE, | 	HCL_CNODE_FALSE, | ||||||
|  |  | ||||||
| 	HCL_CNODE_CONS, | 	HCL_CNODE_CONS, | ||||||
| 	HCL_CNODE_LIST | 	HCL_CNODE_ELIST, /* empty list */ | ||||||
|  | 	HCL_CNODE_SHELL  /* pseudo-node to hold another actual node */ | ||||||
| }; | }; | ||||||
| typedef enum hcl_cnode_type_t hcl_cnode_type_t; | typedef enum hcl_cnode_type_t hcl_cnode_type_t; | ||||||
|  |  | ||||||
| @ -220,9 +221,9 @@ typedef enum hcl_cnode_type_t hcl_cnode_type_t; | |||||||
| #define HCL_CNODE_CONS_CDR(x) ((x)->u.cons.cdr) | #define HCL_CNODE_CONS_CDR(x) ((x)->u.cons.cdr) | ||||||
|  |  | ||||||
|  |  | ||||||
| #define HCL_CNODE_IS_LIST(x) ((x)->cn_type == HCL_CNODE_LIST) | #define HCL_CNODE_IS_ELIST(x) ((x)->cn_type == HCL_CNODE_ELIST) | ||||||
| #define HCL_CNODE_IS_LIST_CONCODED(x) ((x)->cn_type == HCL_CNODE_LIST && (x)->u.list.concode == (code)) | #define HCL_CNODE_IS_ELIST_CONCODED(x) ((x)->cn_type == HCL_CNODE_ELIST && (x)->u.elist.concode == (code)) | ||||||
| #define HCL_CNODE_LIST_CONCODE(x) ((x)->u.list.concode) | #define HCL_CNODE_ELIST_CONCODE(x) ((x)->u.elist.concode) | ||||||
|  |  | ||||||
| /* NOTE: hcl_cnode_t used by the built-in compiler is not an OOP object */ | /* NOTE: hcl_cnode_t used by the built-in compiler is not an OOP object */ | ||||||
| struct hcl_cnode_t | struct hcl_cnode_t | ||||||
| @ -260,7 +261,11 @@ struct hcl_cnode_t | |||||||
| 		struct | 		struct | ||||||
| 		{ | 		{ | ||||||
| 			hcl_concode_t concode; | 			hcl_concode_t concode; | ||||||
| 		} list; | 		} elist; | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			hcl_cnode_t* obj; | ||||||
|  | 		} shell; | ||||||
| 	} u; | 	} u; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @ -1359,7 +1364,8 @@ hcl_cnode_t* hcl_makecnodefpdeclit (hcl_t* hcl, const hcl_ioloc_t* loc, const  h | |||||||
| hcl_cnode_t* hcl_makecnodesmptrlit (hcl_t* hcl, const hcl_ioloc_t* loc, const  hcl_oocs_t* tok, hcl_oow_t v); | hcl_cnode_t* hcl_makecnodesmptrlit (hcl_t* hcl, const hcl_ioloc_t* loc, const  hcl_oocs_t* tok, hcl_oow_t v); | ||||||
| hcl_cnode_t* hcl_makecnodeerrlit (hcl_t* hcl, const hcl_ioloc_t* loc, const  hcl_oocs_t* tok, hcl_ooi_t v); | hcl_cnode_t* hcl_makecnodeerrlit (hcl_t* hcl, const hcl_ioloc_t* loc, const  hcl_oocs_t* tok, hcl_ooi_t v); | ||||||
| hcl_cnode_t* hcl_makecnodecons (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_cnode_t* car, hcl_cnode_t* cdr); | hcl_cnode_t* hcl_makecnodecons (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_cnode_t* car, hcl_cnode_t* cdr); | ||||||
| hcl_cnode_t* hcl_makecnodelist (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_concode_t type); | hcl_cnode_t* hcl_makecnodeelist (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_concode_t type); | ||||||
|  | hcl_cnode_t* hcl_makecnodeshell (hcl_t* hcl, const hcl_ioloc_t* loc, hcl_cnode_t* obj); | ||||||
| void hcl_freesinglecnode (hcl_t* hcl, hcl_cnode_t* c); | void hcl_freesinglecnode (hcl_t* hcl, hcl_cnode_t* c); | ||||||
| void hcl_freecnode (hcl_t* hcl, hcl_cnode_t* c); | void hcl_freecnode (hcl_t* hcl, hcl_cnode_t* c); | ||||||
| hcl_oow_t hcl_countcnodecons (hcl_t* hcl, hcl_cnode_t* cons); | hcl_oow_t hcl_countcnodecons (hcl_t* hcl, hcl_cnode_t* cons); | ||||||
|  | |||||||
| @ -1469,7 +1469,7 @@ static HCL_INLINE hcl_cnode_t* leave_list (hcl_t* hcl, int* flagv, int* oldflagv | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* the list is empty */ | 	/* the list is empty */ | ||||||
| 	return hcl_makecnodelist(hcl, &loc, concode); | 	return hcl_makecnodeelist(hcl, &loc, concode); | ||||||
| } | } | ||||||
|  |  | ||||||
| static HCL_INLINE int can_dot_list (hcl_t* hcl) | static HCL_INLINE int can_dot_list (hcl_t* hcl) | ||||||
| @ -1555,12 +1555,12 @@ static int chain_to_list (hcl_t* hcl, hcl_cnode_t* obj) | |||||||
| 	if (flagv & CLOSED) | 	if (flagv & CLOSED) | ||||||
| 	{ | 	{ | ||||||
| 		/* the list has already been closed and cannot add more items | 		/* the list has already been closed and cannot add more items | ||||||
| 		 * for instance,  see this faulty expression [1 2 . 3 4 ]. | 		 * for instance,  see this faulty expression #(1 2 . 3 4 ). | ||||||
| 		 * you can have only 1 item  after the period. this condition | 		 * you can have only 1 item  after the period. this condition | ||||||
| 		 * can only be triggered by a wrong qlist where a period is | 		 * can only be triggered by a wrong qlist where a period is | ||||||
| 		 * allowed. so i can safely hard-code the error code to | 		 * allowed. so i can safely hard-code the error code to | ||||||
| 		 * HCL_SYNERR_RBRACK. */ | 		 * HCL_SYNERR_RPAREN */ | ||||||
| 		hcl_setsynerr (hcl, HCL_SYNERR_RBRACK, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); | 		hcl_setsynerr (hcl, HCL_SYNERR_RPAREN, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	else if (flagv & DOTTED) | 	else if (flagv & DOTTED) | ||||||
| @ -1575,7 +1575,25 @@ static int chain_to_list (hcl_t* hcl, hcl_cnode_t* obj) | |||||||
| 		tail = rstl->tail; | 		tail = rstl->tail; | ||||||
| 		HCL_ASSERT (hcl, tail != HCL_NULL); | 		HCL_ASSERT (hcl, tail != HCL_NULL); | ||||||
| 		HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(tail)); | 		HCL_ASSERT (hcl, HCL_CNODE_IS_CONS(tail)); | ||||||
|  |  | ||||||
|  | 		if (HCL_CNODE_IS_CONS(obj) && HCL_CNODE_CONS_CONCODE(obj) != HCL_CONCODE_QLIST) | ||||||
|  | 		{ | ||||||
|  | 			hcl_cnode_t* shell; | ||||||
|  |  | ||||||
|  | 			/* if the last element is another non-data list | ||||||
|  | 			 * for example, #( 1 2 . [ 3 4 5  ])  | ||||||
|  | 			 * use a shell node to wrap the actual object list node head | ||||||
|  | 			 * for the compiler. | ||||||
|  | 			 */ | ||||||
|  | 			shell = hcl_makecnodeshell(hcl, HCL_CNODE_GET_LOC(obj), obj); | ||||||
|  | 			if (HCL_UNLIKELY(!shell)) return -1; | ||||||
|  |  | ||||||
|  | 			tail->u.cons.cdr = shell; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
| 			tail->u.cons.cdr = obj; | 			tail->u.cons.cdr = obj; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		/* update the flag to CLOSED so that you can have more than | 		/* update the flag to CLOSED so that you can have more than | ||||||
| 		 * one item after the dot. */ | 		 * one item after the dot. */ | ||||||
| @ -1688,7 +1706,8 @@ static hcl_cnode_t* read_vlist (hcl_t* hcl) | |||||||
| 		return vh; | 		return vh; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return hcl_makecnodelist(hcl, &start_loc, HCL_CONCODE_VLIST); | 	/* this is an empty list */ | ||||||
|  | 	return hcl_makecnodeelist(hcl, &start_loc, HCL_CONCODE_VLIST); | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	if (vh) hcl_freecnode (hcl, vh); | 	if (vh) hcl_freecnode (hcl, vh); | ||||||
| @ -1983,8 +2002,7 @@ static hcl_cnode_t* read_object (hcl_t* hcl) | |||||||
| 			/* if so, append the element read into the quote list */ | 			/* if so, append the element read into the quote list */ | ||||||
| 			if (chain_to_list(hcl, obj) <= -1) goto oops; | 			if (chain_to_list(hcl, obj) <= -1) goto oops; | ||||||
|  |  | ||||||
| 			/* exit out of the quoted list. the quoted list can have | 			/* exit out of the quoted list. the quoted list can have one element only. */ | ||||||
| 			 * one element only. */ |  | ||||||
| 			obj = leave_list(hcl, &flagv, &oldflagv); | 			obj = leave_list(hcl, &flagv, &oldflagv); | ||||||
|  |  | ||||||
| 			/* one level up toward the top */ | 			/* one level up toward the top */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user