added HCL_LOG_PREFER_JSON and implemented %J

This commit is contained in:
hyung-hwan 2018-03-02 07:44:13 +00:00
parent 450526215a
commit 60a32bf642
5 changed files with 107 additions and 54 deletions

26
README.md Normal file
View File

@ -0,0 +1,26 @@
# HCL - Hybrid Command Language
## Language Syntax
A HCL program is composed of 0 or more expressions.
## Special Form Expression
* break
* defun
* do
* elif
* else
* if
* lambda
* return
* set
* until
* while
## literals
* #nil
* #true
* #false

View File

@ -1011,7 +1011,6 @@ struct hcl_t
hcl_oop_t _else; /* symbol */ hcl_oop_t _else; /* symbol */
hcl_oop_t _if; /* symbol */ hcl_oop_t _if; /* symbol */
hcl_oop_t _lambda; /* symbol */ hcl_oop_t _lambda; /* symbol */
hcl_oop_t _quote; /* symbol */
hcl_oop_t _return; /* symbol */ hcl_oop_t _return; /* symbol */
hcl_oop_t _set; /* symbol */ hcl_oop_t _set; /* symbol */
hcl_oop_t _until; /* symbol */ hcl_oop_t _until; /* symbol */
@ -1156,28 +1155,29 @@ struct hcl_t
enum hcl_log_mask_t enum hcl_log_mask_t
{ {
HCL_LOG_DEBUG = (1 << 0), HCL_LOG_DEBUG = (1 << 0),
HCL_LOG_INFO = (1 << 1), HCL_LOG_INFO = (1 << 1),
HCL_LOG_WARN = (1 << 2), HCL_LOG_WARN = (1 << 2),
HCL_LOG_ERROR = (1 << 3), HCL_LOG_ERROR = (1 << 3),
HCL_LOG_FATAL = (1 << 4), HCL_LOG_FATAL = (1 << 4),
HCL_LOG_UNTYPED = (1 << 6), /* only to be used by HCL_DEBUGx() and HCL_INFOx() */ HCL_LOG_UNTYPED = (1 << 6), /* only to be used by HCL_DEBUGx() and HCL_INFOx() */
HCL_LOG_COMPILER = (1 << 7), HCL_LOG_COMPILER = (1 << 7),
HCL_LOG_VM = (1 << 8), HCL_LOG_VM = (1 << 8),
HCL_LOG_MNEMONIC = (1 << 9), /* bytecode mnemonic */ HCL_LOG_MNEMONIC = (1 << 9), /* bytecode mnemonic */
HCL_LOG_GC = (1 << 10), HCL_LOG_GC = (1 << 10),
HCL_LOG_IC = (1 << 11), /* instruction cycle, fetch-decode-execute */ HCL_LOG_IC = (1 << 11), /* instruction cycle, fetch-decode-execute */
HCL_LOG_PRIMITIVE = (1 << 12), HCL_LOG_PRIMITIVE = (1 << 12),
HCL_LOG_APP = (1 << 13), /* hcl applications, set by hcl logging primitive */ HCL_LOG_APP = (1 << 13), /* hcl applications, set by hcl logging primitive */
HCL_LOG_ALL_LEVELS = (HCL_LOG_DEBUG | HCL_LOG_INFO | HCL_LOG_WARN | HCL_LOG_ERROR | HCL_LOG_FATAL), HCL_LOG_ALL_LEVELS = (HCL_LOG_DEBUG | HCL_LOG_INFO | HCL_LOG_WARN | HCL_LOG_ERROR | HCL_LOG_FATAL),
HCL_LOG_ALL_TYPES = (HCL_LOG_UNTYPED | HCL_LOG_COMPILER | HCL_LOG_VM | HCL_LOG_MNEMONIC | HCL_LOG_GC | HCL_LOG_IC | HCL_LOG_PRIMITIVE | HCL_LOG_APP), HCL_LOG_ALL_TYPES = (HCL_LOG_UNTYPED | HCL_LOG_COMPILER | HCL_LOG_VM | HCL_LOG_MNEMONIC | HCL_LOG_GC | HCL_LOG_IC | HCL_LOG_PRIMITIVE | HCL_LOG_APP),
HCL_LOG_STDOUT = (1 << 14), /* write log messages to stdout without timestamp. HCL_LOG_STDOUT wins over HCL_LOG_STDERR. */ HCL_LOG_STDOUT = (1 << 14), /* write log messages to stdout without timestamp. HCL_LOG_STDOUT wins over HCL_LOG_STDERR. */
HCL_LOG_STDERR = (1 << 15) /* write log messages to stderr without timestamp. */ HCL_LOG_STDERR = (1 << 15), /* write log messages to stderr without timestamp. */
HCL_LOG_PREFER_JSON = (1 << 30) /* write a object in the json format. don't set this explicitly. use %J instead */
}; };
typedef enum hcl_log_mask_t hcl_log_mask_t; typedef enum hcl_log_mask_t hcl_log_mask_t;

View File

