mirror of
https://github.com/janet-lang/janet
synced 2024-09-28 07:08:14 +00:00
Add self reference in closures without having to use vars.
This commit is contained in:
parent
0531866954
commit
acb706ca3a
26
README.md
26
README.md
@ -27,31 +27,17 @@ Byte code interpreter with an assembly interface
|
|||||||
Proper tail calls for functional code
|
Proper tail calls for functional code
|
||||||
Direct interop with C
|
Direct interop with C
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Compiling and Running
|
## Compiling and Running
|
||||||
|
|
||||||
Clone the repository and run:
|
To build the runtime and run test, run
|
||||||
```sh
|
```sh
|
||||||
make run
|
make test
|
||||||
```
|
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also use the `--help` option to see more usage information for the vm.
|
A repl can also be run with
|
||||||
|
```sh
|
||||||
## Running Tests
|
make repl
|
||||||
|
```
|
||||||
Simply run `make test` to run the currently minimal test suite.
|
|
||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
|
|
||||||
|
@ -150,6 +150,7 @@ void dstc_scope(DstCompiler *c, int flags) {
|
|||||||
scope.defs = NULL;
|
scope.defs = NULL;
|
||||||
scope.slots = NULL;
|
scope.slots = NULL;
|
||||||
scope.smax = -1;
|
scope.smax = -1;
|
||||||
|
scope.selfconst = -1;
|
||||||
scope.bytecode_start = dst_v_count(c->buffer);
|
scope.bytecode_start = dst_v_count(c->buffer);
|
||||||
scope.flags = flags;
|
scope.flags = flags;
|
||||||
|
|
||||||
@ -224,7 +225,6 @@ DstSlot dstc_resolve(
|
|||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (scope->syms[i].sym == sym) {
|
if (scope->syms[i].sym == sym) {
|
||||||
ret = scope->syms[i].slot;
|
ret = scope->syms[i].slot;
|
||||||
ret.flags |= DST_SLOT_NAMED;
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,9 @@ struct DstScope {
|
|||||||
* that corresponds to the direct parent's stack will always have value 0. */
|
* that corresponds to the direct parent's stack will always have value 0. */
|
||||||
int32_t *envs;
|
int32_t *envs;
|
||||||
|
|
||||||
|
/* Where to add reference to self in constants */
|
||||||
|
int32_t selfconst;
|
||||||
|
|
||||||
int32_t bytecode_start;
|
int32_t bytecode_start;
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
@ -416,6 +416,7 @@ DstSlot dstc_fn(DstFopts opts, DstAst *ast, int32_t argn, const Dst *argv) {
|
|||||||
DstFopts subopts = dstc_fopts_default(c);
|
DstFopts subopts = dstc_fopts_default(c);
|
||||||
const Dst *params;
|
const Dst *params;
|
||||||
int varargs = 0;
|
int varargs = 0;
|
||||||
|
int selfref = 0;
|
||||||
|
|
||||||
if (argn < 2) {
|
if (argn < 2) {
|
||||||
dstc_cerror(c, ast, "expected at least 2 arguments to function literal");
|
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 */
|
/* Read function parameters */
|
||||||
parami = 0;
|
parami = 0;
|
||||||
arity = 0;
|
arity = 0;
|
||||||
head = dst_ast_unwrap(argv[0]);
|
head = dst_ast_unwrap1(argv[0]);
|
||||||
if (dst_checktype(head, DST_SYMBOL)) parami = 1;
|
if (dst_checktype(head, DST_SYMBOL)) {
|
||||||
|
selfref = 1;
|
||||||
|
parami = 1;
|
||||||
|
}
|
||||||
if (parami >= argn) {
|
if (parami >= argn) {
|
||||||
dstc_cerror(c, dst_ast_node(argv[0]), "expected function parameters");
|
dstc_cerror(c, dst_ast_node(argv[0]), "expected function parameters");
|
||||||
return dstc_cslot(dst_wrap_nil());
|
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)) {
|
if (dst_seq_view(paramv, ¶ms, ¶mcount)) {
|
||||||
int32_t i;
|
int32_t i;
|
||||||
for (i = 0; i < paramcount; 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)) {
|
if (dst_checktype(param, DST_SYMBOL)) {
|
||||||
DstSlot slot;
|
DstSlot slot;
|
||||||
/* Check for varargs */
|
/* 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());
|
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 */
|
/* Compile function body */
|
||||||
for (argi = parami + 1; argi < argn; argi++) {
|
for (argi = parami + 1; argi < argn; argi++) {
|
||||||
DstSlot s;
|
DstSlot s;
|
||||||
|
@ -69,8 +69,8 @@ enum DstOpCode {
|
|||||||
DOP_LOAD_FALSE,
|
DOP_LOAD_FALSE,
|
||||||
DOP_LOAD_INTEGER,
|
DOP_LOAD_INTEGER,
|
||||||
DOP_LOAD_CONSTANT,
|
DOP_LOAD_CONSTANT,
|
||||||
DOP_LOAD_SELF,
|
|
||||||
DOP_LOAD_UPVALUE,
|
DOP_LOAD_UPVALUE,
|
||||||
|
DOP_LOAD_SELF,
|
||||||
DOP_SET_UPVALUE,
|
DOP_SET_UPVALUE,
|
||||||
DOP_CLOSURE,
|
DOP_CLOSURE,
|
||||||
DOP_PUSH,
|
DOP_PUSH,
|
||||||
|
Loading…
Reference in New Issue
Block a user