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:
parent
fbbdb6188e
commit
2e3fae05e4
31
lib/cnode.c
31
lib/cnode.c
@ -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;
|
||||||
|
14
lib/comp2.c
14
lib/comp2.c
@ -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;
|
||||||
@ -3229,11 +3235,11 @@ int hcl_compile2 (hcl_t* hcl, hcl_cnode_t* obj)
|
|||||||
case COP_SUBCOMPILE_AND_EXPR:
|
case COP_SUBCOMPILE_AND_EXPR:
|
||||||
if (subcompile_and_expr(hcl) <= -1) goto oops;
|
if (subcompile_and_expr(hcl) <= -1) goto oops;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COP_SUBCOMPILE_OR_EXPR:
|
case COP_SUBCOMPILE_OR_EXPR:
|
||||||
if (subcompile_or_expr(hcl) <= -1) goto oops;
|
if (subcompile_or_expr(hcl) <= -1) goto oops;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COP_POST_AND_EXPR:
|
case COP_POST_AND_EXPR:
|
||||||
if (post_and_expr(hcl) <= -1) goto oops;
|
if (post_and_expr(hcl) <= -1) goto oops;
|
||||||
break;
|
break;
|
||||||
|
@ -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);
|
||||||
|
34
lib/read2.c
34
lib/read2.c
@ -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));
|
||||||
tail->u.cons.cdr = obj;
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user