From c6edf03ae8af52a6debb552b20139e8e15c81b57 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 9 Feb 2019 12:21:11 -0500 Subject: [PATCH] Fix some code style, add tuple/type function. We need to be able to detect tuple type from janet code, otherwise tuples will contain hidden state. The tuple/type function is able to detect the flags in the tuple so the programmer can access them if needed. --- src/core/compile.c | 5 ++--- src/core/marsh.c | 12 ++++++------ src/core/parse.c | 18 +++--------------- src/core/pp.c | 13 ++++++++----- src/core/tuple.c | 19 +++++++++++++++++++ test/suite3.janet | 8 ++++++++ 6 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/core/compile.c b/src/core/compile.c index 97edeb88..a5ffeb71 100644 --- a/src/core/compile.c +++ b/src/core/compile.c @@ -446,7 +446,6 @@ static JanetSlot janetc_tuple(JanetFopts opts, Janet x) { JOP_MAKE_TUPLE); } - static JanetSlot janetc_tablector(JanetFopts opts, Janet x, int op) { JanetCompiler *c = opts.compiler; return janetc_maker(opts, @@ -556,8 +555,8 @@ JanetSlot janetc_value(JanetFopts opts, Janet x) { /* Empty tuple is tuple literal */ if (janet_tuple_length(tup) == 0) { ret = janetc_cslot(x); - } else if (janet_tuple_flag(tup) & JANET_TUPLE_FLAG_BRACKETCTOR) { // [] tuples are not function call - ret = janetc_tuple(opts, x); + } else if (janet_tuple_flag(tup) & JANET_TUPLE_FLAG_BRACKETCTOR) { /* [] tuples are not function call */ + ret = janetc_tuple(opts, x); } else { JanetSlot head = janetc_value(subopts, tup[0]); subopts.flags = JANET_FUNCTION | JANET_CFUNCTION; diff --git a/src/core/marsh.c b/src/core/marsh.c index 89b951a9..f3575094 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -231,7 +231,7 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) { /* marshal the environments if needed */ for (int32_t i = 0; i < def->environments_length; i++) - pushint(st, def->environments[i]); + pushint(st, def->environments[i]); /* marshal the sub funcdefs if needed */ for (int32_t i = 0; i < def->defs_length; i++) @@ -402,10 +402,10 @@ static void marshal_one(MarshalState *st, Janet x, int flags) { goto done; case JANET_TUPLE: { - int32_t i, count,flag; + int32_t i, count, flag; const Janet *tup = janet_unwrap_tuple(x); count = janet_tuple_length(tup); - flag = janet_tuple_flag(tup); + flag = janet_tuple_flag(tup); pushbyte(st, LB_TUPLE); pushint(st, count); pushint(st, flag); @@ -1015,7 +1015,7 @@ static const uint8_t *unmarshal_one( JanetFuncDef *def; data = unmarshal_one_def(st, data + 1, &def, flags + 1); func = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + - def->environments_length * sizeof(JanetFuncEnv)); + def->environments_length * sizeof(JanetFuncEnv)); func->def = def; *out = janet_wrap_function(func); janet_array_push(&st->lookup, *out); @@ -1046,8 +1046,8 @@ static const uint8_t *unmarshal_one( } else if (lead == LB_TUPLE) { /* Tuple */ Janet *tup = janet_tuple_begin(len); - int32_t flag = readint(st, &data); - janet_tuple_flag(tup)=flag; + int32_t flag = readint(st, &data); + janet_tuple_flag(tup) = flag; for (int32_t i = 0; i < len; i++) { data = unmarshal_one(st, data, tup + i, flags + 1); } diff --git a/src/core/parse.c b/src/core/parse.c index b968e477..d14a12e8 100644 --- a/src/core/parse.c +++ b/src/core/parse.c @@ -335,22 +335,14 @@ static int comment(JanetParser *p, JanetParseState *state, uint8_t c) { return 1; } -static Janet close_tuple(JanetParser *p, JanetParseState *state) { +static Janet close_tuple(JanetParser *p, JanetParseState *state, int32_t flag) { Janet *ret = janet_tuple_begin(state->argn); + janet_tuple_flag(ret) = flag; for (int32_t i = state->argn - 1; i >= 0; i--) ret[i] = p->args[--p->argcount]; return janet_wrap_tuple(janet_tuple_end(ret)); } -static Janet close_ltuple(JanetParser *p, JanetParseState *state) { - Janet *ret = janet_tuple_begin(state->argn); - janet_tuple_flag(ret) |= JANET_TUPLE_FLAG_BRACKETCTOR; - for (int32_t i = state->argn - 1; i >= 0; i--) - ret[i] = p->args[--p->argcount]; - return janet_wrap_tuple(janet_tuple_end(ret)); -} - - static Janet close_array(JanetParser *p, JanetParseState *state) { JanetArray *array = janet_array(state->argn); for (int32_t i = state->argn - 1; i >= 0; i--) @@ -495,11 +487,7 @@ static int root(JanetParser *p, JanetParseState *state, uint8_t c) { if (state->flags & PFLAG_ATSYM) { ds = close_array(p, state); } else { - if (c == ']') { - ds = close_ltuple(p, state); - } else { - ds = close_tuple(p, state); - } + ds = close_tuple(p, state, c == ']' ? JANET_TUPLE_FLAG_BRACKETCTOR : 0); } } else if (c == '}' && (state->flags & PFLAG_CURLYBRACKETS)) { if (state->argn & 1) { diff --git a/src/core/pp.c b/src/core/pp.c index 5af5ce8c..872e4634 100644 --- a/src/core/pp.c +++ b/src/core/pp.c @@ -332,16 +332,19 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) { case JANET_ARRAY: case JANET_TUPLE: { + int32_t i, len; + const Janet *arr; int isarray = janet_checktype(x, JANET_ARRAY); - janet_buffer_push_cstring(S->buffer, isarray ? "@[" : "("); + janet_indexed_view(x, &arr, &len); + int hasbrackets = !isarray && (janet_tuple_flag(arr) & JANET_TUPLE_FLAG_BRACKETCTOR); + const char *startstr = isarray ? "@[" : hasbrackets ? "[" : "("; + const char endchar = isarray ? ']' : hasbrackets ? ']' : ')'; + janet_buffer_push_cstring(S->buffer, startstr); S->depth--; S->indent += 2; if (S->depth == 0) { janet_buffer_push_cstring(S->buffer, "..."); } else { - int32_t i, len; - const Janet *arr; - janet_indexed_view(x, &arr, &len); if (!isarray && len >= 5) janet_buffer_push_u8(S->buffer, ' '); if (is_dict_value && len >= 5) print_newline(S, 0); @@ -352,7 +355,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) { } S->indent -= 2; S->depth++; - janet_buffer_push_u8(S->buffer, isarray ? ']' : ')'); + janet_buffer_push_u8(S->buffer, endchar); break; } case JANET_STRUCT: diff --git a/src/core/tuple.c b/src/core/tuple.c index 4276a20b..a648412d 100644 --- a/src/core/tuple.c +++ b/src/core/tuple.c @@ -120,6 +120,16 @@ static Janet cfun_tuple_append(int32_t argc, Janet *argv) { return janet_wrap_tuple(janet_tuple_end(n)); } +static Janet cfun_tuple_type(int32_t argc, Janet *argv) { + janet_fixarity(argc, 1); + const Janet *tup = janet_gettuple(argv, 0); + if (janet_tuple_flag(tup) & JANET_TUPLE_FLAG_BRACKETCTOR) { + return janet_ckeywordv("brackets"); + } else { + return janet_ckeywordv("parens"); + } +} + static const JanetReg tuple_cfuns[] = { { "tuple/slice", cfun_tuple_slice, @@ -142,6 +152,15 @@ static const JanetReg tuple_cfuns[] = { "returns a new tuple. Items are prepended such that the " "last element in items is the first element in the new tuple.") }, + { + "tuple/type", cfun_tuple_type, + JDOC("(tuple/type tup)\n\n" + "Checks how the tuple was constructed. Will return the keyword " + ":brackets if the tuple was parsed with brackets, and :parens " + "otherwise. The two types of tuples will behave the same most of " + "the time, but will print differently and be treated differently by " + "the compiler.") + }, {NULL, NULL, NULL} }; diff --git a/test/suite3.janet b/test/suite3.janet index 90d44b71..097eb26b 100644 --- a/test/suite3.janet +++ b/test/suite3.janet @@ -351,4 +351,12 @@ (def t (put @{} :hi 1)) (assert (deep= t @{:hi 1}) "regression #24") +# Tuple types + +(assert (= (tuple/type '(1 2 3)) :parens) "normal tuple") +(assert (= (tuple/type [1 2 3]) :parens) "normal tuple 1") +(assert (= (tuple/type '[1 2 3]) :brackets) "bracketed tuple 2") +(assert (= (tuple/type (-> '(1 2 3) marshal unmarshal)) :parens) "normal tuple marshalled/unmarshalled") +(assert (= (tuple/type (-> '[1 2 3] marshal unmarshal)) :brackets) "normal tuple marshalled/unmarshalled") + (end-suite)