mirror of
https://github.com/janet-lang/janet
synced 2025-10-30 15:13:03 +00:00
Getting more work done on assembler, parer, and unit tests.
This commit is contained in:
50
unittests/asm_test.c
Normal file
50
unittests/asm_test.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "unit.h"
|
||||
#include <dst/dst.h>
|
||||
|
||||
int main() {
|
||||
DstParseResult pres;
|
||||
DstAssembleOptions opts;
|
||||
DstAssembleResult ares;
|
||||
DstFunction *func;
|
||||
|
||||
FILE *f = fopen("./unittests/sample.dsts", "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET); //same as rewind(f);
|
||||
|
||||
char *string = malloc(fsize + 1);
|
||||
fread(string, fsize, 1, f);
|
||||
fclose(f);
|
||||
|
||||
string[fsize] = 0;
|
||||
|
||||
dst_init();
|
||||
|
||||
pres = dst_parsec(string);
|
||||
free(string);
|
||||
|
||||
if (pres.status == DST_PARSE_ERROR) {
|
||||
dst_puts(dst_formatc("parse error at %d: %s\n", pres.bytes_read, pres.result.error));
|
||||
return 1;
|
||||
}
|
||||
assert(pres.status == DST_PARSE_OK);
|
||||
dst_puts(dst_formatc("\nparse result: %v\n\n", pres.result.value));
|
||||
|
||||
opts.flags = 0;
|
||||
opts.source = pres.result.value;
|
||||
opts.parsemap = dst_wrap_nil();
|
||||
|
||||
ares = dst_asm(opts);
|
||||
if (ares.status == DST_ASSEMBLE_ERROR) {
|
||||
dst_puts(dst_formatc("assembly error: %s\n", ares.result.error));
|
||||
return 1;
|
||||
}
|
||||
assert(ares.status == DST_ASSEMBLE_OK);
|
||||
|
||||
func = dst_asm_func(ares);
|
||||
|
||||
dst_run(dst_wrap_function(func));
|
||||
dst_puts(dst_formatc("result: %v\n", dst_vm_fiber->ret));
|
||||
|
||||
return 0;
|
||||
}
|
||||
88
unittests/fiber_test.c
Normal file
88
unittests/fiber_test.c
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "unit.h"
|
||||
#include <dst/dst.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Create dud funcdef and function */
|
||||
static DstFunction *dud_func(uint32_t slotcount, uint32_t arity, int varargs) {
|
||||
DstFuncDef *def = dst_alloc(DST_MEMORY_FUNCDEF, sizeof(DstFuncDef));
|
||||
def->environments_length = 0;
|
||||
def->constants_length = 0;
|
||||
def->bytecode_length = 0;
|
||||
def->environments = NULL;
|
||||
def->constants = NULL;
|
||||
def->bytecode = NULL;
|
||||
def->flags = varargs ? DST_FUNCDEF_FLAG_VARARG : 0;
|
||||
def->arity = arity;
|
||||
def->slotcount = slotcount;
|
||||
DstFunction *f = dst_alloc(DST_MEMORY_FUNCTION, sizeof(DstFunction));
|
||||
f->envs = NULL;
|
||||
f->def = def;
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Print debug information for a fiber */
|
||||
static void debug_print_fiber(DstFiber *fiber, int showslots) {
|
||||
uint32_t frameindex = fiber->frame;
|
||||
uint32_t frametopindex = fiber->frametop;
|
||||
const char *statusname =
|
||||
fiber->status == DST_FIBER_ALIVE ? "alive" :
|
||||
fiber->status == DST_FIBER_PENDING ? "pending" :
|
||||
fiber->status == DST_FIBER_ERROR ? "error" :
|
||||
"dead";
|
||||
|
||||
printf("fiber at %p\n", fiber);
|
||||
printf(" frame = %d\n", fiber->frame);
|
||||
printf(" frametop = %d\n", fiber->frametop);
|
||||
printf(" stacktop = %d\n", fiber->stacktop);
|
||||
printf(" capacity = %d\n", fiber->capacity);
|
||||
printf(" status = %s\n -----\n", statusname);
|
||||
|
||||
while (frameindex > 0) {
|
||||
DstValue *stack = fiber->data + frameindex;
|
||||
DstStackFrame *frame = dst_stack_frame(stack);
|
||||
uint32_t slots = frametopindex - frameindex;
|
||||
const uint8_t *str;
|
||||
/* Print the stack frame */
|
||||
if (frame->func != NULL)
|
||||
str = dst_to_string(dst_wrap_function(frame->func));
|
||||
else
|
||||
str = dst_cstring("<anonymous>");
|
||||
printf(" at %.*s (slots: %d)\n",
|
||||
dst_string_length(str),
|
||||
(const char *)str,
|
||||
slots);
|
||||
/* Optionally print all values in the stack */
|
||||
if (showslots) {
|
||||
for (uint32_t j = 0; j < slots; j++) {
|
||||
const uint8_t *vstr = dst_to_string(stack[j]);
|
||||
printf(" [%d]: %.*s\n",
|
||||
j,
|
||||
dst_string_length(vstr),
|
||||
(const char *)vstr);
|
||||
}
|
||||
}
|
||||
frametopindex = frameindex - DST_FRAME_SIZE;
|
||||
frameindex = frame->prevframe;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
dst_init();
|
||||
|
||||
DstFunction *f1 = dud_func(5, 0, 1);
|
||||
DstFiber *fiber1 = dst_fiber(10);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
dst_fiber_funcframe(fiber1, f1);
|
||||
}
|
||||
for (int i = 0; i < 13; i++) {
|
||||
dst_fiber_push(fiber1, dst_wrap_integer(i));
|
||||
}
|
||||
for (int i = 0; i < 10; i++) {
|
||||
dst_fiber_popvalue(fiber1);
|
||||
}
|
||||
dst_fiber_funcframe_tail(fiber1, dud_func(20, 0, 0));
|
||||
debug_print_fiber(fiber1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
unittests/parse_test.c
Normal file
19
unittests/parse_test.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "unit.h"
|
||||
#include <dst/dst.h>
|
||||
|
||||
int main() {
|
||||
DstParseResult pres;
|
||||
const uint8_t *str;
|
||||
|
||||
dst_init();
|
||||
|
||||
pres = dst_parsec("'(+ 1 () [] 3 5 :hello \"hi\\h41\")");
|
||||
|
||||
assert(pres.status == DST_PARSE_OK);
|
||||
assert(pres.result.value.type == DST_TUPLE);
|
||||
|
||||
str = dst_to_string(pres.result.value);
|
||||
printf("%.*s\n", dst_string_length(str), (const char *) str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
69
unittests/sample.dsts
Normal file
69
unittests/sample.dsts
Normal file
@@ -0,0 +1,69 @@
|
||||
# A .dsts file will contain VM, assembly for a dst function. This includes
|
||||
# associated constants and what not. The assembler should be able to
|
||||
# simply construct a FuncDef from this file. This file is also parsed
|
||||
# in the same markup as dst itself (extended S expressions)
|
||||
{
|
||||
arity 3
|
||||
source "source file path"
|
||||
varargs false
|
||||
# Name for reference by nested funcdefs
|
||||
name outerfunc
|
||||
# Contains the bytecode for this function. This can be assembly
|
||||
# instructions or integers. Assembly will be converted to integer bytecodes immediately.
|
||||
bytecode [
|
||||
(load-constant 0 bork)
|
||||
(load-constant 1 bip)
|
||||
(add 0 0 1)
|
||||
(add-immediate 0 0 127)
|
||||
(push3 0 0 0)
|
||||
(push3 0 0 0)
|
||||
(push3 0 0 0)
|
||||
(syscall 1 0)
|
||||
(return 0)
|
||||
]
|
||||
# A source map is optional. The sourcemap corresponds with the byte code.
|
||||
# Each number is a 64 bit integer, the concatenation of two 32 bit integers.
|
||||
# These integers represent source character index for each instruction.
|
||||
# This format may change.
|
||||
# map [
|
||||
# 1
|
||||
# 2
|
||||
# 3
|
||||
# 10
|
||||
# 15
|
||||
# 39
|
||||
# 90
|
||||
# 134
|
||||
# ...
|
||||
# ]
|
||||
#
|
||||
# The number of slots available for the function.
|
||||
# Slots can be named as well for convenience.
|
||||
slots [
|
||||
x
|
||||
y
|
||||
z
|
||||
]
|
||||
# Captured outer environments that are referenced
|
||||
environments [ ]
|
||||
# Constants are an array or tuple. For named constants, use a tuple that begins with let
|
||||
# For a literal tuple, use (quote tuple), or 'tuple. Without names, constants must be indexed
|
||||
# from their number
|
||||
# Literal FuncEnvs and Functions may be possible later
|
||||
constants [
|
||||
"hello"
|
||||
(def bork 123)
|
||||
(def bip 456)
|
||||
'(1 2 3)
|
||||
(def atuple (1 2 3))
|
||||
(567)
|
||||
]
|
||||
# Arbitrary meta data can be added to the source
|
||||
my-meta-2 @{
|
||||
1 2 3 4
|
||||
}
|
||||
my-meta {
|
||||
1 2 3 4 5 6 7 8 9 0 11 12 13 14
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,9 @@ int main() {
|
||||
assert(table->count == 2);
|
||||
dst_table_remove(table, dst_cstringv("a"));
|
||||
assert(table->count == 1);
|
||||
assert(dst_equals(
|
||||
dst_table_get(table, dst_cstringv("b")),
|
||||
dst_cstringv("a")
|
||||
));
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user