diff --git a/src/core/asm.c b/src/core/asm.c index b06b0bf6..3b8c59d7 100644 --- a/src/core/asm.c +++ b/src/core/asm.c @@ -85,6 +85,7 @@ static const JanetInstructionDef janet_ops[] = { {"gten", JOP_NUMERIC_GREATER_THAN_EQUAL}, {"gtim", JOP_GREATER_THAN_IMMEDIATE}, {"gtn", JOP_NUMERIC_GREATER_THAN}, + {"in", JOP_IN}, {"jmp", JOP_JUMP}, {"jmpif", JOP_JUMP_IF}, {"jmpno", JOP_JUMP_IF_NOT}, diff --git a/src/core/bytecode.c b/src/core/bytecode.c index fc1ae312..13bb6b3f 100644 --- a/src/core/bytecode.c +++ b/src/core/bytecode.c @@ -80,6 +80,7 @@ enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT] = { JINT_SSS, /* JOP_RESUME, */ JINT_SSU, /* JOP_SIGNAL, */ JINT_SSS, /* JOP_PROPAGATE */ + JINT_SSS, /* JOP_IN, */ JINT_SSS, /* JOP_GET, */ JINT_SSS, /* JOP_PUT, */ JINT_SSU, /* JOP_GET_INDEX, */ diff --git a/src/core/cfuns.c b/src/core/cfuns.c index d0279880..f0e83662 100644 --- a/src/core/cfuns.c +++ b/src/core/cfuns.c @@ -106,6 +106,9 @@ static JanetSlot do_debug(JanetFopts opts, JanetSlot *args) { return t; } static JanetSlot do_in(JanetFopts opts, JanetSlot *args) { + return opreduce(opts, args, JOP_IN, janet_wrap_nil()); +} +static JanetSlot do_get(JanetFopts opts, JanetSlot *args) { return opreduce(opts, args, JOP_GET, janet_wrap_nil()); } static JanetSlot do_put(JanetFopts opts, JanetSlot *args) { @@ -302,7 +305,8 @@ static const JanetFunOptimizer optimizers[] = { {NULL, do_lte}, {NULL, do_eq}, {NULL, do_neq}, - {fixarity2, do_propagate} + {fixarity2, do_propagate}, + {fixarity2, do_get} }; const JanetFunOptimizer *janetc_funopt(uint32_t flags) { diff --git a/src/core/compile.h b/src/core/compile.h index 646692c2..a458e2d4 100644 --- a/src/core/compile.h +++ b/src/core/compile.h @@ -61,6 +61,7 @@ #define JANET_FUN_EQ 30 #define JANET_FUN_NEQ 31 #define JANET_FUN_PROP 32 +#define JANET_FUN_GET 33 /* Compiler typedefs */ typedef struct JanetCompiler JanetCompiler; diff --git a/src/core/corelib.c b/src/core/corelib.c index bf61275a..afcb0bfc 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -262,17 +262,6 @@ static Janet janet_core_setdyn(int32_t argc, Janet *argv) { return argv[1]; } -// XXX inline asm function with a new op - OP_GET_PERMISSIVE? -// This would match up with OP_GET which is used for 'in'. -static Janet janet_core_get(int32_t argc, Janet *argv) { - janet_arity(argc, 2, 3); - Janet result = janet_get_permissive(argv[0], argv[1]); - if (argc == 3 && janet_checktype(result, JANET_NIL)) { - return argv[2]; - } - return result; -} - static Janet janet_core_native(int32_t argc, Janet *argv) { JanetModule init; janet_arity(argc, 1, 2); @@ -696,14 +685,6 @@ static const JanetReg corelib_cfuns[] = { JDOC("(slice x &opt start end)\n\n" "Extract a sub-range of an indexed data strutrue or byte sequence.") }, - { - "get", janet_core_get, - JDOC("(get ds key &opt dflt)\n\n" - "Get the value mapped to key in data structure ds, and return dflt or nil if not found. " - "Similar to in, but will not throw an error if the key is invalid for the data structure " - "unless the data structure is an abstract type. In that case, the abstract type getter may throw " - "an error.") - }, {NULL, NULL, NULL} }; @@ -785,7 +766,7 @@ static void templatize_varop( SSI(JOP_GET_INDEX, 3, 0, 0), /* accum = args[0] */ SI(JOP_LOAD_INTEGER, 5, 1), /* i = 1 */ /* Main loop */ - SSS(JOP_GET, 4, 0, 5), /* operand = args[i] */ + SSS(JOP_IN, 4, 0, 5), /* operand = args[i] */ SSS(op, 3, 3, 4), /* accum = accum op operand */ SSI(JOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */ SSI(JOP_EQUALS, 2, 5, 1), /* jump? = (i == argn) */ @@ -833,7 +814,7 @@ static void templatize_comparator( SI(JOP_LOAD_INTEGER, 5, 1), /* i = 1 */ /* Main loop */ - SSS(JOP_GET, 4, 0, 5), /* next = args[i] */ + SSS(JOP_IN, 4, 0, 5), /* next = args[i] */ SSS(op, 2, 3, 4), /* jump? = last compare next */ SI(JOP_JUMP_IF_NOT, 2, 7), /* if not jump? goto fail (return false) */ SSI(JOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */ @@ -880,7 +861,7 @@ static void make_apply(JanetTable *env) { SI(JOP_LOAD_INTEGER, 4, 0), /* i = 0 */ /* Main loop */ - SSS(JOP_GET, 5, 1, 4), /* x = args[i] */ + SSS(JOP_IN, 5, 1, 4), /* x = args[i] */ SSI(JOP_ADD_IMMEDIATE, 4, 4, 1), /* i++ */ SSI(JOP_EQUALS, 3, 4, 2), /* jump? = (i == argn) */ SI(JOP_JUMP_IF, 3, 3), /* if jump? go forward 3 */ @@ -920,6 +901,14 @@ static const uint32_t resume_asm[] = { JOP_RETURN }; static const uint32_t in_asm[] = { + JOP_IN | (1 << 24), + JOP_LOAD_NIL | (3 << 8), + JOP_EQUALS | (3 << 8) | (3 << 24), + JOP_JUMP_IF | (3 << 8) | (2 << 16), + JOP_RETURN, + JOP_RETURN | (2 << 8) +}; +static const uint32_t get_asm[] = { JOP_GET | (1 << 24), JOP_LOAD_NIL | (3 << 8), JOP_EQUALS | (3 << 8) | (3 << 24), @@ -986,6 +975,13 @@ JanetTable *janet_core_env(JanetTable *replacements) { "strings, symbols, and buffers are all associative and can be used. Arrays, tuples, strings, buffers, " "and symbols must use integer keys that are in bounds or an error is raised. Structs and tables can " "take any value as a key except nil and will return nil or dflt if not found.")); + janet_quick_asm(env, JANET_FUN_GET, + "get", 3, 2, 3, 4, get_asm, sizeof(in_asm), + JDOC("(get ds key &opt dflt)\n\n" + "Get the value mapped to key in data structure ds, and return dflt or nil if not found. " + "Similar to in, but will not throw an error if the key is invalid for the data structure " + "unless the data structure is an abstract type. In that case, the abstract type getter may throw " + "an error.")); janet_quick_asm(env, JANET_FUN_PUT, "put", 3, 3, 3, 3, put_asm, sizeof(put_asm), JDOC("(put ds key value)\n\n" diff --git a/src/core/specials.c b/src/core/specials.c index 8fa650b4..1f82b099 100644 --- a/src/core/specials.c +++ b/src/core/specials.c @@ -146,7 +146,7 @@ static int destructure(JanetCompiler *c, janetc_emit_ssu(c, JOP_GET_INDEX, nextright, right, (uint8_t) i, 1); } else { JanetSlot k = janetc_cslot(janet_wrap_integer(i)); - janetc_emit_sss(c, JOP_GET, nextright, right, k, 1); + janetc_emit_sss(c, JOP_IN, nextright, right, k, 1); } if (destructure(c, subval, nextright, leaf, attr)) janetc_freeslot(c, nextright); @@ -162,7 +162,7 @@ static int destructure(JanetCompiler *c, if (janet_checktype(kvs[i].key, JANET_NIL)) continue; JanetSlot nextright = janetc_farslot(c); JanetSlot k = janetc_value(janetc_fopts_default(c), kvs[i].key); - janetc_emit_sss(c, JOP_GET, nextright, right, k, 1); + janetc_emit_sss(c, JOP_IN, nextright, right, k, 1); if (destructure(c, kvs[i].value, nextright, leaf, attr)) janetc_freeslot(c, nextright); } diff --git a/src/core/value.c b/src/core/value.c index 4e9f8bea..bc1c43ad 100644 --- a/src/core/value.c +++ b/src/core/value.c @@ -156,7 +156,7 @@ bad: } /* Gets a value and returns. Can panic. */ -Janet janet_get(Janet ds, Janet key) { +Janet janet_in(Janet ds, Janet key) { Janet value; switch (janet_type(ds)) { default: @@ -207,7 +207,7 @@ Janet janet_get(Janet ds, Janet key) { return value; } -Janet janet_get_permissive(Janet ds, Janet key) { +Janet janet_get(Janet ds, Janet key) { JanetType t = janet_type(ds); switch (t) { default: diff --git a/src/core/vm.c b/src/core/vm.c index 0cc69324..984ab3cf 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -203,7 +203,7 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) { key = callee; } fiber->stacktop = fiber->stackstart; - return janet_get(ds, key); + return janet_in(ds, key); } /* Get a callable from a keyword method name and check ensure that it is valid. */ @@ -274,6 +274,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) &&label_JOP_RESUME, &&label_JOP_SIGNAL, &&label_JOP_PROPAGATE, + &&label_JOP_IN, &&label_JOP_GET, &&label_JOP_PUT, &&label_JOP_GET_INDEX, @@ -475,7 +476,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) &&label_unknown_op, &&label_unknown_op, &&label_unknown_op, - &&label_unknown_op, &&label_unknown_op }; #endif @@ -911,6 +911,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) janet_putindex(stack[A], C, stack[B]); vm_checkgc_pcnext(); + VM_OP(JOP_IN) + vm_commit(); + stack[A] = janet_in(stack[B], stack[C]); + vm_pcnext(); + VM_OP(JOP_GET) vm_commit(); stack[A] = janet_get(stack[B], stack[C]); diff --git a/src/include/janet.h b/src/include/janet.h index eda37ae5..e9f56bb1 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1021,6 +1021,7 @@ enum JanetOpCode { JOP_RESUME, JOP_SIGNAL, JOP_PROPAGATE, + JOP_IN, JOP_GET, JOP_PUT, JOP_GET_INDEX, @@ -1284,8 +1285,8 @@ JANET_API int janet_equals(Janet x, Janet y); JANET_API int32_t janet_hash(Janet x); JANET_API int janet_compare(Janet x, Janet y); JANET_API int janet_cstrcmp(const uint8_t *str, const char *other); +JANET_API Janet janet_in(Janet ds, Janet key); JANET_API Janet janet_get(Janet ds, Janet key); -JANET_API Janet janet_get_permissive(Janet ds, Janet key); JANET_API Janet janet_getindex(Janet ds, int32_t index); JANET_API int32_t janet_length(Janet x); JANET_API Janet janet_lengthv(Janet x);