diff --git a/README.md b/README.md index ae0fa9e4..4edc8b17 100644 --- a/README.md +++ b/README.md @@ -27,31 +27,17 @@ Byte code interpreter with an assembly interface Proper tail calls for functional code Direct interop with C - - ## Compiling and Running -Clone the repository and run: +To build the runtime and run test, run ```sh -make run -``` -To build the runtime and launch a repl. - -## Basic programs - -To run some basic programs, run the client with one argument, the name of the -file to run. For example, the client that is built will be located in the -client directory, so running a program `script.dst` from the project directory -would be -```bash -client/dst script.dst +make test ``` -You can also use the `--help` option to see more usage information for the vm. - -## Running Tests - -Simply run `make test` to run the currently minimal test suite. +A repl can also be run with +```sh +make repl +``` ## Todo diff --git a/core/compile.c b/core/compile.c index f4510574..185eb985 100644 --- a/core/compile.c +++ b/core/compile.c @@ -150,6 +150,7 @@ void dstc_scope(DstCompiler *c, int flags) { scope.defs = NULL; scope.slots = NULL; scope.smax = -1; + scope.selfconst = -1; scope.bytecode_start = dst_v_count(c->buffer); scope.flags = flags; @@ -224,7 +225,6 @@ DstSlot dstc_resolve( for (i = 0; i < len; i++) { if (scope->syms[i].sym == sym) { ret = scope->syms[i].slot; - ret.flags |= DST_SLOT_NAMED; goto found; } } diff --git a/core/compile.h b/core/compile.h index 6fe5281f..85c92005 100644 --- a/core/compile.h +++ b/core/compile.h @@ -91,6 +91,9 @@ struct DstScope { * that corresponds to the direct parent's stack will always have value 0. */ int32_t *envs; + /* Where to add reference to self in constants */ + int32_t selfconst; + int32_t bytecode_start; int flags; }; diff --git a/core/compile_specials.c b/core/compile_specials.c index 797ea82e..d0dce7dd 100644 --- a/core/compile_specials.c +++ b/core/compile_specials.c @@ -416,6 +416,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { DstFopts subopts = dstc_fopts_default(c); const Dst *params; int varargs = 0; + int selfref = 0; if (argn < 2) { dstc_cerror(c, ast, "expected at least 2 arguments to function literal"); @@ -428,8 +429,11 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { /* Read function parameters */ parami = 0; arity = 0; - head = dst_ast_unwrap(argv[0]); - if (dst_checktype(head, DST_SYMBOL)) parami = 1; + head = dst_ast_unwrap1(argv[0]); + if (dst_checktype(head, DST_SYMBOL)) { + selfref = 1; + parami = 1; + } if (parami >= argn) { dstc_cerror(c, dst_ast_node(argv[0]), "expected function parameters"); return dstc_cslot(dst_wrap_nil()); @@ -438,7 +442,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { if (dst_seq_view(paramv, ¶ms, ¶mcount)) { int32_t i; for (i = 0; i < paramcount; i++) { - Dst param = dst_ast_unwrap(params[i]); + Dst param = dst_ast_unwrap1(params[i]); if (dst_checktype(param, DST_SYMBOL)) { DstSlot slot; /* Check for varargs */ @@ -467,6 +471,17 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) { return dstc_cslot(dst_wrap_nil()); } + /* Check for self ref */ + if (selfref) { + DstSlot slot; + slot.envindex = 0; + slot.flags = DST_SLOT_NAMED | DST_FUNCTION; + slot.constant = dst_wrap_nil(); + slot.index = dstc_lsloti(c); + dstc_emit(c, ast, (slot.index << 8) | DOP_LOAD_SELF); + dstc_nameslot(c, dst_unwrap_symbol(head), slot); + } + /* Compile function body */ for (argi = parami + 1; argi < argn; argi++) { DstSlot s; diff --git a/core/opcodes.h b/core/opcodes.h index f564aef7..298af8a5 100644 --- a/core/opcodes.h +++ b/core/opcodes.h @@ -69,8 +69,8 @@ enum DstOpCode { DOP_LOAD_FALSE, DOP_LOAD_INTEGER, DOP_LOAD_CONSTANT, - DOP_LOAD_SELF, DOP_LOAD_UPVALUE, + DOP_LOAD_SELF, DOP_SET_UPVALUE, DOP_CLOSURE, DOP_PUSH,