1
0
mirror of https://github.com/janet-lang/janet synced 2025-07-05 19:42:55 +00:00

Use keywords in the assembly interface.

This is simply more idiomatic, removes some unused and undocumented
features of the assembly interface, and simplifies it somewhat.
This commit is contained in:
Calvin Rose 2020-05-19 13:17:50 -05:00
parent 070baea3c4
commit e623690295
4 changed files with 35 additions and 64 deletions

View File

@ -2,6 +2,8 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## Unreleased - ??? ## Unreleased - ???
- `asm` and `disasm` functions now use keywords instead of macros for keys. Also
some slight changes to the way constants are encoded (remove wrapping `quote` in some cases).
- Expose current macro form inside macros as (dyn :macro-form) - Expose current macro form inside macros as (dyn :macro-form)
- Add `tracev` macro. - Add `tracev` macro.
- Fix compiler bug that emitted incorrect code in some cases for while loops that create closures. - Fix compiler bug that emitted incorrect code in some cases for while loops that create closures.

View File

@ -2397,7 +2397,7 @@
(defn .bytecode (defn .bytecode
"Get the bytecode for the current function." "Get the bytecode for the current function."
[&opt n] [&opt n]
((.disasm n) 'bytecode)) ((.disasm n) :bytecode))
(defn .ppasm (defn .ppasm
"Pretty prints the assembly for the current function" "Pretty prints the assembly for the current function"
@ -2405,13 +2405,13 @@
(def frame (.frame n)) (def frame (.frame n))
(def func (frame :function)) (def func (frame :function))
(def dasm (disasm-alias func)) (def dasm (disasm-alias func))
(def bytecode (in dasm 'bytecode)) (def bytecode (in dasm :bytecode))
(def pc (frame :pc)) (def pc (frame :pc))
(def sourcemap (in dasm 'sourcemap)) (def sourcemap (in dasm :sourcemap))
(var last-loc [-2 -2]) (var last-loc [-2 -2])
(print "\n signal: " (.signal)) (print "\n signal: " (.signal))
(print " function: " (dasm 'name) " [" (in dasm 'source "") "]") (print " function: " (dasm :name) " [" (in dasm :source "") "]")
(when-let [constants (dasm 'constants)] (when-let [constants (dasm :constants)]
(printf " constants: %.4q" constants)) (printf " constants: %.4q" constants))
(printf " slots: %.4q\n" (frame :slots)) (printf " slots: %.4q\n" (frame :slots))
(def padding (string/repeat " " 20)) (def padding (string/repeat " " 20))

View File

@ -53,7 +53,6 @@ struct JanetAssembler {
Janet name; Janet name;
JanetTable labels; /* keyword -> bytecode index */ JanetTable labels; /* keyword -> bytecode index */
JanetTable constants; /* symbol -> constant index */
JanetTable slots; /* symbol -> slot index */ JanetTable slots; /* symbol -> slot index */
JanetTable envs; /* symbol -> environment index */ JanetTable envs; /* symbol -> environment index */
JanetTable defs; /* symbol -> funcdefs index */ JanetTable defs; /* symbol -> funcdefs index */
@ -172,7 +171,6 @@ static void janet_asm_deinit(JanetAssembler *a) {
janet_table_deinit(&a->slots); janet_table_deinit(&a->slots);
janet_table_deinit(&a->labels); janet_table_deinit(&a->labels);
janet_table_deinit(&a->envs); janet_table_deinit(&a->envs);
janet_table_deinit(&a->constants);
janet_table_deinit(&a->defs); janet_table_deinit(&a->defs);
} }
@ -252,9 +250,6 @@ static int32_t doarg_1(
case JANET_OAT_ENVIRONMENT: case JANET_OAT_ENVIRONMENT:
c = &a->envs; c = &a->envs;
break; break;
case JANET_OAT_CONSTANT:
c = &a->constants;
break;
case JANET_OAT_LABEL: case JANET_OAT_LABEL:
c = &a->labels; c = &a->labels;
break; break;
@ -506,7 +501,6 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
a.defs_capacity = 0; a.defs_capacity = 0;
a.name = janet_wrap_nil(); a.name = janet_wrap_nil();
janet_table_init(&a.labels, 0); janet_table_init(&a.labels, 0);
janet_table_init(&a.constants, 0);
janet_table_init(&a.slots, 0); janet_table_init(&a.slots, 0);
janet_table_init(&a.envs, 0); janet_table_init(&a.envs, 0);
janet_table_init(&a.defs, 0); janet_table_init(&a.defs, 0);
@ -534,34 +528,34 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
"expected struct or table for assembly source"); "expected struct or table for assembly source");
/* Check for function name */ /* Check for function name */
a.name = janet_get1(s, janet_csymbolv("name")); a.name = janet_get1(s, janet_ckeywordv("name"));
if (!janet_checktype(a.name, JANET_NIL)) { if (!janet_checktype(a.name, JANET_NIL)) {
def->name = janet_to_string(a.name); def->name = janet_to_string(a.name);
} }
/* Set function arity */ /* Set function arity */
x = janet_get1(s, janet_csymbolv("arity")); x = janet_get1(s, janet_ckeywordv("arity"));
def->arity = janet_checkint(x) ? janet_unwrap_integer(x) : 0; def->arity = janet_checkint(x) ? janet_unwrap_integer(x) : 0;
janet_asm_assert(&a, def->arity >= 0, "arity must be non-negative"); janet_asm_assert(&a, def->arity >= 0, "arity must be non-negative");
x = janet_get1(s, janet_csymbolv("max-arity")); x = janet_get1(s, janet_ckeywordv("max-arity"));
def->max_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity; def->max_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity;
janet_asm_assert(&a, def->max_arity >= def->arity, "max-arity must be greater than or equal to arity"); janet_asm_assert(&a, def->max_arity >= def->arity, "max-arity must be greater than or equal to arity");
x = janet_get1(s, janet_csymbolv("min-arity")); x = janet_get1(s, janet_ckeywordv("min-arity"));
def->min_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity; def->min_arity = janet_checkint(x) ? janet_unwrap_integer(x) : def->arity;
janet_asm_assert(&a, def->min_arity <= def->arity, "min-arity must be less than or equal to arity"); janet_asm_assert(&a, def->min_arity <= def->arity, "min-arity must be less than or equal to arity");
/* Check vararg */ /* Check vararg */
x = janet_get1(s, janet_csymbolv("vararg")); x = janet_get1(s, janet_ckeywordv("vararg"));
if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_VARARG; if (janet_truthy(x)) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
/* Check source */ /* Check source */
x = janet_get1(s, janet_csymbolv("source")); x = janet_get1(s, janet_ckeywordv("source"));
if (janet_checktype(x, JANET_STRING)) def->source = janet_unwrap_string(x); if (janet_checktype(x, JANET_STRING)) def->source = janet_unwrap_string(x);
/* Create slot aliases */ /* Create slot aliases */
x = janet_get1(s, janet_csymbolv("slots")); x = janet_get1(s, janet_ckeywordv("slots"));
if (janet_indexed_view(x, &arr, &count)) { if (janet_indexed_view(x, &arr, &count)) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
Janet v = arr[i]; Janet v = arr[i];
@ -582,7 +576,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
} }
/* Parse constants */ /* Parse constants */
x = janet_get1(s, janet_csymbolv("constants")); x = janet_get1(s, janet_ckeywordv("constants"));
if (janet_indexed_view(x, &arr, &count)) { if (janet_indexed_view(x, &arr, &count)) {
def->constants_length = count; def->constants_length = count;
def->constants = malloc(sizeof(Janet) * (size_t) count); def->constants = malloc(sizeof(Janet) * (size_t) count);
@ -591,25 +585,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
Janet ct = arr[i]; Janet ct = arr[i];
if (janet_checktype(ct, JANET_TUPLE) && def->constants[i] = ct;
janet_tuple_length(janet_unwrap_tuple(ct)) > 1 &&
janet_checktype(janet_unwrap_tuple(ct)[0], JANET_SYMBOL)) {
const Janet *t = janet_unwrap_tuple(ct);
int32_t tcount = janet_tuple_length(t);
const uint8_t *macro = janet_unwrap_symbol(t[0]);
if (0 == janet_cstrcmp(macro, "quote")) {
def->constants[i] = t[1];
} else if (tcount == 3 &&
janet_checktype(t[1], JANET_SYMBOL) &&
0 == janet_cstrcmp(macro, "def")) {
def->constants[i] = t[2];
janet_table_put(&a.constants, t[1], janet_wrap_integer(i));
} else {
janet_asm_errorv(&a, janet_formatc("could not parse constant \"%v\"", ct));
}
} else {
def->constants[i] = ct;
}
} }
} else { } else {
def->constants = NULL; def->constants = NULL;
@ -617,7 +593,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
} }
/* Parse sub funcdefs */ /* Parse sub funcdefs */
x = janet_get1(s, janet_csymbolv("closures")); x = janet_get1(s, janet_ckeywordv("closures"));
if (janet_indexed_view(x, &arr, &count)) { if (janet_indexed_view(x, &arr, &count)) {
int32_t i; int32_t i;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
@ -628,7 +604,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
if (subres.status != JANET_ASSEMBLE_OK) { if (subres.status != JANET_ASSEMBLE_OK) {
janet_asm_errorv(&a, subres.error); janet_asm_errorv(&a, subres.error);
} }
subname = janet_get1(arr[i], janet_csymbolv("name")); subname = janet_get1(arr[i], janet_ckeywordv("name"));
if (!janet_checktype(subname, JANET_NIL)) { if (!janet_checktype(subname, JANET_NIL)) {
janet_table_put(&a.defs, subname, janet_wrap_integer(def->defs_length)); janet_table_put(&a.defs, subname, janet_wrap_integer(def->defs_length));
} }
@ -647,7 +623,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
} }
/* Parse bytecode and labels */ /* Parse bytecode and labels */
x = janet_get1(s, janet_csymbolv("bytecode")); x = janet_get1(s, janet_ckeywordv("bytecode"));
if (janet_indexed_view(x, &arr, &count)) { if (janet_indexed_view(x, &arr, &count)) {
/* Do labels and find length */ /* Do labels and find length */
int32_t blength = 0; int32_t blength = 0;
@ -703,7 +679,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
a.errindex = -1; a.errindex = -1;
/* Check for source mapping */ /* Check for source mapping */
x = janet_get1(s, janet_csymbolv("sourcemap")); x = janet_get1(s, janet_ckeywordv("sourcemap"));
if (janet_indexed_view(x, &arr, &count)) { if (janet_indexed_view(x, &arr, &count)) {
janet_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode"); janet_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode");
def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) count); def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) count);
@ -864,33 +840,26 @@ Janet janet_disasm(JanetFuncDef *def) {
JanetArray *bcode = janet_array(def->bytecode_length); JanetArray *bcode = janet_array(def->bytecode_length);
JanetArray *constants; JanetArray *constants;
JanetTable *ret = janet_table(10); JanetTable *ret = janet_table(10);
janet_table_put(ret, janet_csymbolv("arity"), janet_wrap_integer(def->arity)); janet_table_put(ret, janet_ckeywordv("arity"), janet_wrap_integer(def->arity));
janet_table_put(ret, janet_csymbolv("min-arity"), janet_wrap_integer(def->min_arity)); janet_table_put(ret, janet_ckeywordv("min-arity"), janet_wrap_integer(def->min_arity));
janet_table_put(ret, janet_csymbolv("max-arity"), janet_wrap_integer(def->max_arity)); janet_table_put(ret, janet_ckeywordv("max-arity"), janet_wrap_integer(def->max_arity));
janet_table_put(ret, janet_csymbolv("bytecode"), janet_wrap_array(bcode)); janet_table_put(ret, janet_ckeywordv("bytecode"), janet_wrap_array(bcode));
if (NULL != def->source) { if (NULL != def->source) {
janet_table_put(ret, janet_csymbolv("source"), janet_wrap_string(def->source)); janet_table_put(ret, janet_ckeywordv("source"), janet_wrap_string(def->source));
} }
if (def->flags & JANET_FUNCDEF_FLAG_VARARG) { if (def->flags & JANET_FUNCDEF_FLAG_VARARG) {
janet_table_put(ret, janet_csymbolv("vararg"), janet_wrap_true()); janet_table_put(ret, janet_ckeywordv("vararg"), janet_wrap_true());
} }
if (NULL != def->name) { if (NULL != def->name) {
janet_table_put(ret, janet_csymbolv("name"), janet_wrap_string(def->name)); janet_table_put(ret, janet_ckeywordv("name"), janet_wrap_string(def->name));
} }
/* Add constants */ /* Add constants */
if (def->constants_length > 0) { if (def->constants_length > 0) {
constants = janet_array(def->constants_length); constants = janet_array(def->constants_length);
janet_table_put(ret, janet_csymbolv("constants"), janet_wrap_array(constants)); janet_table_put(ret, janet_ckeywordv("constants"), janet_wrap_array(constants));
for (i = 0; i < def->constants_length; i++) { for (i = 0; i < def->constants_length; i++) {
Janet src = def->constants[i]; constants->data[i] = def->constants[i];
Janet dest;
if (janet_checktype(src, JANET_TUPLE)) {
dest = janet_wrap_tuple(tup2(janet_csymbolv("quote"), src));
} else {
dest = src;
}
constants->data[i] = dest;
} }
constants->count = def->constants_length; constants->count = def->constants_length;
} }
@ -912,7 +881,7 @@ Janet janet_disasm(JanetFuncDef *def) {
sourcemap->data[i] = janet_wrap_tuple(janet_tuple_end(t)); sourcemap->data[i] = janet_wrap_tuple(janet_tuple_end(t));
} }
sourcemap->count = def->bytecode_length; sourcemap->count = def->bytecode_length;
janet_table_put(ret, janet_csymbolv("sourcemap"), janet_wrap_array(sourcemap)); janet_table_put(ret, janet_ckeywordv("sourcemap"), janet_wrap_array(sourcemap));
} }
/* Add environments */ /* Add environments */
@ -922,7 +891,7 @@ Janet janet_disasm(JanetFuncDef *def) {
envs->data[i] = janet_wrap_integer(def->environments[i]); envs->data[i] = janet_wrap_integer(def->environments[i]);
} }
envs->count = def->environments_length; envs->count = def->environments_length;
janet_table_put(ret, janet_csymbolv("environments"), janet_wrap_array(envs)); janet_table_put(ret, janet_ckeywordv("environments"), janet_wrap_array(envs));
} }
/* Add closures */ /* Add closures */
@ -933,11 +902,11 @@ Janet janet_disasm(JanetFuncDef *def) {
defs->data[i] = janet_disasm(def->defs[i]); defs->data[i] = janet_disasm(def->defs[i]);
} }
defs->count = def->defs_length; defs->count = def->defs_length;
janet_table_put(ret, janet_csymbolv("defs"), janet_wrap_array(defs)); janet_table_put(ret, janet_ckeywordv("defs"), janet_wrap_array(defs));
} }
/* Add slotcount */ /* Add slotcount */
janet_table_put(ret, janet_csymbolv("slotcount"), janet_wrap_integer(def->slotcount)); janet_table_put(ret, janet_ckeywordv("slotcount"), janet_wrap_integer(def->slotcount));
return janet_wrap_struct(janet_table_to_struct(ret)); return janet_wrap_struct(janet_table_to_struct(ret));
} }

View File

@ -91,8 +91,8 @@
# Assembly test # Assembly test
# Fibonacci sequence, implemented with naive recursion. # Fibonacci sequence, implemented with naive recursion.
(def fibasm (asm '{ (def fibasm (asm '{
arity 1 :arity 1
bytecode [ :bytecode [
(ltim 1 0 0x2) # $1 = $0 < 2 (ltim 1 0 0x2) # $1 = $0 < 2
(jmpif 1 :done) # if ($1) goto :done (jmpif 1 :done) # if ($1) goto :done
(lds 1) # $1 = self (lds 1) # $1 = self