@ -1002,6 +1002,11 @@ static HCL_INLINE int print_formatted (hcl_t* hcl, hcl_ooi_t nargs, hcl_fmtout_t
if (hcl_outfmtobj(hcl, data->mask, arg, outbfmt) <= -1) goto oops; if (hcl_outfmtobj(hcl, data->mask, arg, outbfmt) <= -1) goto oops;
break; break;
case 'J':
GET_NEXT_ARG_TO (hcl, nargs, &arg_state, arg);
if (hcl_outfmtobj(hcl, data->mask | HCL_LOG_PREFER_JSON, arg, outbfmt) <= -1) goto oops;
break;
number: number:
{ {
const hcl_ooch_t* nsptr; const hcl_ooch_t* nsptr;

View File

@ -588,6 +588,10 @@ static int logfmtv (hcl_t* hcl, const fmtchar_t* fmt, hcl_fmtout_t* data, va_lis
if (hcl_outfmtobj(hcl, data->mask, va_arg(ap, hcl_oop_t), outbfmt) <= -1) goto oops; if (hcl_outfmtobj(hcl, data->mask, va_arg(ap, hcl_oop_t), outbfmt) <= -1) goto oops;
break; break;
case 'J':
if (hcl_outfmtobj(hcl, data->mask | HCL_LOG_PREFER_JSON, va_arg(ap, hcl_oop_t), outbfmt) <= -1) goto oops;
break;
#if 0 #if 0
case 'e': case 'e':
case 'E': case 'E':

View File

@ -196,6 +196,34 @@ static HCL_INLINE int outfmt_obj (hcl_t* hcl, int mask, hcl_oop_t obj, hcl_outbf
print_stack_t ps; print_stack_t ps;
int brand; int brand;
int word_index; int word_index;
int word_offset;
int json;
static const hcl_bch_t *opening_parens[][2] =
{
{ "(", "(" }, /*HCL_CONCODE_XLIST */
{ "#(", "[" }, /*HCL_CONCODE_ARRAY */
{ "#[", "[" }, /*HCL_CONCODE_BYTEARRAY */
{ "#{", "{" }, /*HCL_CONCODE_DIC */
{ "[", "]" } /*HCL_CONCODE_QLIST */
};
static const hcl_bch_t *closing_parens[][2] =
{
{ ")", ")" }, /*HCL_CONCODE_XLIST */
{ ")", "]" }, /*HCL_CONCODE_ARRAY */
{ "]", "]" }, /*HCL_CONCODE_BYTEARRAY */
{ "}", "}" }, /*HCL_CONCODE_DIC */
{ "]", "]" } /*HCL_CONCODE_QLIST */
};
static const hcl_bch_t* breakers[][2] =
{
{ " ", "," }, /* item breaker */
{ " ", ":" } /* key value breaker */
};
json = !!(mask & HCL_LOG_PREFER_JSON);
next: next:
switch ((brand = HCL_BRANDOF(hcl, obj))) switch ((brand = HCL_BRANDOF(hcl, obj)))
@ -223,14 +251,17 @@ next:
case HCL_BRAND_NIL: case HCL_BRAND_NIL:
word_index = WORD_NIL; word_index = WORD_NIL;
word_offset = json;
goto print_word; goto print_word;
case HCL_BRAND_TRUE: case HCL_BRAND_TRUE:
word_index = WORD_TRUE; word_index = WORD_TRUE;
word_offset = json;
goto print_word; goto print_word;
case HCL_BRAND_FALSE: case HCL_BRAND_FALSE:
word_index = WORD_FALSE; word_index = WORD_FALSE;
word_offset = json;
goto print_word; goto print_word;
case HCL_BRAND_PBIGINT: case HCL_BRAND_PBIGINT:
@ -311,28 +342,13 @@ next:
case HCL_BRAND_CONS: case HCL_BRAND_CONS:
{ {
static hcl_bch_t *opening_paren[] =
{
"(", /*HCL_CONCODE_XLIST */
"#(", /*HCL_CONCODE_ARRAY */
"#[", /*HCL_CONCODE_BYTEARRAY */
"#{", /*HCL_CONCODE_DIC */
"[" /*HCL_CONCODE_QLIST */
};
static hcl_bch_t *closing_paren[] =
{
")", /*HCL_CONCODE_XLIST */
")", /*HCL_CONCODE_ARRAY */
"]", /*HCL_CONCODE_BYTEARRAY */
"}", /*HCL_CONCODE_DIC */
"]" /*HCL_CONCODE_QLIST */
};
int concode; int concode;
/* this part is to print a linked list of cells. ignore the
* request to output in the json format */
concode = HCL_OBJ_GET_FLAGS_SYNCODE(obj); concode = HCL_OBJ_GET_FLAGS_SYNCODE(obj);
if (outbfmt(hcl, mask, opening_paren[concode]) <= -1) return -1; if (outbfmt(hcl, mask, opening_parens[concode][0]) <= -1) return -1;
cur = obj; cur = obj;
do do
@ -384,11 +400,11 @@ next:
} }
/* The CDR part points to a pair. proceed to it */ /* The CDR part points to a pair. proceed to it */
if (outbfmt(hcl, mask, " ") <= -1) return -1; if (outbfmt(hcl, mask, breakers[0][0]) <= -1) return -1;
} }
while (1); while (1);
if (outbfmt(hcl, mask, closing_paren[concode]) <= -1) return -1; if (outbfmt(hcl, mask, closing_parens[concode][0]) <= -1) return -1;
break; break;
} }
@ -396,11 +412,11 @@ next:
{ {
hcl_oow_t arridx; hcl_oow_t arridx;
if (outbfmt(hcl, mask, "#(") <= -1) return -1; if (outbfmt(hcl, mask, opening_parens[HCL_CONCODE_ARRAY][json]) <= -1) return -1;
if (HCL_OBJ_GET_SIZE(obj) <= 0) if (HCL_OBJ_GET_SIZE(obj) <= 0)
{ {
if (outbfmt(hcl, mask, ")") <= -1) return -1; if (outbfmt(hcl, mask, closing_parens[HCL_CONCODE_ARRAY][json]) <= -1) return -1;
break; break;
} }
arridx = 0; arridx = 0;
@ -428,7 +444,7 @@ next:
obj = ((hcl_oop_oop_t)obj)->slot[arridx]; obj = ((hcl_oop_oop_t)obj)->slot[arridx];
if (arridx > 0) if (arridx > 0)
{ {
if (outbfmt(hcl, mask, " ") <= -1) return -1; if (outbfmt(hcl, mask, breakers[0][json]) <= -1) return -1;
} }
/* Jump to the 'next' label so that the object /* Jump to the 'next' label so that the object
* pointed to by 'obj' is printed. Once it * pointed to by 'obj' is printed. Once it
@ -448,14 +464,16 @@ next:
case HCL_BRAND_BYTE_ARRAY: case HCL_BRAND_BYTE_ARRAY:
{ {
hcl_oow_t i; hcl_oow_t i;
if (outbfmt(hcl, mask, opening_parens[HCL_CONCODE_BYTEARRAY][json]) <= -1) return -1;
if (outbfmt(hcl, mask, "#[") <= -1) return -1; if (HCL_OBJ_GET_SIZE(obj) > 0)
for (i = 0; i < HCL_OBJ_GET_SIZE(obj); i++)
{ {
if (outbfmt(hcl, mask, "%hs%d", ((i > 0)? " ": ""), ((hcl_oop_byte_t)obj)->slot[i]) <= -1) return -1; if (outbfmt(hcl, mask, "%d", ((hcl_oop_byte_t)obj)->slot[0]) <= -1) return -1;
for (i = 1; i < HCL_OBJ_GET_SIZE(obj); i++)
{
if (outbfmt(hcl, mask, "%hs%d", breakers[0][json], ((hcl_oop_byte_t)obj)->slot[i]) <= -1) return -1;
}
} }
if (outbfmt(hcl, mask, "]") <= -1) return -1; if (outbfmt(hcl, mask, closing_parens[HCL_CONCODE_BYTEARRAY][json]) <= -1) return -1;
break; break;
} }
@ -464,13 +482,13 @@ next:
hcl_oow_t bucidx, bucsize, buctally; hcl_oow_t bucidx, bucsize, buctally;
hcl_oop_dic_t dic; hcl_oop_dic_t dic;
if (outbfmt(hcl, mask, "#{") <= -1) return -1; if (outbfmt(hcl, mask, opening_parens[HCL_CONCODE_DIC][json]) <= -1) return -1;
dic = (hcl_oop_dic_t)obj; dic = (hcl_oop_dic_t)obj;
HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(dic->tally)); HCL_ASSERT (hcl, HCL_OOP_IS_SMOOI(dic->tally));
if (HCL_OOP_TO_SMOOI(dic->tally) <= 0) if (HCL_OOP_TO_SMOOI(dic->tally) <= 0)
{ {
if (outbfmt(hcl, mask, "}") <= -1) return -1; if (outbfmt(hcl, mask, closing_parens[HCL_CONCODE_DIC][json]) <= -1) return -1;
break; break;
} }
bucidx = 0; bucidx = 0;
@ -496,7 +514,7 @@ next:
if (bucidx >= bucsize) if (bucidx >= bucsize)
{ {
/* done. scanned the entire bucket */ /* done. scanned the entire bucket */
if (outbfmt(hcl, mask, "}") <= -1) return -1; if (outbfmt(hcl, mask, closing_parens[HCL_CONCODE_DIC][json]) <= -1) return -1;
break; break;
} }
@ -537,7 +555,7 @@ next:
if (buctally > 0) if (buctally > 0)
{ {
if (outbfmt(hcl, mask, " ") <= -1) return -1; if (outbfmt(hcl, mask, breakers[buctally & 1][json]) <= -1) return -1;
} }
/* Jump to the 'next' label so that the object /* Jump to the 'next' label so that the object
@ -606,7 +624,7 @@ next:
return -1; return -1;
print_word: print_word:
if (outbfmt(hcl, mask, "%.*js", word[word_index].len, word[word_index].ptr) <= -1) return -1; if (outbfmt(hcl, mask, "%.*js", word[word_index].len - word_offset, word[word_index].ptr + word_offset) <= -1) return -1;
break; break;
} }