mirror of
https://github.com/janet-lang/janet
synced 2025-05-12 04:14:11 +00:00
Add some test code and fix sqlite3 native example.
This commit is contained in:
parent
ed9037e603
commit
c0e373f420
@ -1,7 +1,5 @@
|
|||||||
# Dst Bytecode Reference
|
# Dst Bytecode Reference
|
||||||
|
|
||||||
### Dst alpha 0.0.0
|
|
||||||
|
|
||||||
This document outlines the Dst bytecode format, and core ideas in the runtime
|
This document outlines the Dst bytecode format, and core ideas in the runtime
|
||||||
that are closely related to the bytecode. It should enable the reader
|
that are closely related to the bytecode. It should enable the reader
|
||||||
to write dst assembly code and hopefully understand the dst internals better.
|
to write dst assembly code and hopefully understand the dst internals better.
|
||||||
@ -62,8 +60,9 @@ Fibers also have an incomplete stack frame for the next function call on top
|
|||||||
of their stacks. Making a function call involves pushing arguments to this
|
of their stacks. Making a function call involves pushing arguments to this
|
||||||
temporary stack, and then invoking either the CALL or TCALL instructions.
|
temporary stack, and then invoking either the CALL or TCALL instructions.
|
||||||
Arguments for the next function call are pushed via the PUSH, PUSH2, PUSH3, and
|
Arguments for the next function call are pushed via the PUSH, PUSH2, PUSH3, and
|
||||||
PUSHA instructions. The stack of a fiber will grow as large as needed, so
|
PUSHA instructions. The stack of a fiber will grow as large as needed, although by
|
||||||
recursive algorithms can be used without fear of stack overflow.
|
default dst will limit the maximum size of a fiber's stack.
|
||||||
|
The maximum stack size can be modified on a per fiber basis.
|
||||||
|
|
||||||
The slots in the stack are exposed as virtual registers to instructions. They
|
The slots in the stack are exposed as virtual registers to instructions. They
|
||||||
can hold any Dst value.
|
can hold any Dst value.
|
||||||
@ -72,7 +71,7 @@ can hold any Dst value.
|
|||||||
|
|
||||||
All functions in dst are closures; they combine some bytecode instructions
|
All functions in dst are closures; they combine some bytecode instructions
|
||||||
with 0 or more environments. In the C source, a closure (hereby the same as
|
with 0 or more environments. In the C source, a closure (hereby the same as
|
||||||
a function) is represented by the type `DstFunc *`. The bytecode instruction
|
a function) is represented by the type `DstFunction *`. The bytecode instruction
|
||||||
part of the function is represented by `DstFuncDef *`, and a function environment
|
part of the function is represented by `DstFuncDef *`, and a function environment
|
||||||
is represented with `DstFuncEnv *`.
|
is represented with `DstFuncEnv *`.
|
||||||
|
|
||||||
@ -95,10 +94,12 @@ have a destination register, and 1 or 2 source register. Registers are simply
|
|||||||
named with positive integers.
|
named with positive integers.
|
||||||
|
|
||||||
Each instruction is a 32 bit integer, meaning that the instruction set is a constant
|
Each instruction is a 32 bit integer, meaning that the instruction set is a constant
|
||||||
width instruction set like MIPS. The opcode of each instruction is the least significant
|
width RISC instruction set like MIPS. The opcode of each instruction is the least significant
|
||||||
byte of the instruction. The highest bit of
|
byte of the instruction. The highest bit of
|
||||||
this leading byte is reserved for debugging purpose, so there are 128 possible opcodes encodable
|
this leading byte is reserved for debugging purpose, so there are 128 possible opcodes encodable
|
||||||
with this scheme. The current implementation uses about half of these possible opcodes.
|
with this scheme. Not all of these possible opcode are defined, and will trap the interpreter
|
||||||
|
and emit a debug signal. Note that this mean an unknown opcode is still valid bytecode, it will
|
||||||
|
just put the interpreter into a debug state when executed.
|
||||||
|
|
||||||
```
|
```
|
||||||
X - Payload bits
|
X - Payload bits
|
||||||
@ -117,13 +118,13 @@ There are a few instruction variants that divide these payload bits.
|
|||||||
arguments. The payload is essentially ignored.
|
arguments. The payload is essentially ignored.
|
||||||
* 1 arg - All payload bits correspond to a single value, usually a signed or unsigned integer.
|
* 1 arg - All payload bits correspond to a single value, usually a signed or unsigned integer.
|
||||||
Used for instructions of 1 argument, like returning a value, yielding a value to the parent fiber,
|
Used for instructions of 1 argument, like returning a value, yielding a value to the parent fiber,
|
||||||
or doing a jump.
|
or doing a (relative) jump.
|
||||||
* 2 arg - Payload is split into byte 2 and bytes 3 and 4.
|
* 2 arg - Payload is split into byte 2 and bytes 3 and 4.
|
||||||
The first argument is the 8 bit value from byte 2, and the second argument is the 16 bit value
|
The first argument is the 8 bit value from byte 2, and the second argument is the 16 bit value
|
||||||
from bytes 3 and 4 (`instruction >> 16`). Used for instructions of two arguments, like move, normal
|
from bytes 3 and 4 (`instruction >> 16`). Used for instructions of two arguments, like move, normal
|
||||||
function calls, conditionals, etc.
|
function calls, conditionals, etc.
|
||||||
* 3 arg - Bytes 2, 3, and 4 each correspond to an 8 bit argument.
|
* 3 arg - Bytes 2, 3, and 4 each correspond to an 8 bit argument.
|
||||||
Used for arithmetic operations.
|
Used for arithmetic operations, emitting a signal, etc.
|
||||||
|
|
||||||
These instruction variants can be further refined based on the semantics of the arguments.
|
These instruction variants can be further refined based on the semantics of the arguments.
|
||||||
Some instructions may treat an argument as a slot index, while other instructions
|
Some instructions may treat an argument as a slot index, while other instructions
|
||||||
@ -222,6 +223,7 @@ failure to return or error.
|
|||||||
| `ret` | `(ret val)` | Return $val |
|
| `ret` | `(ret val)` | Return $val |
|
||||||
| `retn` | `(retn)` | Return nil |
|
| `retn` | `(retn)` | Return nil |
|
||||||
| `setu` | `(setu env index val)` | envs[env][index] = $val |
|
| `setu` | `(setu env index val)` | envs[env][index] = $val |
|
||||||
|
| `sig` | `(sig dest value sigtype)` | $dest = emit $value as sigtype |
|
||||||
| `sl` | `(sl dest lhs rhs)` | $dest = $lhs << $rhs |
|
| `sl` | `(sl dest lhs rhs)` | $dest = $lhs << $rhs |
|
||||||
| `slim` | `(slim dest lhs shamt)` | $dest = $lhs << shamt |
|
| `slim` | `(slim dest lhs shamt)` | $dest = $lhs << shamt |
|
||||||
| `sr` | `(sr dest lhs rhs)` | $dest = $lhs >> $rhs |
|
| `sr` | `(sr dest lhs rhs)` | $dest = $lhs >> $rhs |
|
||||||
@ -231,5 +233,4 @@ failure to return or error.
|
|||||||
| `sub` | `(sub dest lhs rhs)` | $dest = $lhs - $rhs |
|
| `sub` | `(sub dest lhs rhs)` | $dest = $lhs - $rhs |
|
||||||
| `tcall` | `(tcall callee)` | Return call($callee) |
|
| `tcall` | `(tcall callee)` | Return call($callee) |
|
||||||
| `tchck` | `(tcheck slot types)` | Assert $slot does matches types |
|
| `tchck` | `(tcheck slot types)` | Assert $slot does matches types |
|
||||||
| `yield` | `(yield dest value)` | $dest = yield $value to parent |
|
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ static int sql_sql(DstArgs args) {
|
|||||||
const uint8_t *str;
|
const uint8_t *str;
|
||||||
DstArray *rows;
|
DstArray *rows;
|
||||||
sqlite3 **conn;
|
sqlite3 **conn;
|
||||||
dst_fixarity(args, 2);
|
DST_FIXARITY(args, 2);
|
||||||
dst_checkabstract(args, 0, &sql_conn_type);
|
DST_CHECKABSTRACT(args, 0, &sql_conn_type);
|
||||||
conn = (sqlite3 **)dst_unwrap_abstract(args.v[0]);
|
conn = (sqlite3 **)dst_unwrap_abstract(args.v[0]);
|
||||||
dst_arg_string(str, args, 1);
|
DST_ARG_STRING(str, args, 1);
|
||||||
rows = dst_array(10);
|
rows = dst_array(10);
|
||||||
status = sqlite3_exec(
|
status = sqlite3_exec(
|
||||||
*conn,
|
*conn,
|
||||||
|
@ -206,6 +206,7 @@ recur:
|
|||||||
i = frame->prevframe;
|
i = frame->prevframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Explicit tail recursion */
|
||||||
if (fiber->child) {
|
if (fiber->child) {
|
||||||
fiber = fiber->child;
|
fiber = fiber->child;
|
||||||
goto recur;
|
goto recur;
|
||||||
|
@ -715,8 +715,8 @@ static void *op_lookup[255] = {
|
|||||||
retreg = dst_wrap_nil();
|
retreg = dst_wrap_nil();
|
||||||
args.v = fiber->data + fiber->frame;
|
args.v = fiber->data + fiber->frame;
|
||||||
args.ret = &retreg;
|
args.ret = &retreg;
|
||||||
if (dst_unwrap_cfunction(callee)(args)) {
|
if ((signal = dst_unwrap_cfunction(callee)(args))) {
|
||||||
goto vm_error;
|
goto vm_exit;
|
||||||
}
|
}
|
||||||
goto vm_return_cfunc;
|
goto vm_return_cfunc;
|
||||||
}
|
}
|
||||||
@ -739,8 +739,8 @@ static void *op_lookup[255] = {
|
|||||||
retreg = dst_wrap_nil();
|
retreg = dst_wrap_nil();
|
||||||
args.v = fiber->data + fiber->frame;
|
args.v = fiber->data + fiber->frame;
|
||||||
args.ret = &retreg;
|
args.ret = &retreg;
|
||||||
if (dst_unwrap_cfunction(callee)(args)) {
|
if ((signal = dst_unwrap_cfunction(callee)(args))) {
|
||||||
goto vm_error;
|
goto vm_exit;
|
||||||
}
|
}
|
||||||
goto vm_return_cfunc_tail;
|
goto vm_return_cfunc_tail;
|
||||||
}
|
}
|
||||||
|
@ -93,5 +93,31 @@
|
|||||||
(assert (= myvar 4) "fiber resumes properly from debug state")
|
(assert (= myvar 4) "fiber resumes properly from debug state")
|
||||||
(assert (= (fiber.status myfiber) :dead) "fiber properly dies from debug state")
|
(assert (= (fiber.status myfiber) :dead) "fiber properly dies from debug state")
|
||||||
|
|
||||||
|
# Test max triangle program
|
||||||
|
|
||||||
|
# Find the maximum path from the top (root)
|
||||||
|
# of the triangle to the leaves of the triangle.
|
||||||
|
|
||||||
|
(defn myfold [xs ys]
|
||||||
|
(let [xs1 (tuple.prepend xs 0)
|
||||||
|
xs2 (tuple.append xs 0)
|
||||||
|
m1 (map + xs1 ys)
|
||||||
|
m2 (map + xs2 ys)]
|
||||||
|
(map max m1 m2)))
|
||||||
|
|
||||||
|
(defn maxpath [t]
|
||||||
|
(extreme > (reduce myfold () t)))
|
||||||
|
|
||||||
|
# Test it
|
||||||
|
# Maximum path is 3 -> 10 -> 3 -> 9 for a total of 25
|
||||||
|
|
||||||
|
(def triangle '[
|
||||||
|
[3]
|
||||||
|
[7 10]
|
||||||
|
[4 3 7]
|
||||||
|
[8 9 1 3]
|
||||||
|
])
|
||||||
|
|
||||||
|
(assert (= (maxpath triangle) 25) `max triangle`)
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user