mirror of
https://github.com/janet-lang/janet
synced 2024-06-25 22:53:16 +00:00
Replace unquote-splicing with a more general splce special form.
This allows splicing behavior in normal function calls.
This commit is contained in:
parent
484597eaae
commit
89bd38890e
|
@ -321,12 +321,40 @@ JanetSlot *janetc_toslotskv(JanetCompiler *c, Janet ds) {
|
||||||
/* Push slots load via janetc_toslots. */
|
/* Push slots load via janetc_toslots. */
|
||||||
void janetc_pushslots(JanetCompiler *c, JanetSlot *slots) {
|
void janetc_pushslots(JanetCompiler *c, JanetSlot *slots) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
for (i = 0; i < janet_v_count(slots) - 2; i += 3)
|
int32_t count = janet_v_count(slots);
|
||||||
janetc_emit_sss(c, JOP_PUSH_3, slots[i], slots[i+1], slots[i+2], 0);
|
for (i = 0; i < count;) {
|
||||||
if (i == janet_v_count(slots) - 2)
|
if (slots[i].flags & JANET_SLOT_SPLICED) {
|
||||||
janetc_emit_ss(c, JOP_PUSH_2, slots[i], slots[i+1], 0);
|
janetc_emit_s(c, JOP_PUSH_ARRAY, slots[i], 0);
|
||||||
else if (i == janet_v_count(slots) - 1)
|
i++;
|
||||||
janetc_emit_s(c, JOP_PUSH, slots[i], 0);
|
} else if (i + 1 == count) {
|
||||||
|
janetc_emit_s(c, JOP_PUSH, slots[i], 0);
|
||||||
|
i++;
|
||||||
|
} else if (slots[i + 1].flags & JANET_SLOT_SPLICED) {
|
||||||
|
janetc_emit_s(c, JOP_PUSH, slots[i], 0);
|
||||||
|
janetc_emit_s(c, JOP_PUSH_ARRAY, slots[i+1], 0);
|
||||||
|
i += 2;
|
||||||
|
} else if (i + 2 == count) {
|
||||||
|
janetc_emit_ss(c, JOP_PUSH_2, slots[i], slots[i+1], 0);
|
||||||
|
i += 2;
|
||||||
|
} else if (slots[i + 2].flags & JANET_SLOT_SPLICED) {
|
||||||
|
janetc_emit_ss(c, JOP_PUSH_2, slots[i], slots[i+1], 0);
|
||||||
|
janetc_emit_s(c, JOP_PUSH_ARRAY, slots[i+2], 0);
|
||||||
|
i += 3;
|
||||||
|
} else {
|
||||||
|
janetc_emit_sss(c, JOP_PUSH_3, slots[i], slots[i+1], slots[i+2], 0);
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a list of slots has any spliced slots */
|
||||||
|
static int has_spliced(JanetSlot *slots) {
|
||||||
|
int32_t i;
|
||||||
|
for (i = 0; i < janet_v_count(slots); i++) {
|
||||||
|
if (slots[i].flags & JANET_SLOT_SPLICED)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free slots loaded via janetc_toslots */
|
/* Free slots loaded via janetc_toslots */
|
||||||
|
@ -361,7 +389,7 @@ static JanetSlot janetc_call(JanetFopts opts, JanetSlot *slots, JanetSlot fun) {
|
||||||
JanetSlot retslot;
|
JanetSlot retslot;
|
||||||
JanetCompiler *c = opts.compiler;
|
JanetCompiler *c = opts.compiler;
|
||||||
int specialized = 0;
|
int specialized = 0;
|
||||||
if (fun.flags & JANET_SLOT_CONSTANT) {
|
if (fun.flags & JANET_SLOT_CONSTANT && !has_spliced(slots)) {
|
||||||
if (janet_checktype(fun.constant, JANET_FUNCTION)) {
|
if (janet_checktype(fun.constant, JANET_FUNCTION)) {
|
||||||
JanetFunction *f = janet_unwrap_function(fun.constant);
|
JanetFunction *f = janet_unwrap_function(fun.constant);
|
||||||
const JanetFunOptimizer *o = janetc_funopt(f->def->flags);
|
const JanetFunOptimizer *o = janetc_funopt(f->def->flags);
|
||||||
|
@ -521,6 +549,7 @@ JanetSlot janetc_value(JanetFopts opts, Janet x) {
|
||||||
ret = janetc_call(opts, janetc_toslots(c, tup + 1, janet_tuple_length(tup) - 1), head);
|
ret = janetc_call(opts, janetc_toslots(c, tup + 1, janet_tuple_length(tup) - 1), head);
|
||||||
janetc_freeslot(c, head);
|
janetc_freeslot(c, head);
|
||||||
}
|
}
|
||||||
|
ret.flags &= ~JANET_SLOT_SPLICED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JANET_SYMBOL:
|
case JANET_SYMBOL:
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
(:= index (+ index 1)))
|
(:= index (+ index 1)))
|
||||||
(array/push modifiers (string buf ")\n\n" docstr))
|
(array/push modifiers (string buf ")\n\n" docstr))
|
||||||
# Build return value
|
# Build return value
|
||||||
~(def ,name ;modifiers (fn ,name ;(tuple/slice more start)))))
|
~(def ,name ,;modifiers (fn ,name ,;(tuple/slice more start)))))
|
||||||
|
|
||||||
(defn defmacro :macro
|
(defn defmacro :macro
|
||||||
"Define a macro."
|
"Define a macro."
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
(defmacro def-
|
(defmacro def-
|
||||||
"Define a private value that will not be exported."
|
"Define a private value that will not be exported."
|
||||||
[name & more]
|
[name & more]
|
||||||
~(def name :private ;more))
|
~(def name :private ,;more))
|
||||||
|
|
||||||
(defn defglobal
|
(defn defglobal
|
||||||
"Dynamically create a global def."
|
"Dynamically create a global def."
|
||||||
|
@ -165,12 +165,12 @@
|
||||||
(defmacro when
|
(defmacro when
|
||||||
"Evaluates the body when the condition is true. Otherwise returns nil."
|
"Evaluates the body when the condition is true. Otherwise returns nil."
|
||||||
[condition & body]
|
[condition & body]
|
||||||
~(if ,condition (do ;body)))
|
~(if ,condition (do ,;body)))
|
||||||
|
|
||||||
(defmacro unless
|
(defmacro unless
|
||||||
"Shorthand for (when (not ... "
|
"Shorthand for (when (not ... "
|
||||||
[condition & body]
|
[condition & body]
|
||||||
~(if ,condition nil (do ;body)))
|
~(if ,condition nil (do ,;body)))
|
||||||
|
|
||||||
(defmacro cond
|
(defmacro cond
|
||||||
"Evaluates conditions sequentially until the first true condition
|
"Evaluates conditions sequentially until the first true condition
|
||||||
|
@ -404,7 +404,7 @@
|
||||||
"Create a generator expression using the loop syntax. Returns a fiber
|
"Create a generator expression using the loop syntax. Returns a fiber
|
||||||
that yields all values inside the loop in order. See loop for details."
|
that yields all values inside the loop in order. See loop for details."
|
||||||
[head & body]
|
[head & body]
|
||||||
~(fiber/new (fn [&] (loop ,head (yield (do ;body))))))
|
~(fiber/new (fn [&] (loop ,head (yield (do ,;body))))))
|
||||||
|
|
||||||
(defmacro for
|
(defmacro for
|
||||||
"Do a c style for loop for side effects. Returns nil."
|
"Do a c style for loop for side effects. Returns nil."
|
||||||
|
@ -416,21 +416,23 @@
|
||||||
[binding ind & body]
|
[binding ind & body]
|
||||||
(apply loop [tuple binding :in ind] body))
|
(apply loop [tuple binding :in ind] body))
|
||||||
|
|
||||||
(defn sum [xs]
|
(defmacro coro
|
||||||
|
"A wrapper for making fibers. Same as (fiber/new (fn [&] ...body))."
|
||||||
|
[& body]
|
||||||
|
(tuple fiber/new (tuple 'fn '[&] ;body)))
|
||||||
|
|
||||||
|
(defn sum
|
||||||
|
[xs]
|
||||||
(var accum 0)
|
(var accum 0)
|
||||||
(loop [x :in xs] (+= accum x))
|
(loop [x :in xs] (+= accum x))
|
||||||
accum)
|
accum)
|
||||||
|
|
||||||
(defn product [xs]
|
(defn product
|
||||||
|
[xs]
|
||||||
(var accum 1)
|
(var accum 1)
|
||||||
(loop [x :in xs] (*= accum x))
|
(loop [x :in xs] (*= accum x))
|
||||||
accum)
|
accum)
|
||||||
|
|
||||||
(defmacro coro
|
|
||||||
"A wrapper for making fibers. Same as (fiber/new (fn [&] ...body))."
|
|
||||||
[& body]
|
|
||||||
(tuple fiber/new (apply tuple 'fn '[&] body)))
|
|
||||||
|
|
||||||
(defmacro if-let
|
(defmacro if-let
|
||||||
"Takes the first one or two forms in a vector and if both are true binds
|
"Takes the first one or two forms in a vector and if both are true binds
|
||||||
all the forms with let and evaluates the first expression else
|
all the forms with let and evaluates the first expression else
|
||||||
|
@ -466,7 +468,7 @@
|
||||||
"Takes the first one or two forms in vector and if true binds
|
"Takes the first one or two forms in vector and if true binds
|
||||||
all the forms with let and evaluates the body"
|
all the forms with let and evaluates the body"
|
||||||
[bindings & body]
|
[bindings & body]
|
||||||
~(if-let ,bindings (do ;body)))
|
~(if-let ,bindings (do ,;body)))
|
||||||
|
|
||||||
(defn comp
|
(defn comp
|
||||||
"Takes multiple functions and returns a function that is the composition
|
"Takes multiple functions and returns a function that is the composition
|
||||||
|
@ -479,8 +481,8 @@
|
||||||
3 (let [[f g h] functions] (fn [x] (f (g (h x)))))
|
3 (let [[f g h] functions] (fn [x] (f (g (h x)))))
|
||||||
4 (let [[f g h i] functions] (fn [x] (f (g (h (i x))))))
|
4 (let [[f g h i] functions] (fn [x] (f (g (h (i x))))))
|
||||||
(let [[f g h i j] functions]
|
(let [[f g h i j] functions]
|
||||||
(apply comp (fn [x] (f (g (h (i (j x))))))
|
(comp (fn [x] (f (g (h (i (j x))))))
|
||||||
(tuple/slice functions 5 -1)))))
|
;(tuple/slice functions 5 -1)))))
|
||||||
|
|
||||||
(defn identity
|
(defn identity
|
||||||
"A function that returns its first argument."
|
"A function that returns its first argument."
|
||||||
|
@ -590,7 +592,7 @@
|
||||||
(loop [i :range [0 limit]]
|
(loop [i :range [0 limit]]
|
||||||
(def args (array/new ninds))
|
(def args (array/new ninds))
|
||||||
(loop [j :range [0 ninds]] (:= args.j inds.j.i))
|
(loop [j :range [0 ninds]] (:= args.j inds.j.i))
|
||||||
(:= res.i (apply f args))))
|
(:= res.i (f ;args))))
|
||||||
res)
|
res)
|
||||||
|
|
||||||
(defn mapcat
|
(defn mapcat
|
||||||
|
@ -696,7 +698,7 @@
|
||||||
(fn [& args]
|
(fn [& args]
|
||||||
(def ret @[])
|
(def ret @[])
|
||||||
(loop [f :in funs]
|
(loop [f :in funs]
|
||||||
(array/push ret (apply f args)))
|
(array/push ret (f ;args)))
|
||||||
(tuple/slice ret 0)))
|
(tuple/slice ret 0)))
|
||||||
|
|
||||||
(defmacro juxt
|
(defmacro juxt
|
||||||
|
@ -738,7 +740,7 @@
|
||||||
"Partial function application."
|
"Partial function application."
|
||||||
[f & more]
|
[f & more]
|
||||||
(if (zero? (length more)) f
|
(if (zero? (length more)) f
|
||||||
(fn [& r] (apply f (array/concat @[] more r)))))
|
(fn [& r] (f ;more ;r))))
|
||||||
|
|
||||||
(defn every?
|
(defn every?
|
||||||
"Returns true if each value in is truthy, otherwise the first
|
"Returns true if each value in is truthy, otherwise the first
|
||||||
|
@ -787,7 +789,7 @@ value, one key will be ignored."
|
||||||
The key then, is associated to the function's return value"
|
The key then, is associated to the function's return value"
|
||||||
[coll a-key a-function & args]
|
[coll a-key a-function & args]
|
||||||
(def old-value coll.a-key)
|
(def old-value coll.a-key)
|
||||||
(:= coll.a-key (apply a-function old-value args)))
|
(:= coll.a-key (a-function old-value ;args)))
|
||||||
|
|
||||||
(defn merge-into
|
(defn merge-into
|
||||||
"Merges multiple tables/structs into a table. If a key appears in more than one
|
"Merges multiple tables/structs into a table. If a key appears in more than one
|
||||||
|
@ -857,7 +859,7 @@ value, one key will be ignored."
|
||||||
(def res @[])
|
(def res @[])
|
||||||
(def ncol (length cols))
|
(def ncol (length cols))
|
||||||
(when (> ncol 0)
|
(when (> ncol 0)
|
||||||
(def len (apply min (map length cols)))
|
(def len (min ;(map length cols)))
|
||||||
(loop [i :range [0 len]
|
(loop [i :range [0 len]
|
||||||
ci :range [0 ncol]]
|
ci :range [0 ncol]]
|
||||||
(array/push res cols.ci.i)))
|
(array/push res cols.ci.i)))
|
||||||
|
@ -1008,16 +1010,16 @@ value, one key will be ignored."
|
||||||
|
|
||||||
(defn expandall [t]
|
(defn expandall [t]
|
||||||
(def args (map macex1 (tuple/slice t 1)))
|
(def args (map macex1 (tuple/slice t 1)))
|
||||||
(apply tuple t.0 args))
|
(tuple t.0 ;args))
|
||||||
|
|
||||||
(defn expandfn [t]
|
(defn expandfn [t]
|
||||||
(if (symbol? t.1)
|
(if (symbol? t.1)
|
||||||
(do
|
(do
|
||||||
(def args (map macex1 (tuple/slice t 3)))
|
(def args (map macex1 (tuple/slice t 3)))
|
||||||
(apply tuple 'fn t.1 t.2 args))
|
(tuple 'fn t.1 t.2 ;args))
|
||||||
(do
|
(do
|
||||||
(def args (map macex1 (tuple/slice t 2)))
|
(def args (map macex1 (tuple/slice t 2)))
|
||||||
(apply tuple 'fn t.1 args))))
|
(tuple 'fn t.1 ;args))))
|
||||||
|
|
||||||
(defn expandqq [t]
|
(defn expandqq [t]
|
||||||
(defn qq [x]
|
(defn qq [x]
|
||||||
|
@ -1052,7 +1054,7 @@ value, one key will be ignored."
|
||||||
(def m? entry:macro)
|
(def m? entry:macro)
|
||||||
(cond
|
(cond
|
||||||
s (s t)
|
s (s t)
|
||||||
m? (apply m (tuple/slice t 1))
|
m? (m ;(tuple/slice t 1))
|
||||||
(tuple/slice (map macex1 t))))
|
(tuple/slice (map macex1 t))))
|
||||||
|
|
||||||
(def ret
|
(def ret
|
||||||
|
@ -1358,7 +1360,7 @@ value, one key will be ignored."
|
||||||
|
|
||||||
(defn import*
|
(defn import*
|
||||||
[env path & args]
|
[env path & args]
|
||||||
(def targs (apply table args))
|
(def targs (table ;args))
|
||||||
(def {:as as
|
(def {:as as
|
||||||
:prefix prefix} targs)
|
:prefix prefix} targs)
|
||||||
(def newenv (require path targs))
|
(def newenv (require path targs))
|
||||||
|
@ -1383,7 +1385,7 @@ value, one key will be ignored."
|
||||||
x
|
x
|
||||||
(string x)))
|
(string x)))
|
||||||
args))
|
args))
|
||||||
(apply tuple import* '_env (string path) argm))
|
(tuple import* '_env (string path) ;argm))
|
||||||
|
|
||||||
(defn repl
|
(defn repl
|
||||||
"Run a repl. The first parameter is an optional function to call to
|
"Run a repl. The first parameter is an optional function to call to
|
||||||
|
|
|
@ -171,7 +171,7 @@ static void popstate(JanetParser *p, Janet val) {
|
||||||
const char *which =
|
const char *which =
|
||||||
(c == '\'') ? "quote" :
|
(c == '\'') ? "quote" :
|
||||||
(c == ',') ? "unquote" :
|
(c == ',') ? "unquote" :
|
||||||
(c == ';') ? "unquote-splicing" :
|
(c == ';') ? "splice" :
|
||||||
(c == '~') ? "quasiquote" : "<unknown>";
|
(c == '~') ? "quasiquote" : "<unknown>";
|
||||||
t[0] = janet_csymbolv(which);
|
t[0] = janet_csymbolv(which);
|
||||||
t[1] = val;
|
t[1] = val;
|
||||||
|
|
|
@ -34,20 +34,26 @@ static JanetSlot janetc_quote(JanetFopts opts, int32_t argn, const Janet *argv)
|
||||||
return janetc_cslot(argv[0]);
|
return janetc_cslot(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JanetSlot janetc_splice(JanetFopts opts, int32_t argn, const Janet *argv) {
|
||||||
|
JanetSlot ret;
|
||||||
|
if (argn != 1) {
|
||||||
|
janetc_cerror(opts.compiler, "expected 1 argument");
|
||||||
|
return janetc_cslot(janet_wrap_nil());
|
||||||
|
}
|
||||||
|
ret = janetc_value(opts, argv[0]);
|
||||||
|
ret.flags |= JANET_SLOT_SPLICED;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static JanetSlot qq_slots(JanetFopts opts, JanetSlot *slots, int makeop) {
|
static JanetSlot qq_slots(JanetFopts opts, JanetSlot *slots, int makeop) {
|
||||||
JanetSlot target = janetc_gettarget(opts);
|
JanetSlot target = janetc_gettarget(opts);
|
||||||
int32_t i;
|
janetc_pushslots(opts.compiler, slots);
|
||||||
for (i = 0; i < janet_v_count(slots); i++) {
|
|
||||||
JanetSlot s = slots[i];
|
|
||||||
int op = (s.flags & JANET_SLOT_SPLICED) ? JOP_PUSH_ARRAY : JOP_PUSH;
|
|
||||||
janetc_emit_s(opts.compiler, op, s, 0);
|
|
||||||
}
|
|
||||||
janetc_freeslots(opts.compiler, slots);
|
janetc_freeslots(opts.compiler, slots);
|
||||||
janetc_emit_s(opts.compiler, makeop, target, 1);
|
janetc_emit_s(opts.compiler, makeop, target, 1);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JanetSlot quasiquote(JanetFopts opts, Janet x, int can_splice) {
|
static JanetSlot quasiquote(JanetFopts opts, Janet x) {
|
||||||
JanetSlot *slots = NULL;
|
JanetSlot *slots = NULL;
|
||||||
switch (janet_type(x)) {
|
switch (janet_type(x)) {
|
||||||
default:
|
default:
|
||||||
|
@ -59,20 +65,11 @@ static JanetSlot quasiquote(JanetFopts opts, Janet x, int can_splice) {
|
||||||
len = janet_tuple_length(tup);
|
len = janet_tuple_length(tup);
|
||||||
if (len > 1 && janet_checktype(tup[0], JANET_SYMBOL)) {
|
if (len > 1 && janet_checktype(tup[0], JANET_SYMBOL)) {
|
||||||
const uint8_t *head = janet_unwrap_symbol(tup[0]);
|
const uint8_t *head = janet_unwrap_symbol(tup[0]);
|
||||||
if (!janet_cstrcmp(head, "unquote")) {
|
if (!janet_cstrcmp(head, "unquote"))
|
||||||
return janetc_value(janetc_fopts_default(opts.compiler), tup[1]);
|
return janetc_value(janetc_fopts_default(opts.compiler), tup[1]);
|
||||||
} else if (!janet_cstrcmp(head, "unquote-splicing")) {
|
|
||||||
JanetSlot s;
|
|
||||||
if (!can_splice) {
|
|
||||||
janetc_cerror(opts.compiler, "cannot use unquote-splicing here");
|
|
||||||
}
|
|
||||||
s = janetc_value(janetc_fopts_default(opts.compiler), tup[1]);
|
|
||||||
s.flags |= JANET_SLOT_SPLICED;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
janet_v_push(slots, quasiquote(opts, tup[i], 1));
|
janet_v_push(slots, quasiquote(opts, tup[i]));
|
||||||
return qq_slots(opts, slots, JOP_MAKE_TUPLE);
|
return qq_slots(opts, slots, JOP_MAKE_TUPLE);
|
||||||
}
|
}
|
||||||
case JANET_ARRAY:
|
case JANET_ARRAY:
|
||||||
|
@ -80,7 +77,7 @@ static JanetSlot quasiquote(JanetFopts opts, Janet x, int can_splice) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
JanetArray *array = janet_unwrap_array(x);
|
JanetArray *array = janet_unwrap_array(x);
|
||||||
for (i = 0; i < array->count; i++)
|
for (i = 0; i < array->count; i++)
|
||||||
janet_v_push(slots, quasiquote(opts, array->data[i], 1));
|
janet_v_push(slots, quasiquote(opts, array->data[i]));
|
||||||
return qq_slots(opts, slots, JOP_MAKE_ARRAY);
|
return qq_slots(opts, slots, JOP_MAKE_ARRAY);
|
||||||
}
|
}
|
||||||
case JANET_TABLE:
|
case JANET_TABLE:
|
||||||
|
@ -90,8 +87,12 @@ static JanetSlot quasiquote(JanetFopts opts, Janet x, int can_splice) {
|
||||||
int32_t len, cap;
|
int32_t len, cap;
|
||||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||||
while ((kv = janet_dictionary_next(kvs, cap, kv))) {
|
while ((kv = janet_dictionary_next(kvs, cap, kv))) {
|
||||||
janet_v_push(slots, quasiquote(opts, kv->key, 0));
|
JanetSlot key = quasiquote(opts, kv->key);
|
||||||
janet_v_push(slots, quasiquote(opts, kv->value, 0));
|
JanetSlot value = quasiquote(opts, kv->value);
|
||||||
|
key.flags &= ~JANET_SLOT_SPLICED;
|
||||||
|
value.flags &= ~JANET_SLOT_SPLICED;
|
||||||
|
janet_v_push(slots, key);
|
||||||
|
janet_v_push(slots, value);
|
||||||
}
|
}
|
||||||
return qq_slots(opts, slots,
|
return qq_slots(opts, slots,
|
||||||
janet_checktype(x, JANET_TABLE) ? JOP_MAKE_TABLE : JOP_MAKE_STRUCT);
|
janet_checktype(x, JANET_TABLE) ? JOP_MAKE_TABLE : JOP_MAKE_STRUCT);
|
||||||
|
@ -104,7 +105,7 @@ static JanetSlot janetc_quasiquote(JanetFopts opts, int32_t argn, const Janet *a
|
||||||
janetc_cerror(opts.compiler, "expected 1 argument");
|
janetc_cerror(opts.compiler, "expected 1 argument");
|
||||||
return janetc_cslot(janet_wrap_nil());
|
return janetc_cslot(janet_wrap_nil());
|
||||||
}
|
}
|
||||||
return quasiquote(opts, argv[0], 0);
|
return quasiquote(opts, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JanetSlot janetc_unquote(JanetFopts opts, int32_t argn, const Janet *argv) {
|
static JanetSlot janetc_unquote(JanetFopts opts, int32_t argn, const Janet *argv) {
|
||||||
|
@ -114,13 +115,6 @@ static JanetSlot janetc_unquote(JanetFopts opts, int32_t argn, const Janet *argv
|
||||||
return janetc_cslot(janet_wrap_nil());
|
return janetc_cslot(janet_wrap_nil());
|
||||||
}
|
}
|
||||||
|
|
||||||
static JanetSlot janetc_unquote_splicing(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|
||||||
(void) argn;
|
|
||||||
(void) argv;
|
|
||||||
janetc_cerror(opts.compiler, "cannot use unquote-splicing here");
|
|
||||||
return janetc_cslot(janet_wrap_nil());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Preform destructuring. Be careful to
|
/* Preform destructuring. Be careful to
|
||||||
* keep the order registers are freed.
|
* keep the order registers are freed.
|
||||||
* Returns if the slot 'right' can be freed. */
|
* Returns if the slot 'right' can be freed. */
|
||||||
|
@ -661,8 +655,9 @@ static const JanetSpecial janetc_specials[] = {
|
||||||
{"if", janetc_if},
|
{"if", janetc_if},
|
||||||
{"quasiquote", janetc_quasiquote},
|
{"quasiquote", janetc_quasiquote},
|
||||||
{"quote", janetc_quote},
|
{"quote", janetc_quote},
|
||||||
|
{"splice", janetc_splice},
|
||||||
|
{"unquote", janetc_unquote},
|
||||||
{"unquote", janetc_unquote},
|
{"unquote", janetc_unquote},
|
||||||
{"unquote-splicing", janetc_unquote_splicing},
|
|
||||||
{"var", janetc_var},
|
{"var", janetc_var},
|
||||||
{"while", janetc_while}
|
{"while", janetc_while}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user