mirror of
https://github.com/janet-lang/janet
synced 2026-04-10 17:01:28 +00:00
Compare commits
38 Commits
0.3.0
...
core-image
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b61d1a0a0e | ||
|
|
89ef4eb634 | ||
|
|
114a45306d | ||
|
|
fe27df528c | ||
|
|
6321c30cb1 | ||
|
|
8343c9edd1 | ||
|
|
74e1a3273f | ||
|
|
1394dbbd57 | ||
|
|
f6a3853131 | ||
|
|
49465f71f3 | ||
|
|
960cf76eb5 | ||
|
|
1b735564fa | ||
|
|
7ae01d25dd | ||
|
|
cb5263d2d8 | ||
|
|
602092f6d5 | ||
|
|
d3a067a665 | ||
|
|
98a26f5ce3 | ||
|
|
09d9dca5f5 | ||
|
|
8a3f512746 | ||
|
|
19e59705b9 | ||
|
|
367c9da856 | ||
|
|
4bcf6565cd | ||
|
|
0c950d0846 | ||
|
|
7ba925c50a | ||
|
|
cb3b9dd76f | ||
|
|
f4fa55027b | ||
|
|
0fe11adb9c | ||
|
|
b138ee6e8e | ||
|
|
a66f19f636 | ||
|
|
c76f4e89d8 | ||
|
|
85a211b26b | ||
|
|
fe3620529f | ||
|
|
a7551e9b4e | ||
|
|
46c540b93e | ||
|
|
32c209ede9 | ||
|
|
0d293cd3f5 | ||
|
|
f284776490 | ||
|
|
38a7e4faf1 |
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,6 +1,19 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 0.4.0 - ??
|
||||
- Add methods to parser values that mirror the api.
|
||||
- Add janet\_getmethod to CAPI for easier use of method like syntax.
|
||||
- Add get/set to abstract types to allow them to behave more
|
||||
like objects with methods.
|
||||
- Add parser/insert to modify parser state programmatically
|
||||
- Add debug/stacktrace for easy, pretty stacktraces
|
||||
- Remove the status-pp function
|
||||
- Update API to run-context to be much more sane
|
||||
- Add :lflags option to cook/make-native
|
||||
- Disallow NaNs as table or struct keys
|
||||
- Update module resolution paths and format
|
||||
|
||||
## 0.3.0 - 2019-26-01
|
||||
- Add amalgamated build to janet for easier embedding.
|
||||
- Add os/date function
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019 Calvin Rose
|
||||
Copyright (c) 2019 Calvin Rose and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
39
Makefile
39
Makefile
@@ -47,7 +47,7 @@ else
|
||||
CLIBS:=$(CLIBS) -lrt
|
||||
endif
|
||||
|
||||
$(shell mkdir -p build/core build/mainclient build/webclient)
|
||||
$(shell mkdir -p build/core build/mainclient build/webclient build/boot)
|
||||
|
||||
# Source headers
|
||||
JANET_HEADERS=$(sort $(wildcard src/include/janet/*.h))
|
||||
@@ -60,14 +60,33 @@ JANET_WEBCLIENT_SOURCES=$(sort $(wildcard src/webclient/*.c))
|
||||
|
||||
all: $(JANET_TARGET) $(JANET_LIBRARY)
|
||||
|
||||
##################################################################
|
||||
##### The bootstrap interpreter that compiles the core image #####
|
||||
##################################################################
|
||||
|
||||
JANET_BOOT_OBJECTS=$(patsubst src/%.c,build/%.boot.o,$(JANET_CORE_SOURCES) src/boot/boot.c) \
|
||||
build/core.gen.o \
|
||||
build/boot.gen.o
|
||||
|
||||
build/%.boot.o: src/%.c
|
||||
$(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ -c $<
|
||||
|
||||
build/janet_boot: $(JANET_BOOT_OBJECTS)
|
||||
$(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ $^ $(CLIBS)
|
||||
|
||||
# Now the reason we bootstrap in the first place
|
||||
build/core_image.c: build/janet_boot
|
||||
build/janet_boot
|
||||
|
||||
##########################################################
|
||||
##### The main interpreter program and shared object #####
|
||||
##########################################################
|
||||
|
||||
JANET_CORE_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_CORE_SOURCES)) build/core.gen.o
|
||||
JANET_CORE_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_CORE_SOURCES)) build/core_image.o
|
||||
JANET_MAINCLIENT_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_MAINCLIENT_SOURCES)) build/init.gen.o
|
||||
|
||||
%.gen.o: %.gen.c
|
||||
# Compile the core image generated by the bootstrap build
|
||||
build/core_image.o: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
build/%.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
@@ -92,11 +111,14 @@ EMCFLAGS=-std=c99 -Wall -Wextra -Isrc/include -O2 \
|
||||
JANET_EMTARGET=build/janet.js
|
||||
JANET_WEB_SOURCES=$(JANET_CORE_SOURCES) $(JANET_WEBCLIENT_SOURCES)
|
||||
JANET_EMOBJECTS=$(patsubst src/%.c,build/%.bc,$(JANET_WEB_SOURCES)) \
|
||||
build/webinit.gen.bc build/core.gen.bc
|
||||
build/webinit.gen.bc build/core_image.bc
|
||||
|
||||
%.gen.bc: %.gen.c
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
build/core_image.bc: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
build/%.bc: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
@@ -109,6 +131,9 @@ emscripten: $(JANET_EMTARGET)
|
||||
##### Generated C files #####
|
||||
#############################
|
||||
|
||||
%.gen.o: %.gen.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
build/xxd: tools/xxd.c
|
||||
$(CC) $< -o $@
|
||||
|
||||
@@ -118,12 +143,14 @@ build/init.gen.c: src/mainclient/init.janet build/xxd
|
||||
build/xxd $< $@ janet_gen_init
|
||||
build/webinit.gen.c: src/webclient/webinit.janet build/xxd
|
||||
build/xxd $< $@ janet_gen_webinit
|
||||
build/boot.gen.c: src/boot/boot.janet build/xxd
|
||||
build/xxd $< $@ janet_gen_boot
|
||||
|
||||
########################
|
||||
##### Amalgamation #####
|
||||
########################
|
||||
|
||||
amalg: build/janet.c build/janet.h
|
||||
amalg: build/janet.c build/janet.h build/core_image.c
|
||||
|
||||
build/janet.c: $(JANET_LOCAL_HEADERS) $(JANET_CORE_SOURCES) tools/amalg.janet $(JANET_TARGET)
|
||||
$(JANET_TARGET) tools/amalg.janet > $@
|
||||
@@ -165,7 +192,7 @@ dist: build/janet-dist.tar.gz
|
||||
|
||||
build/janet-%.tar.gz: $(JANET_TARGET) src/include/janet/janet.h \
|
||||
janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) \
|
||||
build/doc.html README.md
|
||||
build/doc.html README.md build/janet.c
|
||||
tar -czvf $@ $^
|
||||
|
||||
#########################
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[](https://gitter.im/janet-language/community)
|
||||
|
||||
[](https://travis-ci.org/janet-lang/janet)
|
||||
[](https://ci.appveyor.com/project/janet-lang/janet)
|
||||
|
||||
@@ -85,7 +87,7 @@ A repl is launched when the binary is invoked with no arguments. Pass the -h fla
|
||||
to display the usage information. Individual scripts can be run with `./janet myscript.janet`
|
||||
|
||||
If you are looking to explore, you can print a list of all available macros, functions, and constants
|
||||
by entering the command `(all-symbols)` into the repl.
|
||||
by entering the command `(all-bindings)` into the repl.
|
||||
|
||||
```
|
||||
$ ./janet
|
||||
@@ -175,9 +177,10 @@ Building with emscripten on windows is currently unsupported.
|
||||
|
||||
See the examples directory for some example janet code.
|
||||
|
||||
## IRC
|
||||
## Discussion
|
||||
|
||||
Feel free to ask questions and join discussion on [the #janet channel on Freenode](https://webchat.freenode.net/)
|
||||
Feel free to ask questions and join discussion on the [Janet Gitter Channel](https://gitter.im/janet-language/community).
|
||||
Alternatively, check out [the #janet channel on Freenode](https://webchat.freenode.net/)
|
||||
|
||||
## Why Janet
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
mkdir build
|
||||
mkdir build\core
|
||||
mkdir build\mainclient
|
||||
mkdir build\boot
|
||||
|
||||
@rem Build the xxd tool for generating sources
|
||||
@cl /nologo /c tools/xxd.c /Fobuild\xxd.obj
|
||||
@@ -34,12 +35,33 @@ mkdir build\mainclient
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
@build\xxd.exe src\mainclient\init.janet build\init.gen.c janet_gen_init
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
@build\xxd.exe src\boot\boot.janet build\boot.gen.c janet_gen_boot
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
|
||||
@rem Build the generated sources
|
||||
@%JANET_COMPILE% /Fobuild\core\core.gen.obj build\core.gen.c
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
@%JANET_COMPILE% /Fobuild\mainclient\init.gen.obj build\init.gen.c
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
@%JANET_COMPILE% /Fobuild\boot\boot.gen.obj build\boot.gen.c
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
|
||||
@rem Build the bootstrap interpretter
|
||||
for %%f in (src\core\*.c) do (
|
||||
@%JANET_COMPILE% /DJANET_BOOTSTRAP /Fobuild\boot\%%~nf.obj %%f
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
)
|
||||
for %%f in (src\boot\*.c) do (
|
||||
@%JANET_COMPILE% /DJANET_BOOTSTRAP /Fobuild\boot\%%~nf.obj %%f
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
)
|
||||
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
build\janet_boot
|
||||
|
||||
@rem Build the core image
|
||||
@%JANET_COMPILE% /Fobuild\core_image.obj build\core_image.c
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
|
||||
@rem Build the sources
|
||||
for %%f in (src\core\*.c) do (
|
||||
@@ -54,7 +76,7 @@ for %%f in (src\mainclient\*.c) do (
|
||||
)
|
||||
|
||||
@rem Link everything to main client
|
||||
%JANET_LINK% /out:janet.exe build\core\*.obj build\mainclient\*.obj
|
||||
%JANET_LINK% /out:janet.exe build\core\*.obj build\mainclient\*.obj build\core_image.obj
|
||||
@if errorlevel 1 goto :BUILDFAIL
|
||||
|
||||
echo === Successfully built janet.exe for Windows ===
|
||||
@@ -101,6 +123,8 @@ copy README.md dist\README.md
|
||||
copy janet.lib dist\janet.lib
|
||||
copy janet.exp dist\janet.exp
|
||||
copy src\include\janet\janet.h dist\janet.h
|
||||
copy tools\cook.janet dist\cook.janet
|
||||
copy tools\highlight.janet dist\highlight.janet
|
||||
exit /b 0
|
||||
|
||||
:TESTFAIL
|
||||
|
||||
23
examples/numarray/build.janet
Normal file
23
examples/numarray/build.janet
Normal file
@@ -0,0 +1,23 @@
|
||||
(import cook)
|
||||
|
||||
(cook/make-native
|
||||
:name "numarray"
|
||||
:source @["numarray.c"])
|
||||
|
||||
(import build/numarray :prefix "")
|
||||
|
||||
(def a (numarray/new 30))
|
||||
(print (get a 20))
|
||||
(print (a 20))
|
||||
|
||||
(put a 5 3.14)
|
||||
(print (a 5))
|
||||
(set (a 5) 100)
|
||||
(print (a 5))
|
||||
|
||||
# (numarray/scale a 5))
|
||||
# ((a :scale) a 5)
|
||||
(:scale a 5)
|
||||
(for i 0 10 (print (a i)))
|
||||
|
||||
(print "sum=" (:sum a))
|
||||
115
examples/numarray/numarray.c
Normal file
115
examples/numarray/numarray.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <stdlib.h>
|
||||
#include <janet/janet.h>
|
||||
|
||||
typedef struct {
|
||||
double * data;
|
||||
size_t size;
|
||||
} num_array;
|
||||
|
||||
static num_array * num_array_init(num_array * array,size_t size) {
|
||||
array->data=(double *)calloc(size,sizeof(double));
|
||||
array->size=size;
|
||||
return array;
|
||||
}
|
||||
|
||||
static void num_array_deinit(num_array * array) {
|
||||
free(array->data);
|
||||
}
|
||||
|
||||
static int num_array_gc(void *p, size_t s) {
|
||||
(void) s;
|
||||
num_array * array=(num_array *)p;
|
||||
num_array_deinit(array);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Janet num_array_get(void *p, Janet key);
|
||||
void num_array_put(void *p, Janet key, Janet value);
|
||||
|
||||
static const JanetAbstractType num_array_type = {
|
||||
"numarray",
|
||||
num_array_gc,
|
||||
NULL,
|
||||
num_array_get,
|
||||
num_array_put
|
||||
};
|
||||
|
||||
static Janet num_array_new(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
int32_t size=janet_getinteger(argv,0);
|
||||
num_array * array = (num_array *)janet_abstract(&num_array_type,sizeof(num_array));
|
||||
num_array_init(array,size);
|
||||
return janet_wrap_abstract(array);
|
||||
}
|
||||
|
||||
static Janet num_array_scale(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
num_array * array = (num_array *)janet_getabstract(argv,0,&num_array_type);
|
||||
double factor = janet_getnumber(argv,1);
|
||||
size_t i;
|
||||
for (i=0;i<array->size;i++) {
|
||||
array->data[i]*=factor;
|
||||
}
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static Janet num_array_sum(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
num_array * array = (num_array *)janet_getabstract(argv,0,&num_array_type);
|
||||
double sum = 0;
|
||||
for (size_t i=0;i<array->size;i++) sum+=array->data[i];
|
||||
return janet_wrap_number(sum);
|
||||
}
|
||||
|
||||
void num_array_put(void *p, Janet key, Janet value) {
|
||||
size_t index;
|
||||
num_array * array=(num_array *)p;
|
||||
if (!janet_checkint(key))
|
||||
janet_panic("expected integer key");
|
||||
if (!janet_checktype(value,JANET_NUMBER))
|
||||
janet_panic("expected number value");
|
||||
|
||||
index = (size_t)janet_unwrap_integer(key);
|
||||
if (index < array->size) {
|
||||
array->data[index]=janet_unwrap_number(value);
|
||||
}
|
||||
}
|
||||
|
||||
static const JanetMethod methods[] = {
|
||||
{"scale", num_array_scale},
|
||||
{"sum", num_array_sum},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
Janet num_array_get(void *p, Janet key) {
|
||||
size_t index;
|
||||
Janet value;
|
||||
num_array * array=(num_array *)p;
|
||||
if (janet_checktype(key, JANET_KEYWORD))
|
||||
return janet_getmethod(janet_unwrap_keyword(key), methods);
|
||||
if (!janet_checkint(key))
|
||||
janet_panic("expected integer key");
|
||||
index = (size_t)janet_unwrap_integer(key);
|
||||
if (index >= array->size) {
|
||||
value = janet_wrap_nil();
|
||||
} else {
|
||||
value = janet_wrap_number(array->data[index]);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static const JanetReg cfuns[] = {
|
||||
{"numarray/new", num_array_new,
|
||||
"(numarray/new size)\n\n"
|
||||
"Create new numarray"
|
||||
},
|
||||
{"numarray/scale", num_array_scale,
|
||||
"(numarray/scale numarray factor)\n\n"
|
||||
"scale numarray by factor"
|
||||
},
|
||||
{NULL,NULL,NULL}
|
||||
};
|
||||
|
||||
JANET_MODULE_ENTRY(JanetTable *env) {
|
||||
janet_cfuns(env, "numarray", cfuns);
|
||||
}
|
||||
43
src/boot/boot.c
Normal file
43
src/boot/boot.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <janet/janet.h>
|
||||
|
||||
extern const unsigned char *janet_gen_boot;
|
||||
extern int32_t janet_gen_boot_size;
|
||||
|
||||
int main() {
|
||||
int status;
|
||||
JanetTable *env;
|
||||
|
||||
/* Set up VM */
|
||||
janet_init();
|
||||
env = janet_core_env();
|
||||
|
||||
/* Run bootstrap script to generate core image */
|
||||
status = janet_dobytes(env, janet_gen_boot, janet_gen_boot_size, "boot.janet", NULL);
|
||||
|
||||
/* Deinitialize vm */
|
||||
janet_deinit();
|
||||
|
||||
return status;
|
||||
}
|
||||
40
src/boot/boot.janet
Normal file
40
src/boot/boot.janet
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright (C) Calvin Rose 2019
|
||||
|
||||
# The bootstrap script is used to produce the source file for
|
||||
# embedding the core image.
|
||||
|
||||
# Tool to dump a marshalled version of the janet core to stdout. The
|
||||
# image should eventually allow janet to be started from a pre-compiled
|
||||
# image rather than recompiled every time from the embedded source. More
|
||||
# work will go into shrinking the image (it isn't currently that large but
|
||||
# could be smaller), creating the mechanism to load the image, and modifying
|
||||
# the build process to compile janet with a built image rather than
|
||||
# embedded source.
|
||||
|
||||
# Get image. This image contains as much of the core library and documentation that
|
||||
# can be written to an image (no cfunctions, no abstracts (stdout, stdin, stderr)),
|
||||
# everything else goes. Cfunctions and abstracts will be referenced from a registry
|
||||
# table which will be generated on janet startup.
|
||||
(do
|
||||
(def image (let [env-pairs (pairs (env-lookup *env*))
|
||||
essential-pairs (filter (fn [[k v]] (or (cfunction? v) (abstract? v))) env-pairs)
|
||||
lookup (table ;(mapcat identity essential-pairs))
|
||||
reverse-lookup (invert lookup)]
|
||||
(marshal *env* reverse-lookup)))
|
||||
|
||||
# Create C source file that contains images a uint8_t buffer. This
|
||||
# can be compiled and linked statically into the main janet library
|
||||
# and example client.
|
||||
(def chunks (seq [b :in image] (string b)))
|
||||
(def image-file (file/open "build/core_image.c" :w))
|
||||
(file/write image-file
|
||||
"#include <janet/janet.h>\n"
|
||||
"static const unsigned char janet_core_image_bytes[] = {")
|
||||
(loop [line :in (partition 16 chunks)]
|
||||
(def str (string ;(interpose ", " line)))
|
||||
(file/write image-file str ",\n"))
|
||||
(file/write image-file
|
||||
"0};\n\n"
|
||||
"const unsigned char *janet_core_image = janet_core_image_bytes;\n"
|
||||
"size_t janet_core_image_size = sizeof(janet_core_image_bytes);\n")
|
||||
(file/close image-file))
|
||||
@@ -267,5 +267,5 @@ static const JanetReg array_cfuns[] = {
|
||||
|
||||
/* Load the array module */
|
||||
void janet_lib_array(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, array_cfuns);
|
||||
janet_core_cfuns(env, NULL, array_cfuns);
|
||||
}
|
||||
|
||||
@@ -951,7 +951,7 @@ static const JanetReg asm_cfuns[] = {
|
||||
|
||||
/* Load the library */
|
||||
void janet_lib_asm(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, asm_cfuns);
|
||||
janet_core_cfuns(env, NULL, asm_cfuns);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -387,5 +387,5 @@ static const JanetReg buffer_cfuns[] = {
|
||||
};
|
||||
|
||||
void janet_lib_buffer(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, buffer_cfuns);
|
||||
janet_core_cfuns(env, NULL, buffer_cfuns);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#endif
|
||||
|
||||
void janet_panicv(Janet message) {
|
||||
if (janet_vm_fiber != NULL) {
|
||||
janet_fiber_push(janet_vm_fiber, message);
|
||||
longjmp(janet_vm_fiber->buf, 1);
|
||||
if (janet_vm_return_reg != NULL) {
|
||||
*janet_vm_return_reg = message;
|
||||
longjmp(*janet_vm_jmp_buf, 1);
|
||||
} else {
|
||||
fputs((const char *)janet_formatc("janet top level panic - %v\n", message), stdout);
|
||||
exit(1);
|
||||
@@ -73,6 +73,16 @@ type janet_get##name(const Janet *argv, int32_t n) { \
|
||||
return janet_unwrap_##name(x); \
|
||||
}
|
||||
|
||||
Janet janet_getmethod(const uint8_t *method, const JanetMethod *methods) {
|
||||
while (methods->name) {
|
||||
if (!janet_cstrcmp(method, methods->name))
|
||||
return janet_wrap_cfunction(methods->cfun);
|
||||
methods++;
|
||||
}
|
||||
janet_panicf("unknown method %S invoked", method);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
DEFINE_GETTER(number, NUMBER, double)
|
||||
DEFINE_GETTER(array, ARRAY, JanetArray *)
|
||||
DEFINE_GETTER(tuple, TUPLE, const Janet *)
|
||||
|
||||
@@ -101,8 +101,15 @@ static JanetSlot do_get(JanetFopts opts, JanetSlot *args) {
|
||||
return opreduce(opts, args, JOP_GET, janet_wrap_nil());
|
||||
}
|
||||
static JanetSlot do_put(JanetFopts opts, JanetSlot *args) {
|
||||
janetc_emit_sss(opts.compiler, JOP_PUT, args[0], args[1], args[2], 0);
|
||||
return args[0];
|
||||
if (opts.flags & JANET_FOPTS_DROP) {
|
||||
janetc_emit_sss(opts.compiler, JOP_PUT, args[0], args[1], args[2], 0);
|
||||
return janetc_cslot(janet_wrap_nil());
|
||||
} else {
|
||||
JanetSlot t = janetc_gettarget(opts);
|
||||
janetc_copy(opts.compiler, t, args[0]);
|
||||
janetc_emit_sss(opts.compiler, JOP_PUT, t, args[1], args[2], 0);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
static JanetSlot do_length(JanetFopts opts, JanetSlot *args) {
|
||||
return genericSS(opts, JOP_LENGTH, args[0]);
|
||||
|
||||
@@ -738,5 +738,5 @@ static const JanetReg compile_cfuns[] = {
|
||||
};
|
||||
|
||||
void janet_lib_compile(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, compile_cfuns);
|
||||
janet_core_cfuns(env, NULL, compile_cfuns);
|
||||
}
|
||||
|
||||
@@ -723,7 +723,8 @@
|
||||
nil if not found. Note their is no way to differentiate a nil from the indexed collection
|
||||
and a not found. Consider find-index if this is an issue."
|
||||
[pred ind]
|
||||
(get ind (find-index pred ind)))
|
||||
(def i (find-index pred ind))
|
||||
(if (= i nil) nil (get ind i)))
|
||||
|
||||
(defn take-until
|
||||
"Given a predicate, take only elements from an indexed type that satisfy
|
||||
@@ -1066,6 +1067,20 @@ value, one key will be ignored."
|
||||
(++ i))
|
||||
ret)
|
||||
|
||||
(defn partition
|
||||
"Partition an indexed data structure into tuples
|
||||
of size n. Returns a new array."
|
||||
[n ind]
|
||||
(var i 0) (var nextn n)
|
||||
(def len (length ind))
|
||||
(def ret (array/new (math/ceil (/ len n))))
|
||||
(while (<= nextn len)
|
||||
(array/push ret (tuple/slice ind i nextn))
|
||||
(set i nextn)
|
||||
(+= nextn n))
|
||||
(if (not= i len) (array/push ret (tuple/slice ind i)))
|
||||
ret)
|
||||
|
||||
###
|
||||
###
|
||||
### Pattern Matching
|
||||
@@ -1384,17 +1399,56 @@ value, one key will be ignored."
|
||||
(def newenv (table/setproto @{} parent))
|
||||
newenv)
|
||||
|
||||
(defn bad-parse
|
||||
"Default handler for a parse error."
|
||||
[p where]
|
||||
(file/write stderr
|
||||
"parse error in "
|
||||
where
|
||||
" around byte "
|
||||
(string (parser/where p))
|
||||
": "
|
||||
(or (parser/error p) "unmatched delimiter")
|
||||
"\n"))
|
||||
|
||||
(defn bad-compile
|
||||
"Default handler for a compile error."
|
||||
[msg macrof where]
|
||||
(file/write stderr "compile error: " msg " while compiling " where "\n")
|
||||
(when macrof (debug/stacktrace macrof)))
|
||||
|
||||
(defn getline
|
||||
"Read a line from stdin into a buffer."
|
||||
[buf p &]
|
||||
(default buf @"")
|
||||
(when p (file/write stdout p))
|
||||
(file/read stdin :line buf)
|
||||
buf)
|
||||
|
||||
(defn run-context
|
||||
"Run a context. This evaluates expressions of janet in an environment,
|
||||
and is encapsulates the parsing, compilation, and evaluation of janet.
|
||||
env is the environment to evaluate the code in, chunks is a function
|
||||
that returns strings or buffers of source code (from a repl, file,
|
||||
network connection, etc. onstatus is a callback that is
|
||||
invoked when a result is returned or any other signal is raised.
|
||||
and is encapsulates the parsing, compilation, and evaluation.
|
||||
opts is a table or struct of options. The options are as follows:\n\n\t
|
||||
:chunks - callback to read into a buffer - default is getline\n\t
|
||||
:on-parse-error - callback when parsing fails - default is bad-parse\n\t
|
||||
:env - the environment to compile against - default is *env*\n\t
|
||||
:source - string path of source for better errors - default is \"<anonymous>\"\n\t
|
||||
:on-compile-error - callback when compilation fails - default is bad-compile\n\t
|
||||
:on-status - callback when a value is evaluated - default is debug/stacktrace"
|
||||
[opts]
|
||||
|
||||
This function can be used to implement a repl very easily, simply
|
||||
pass a function that reads line from stdin to chunks, status-pp to onstatus"
|
||||
[env chunks onstatus where &]
|
||||
(def {:env env
|
||||
:chunks chunks
|
||||
:on-status onstatus
|
||||
:on-compile-error on-compile-error
|
||||
:on-parse-error on-parse-error
|
||||
:source where} opts)
|
||||
(default env *env*)
|
||||
(default chunks getline)
|
||||
(default onstatus debug/stacktrace)
|
||||
(default on-compile-error bad-compile)
|
||||
(default on-parse-error bad-parse)
|
||||
(default where "<anonymous>")
|
||||
|
||||
# Are we done yet?
|
||||
(var going true)
|
||||
@@ -1414,17 +1468,14 @@ value, one key will be ignored."
|
||||
(do
|
||||
(set good false)
|
||||
(def {:error err :start start :end end :fiber errf} res)
|
||||
(onstatus
|
||||
:compile
|
||||
(def msg
|
||||
(if (<= 0 start)
|
||||
(string err "\n at (" start ":" end ")")
|
||||
err)
|
||||
errf
|
||||
where))))
|
||||
(string "compile error: " err " at (" start ":" end ")")
|
||||
err))
|
||||
(on-compile-error msg errf where))))
|
||||
:a))
|
||||
(def res (resume f nil))
|
||||
(when good
|
||||
(if going (onstatus (fiber/status f) res f where))))
|
||||
(when good (if going (onstatus f res))))
|
||||
|
||||
(def oldenv *env*)
|
||||
(set *env* env)
|
||||
@@ -1443,73 +1494,19 @@ value, one key will be ignored."
|
||||
(while (parser/has-more p)
|
||||
(eval1 (parser/produce p)))
|
||||
(when (= (parser/status p) :error)
|
||||
(onstatus :parse
|
||||
(string (parser/error p)
|
||||
" around byte " (parser/where p))
|
||||
nil
|
||||
where))))
|
||||
(on-parse-error p where))))
|
||||
|
||||
(if (= (parser/status p) :pending)
|
||||
(onstatus :parse
|
||||
(string "unmatched delimiters " (parser/state p))
|
||||
nil
|
||||
where))
|
||||
(on-parse-error p where))
|
||||
|
||||
(set *env* oldenv)
|
||||
|
||||
env)
|
||||
|
||||
(defn status-pp
|
||||
"Pretty print a signal and associated state. Can be used as the
|
||||
onsignal argument to run-context."
|
||||
[sig x f source]
|
||||
(def title
|
||||
(case sig
|
||||
:parse "parse error"
|
||||
:compile "compile error"
|
||||
:error "error"
|
||||
(string "status " sig)))
|
||||
(file/write stderr
|
||||
(string title " in " source ": ")
|
||||
(if (bytes? x) x (string/pretty x))
|
||||
"\n")
|
||||
(when f
|
||||
(loop
|
||||
[nf :in (reverse (debug/lineage f))
|
||||
{:function func
|
||||
:tail tail
|
||||
:pc pc
|
||||
:c c
|
||||
:name name
|
||||
:source source
|
||||
:source-start start
|
||||
:source-end end} :in (debug/stack nf)]
|
||||
(file/write stderr " in")
|
||||
(when c (file/write stderr " cfunction"))
|
||||
(if name
|
||||
(file/write stderr " " name)
|
||||
(when func (file/write stderr " <anonymous>")))
|
||||
(if source
|
||||
(do
|
||||
(file/write stderr " [" source "]")
|
||||
(if start
|
||||
(file/write
|
||||
stderr
|
||||
" at ("
|
||||
(string start)
|
||||
":"
|
||||
(string end)
|
||||
")"))))
|
||||
(if (and (not start) pc)
|
||||
(file/write stderr " (pc=" (string pc) ")"))
|
||||
(when tail (file/write stderr " (tailcall)"))
|
||||
(file/write stderr "\n"))))
|
||||
|
||||
(defn eval-string
|
||||
"Evaluates a string in the current environment. If more control over the
|
||||
environment is needed, use run-context."
|
||||
[str env &]
|
||||
(default env *env*)
|
||||
(var state (string str))
|
||||
(defn chunks [buf _]
|
||||
(def ret state)
|
||||
@@ -1518,12 +1515,15 @@ value, one key will be ignored."
|
||||
(buffer/push-string buf str)
|
||||
(buffer/push-string buf "\n")))
|
||||
(var returnval nil)
|
||||
(run-context env chunks
|
||||
(fn [sig x f source]
|
||||
(if (= sig :dead)
|
||||
(set returnval x)
|
||||
(status-pp sig x f source)))
|
||||
"eval")
|
||||
(run-context {:env env
|
||||
:chunks chunks
|
||||
:on-compile-error error
|
||||
:on-parse-error error
|
||||
:on-status (fn [f val]
|
||||
(set returnval val)
|
||||
(if-not (= (fiber/status f) :dead)
|
||||
(debug/stacktrace f val)))
|
||||
:source "eval"})
|
||||
returnval)
|
||||
|
||||
(defn eval
|
||||
@@ -1537,7 +1537,7 @@ value, one key will be ignored."
|
||||
(error (res :error))))
|
||||
|
||||
(def module/paths
|
||||
"The list of paths to look for modules. The followig
|
||||
"The list of paths to look for modules. The following
|
||||
substitutions are preformed on each path. :sys: becomes
|
||||
module/*syspath*, :name: becomes the last part of the module
|
||||
name after the last /, and :all: is the module name literally.
|
||||
@@ -1546,14 +1546,16 @@ value, one key will be ignored."
|
||||
@["./:all:.janet"
|
||||
"./:all:/init.janet"
|
||||
":sys:/:all:.janet"
|
||||
":sys:/:all:/init.janet"])
|
||||
":sys:/:all:/init.janet"
|
||||
":all:"])
|
||||
|
||||
(def module/native-paths
|
||||
"See doc for module/paths"
|
||||
@["./:all:.:native:"
|
||||
"./:all:/:name:.:native:"
|
||||
":sys:/:all:.:native:"
|
||||
":sys:/:all:/:name:.:native:"])
|
||||
":sys:/:all:/:name:.:native:"
|
||||
":all:"])
|
||||
|
||||
(var module/*syspath*
|
||||
"The path where globally installed libraries are located.
|
||||
@@ -1576,7 +1578,7 @@ value, one key will be ignored."
|
||||
(string/replace ":sys:" module/*syspath*)
|
||||
(string/replace ":native:" nati)
|
||||
(string/replace ":all:" path)))
|
||||
(array/push (map sub-path paths) path))
|
||||
(map sub-path paths))
|
||||
|
||||
(def module/cache
|
||||
"Table mapping loaded module identifiers to their environments."
|
||||
@@ -1588,62 +1590,51 @@ value, one key will be ignored."
|
||||
@{})
|
||||
|
||||
# Require helpers
|
||||
(defn- check-mod
|
||||
[f testpath]
|
||||
(or f (file/open testpath)))
|
||||
(defn- find-mod [path]
|
||||
(def paths (module/find path module/paths))
|
||||
(reduce check-mod nil paths))
|
||||
(defn- check-native
|
||||
[p testpath]
|
||||
(or p
|
||||
(do
|
||||
(def f (file/open testpath))
|
||||
(if f (do (file/close f) testpath)))))
|
||||
(defn- find-native [path]
|
||||
(def paths (module/find path module/native-paths))
|
||||
(reduce check-native nil paths))
|
||||
(defn- fexists [path]
|
||||
(def f (file/open path))
|
||||
(if f (do (file/close f) path)))
|
||||
|
||||
(defn require
|
||||
"Require a module with the given name. Will search all of the paths in
|
||||
module/paths, then the path as a raw file path. Returns the new environment
|
||||
returned from compiling and running the file."
|
||||
[path & args]
|
||||
(when (get module/loading path)
|
||||
(error (string "circular dependency: module " path " is loading")))
|
||||
(def {:exit exit-on-error} (table ;args))
|
||||
(if-let [check (get module/cache path)]
|
||||
check
|
||||
(if-let [f (find-mod path)]
|
||||
(if-let [modpath (find fexists (module/find path module/paths))]
|
||||
(do
|
||||
(when (get module/loading modpath)
|
||||
(error (string "circular dependency: file " modpath " is loading")))
|
||||
# Normal janet module
|
||||
(def f (file/open modpath))
|
||||
(def newenv (make-env))
|
||||
(put module/loading path true)
|
||||
(put module/loading modpath true)
|
||||
(defn chunks [buf _] (file/read f 2048 buf))
|
||||
(run-context newenv chunks
|
||||
(fn [sig x f source]
|
||||
(when (not= sig :dead)
|
||||
(status-pp sig x f source)
|
||||
(if exit-on-error (os/exit 1))))
|
||||
path)
|
||||
(run-context {:env newenv
|
||||
:chunks chunks
|
||||
:on-status (fn [f x]
|
||||
(when (not= (fiber/status f) :dead)
|
||||
(debug/stacktrace f x)
|
||||
(if exit-on-error (os/exit 1))))
|
||||
:source modpath})
|
||||
(file/close f)
|
||||
(put module/loading path false)
|
||||
(put module/loading modpath false)
|
||||
(put module/cache modpath newenv)
|
||||
(put module/cache path newenv)
|
||||
newenv)
|
||||
(do
|
||||
# Try native module
|
||||
(def n (find-native path))
|
||||
(def n (find fexists (module/find path module/native-paths)))
|
||||
(if (not n)
|
||||
(error (string "could not open file for module " path)))
|
||||
(def e (make-env))
|
||||
(native n e)
|
||||
(put module/cache n e)
|
||||
(put module/cache path e)
|
||||
e))))
|
||||
|
||||
(put _env 'find-native nil)
|
||||
(put _env 'check-native nil)
|
||||
(put _env 'find-mod nil)
|
||||
(put _env 'check-mod nil)
|
||||
(put _env 'fexists nil)
|
||||
|
||||
(defn import*
|
||||
"Import a module into a given environment table. This is the
|
||||
@@ -1678,14 +1669,16 @@ value, one key will be ignored."
|
||||
caught."
|
||||
[chunks onsignal &]
|
||||
(def newenv (make-env))
|
||||
(default chunks (fn [buf _] (file/read stdin :line buf)))
|
||||
(default onsignal (fn [sig x f source]
|
||||
(case sig
|
||||
(default onsignal (fn [f x]
|
||||
(case (fiber/status f)
|
||||
:dead (do
|
||||
(put newenv '_ @{:value x})
|
||||
(print (string/pretty x 20)))
|
||||
(status-pp sig x f source))))
|
||||
(run-context newenv chunks onsignal "repl"))
|
||||
(debug/stacktrace f x))))
|
||||
(run-context {:env newenv
|
||||
:chunks chunks
|
||||
:on-status onsignal
|
||||
:source "repl"}))
|
||||
|
||||
(defmacro meta
|
||||
"Add metadata to the current environment."
|
||||
|
||||
@@ -28,8 +28,13 @@
|
||||
#endif
|
||||
|
||||
/* Generated bytes */
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
extern const unsigned char *janet_gen_core;
|
||||
extern int32_t janet_gen_core_size;
|
||||
#else
|
||||
extern const unsigned char *janet_core_image;
|
||||
extern size_t janet_core_image_size;
|
||||
#endif
|
||||
|
||||
/* Use LoadLibrary on windows or dlopen on posix to load dynamic libaries
|
||||
* with native code. */
|
||||
@@ -371,7 +376,7 @@ static const JanetReg corelib_cfuns[] = {
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
#ifndef JANET_NO_BOOTSTRAP
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
|
||||
/* Utility for inline assembly */
|
||||
static void janet_quick_asm(
|
||||
@@ -595,12 +600,9 @@ static const uint32_t bnot_asm[] = {
|
||||
|
||||
JanetTable *janet_core_env(void) {
|
||||
JanetTable *env = janet_table(0);
|
||||
Janet ret = janet_wrap_table(env);
|
||||
janet_core_cfuns(env, NULL, corelib_cfuns);
|
||||
|
||||
/* Load main functions */
|
||||
janet_cfuns(env, NULL, corelib_cfuns);
|
||||
|
||||
#ifndef JANET_NO_BOOTSTRAP
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
janet_quick_asm(env, JANET_FUN_YIELD, "debug", 0, 1, debug_asm, sizeof(debug_asm),
|
||||
JDOC("(debug)\n\n"
|
||||
"Throws a debug signal that can be caught by a parent fiber and used to inspect "
|
||||
@@ -731,11 +733,11 @@ JanetTable *janet_core_env(void) {
|
||||
JDOC("The build identifier of the running janet program."));
|
||||
|
||||
/* Allow references to the environment */
|
||||
janet_def(env, "_env", ret, JDOC("The environment table for the current scope."));
|
||||
#endif
|
||||
janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope."));
|
||||
|
||||
/* Set as gc root */
|
||||
janet_gcroot(janet_wrap_table(env));
|
||||
#endif
|
||||
|
||||
/* Load auxiliary envs */
|
||||
janet_lib_io(env);
|
||||
@@ -756,9 +758,26 @@ JanetTable *janet_core_env(void) {
|
||||
janet_lib_asm(env);
|
||||
#endif
|
||||
|
||||
#ifndef JANET_NO_BOOTSTRAP
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
/* Run bootstrap source */
|
||||
janet_dobytes(env, janet_gen_core, janet_gen_core_size, "core.janet", NULL);
|
||||
#else
|
||||
|
||||
/* Unmarshal from core image */
|
||||
Janet marsh_out;
|
||||
int status = janet_unmarshal(
|
||||
janet_core_image,
|
||||
janet_core_image_size,
|
||||
0,
|
||||
&marsh_out,
|
||||
env,
|
||||
NULL);
|
||||
if (status) {
|
||||
printf("error unmarshaling core image\n");
|
||||
exit(1);
|
||||
}
|
||||
janet_gcroot(marsh_out);
|
||||
env = janet_unwrap_table(marsh_out);
|
||||
#endif
|
||||
|
||||
return env;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "gc.h"
|
||||
#include "state.h"
|
||||
#include "util.h"
|
||||
#include "vector.h"
|
||||
#endif
|
||||
|
||||
/* Implements functionality to build a debugger from within janet.
|
||||
@@ -90,6 +91,74 @@ void janet_debug_find(
|
||||
}
|
||||
}
|
||||
|
||||
/* Error reporting. This can be emulated from within Janet, but for
|
||||
* consitency with the top level code it is defined once. */
|
||||
void janet_stacktrace(JanetFiber *fiber, Janet err) {
|
||||
int32_t fi;
|
||||
const char *errstr = (const char *)janet_to_string(err);
|
||||
JanetFiber **fibers = NULL;
|
||||
int wrote_error = 0;
|
||||
|
||||
while (fiber) {
|
||||
janet_v_push(fibers, fiber);
|
||||
fiber = fiber->child;
|
||||
}
|
||||
|
||||
for (fi = janet_v_count(fibers) - 1; fi >= 0; fi--) {
|
||||
fiber = fibers[fi];
|
||||
int32_t i = fiber->frame;
|
||||
while (i > 0) {
|
||||
JanetStackFrame *frame = (JanetStackFrame *)(fiber->data + i - JANET_FRAME_SIZE);
|
||||
JanetFuncDef *def = NULL;
|
||||
i = frame->prevframe;
|
||||
|
||||
/* Print prelude to stack frame */
|
||||
if (!wrote_error) {
|
||||
JanetFiberStatus status = janet_fiber_status(fiber);
|
||||
const char *prefix = status == JANET_STATUS_ERROR ? "" : "status ";
|
||||
fprintf(stderr, "%s%s: %s\n",
|
||||
prefix,
|
||||
janet_status_names[status],
|
||||
errstr);
|
||||
wrote_error = 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, " in");
|
||||
|
||||
if (frame->func) {
|
||||
def = frame->func->def;
|
||||
fprintf(stderr, " %s", def->name ? (const char *)def->name : "<anonymous>");
|
||||
if (def->source) {
|
||||
fprintf(stderr, " [%s]", (const char *)def->source);
|
||||
}
|
||||
} else {
|
||||
JanetCFunction cfun = (JanetCFunction)(frame->pc);
|
||||
if (cfun) {
|
||||
Janet name = janet_table_get(janet_vm_registry, janet_wrap_cfunction(cfun));
|
||||
if (!janet_checktype(name, JANET_NIL))
|
||||
fprintf(stderr, " %s", (const char *)janet_to_string(name));
|
||||
else
|
||||
fprintf(stderr, " <cfunction>");
|
||||
}
|
||||
}
|
||||
if (frame->flags & JANET_STACKFRAME_TAILCALL)
|
||||
fprintf(stderr, " (tailcall)");
|
||||
if (frame->func && frame->pc) {
|
||||
int32_t off = (int32_t) (frame->pc - def->bytecode);
|
||||
if (def->sourcemap) {
|
||||
JanetSourceMapping mapping = def->sourcemap[off];
|
||||
fprintf(stderr, " at (%d:%d)", mapping.start, mapping.end);
|
||||
} else {
|
||||
fprintf(stderr, " pc=%d", off);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
janet_v_free(fibers);
|
||||
}
|
||||
|
||||
/*
|
||||
* CFuns
|
||||
*/
|
||||
@@ -218,6 +287,13 @@ static Janet cfun_debug_stack(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_array(array);
|
||||
}
|
||||
|
||||
static Janet cfun_debug_stacktrace(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
janet_stacktrace(fiber, argv[1]);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static Janet cfun_debug_argstack(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
@@ -280,6 +356,13 @@ static const JanetReg debug_cfuns[] = {
|
||||
"\t:slots - array of all values in each slot\n"
|
||||
"\t:tail - boolean indicating a tail call")
|
||||
},
|
||||
{
|
||||
"debug/stacktrace", cfun_debug_stacktrace,
|
||||
JDOC("(debug/stacktrace fiber err)\n\n"
|
||||
"Prints a nice looking stacktrace for a fiber. The error message "
|
||||
"err must be passed to the function as fiber's do not keep track of "
|
||||
"the last error they have thrown. Returns the fiber.")
|
||||
},
|
||||
{
|
||||
"debug/lineage", cfun_debug_lineage,
|
||||
JDOC("(debug/lineage fib)\n\n"
|
||||
@@ -293,5 +376,5 @@ static const JanetReg debug_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_debug(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, debug_cfuns);
|
||||
janet_core_cfuns(env, NULL, debug_cfuns);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t
|
||||
fiber->stacktop = newstacktop;
|
||||
}
|
||||
if (janet_fiber_funcframe(fiber, callee)) return NULL;
|
||||
janet_fiber_frame(fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
||||
return fiber;
|
||||
}
|
||||
|
||||
@@ -432,5 +433,5 @@ static const JanetReg fiber_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_fiber(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, fiber_cfuns);
|
||||
janet_core_cfuns(env, NULL, fiber_cfuns);
|
||||
}
|
||||
|
||||
@@ -49,10 +49,13 @@ struct IOFile {
|
||||
};
|
||||
|
||||
static int cfun_io_gc(void *p, size_t len);
|
||||
static Janet io_file_get(void *p, Janet);
|
||||
|
||||
JanetAbstractType cfun_io_filetype = {
|
||||
"core/file",
|
||||
cfun_io_gc,
|
||||
NULL,
|
||||
io_file_get,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -305,6 +308,22 @@ static Janet cfun_io_fseek(int32_t argc, Janet *argv) {
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static JanetMethod io_file_methods[] = {
|
||||
{"close", cfun_io_fclose},
|
||||
{"read", cfun_io_fread},
|
||||
{"write", cfun_io_fwrite},
|
||||
{"flush", cfun_io_fflush},
|
||||
{"seek", cfun_io_fseek},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static Janet io_file_get(void *p, Janet key) {
|
||||
(void) p;
|
||||
if (!janet_checktype(key, JANET_KEYWORD))
|
||||
janet_panicf("expected keyword, got %v", key);
|
||||
return janet_getmethod(janet_unwrap_keyword(key), io_file_methods);
|
||||
}
|
||||
|
||||
static const JanetReg io_cfuns[] = {
|
||||
{
|
||||
"file/open", cfun_io_fopen,
|
||||
@@ -375,18 +394,18 @@ static const JanetReg io_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_io(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, io_cfuns);
|
||||
janet_core_cfuns(env, NULL, io_cfuns);
|
||||
|
||||
/* stdout */
|
||||
janet_def(env, "stdout",
|
||||
janet_core_def(env, "stdout",
|
||||
makef(stdout, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
JDOC("The standard output file."));
|
||||
/* stderr */
|
||||
janet_def(env, "stderr",
|
||||
janet_core_def(env, "stderr",
|
||||
makef(stderr, IO_APPEND | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
JDOC("The standard error file."));
|
||||
/* stdin */
|
||||
janet_def(env, "stdin",
|
||||
janet_core_def(env, "stdin",
|
||||
makef(stdin, IO_READ | IO_NOT_CLOSEABLE | IO_SERIALIZABLE),
|
||||
JDOC("The standard input file."));
|
||||
}
|
||||
|
||||
@@ -124,15 +124,20 @@ JanetTable *janet_env_lookup(JanetTable *env) {
|
||||
|
||||
/* Marshal an integer onto the buffer */
|
||||
static void pushint(MarshalState *st, int32_t x) {
|
||||
if (x >= 0 && x < 200) {
|
||||
if (x >= 0 && x < 128) {
|
||||
janet_buffer_push_u8(st->buf, x);
|
||||
} else if (x <= 8191 && x >= -8192) {
|
||||
uint8_t intbuf[2];
|
||||
intbuf[0] = ((x >> 8) & 0x3F) | 0x80;
|
||||
intbuf[1] = x & 0xFF;
|
||||
janet_buffer_push_bytes(st->buf, intbuf, 2);
|
||||
} else {
|
||||
uint8_t intbuf[5];
|
||||
intbuf[0] = LB_INTEGER;
|
||||
intbuf[1] = x & 0xFF;
|
||||
intbuf[2] = (x >> 8) & 0xFF;
|
||||
intbuf[3] = (x >> 16) & 0xFF;
|
||||
intbuf[4] = (x >> 24) & 0xFF;
|
||||
intbuf[1] = (x >> 24) & 0xFF;
|
||||
intbuf[2] = (x >> 16) & 0xFF;
|
||||
intbuf[3] = (x >> 8) & 0xFF;
|
||||
intbuf[4] = x & 0xFF;
|
||||
janet_buffer_push_bytes(st->buf, intbuf, 5);
|
||||
}
|
||||
}
|
||||
@@ -234,10 +239,12 @@ static void marshal_one_def(MarshalState *st, JanetFuncDef *def, int flags) {
|
||||
|
||||
/* marshal source maps if needed */
|
||||
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
|
||||
int32_t current = 0;
|
||||
for (int32_t i = 0; i < def->bytecode_length; i++) {
|
||||
JanetSourceMapping map = def->sourcemap[i];
|
||||
pushint(st, map.start);
|
||||
pushint(st, map.end);
|
||||
pushint(st, map.start - current);
|
||||
pushint(st, map.end - map.start);
|
||||
current = map.end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,14 +553,19 @@ static int32_t readint(UnmarshalState *st, const uint8_t **atdata) {
|
||||
const uint8_t *data = *atdata;
|
||||
int32_t ret;
|
||||
if (data >= st->end) longjmp(st->err, UMR_EOS);
|
||||
if (*data < 200) {
|
||||
if (*data < 128) {
|
||||
ret = *data++;
|
||||
} else if (*data < 192) {
|
||||
if (data + 2 > st->end) longjmp(st->err, UMR_EOS);
|
||||
ret = ((data[0] & 0x3F) << 8) + data[1];
|
||||
ret = ((ret << 18) >> 18);
|
||||
data += 2;
|
||||
} else if (*data == LB_INTEGER) {
|
||||
if (data + 5 > st->end) longjmp(st->err, UMR_EOS);
|
||||
ret = (data[1]) |
|
||||
(data[2] << 8) |
|
||||
(data[3] << 16) |
|
||||
(data[4] << 24);
|
||||
ret = (data[1] << 24) |
|
||||
(data[2] << 16) |
|
||||
(data[3] << 8) |
|
||||
data[4];
|
||||
data += 5;
|
||||
} else {
|
||||
longjmp(st->err, UMR_EXPECTED_INTEGER);
|
||||
@@ -748,13 +760,16 @@ static const uint8_t *unmarshal_one_def(
|
||||
|
||||
/* Unmarshal source maps if needed */
|
||||
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
|
||||
int32_t current = 0;
|
||||
def->sourcemap = malloc(sizeof(JanetSourceMapping) * bytecode_length);
|
||||
if (!def->sourcemap) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
for (int32_t i = 0; i < bytecode_length; i++) {
|
||||
def->sourcemap[i].start = readint(st, &data);
|
||||
def->sourcemap[i].end = readint(st, &data);
|
||||
current += readint(st, &data);
|
||||
def->sourcemap[i].start = current;
|
||||
current += readint(st, &data);
|
||||
def->sourcemap[i].end = current;
|
||||
}
|
||||
} else {
|
||||
def->sourcemap = NULL;
|
||||
@@ -905,8 +920,8 @@ static const uint8_t *unmarshal_one(
|
||||
EXTRA(1);
|
||||
lead = data[0];
|
||||
if (lead < 200) {
|
||||
*out = janet_wrap_integer(lead);
|
||||
return data + 1;
|
||||
*out = janet_wrap_integer(readint(st, &data));
|
||||
return data;
|
||||
}
|
||||
switch (lead) {
|
||||
case LB_NIL:
|
||||
@@ -1175,5 +1190,5 @@ static const JanetReg marsh_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_marsh(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, marsh_cfuns);
|
||||
janet_core_cfuns(env, NULL, marsh_cfuns);
|
||||
}
|
||||
|
||||
@@ -181,8 +181,8 @@ static const JanetReg math_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_math(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, math_cfuns);
|
||||
#ifndef JANET_NO_BOOTSTRAP
|
||||
janet_core_cfuns(env, NULL, math_cfuns);
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
janet_def(env, "math/pi", janet_wrap_number(3.1415926535897931),
|
||||
JDOC("The value pi."));
|
||||
janet_def(env, "math/e", janet_wrap_number(2.7182818284590451),
|
||||
|
||||
@@ -378,5 +378,5 @@ static const JanetReg os_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_os(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, os_cfuns);
|
||||
janet_core_cfuns(env, NULL, os_cfuns);
|
||||
}
|
||||
|
||||
@@ -609,10 +609,14 @@ static int parsergc(void *p, size_t size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Janet parserget(void *p, Janet key);
|
||||
|
||||
static JanetAbstractType janet_parse_parsertype = {
|
||||
"core/parser",
|
||||
parsergc,
|
||||
parsermark
|
||||
parsermark,
|
||||
parserget,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* C Function parser */
|
||||
@@ -649,6 +653,39 @@ static Janet cfun_parse_consume(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_integer(i);
|
||||
}
|
||||
|
||||
static Janet cfun_parse_insert(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
JanetParseState *s = p->states + p->statecount - 1;
|
||||
if (s->consumer == tokenchar) {
|
||||
janet_parser_consume(p, ' ');
|
||||
p->offset--;
|
||||
s = p->states + p->statecount - 1;
|
||||
}
|
||||
if (s->flags & PFLAG_CONTAINER) {
|
||||
s->argn++;
|
||||
if (p->statecount == 1) p->pending++;
|
||||
push_arg(p, argv[1]);
|
||||
} else if (s->flags & (PFLAG_STRING | PFLAG_LONGSTRING)) {
|
||||
const uint8_t *str = janet_to_string(argv[1]);
|
||||
int32_t slen = janet_string_length(str);
|
||||
size_t newcount = p->bufcount + slen;
|
||||
if (p->bufcap > p->bufcount + slen) {
|
||||
size_t newcap = 2 * newcount;
|
||||
p->buf = realloc(p->buf, newcap);
|
||||
if (p->buf == NULL) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
p->bufcap = newcap;
|
||||
}
|
||||
memcpy(p->buf + p->bufcount, str, slen);
|
||||
p->bufcount = newcount;
|
||||
} else {
|
||||
janet_panic("cannot insert value into parser");
|
||||
}
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static Janet cfun_parse_has_more(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetParser *p = janet_getabstract(argv, 0, &janet_parse_parsertype);
|
||||
@@ -737,6 +774,26 @@ static Janet cfun_parse_state(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_string(str);
|
||||
}
|
||||
|
||||
static const JanetMethod parser_methods[] = {
|
||||
{"byte", cfun_parse_byte},
|
||||
{"consume", cfun_parse_consume},
|
||||
{"error", cfun_parse_error},
|
||||
{"flush", cfun_parse_flush},
|
||||
{"has-more", cfun_parse_has_more},
|
||||
{"insert", cfun_parse_insert},
|
||||
{"produce", cfun_parse_produce},
|
||||
{"state", cfun_parse_state},
|
||||
{"status", cfun_parse_status},
|
||||
{"where", cfun_parse_where},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static Janet parserget(void *p, Janet key) {
|
||||
(void) p;
|
||||
if (!janet_checktype(key, JANET_KEYWORD)) janet_panicf("expected keyword method");
|
||||
return janet_getmethod(janet_unwrap_keyword(key), parser_methods);
|
||||
}
|
||||
|
||||
static const JanetReg parse_cfuns[] = {
|
||||
{
|
||||
"parser/new", cfun_parse_parser,
|
||||
@@ -807,10 +864,17 @@ static const JanetReg parse_cfuns[] = {
|
||||
"in the byte stream as a tuple (line, column). Lines and columns are counted from "
|
||||
"1, (the first byte is line 1, column 1) and a newline is considered ASCII 0x0A.")
|
||||
},
|
||||
{
|
||||
"parser/insert", cfun_parse_insert,
|
||||
JDOC("(parser/insert parser value)\n\n"
|
||||
"Insert a value into the parser. This means that the parser state can be manipulated "
|
||||
"in between chunks of bytes. This would allow a user to add extra elements to arrays "
|
||||
"and tuples, for example. Returns the parser.")
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* Load the library */
|
||||
void janet_lib_parse(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, parse_cfuns);
|
||||
janet_core_cfuns(env, NULL, parse_cfuns);
|
||||
}
|
||||
|
||||
@@ -990,7 +990,6 @@ static uint32_t compile1(Builder *b, Janet peg) {
|
||||
typedef struct {
|
||||
uint32_t *bytecode;
|
||||
Janet *constants;
|
||||
uint32_t main_rule;
|
||||
uint32_t num_constants;
|
||||
} Peg;
|
||||
|
||||
@@ -1005,11 +1004,13 @@ static int peg_mark(void *p, size_t size) {
|
||||
static JanetAbstractType peg_type = {
|
||||
"core/peg",
|
||||
NULL,
|
||||
peg_mark
|
||||
peg_mark,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Convert Builder to Peg (Janet Abstract Value) */
|
||||
static Peg *make_peg(Builder *b, uint32_t main_rule) {
|
||||
static Peg *make_peg(Builder *b) {
|
||||
size_t bytecode_size = janet_v_count(b->bytecode) * sizeof(uint32_t);
|
||||
size_t constants_size = janet_v_count(b->constants) * sizeof(Janet);
|
||||
size_t total_size = bytecode_size + constants_size + sizeof(Peg);
|
||||
@@ -1018,7 +1019,6 @@ static Peg *make_peg(Builder *b, uint32_t main_rule) {
|
||||
peg->bytecode = (uint32_t *)(mem + sizeof(Peg));
|
||||
peg->constants = (Janet *)(mem + sizeof(Peg) + bytecode_size);
|
||||
peg->num_constants = janet_v_count(b->constants);
|
||||
peg->main_rule = main_rule;
|
||||
memcpy(peg->bytecode, b->bytecode, bytecode_size);
|
||||
memcpy(peg->constants, b->constants, constants_size);
|
||||
return peg;
|
||||
@@ -1035,8 +1035,8 @@ static Peg *compile_peg(Janet x) {
|
||||
builder.nexttag = 1;
|
||||
builder.form = x;
|
||||
builder.depth = JANET_RECURSION_GUARD;
|
||||
uint32_t main_rule = compile1(&builder, x);
|
||||
Peg *peg = make_peg(&builder, main_rule);
|
||||
compile1(&builder, x);
|
||||
Peg *peg = make_peg(&builder);
|
||||
builder_cleanup(&builder);
|
||||
return peg;
|
||||
}
|
||||
@@ -1082,7 +1082,7 @@ static Janet cfun_peg_match(int32_t argc, Janet *argv) {
|
||||
|
||||
s.constants = peg->constants;
|
||||
s.bytecode = peg->bytecode;
|
||||
const uint8_t *result = peg_rule(&s, s.bytecode + peg->main_rule, bytes.bytes + start);
|
||||
const uint8_t *result = peg_rule(&s, s.bytecode, bytes.bytes + start);
|
||||
return result ? janet_wrap_array(s.captures) : janet_wrap_nil();
|
||||
}
|
||||
|
||||
@@ -1103,5 +1103,5 @@ static const JanetReg peg_cfuns[] = {
|
||||
|
||||
/* Load the peg module */
|
||||
void janet_lib_peg(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, peg_cfuns);
|
||||
janet_core_cfuns(env, NULL, peg_cfuns);
|
||||
}
|
||||
|
||||
@@ -23,63 +23,8 @@
|
||||
#ifndef JANET_AMALG
|
||||
#include <janet/janet.h>
|
||||
#include "state.h"
|
||||
#include "vector.h"
|
||||
#endif
|
||||
|
||||
/* Error reporting */
|
||||
void janet_stacktrace(JanetFiber *fiber, const char *errtype, Janet err) {
|
||||
int32_t fi;
|
||||
const char *errstr = (const char *)janet_to_string(err);
|
||||
JanetFiber **fibers = NULL;
|
||||
fprintf(stderr, "%s error: %s\n", errtype, errstr);
|
||||
|
||||
while (fiber) {
|
||||
janet_v_push(fibers, fiber);
|
||||
fiber = fiber->child;
|
||||
}
|
||||
|
||||
for (fi = janet_v_count(fibers) - 1; fi >= 0; fi--) {
|
||||
fiber = fibers[fi];
|
||||
int32_t i = fiber->frame;
|
||||
while (i > 0) {
|
||||
JanetStackFrame *frame = (JanetStackFrame *)(fiber->data + i - JANET_FRAME_SIZE);
|
||||
JanetFuncDef *def = NULL;
|
||||
i = frame->prevframe;
|
||||
fprintf(stderr, " in");
|
||||
if (frame->func) {
|
||||
def = frame->func->def;
|
||||
fprintf(stderr, " %s", def->name ? (const char *)def->name : "<anonymous>");
|
||||
if (def->source) {
|
||||
fprintf(stderr, " [%s]", (const char *)def->source);
|
||||
}
|
||||
} else {
|
||||
JanetCFunction cfun = (JanetCFunction)(frame->pc);
|
||||
if (cfun) {
|
||||
Janet name = janet_table_get(janet_vm_registry, janet_wrap_cfunction(cfun));
|
||||
if (!janet_checktype(name, JANET_NIL))
|
||||
fprintf(stderr, " %s", (const char *)janet_to_string(name));
|
||||
else
|
||||
fprintf(stderr, " <cfunction>");
|
||||
}
|
||||
}
|
||||
if (frame->flags & JANET_STACKFRAME_TAILCALL)
|
||||
fprintf(stderr, " (tailcall)");
|
||||
if (frame->func && frame->pc) {
|
||||
int32_t off = (int32_t) (frame->pc - def->bytecode);
|
||||
if (def->sourcemap) {
|
||||
JanetSourceMapping mapping = def->sourcemap[off];
|
||||
fprintf(stderr, " at (%d:%d)", mapping.start, mapping.end);
|
||||
} else {
|
||||
fprintf(stderr, " pc=%d", off);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
janet_v_free(fibers);
|
||||
}
|
||||
|
||||
/* Run a string */
|
||||
int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out) {
|
||||
JanetParser parser;
|
||||
@@ -90,6 +35,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
Janet ret = janet_wrap_nil();
|
||||
const uint8_t *where = sourcePath ? janet_cstring(sourcePath) : NULL;
|
||||
if (where) janet_gcroot(janet_wrap_string(where));
|
||||
if (NULL == sourcePath) sourcePath = "<unknown>";
|
||||
janet_parser_init(&parser);
|
||||
|
||||
while (!errflags && !done) {
|
||||
@@ -103,13 +49,12 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
JanetFiber *fiber = janet_fiber(f, 64, 0, NULL);
|
||||
JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret);
|
||||
if (status != JANET_SIGNAL_OK) {
|
||||
janet_stacktrace(fiber, "runtime", ret);
|
||||
janet_stacktrace(fiber, ret);
|
||||
errflags |= 0x01;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "source path: %s\n", sourcePath);
|
||||
janet_stacktrace(cres.macrofiber, "compile",
|
||||
janet_wrap_string(cres.error));
|
||||
fprintf(stderr, "compile error in %s: %s\n", sourcePath,
|
||||
(const char *)cres.error);
|
||||
errflags |= 0x02;
|
||||
}
|
||||
}
|
||||
@@ -118,13 +63,15 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
switch (janet_parser_status(&parser)) {
|
||||
case JANET_PARSE_ERROR:
|
||||
errflags |= 0x04;
|
||||
fprintf(stderr, "parse error: %s\n", janet_parser_error(&parser));
|
||||
fprintf(stderr, "parse error in %s: %s\n",
|
||||
sourcePath, janet_parser_error(&parser));
|
||||
break;
|
||||
case JANET_PARSE_PENDING:
|
||||
if (index >= len) {
|
||||
if (dudeol) {
|
||||
errflags |= 0x04;
|
||||
fprintf(stderr, "internal parse error: unexpected end of source\n");
|
||||
fprintf(stderr, "internal parse error in %s: unexpected end of source\n",
|
||||
sourcePath);
|
||||
} else {
|
||||
dudeol = 1;
|
||||
janet_parser_consume(&parser, '\n');
|
||||
|
||||
@@ -221,7 +221,6 @@ static JanetSlot janetc_varset(JanetFopts opts, int32_t argn, const Janet *argv)
|
||||
return rvalue;
|
||||
} else {
|
||||
/* Error */
|
||||
janet_inspect(argv[0]);
|
||||
janetc_cerror(opts.compiler, "expected symbol or tuple for l-value to set");
|
||||
return janetc_cslot(janet_wrap_nil());
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ extern JANET_THREAD_LOCAL int janet_vm_stackn;
|
||||
* Set and unset by janet_run. */
|
||||
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
|
||||
|
||||
/* The current pointer to the inner most jmp_buf. The current
|
||||
* return point for panics. */
|
||||
extern JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf;
|
||||
extern JANET_THREAD_LOCAL Janet *janet_vm_return_reg;
|
||||
|
||||
/* The global registry for c functions. Used to store meta-data
|
||||
* along with otherwise bare c function pointers. */
|
||||
extern JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
||||
|
||||
@@ -619,5 +619,5 @@ static const JanetReg string_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_string(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, string_cfuns);
|
||||
janet_core_cfuns(env, NULL, string_cfuns);
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ static double convert(
|
||||
bignat_lshift_n(mant, shamt);
|
||||
exponent2 -= shamt * BIGNAT_NBIT;
|
||||
for (;exponent < -3; exponent += 4) bignat_div(mant, base * base * base * base);
|
||||
for (;exponent < -2; exponent += 2) bignat_div(mant, base * base);
|
||||
for (;exponent < -1; exponent += 2) bignat_div(mant, base * base);
|
||||
for (;exponent < 0; exponent += 1) bignat_div(mant, base);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <janet/janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
/* Begin creation of a struct */
|
||||
@@ -73,6 +74,7 @@ void janet_struct_put(JanetKV *st, Janet key, Janet value) {
|
||||
int32_t i, j, dist;
|
||||
int32_t bounds[4] = {index, cap, 0, index};
|
||||
if (janet_checktype(key, JANET_NIL) || janet_checktype(value, JANET_NIL)) return;
|
||||
if (janet_checktype(key, JANET_NUMBER) && isnan(janet_unwrap_number(key))) return;
|
||||
/* Avoid extra items */
|
||||
if (janet_struct_hash(st) == janet_struct_length(st)) return;
|
||||
for (dist = 0, j = 0; j < 4; j += 2)
|
||||
@@ -120,9 +122,7 @@ void janet_struct_put(JanetKV *st, Janet key, Janet value) {
|
||||
dist = otherdist;
|
||||
hash = otherhash;
|
||||
} else if (status == 0) {
|
||||
/* This should not happen - it means
|
||||
* than a key was added to the struct more than once */
|
||||
janet_exit("struct double put fail");
|
||||
/* A key was added to the struct more than once */
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -134,15 +134,8 @@ const JanetKV *janet_struct_end(JanetKV *st) {
|
||||
/* Error building struct, probably duplicate values. We need to rebuild
|
||||
* the struct using only the values that went in. The second creation should always
|
||||
* succeed. */
|
||||
int32_t i, realCount;
|
||||
JanetKV *newst;
|
||||
realCount = 0;
|
||||
for (i = 0; i < janet_struct_capacity(st); i++) {
|
||||
JanetKV *kv = st + i;
|
||||
realCount += janet_checktype(kv->key, JANET_NIL) ? 1 : 0;
|
||||
}
|
||||
newst = janet_struct_begin(realCount);
|
||||
for (i = 0; i < janet_struct_capacity(st); i++) {
|
||||
JanetKV *newst = janet_struct_begin(janet_struct_hash(st));
|
||||
for (int32_t i = 0; i < janet_struct_capacity(st); i++) {
|
||||
JanetKV *kv = st + i;
|
||||
if (!janet_checktype(kv->key, JANET_NIL)) {
|
||||
janet_struct_put(newst, kv->key, kv->value);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <janet/janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
/* Initialize a table */
|
||||
@@ -131,6 +132,7 @@ Janet janet_table_remove(JanetTable *t, Janet key) {
|
||||
/* Put a value into the object */
|
||||
void janet_table_put(JanetTable *t, Janet key, Janet value) {
|
||||
if (janet_checktype(key, JANET_NIL)) return;
|
||||
if (janet_checktype(key, JANET_NUMBER) && isnan(janet_unwrap_number(key))) return;
|
||||
if (janet_checktype(value, JANET_NIL)) {
|
||||
janet_table_remove(t, key);
|
||||
} else {
|
||||
@@ -271,5 +273,5 @@ static const JanetReg table_cfuns[] = {
|
||||
|
||||
/* Load the table module */
|
||||
void janet_lib_table(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, table_cfuns);
|
||||
janet_core_cfuns(env, NULL, table_cfuns);
|
||||
}
|
||||
|
||||
@@ -146,5 +146,5 @@ static const JanetReg tuple_cfuns[] = {
|
||||
|
||||
/* Load the tuple module */
|
||||
void janet_lib_tuple(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, tuple_cfuns);
|
||||
janet_core_cfuns(env, NULL, tuple_cfuns);
|
||||
}
|
||||
|
||||
@@ -284,6 +284,24 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef JANET_BOOTSTRAP
|
||||
void janet_core_def(JanetTable *env, const char *name, Janet x, const void *p) {
|
||||
(void) p;
|
||||
janet_table_put(env, janet_csymbolv(name), x);
|
||||
}
|
||||
|
||||
void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns) {
|
||||
(void) regprefix;
|
||||
while (cfuns->name) {
|
||||
Janet name = janet_csymbolv(cfuns->name);
|
||||
Janet fun = janet_wrap_cfunction(cfuns->cfun);
|
||||
janet_core_def(env, cfuns->name, fun, cfuns->documentation);
|
||||
janet_table_put(janet_vm_registry, fun, name);
|
||||
cfuns++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Resolve a symbol in the environment */
|
||||
JanetBindingType janet_resolve(JanetTable *env, const uint8_t *sym, Janet *out) {
|
||||
Janet ref;
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
#endif
|
||||
|
||||
/* Omit docstrings in some builds */
|
||||
#ifdef JANET_NO_BOOTSTRAP
|
||||
#ifndef JANET_BOOTSTRAP
|
||||
#define JDOC(x) NULL
|
||||
#define JANET_NO_BOOTSTRAP
|
||||
#else
|
||||
#define JDOC(x) x
|
||||
#endif
|
||||
@@ -52,6 +53,16 @@ const void *janet_strbinsearch(
|
||||
size_t itemsize,
|
||||
const uint8_t *key);
|
||||
|
||||
/* Inside the janet core, defining globals is different
|
||||
* at bootstrap time and normal runtime */
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
#define janet_core_def janet_def
|
||||
#define janet_core_cfuns janet_cfuns
|
||||
#else
|
||||
void janet_core_def(JanetTable *env, const char *name, Janet x, const void *p);
|
||||
void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns);
|
||||
#endif
|
||||
|
||||
/* Initialize builtin libraries */
|
||||
void janet_lib_io(JanetTable *env);
|
||||
void janet_lib_math(JanetTable *env);
|
||||
|
||||
@@ -219,6 +219,17 @@ Janet janet_get(Janet ds, Janet key) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JANET_ABSTRACT:
|
||||
{
|
||||
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds));
|
||||
if (type->get) {
|
||||
value = (type->get)(janet_unwrap_abstract(ds),key);
|
||||
} else {
|
||||
janet_panicf("no getter for %T ", JANET_TFLAG_LENGTHABLE, ds);
|
||||
value = janet_wrap_nil();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -267,6 +278,17 @@ Janet janet_getindex(Janet ds, int32_t index) {
|
||||
case JANET_STRUCT:
|
||||
value = janet_struct_get(janet_unwrap_struct(ds), janet_wrap_integer(index));
|
||||
break;
|
||||
case JANET_ABSTRACT:
|
||||
{
|
||||
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds));
|
||||
if (type->get) {
|
||||
value = (type->get)(janet_unwrap_abstract(ds),janet_wrap_integer(index));
|
||||
} else {
|
||||
janet_panicf("no getter for %T ", JANET_TFLAG_LENGTHABLE, ds);
|
||||
value = janet_wrap_nil();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -327,6 +349,16 @@ void janet_putindex(Janet ds, int32_t index, Janet value) {
|
||||
janet_table_put(table, janet_wrap_integer(index), value);
|
||||
break;
|
||||
}
|
||||
case JANET_ABSTRACT:
|
||||
{
|
||||
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds));
|
||||
if (type->put) {
|
||||
(type->put)(janet_unwrap_abstract(ds),janet_wrap_integer(index),value);
|
||||
} else {
|
||||
janet_panicf("no setter for %T ", JANET_TFLAG_LENGTHABLE, ds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,5 +399,16 @@ void janet_put(Janet ds, Janet key, Janet value) {
|
||||
case JANET_TABLE:
|
||||
janet_table_put(janet_unwrap_table(ds), key, value);
|
||||
break;
|
||||
case JANET_ABSTRACT:
|
||||
{
|
||||
JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds));
|
||||
if (type->put) {
|
||||
(type->put)(janet_unwrap_abstract(ds),key,value);
|
||||
} else {
|
||||
janet_panicf("no setter for %T ", JANET_TFLAG_LENGTHABLE, ds);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,22 +42,6 @@ void *janet_v_grow(void *v, int32_t increment, int32_t itemsize) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Clone a buffer. */
|
||||
void *janet_v_copymem(void *v, int32_t itemsize) {
|
||||
int32_t *p;
|
||||
if (NULL == v) return NULL;
|
||||
p = malloc(2 * sizeof(int32_t) + itemsize * janet_v__cap(v));
|
||||
if (NULL != p) {
|
||||
memcpy(p, janet_v__raw(v), 2 * sizeof(int32_t) + itemsize * janet_v__cnt(v));
|
||||
return p + 2;
|
||||
} else {
|
||||
{
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
return (void *) (2 * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a buffer to normal allocated memory (forget capacity) */
|
||||
void *janet_v_flattenmem(void *v, int32_t itemsize) {
|
||||
int32_t *p;
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
||||
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
|
||||
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
|
||||
JANET_THREAD_LOCAL Janet *janet_vm_return_reg = NULL;
|
||||
JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
|
||||
/* Virtual registers
|
||||
*
|
||||
@@ -148,7 +150,7 @@ static void *op_lookup[255] = {
|
||||
} while (0)
|
||||
#define vm_return(sig, val) do { \
|
||||
vm_commit(); \
|
||||
janet_fiber_push(fiber, (val)); \
|
||||
janet_vm_return_reg[0] = (val); \
|
||||
return (sig); \
|
||||
} while (0)
|
||||
|
||||
@@ -226,7 +228,7 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
||||
int32_t argn = fiber->stacktop - fiber->stackstart;
|
||||
Janet ds, key;
|
||||
if (argn != 1) janet_panicf("%v called with arity %d, expected 1", callee, argn);
|
||||
if (janet_checktypes(callee, JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY)) {
|
||||
if (janet_checktypes(callee, JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY | JANET_TFLAG_ABSTRACT)) {
|
||||
ds = callee;
|
||||
key = fiber->data[fiber->stackstart];
|
||||
} else {
|
||||
@@ -283,8 +285,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
VM_OP(JOP_RETURN)
|
||||
{
|
||||
Janet retval = stack[D];
|
||||
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||
janet_fiber_popframe(fiber);
|
||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
||||
if (entrance_frame) vm_return(JANET_SIGNAL_OK, retval);
|
||||
vm_restore();
|
||||
stack[A] = retval;
|
||||
vm_checkgc_pcnext();
|
||||
@@ -293,8 +296,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
VM_OP(JOP_RETURN_NIL)
|
||||
{
|
||||
Janet retval = janet_wrap_nil();
|
||||
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||
janet_fiber_popframe(fiber);
|
||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
||||
if (entrance_frame) vm_return(JANET_SIGNAL_OK, retval);
|
||||
vm_restore();
|
||||
stack[A] = retval;
|
||||
vm_checkgc_pcnext();
|
||||
@@ -581,7 +585,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||
Janet ret = janet_unwrap_cfunction(callee)(argc, fiber->data + fiber->frame);
|
||||
janet_fiber_popframe(fiber);
|
||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);
|
||||
/*if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, ret);*/
|
||||
stack = fiber->data + fiber->frame;
|
||||
stack[A] = ret;
|
||||
vm_checkgc_pcnext();
|
||||
@@ -614,6 +618,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
vm_checkgc_next();
|
||||
} else {
|
||||
Janet retreg;
|
||||
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||
vm_commit();
|
||||
if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||
int32_t argc = fiber->stacktop - fiber->stackstart;
|
||||
@@ -624,7 +629,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
retreg = call_nonfn(fiber, callee);
|
||||
}
|
||||
janet_fiber_popframe(fiber);
|
||||
if (fiber->frame == 0)
|
||||
if (entrance_frame)
|
||||
vm_return(JANET_SIGNAL_OK, retreg);
|
||||
vm_restore();
|
||||
stack[A] = retreg;
|
||||
@@ -755,39 +760,45 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
}
|
||||
|
||||
Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
||||
Janet ret;
|
||||
Janet *old_return_reg = janet_vm_return_reg;
|
||||
|
||||
/* Check entry conditions */
|
||||
if (!janet_vm_fiber)
|
||||
janet_panic("janet_call failed because there is no current fiber");
|
||||
if (janet_vm_stackn >= JANET_RECURSION_GUARD)
|
||||
janet_panic("C stack recursed too deeply");
|
||||
JanetFiber *fiber = janet_fiber(fun, 64, argc, argv);
|
||||
if (!fiber)
|
||||
janet_panic("arity mismatch");
|
||||
JanetFiber *old_fiber = janet_vm_fiber;
|
||||
janet_vm_fiber = fiber;
|
||||
janet_gcroot(janet_wrap_fiber(fiber));
|
||||
|
||||
/* Push frame */
|
||||
janet_fiber_pushn(janet_vm_fiber, argv, argc);
|
||||
if (janet_fiber_funcframe(janet_vm_fiber, fun)) {
|
||||
janet_panicf("arity mismatch in %v", fun);
|
||||
}
|
||||
janet_fiber_frame(janet_vm_fiber)->flags |= JANET_STACKFRAME_ENTRANCE;
|
||||
|
||||
/* Set up */
|
||||
int32_t oldn = janet_vm_stackn++;
|
||||
int handle = janet_gclock();
|
||||
janet_vm_return_reg = &ret;
|
||||
|
||||
JanetSignal signal;
|
||||
if (setjmp(fiber->buf)) {
|
||||
signal = JANET_SIGNAL_ERROR;
|
||||
} else {
|
||||
signal = run_vm(fiber, janet_wrap_nil(), JANET_STATUS_NEW);
|
||||
}
|
||||
/* Run vm */
|
||||
JanetSignal signal = run_vm(janet_vm_fiber,
|
||||
janet_wrap_nil(),
|
||||
JANET_STATUS_ALIVE);
|
||||
|
||||
/* Teardown */
|
||||
janet_vm_return_reg = old_return_reg;
|
||||
janet_vm_stackn = oldn;
|
||||
janet_vm_fiber = old_fiber;
|
||||
Janet ret = fiber->data[fiber->stacktop - 1];
|
||||
janet_gcunroot(janet_wrap_fiber(fiber));
|
||||
janet_gcunlock(handle);
|
||||
if (signal == JANET_SIGNAL_ERROR) {
|
||||
old_fiber->child = fiber;
|
||||
janet_fiber_set_status(fiber, signal);
|
||||
janet_panicv(ret);
|
||||
}
|
||||
|
||||
if (signal != JANET_SIGNAL_OK) janet_panicv(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enter the main vm loop */
|
||||
JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
||||
jmp_buf buf;
|
||||
|
||||
/* Check conditions */
|
||||
JanetFiberStatus old_status = janet_fiber_status(fiber);
|
||||
@@ -820,15 +831,19 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
||||
int32_t oldn = janet_vm_stackn++;
|
||||
int handle = janet_vm_gc_suspend;
|
||||
JanetFiber *old_vm_fiber = janet_vm_fiber;
|
||||
jmp_buf *old_vm_jmp_buf = janet_vm_jmp_buf;
|
||||
Janet *old_vm_return_reg = janet_vm_return_reg;
|
||||
|
||||
/* Setup fiber */
|
||||
janet_vm_fiber = fiber;
|
||||
janet_gcroot(janet_wrap_fiber(fiber));
|
||||
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
||||
janet_vm_return_reg = out;
|
||||
janet_vm_jmp_buf = &buf;
|
||||
|
||||
/* Run loop */
|
||||
JanetSignal signal;
|
||||
if (setjmp(fiber->buf)) {
|
||||
if (setjmp(buf)) {
|
||||
signal = JANET_SIGNAL_ERROR;
|
||||
} else {
|
||||
signal = run_vm(fiber, in, old_status);
|
||||
@@ -839,12 +854,11 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
||||
janet_gcunroot(janet_wrap_fiber(fiber));
|
||||
|
||||
/* Restore global state */
|
||||
janet_vm_gc_suspend = handle;
|
||||
janet_vm_gc_suspend = handle;
|
||||
janet_vm_fiber = old_vm_fiber;
|
||||
janet_vm_stackn = oldn;
|
||||
|
||||
/* Pop error or return value from fiber stack */
|
||||
*out = fiber->data[--fiber->stacktop];
|
||||
janet_vm_return_reg = old_vm_return_reg;
|
||||
janet_vm_jmp_buf = old_vm_jmp_buf;
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ extern "C" {
|
||||
|
||||
/***** START SECTION CONFIG *****/
|
||||
|
||||
#define JANET_VERSION "0.3.0"
|
||||
#define JANET_VERSION "0.4.0"
|
||||
|
||||
#ifndef JANET_BUILD
|
||||
#define JANET_BUILD "local"
|
||||
@@ -266,6 +266,7 @@ typedef struct JanetKV JanetKV;
|
||||
typedef struct JanetStackFrame JanetStackFrame;
|
||||
typedef struct JanetAbstractType JanetAbstractType;
|
||||
typedef struct JanetReg JanetReg;
|
||||
typedef struct JanetMethod JanetMethod;
|
||||
typedef struct JanetSourceMapping JanetSourceMapping;
|
||||
typedef struct JanetView JanetView;
|
||||
typedef struct JanetByteView JanetByteView;
|
||||
@@ -603,12 +604,14 @@ struct JanetFiber {
|
||||
int32_t capacity;
|
||||
int32_t maxstack; /* Arbitrary defined limit for stack overflow */
|
||||
int32_t flags; /* Various flags */
|
||||
jmp_buf buf; /* Handle errors */
|
||||
};
|
||||
|
||||
/* Mark if a stack frame is a tail call for debugging */
|
||||
#define JANET_STACKFRAME_TAILCALL 1
|
||||
|
||||
/* Mark if a stack frame is an entrance frame */
|
||||
#define JANET_STACKFRAME_ENTRANCE 2
|
||||
|
||||
/* A stack frame on the fiber. Is stored along with the stack values. */
|
||||
struct JanetStackFrame {
|
||||
JanetFunction *func;
|
||||
@@ -736,6 +739,8 @@ struct JanetAbstractType {
|
||||
const char *name;
|
||||
int (*gc)(void *data, size_t len);
|
||||
int (*gcmark)(void *data, size_t len);
|
||||
Janet (*get)(void *data, Janet key);
|
||||
void (*put)(void *data, Janet key, Janet value);
|
||||
};
|
||||
|
||||
/* Contains information about abstract types */
|
||||
@@ -750,6 +755,11 @@ struct JanetReg {
|
||||
const char *documentation;
|
||||
};
|
||||
|
||||
struct JanetMethod {
|
||||
const char *name;
|
||||
JanetCFunction cfun;
|
||||
};
|
||||
|
||||
struct JanetView {
|
||||
const Janet *items;
|
||||
int32_t len;
|
||||
@@ -1106,7 +1116,6 @@ JANET_API Janet janet_getindex(Janet ds, int32_t index);
|
||||
JANET_API int32_t janet_length(Janet x);
|
||||
JANET_API void janet_put(Janet ds, Janet key, Janet value);
|
||||
JANET_API void janet_putindex(Janet ds, int32_t index, Janet value);
|
||||
JANET_API void janet_inspect(Janet x);
|
||||
|
||||
/* VM functions */
|
||||
JANET_API int janet_init(void);
|
||||
@@ -1114,7 +1123,7 @@ JANET_API void janet_deinit(void);
|
||||
JANET_API JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out);
|
||||
JANET_API JanetSignal janet_pcall(JanetFunction *fun, int32_t argn, const Janet *argv, Janet *out, JanetFiber **f);
|
||||
JANET_API Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv);
|
||||
JANET_API void janet_stacktrace(JanetFiber *fiber, const char *errtype, Janet err);
|
||||
JANET_API void janet_stacktrace(JanetFiber *fiber, Janet err);
|
||||
|
||||
/* C Library helpers */
|
||||
typedef enum {
|
||||
@@ -1142,6 +1151,7 @@ JANET_API void janet_panic_abstract(Janet x, int32_t n, const JanetAbstractType
|
||||
JANET_API void janet_arity(int32_t arity, int32_t min, int32_t max);
|
||||
JANET_API void janet_fixarity(int32_t arity, int32_t fix);
|
||||
|
||||
JANET_API Janet janet_getmethod(const uint8_t *method, const JanetMethod *methods);
|
||||
JANET_API double janet_getnumber(const Janet *argv, int32_t n);
|
||||
JANET_API JanetArray *janet_getarray(const Janet *argv, int32_t n);
|
||||
JANET_API const Janet *janet_gettuple(const Janet *argv, int32_t n);
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
/* Common */
|
||||
Janet janet_line_getter(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
const uint8_t *str = janet_getstring(argv, 0);
|
||||
JanetBuffer *buf = janet_getbuffer(argv, 1);
|
||||
janet_arity(argc, 0, 2);
|
||||
const char *str = (argc >= 1) ? (const char *) janet_getstring(argv, 0) : "";
|
||||
JanetBuffer *buf = (argc >= 2) ? janet_getbuffer(argv, 1) : janet_buffer(10);
|
||||
janet_line_get(str, buf);
|
||||
return argv[0];
|
||||
return janet_wrap_buffer(buf);
|
||||
}
|
||||
|
||||
static void simpleline(JanetBuffer *buffer) {
|
||||
@@ -55,8 +55,8 @@ void janet_line_deinit() {
|
||||
;
|
||||
}
|
||||
|
||||
void janet_line_get(const uint8_t *p, JanetBuffer *buffer) {
|
||||
fputs((const char *)p, stdout);
|
||||
void janet_line_get(const char *p, JanetBuffer *buffer) {
|
||||
fputs(p, stdout);
|
||||
simpleline(buffer);
|
||||
}
|
||||
|
||||
@@ -444,8 +444,8 @@ static int checktermsupport() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void janet_line_get(const uint8_t *p, JanetBuffer *buffer) {
|
||||
prompt = (const char *)p;
|
||||
void janet_line_get(const char *p, JanetBuffer *buffer) {
|
||||
prompt = p;
|
||||
buffer->count = 0;
|
||||
historyi = 0;
|
||||
if (!isatty(STDIN_FILENO) || !checktermsupport()) {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
void janet_line_init();
|
||||
void janet_line_deinit();
|
||||
|
||||
void janet_line_get(const uint8_t *p, JanetBuffer *buffer);
|
||||
void janet_line_get(const char *p, JanetBuffer *buffer);
|
||||
Janet janet_line_getter(int32_t argc, Janet *argv);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ static int enter_loop(void) {
|
||||
Janet ret;
|
||||
JanetSignal status = janet_continue(repl_fiber, janet_wrap_nil(), &ret);
|
||||
if (status == JANET_SIGNAL_ERROR) {
|
||||
janet_stacktrace(repl_fiber, "runtime", ret);
|
||||
janet_stacktrace(repl_fiber, ret);
|
||||
janet_deinit();
|
||||
repl_fiber = NULL;
|
||||
return 1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright 2017-2019 (C) Calvin Rose
|
||||
|
||||
(print (string "Janet " janet/version "-" janet/build " Copyright (C) 2017-2018 Calvin Rose"))
|
||||
(print (string "Janet " janet/version "-" janet/build " Copyright (C) 2017-2019 Calvin Rose"))
|
||||
|
||||
(fiber/new (fn webrepl []
|
||||
(repl (fn get-line [buf p]
|
||||
|
||||
@@ -283,5 +283,22 @@
|
||||
(++ i))
|
||||
(assert (= i 6) "when macro"))
|
||||
|
||||
# Denormal tables and structs
|
||||
|
||||
(assert (= (length {1 2 nil 3}) 1) "nil key struct literal")
|
||||
(assert (= (length @{1 2 nil 3}) 1) "nil key table literal")
|
||||
(assert (= (length (struct 1 2 nil 3)) 1) "nil key struct ctor")
|
||||
(assert (= (length (table 1 2 nil 3)) 1) "nil key table ctor")
|
||||
|
||||
(assert (= (length (struct (/ 0 0) 2 1 3)) 1) "nan key struct ctor")
|
||||
(assert (= (length (table (/ 0 0) 2 1 3)) 1) "nan key table ctor")
|
||||
(assert (= (length {1 2 nil 3}) 1) "nan key struct literal")
|
||||
(assert (= (length @{1 2 nil 3}) 1) "nan key table literal")
|
||||
|
||||
(assert (= (length (struct 2 1 3 nil)) 1) "nil value struct ctor")
|
||||
(assert (= (length (table 2 1 3 nil)) 1) "nil value table ctor")
|
||||
(assert (= (length {1 2 3 nil}) 1) "nil value struct literal")
|
||||
(assert (= (length @{1 2 3 nil}) 1) "nil value table literal")
|
||||
|
||||
(end-suite)
|
||||
|
||||
|
||||
@@ -346,4 +346,9 @@
|
||||
(check-deep '(drop '"hello") "hello" @[])
|
||||
(check-deep '(drop "hello") "hello" @[])
|
||||
|
||||
# Regression #24
|
||||
|
||||
(def t (put @{} :hi 1))
|
||||
(assert (deep= t @{:hi 1}) "regression #24")
|
||||
|
||||
(end-suite)
|
||||
|
||||
@@ -65,11 +65,12 @@
|
||||
# as the version being generated
|
||||
(print "#define JANET_BUILD \"" janet/build "\"")
|
||||
|
||||
(print ```#define JANET_AMALG
|
||||
#include "janet.h"```)
|
||||
(print ```#define JANET_AMALG```)
|
||||
(print ```#include "janet.h"```)
|
||||
|
||||
(each h headers (dofile h))
|
||||
(each s sources (dofile s))
|
||||
|
||||
# Relies on this file being built
|
||||
# Relies on these files being built
|
||||
(dofile "build/core.gen.c")
|
||||
(dofile "build/core_image.c")
|
||||
|
||||
55
tools/bars.janet
Normal file
55
tools/bars.janet
Normal file
@@ -0,0 +1,55 @@
|
||||
# A flexible templater for janet. Compiles
|
||||
# templates to janet functions that produce buffers.
|
||||
|
||||
(defn template
|
||||
"Compile a template string into a function"
|
||||
[source]
|
||||
|
||||
# State for compilation machine
|
||||
(def p (parser/new))
|
||||
(def forms @[])
|
||||
|
||||
(defn parse-chunk
|
||||
"Parse a string and push produced values to forms."
|
||||
[chunk]
|
||||
(parser/consume p chunk)
|
||||
(while (parser/has-more p)
|
||||
(array/push forms (parser/produce p)))
|
||||
(if (= :error (parser/status p))
|
||||
(error (parser/error p))))
|
||||
|
||||
(defn code-chunk
|
||||
"Parse all the forms in str and return them
|
||||
in a tuple prefixed with 'do."
|
||||
[str]
|
||||
(parse-chunk str)
|
||||
true)
|
||||
|
||||
(defn string-chunk
|
||||
"Insert string chunk into parser"
|
||||
[str]
|
||||
(parser/insert p str)
|
||||
(parse-chunk "")
|
||||
true)
|
||||
|
||||
# Run peg
|
||||
(def grammar
|
||||
~{:code-chunk (* "{%" (drop (cmt '(any (if-not "%}" 1)) ,code-chunk)) "%}")
|
||||
:main-chunk (drop (cmt '(any (if-not "{%" 1)) ,string-chunk))
|
||||
:main (any (+ :code-chunk :main-chunk (error "")))})
|
||||
(def parts (peg/match grammar source))
|
||||
|
||||
# Check errors in template and parser
|
||||
(unless parts (error "invalid template syntax"))
|
||||
(parse-chunk "\n")
|
||||
(case (parser/status p)
|
||||
:pending (error (string "unfinished parser state " (parser/state p)))
|
||||
:error (error (parser/error p)))
|
||||
|
||||
# Make ast from forms
|
||||
(def ast ~(fn [params &] (default params @{}) (,buffer ;forms)))
|
||||
|
||||
(def ctor (compile ast *env* source))
|
||||
(if-not (function? ctor)
|
||||
(error (string "could not compile template")))
|
||||
(ctor))
|
||||
@@ -79,14 +79,14 @@
|
||||
(defn- make-define
|
||||
"Generate strings for adding custom defines to the compiler."
|
||||
[define value]
|
||||
(def prefix (if is-win "\\D" "-D"))
|
||||
(def prefix (if is-win "/D" "-D"))
|
||||
(if value
|
||||
(string prefix define "=" value)
|
||||
(string prefix define)))
|
||||
|
||||
(defn- make-defines
|
||||
"Generate many defines. Takes a dictionary of defines. If a value is
|
||||
true, generates -DNAME (\\DNAME on windows), otherwise -DNAME=value."
|
||||
true, generates -DNAME (/DNAME on windows), otherwise -DNAME=value."
|
||||
[defines]
|
||||
(seq [[d v] :pairs defines] (make-define d (if (not= v true) v))))
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
(def OPTIMIZE 2)
|
||||
(def CC (if is-win "cl" "cc"))
|
||||
(def LD (if is-win "link" (string CC " -shared")))
|
||||
(def CFLAGS (string (if is-win "/0" "-std=c99 -Wall -Wextra -fpic -O") OPTIMIZE))
|
||||
(def CFLAGS (string (if is-win "/O" "-std=c99 -Wall -Wextra -fpic -O") OPTIMIZE))
|
||||
|
||||
(defn- compile-c
|
||||
"Compile a C file into an object file."
|
||||
@@ -112,11 +112,12 @@
|
||||
[opts target & objects]
|
||||
(def ld (or (opts :linker) LD))
|
||||
(def cflags (or (opts :cflags) CFLAGS))
|
||||
(def lflags (or (opts :lflags) ""))
|
||||
(def olist (string/join objects " "))
|
||||
(if (older-than-some target objects)
|
||||
(if is-win
|
||||
(shell ld "/out:" target " " olist)
|
||||
(shell ld " " cflags " -o " target " " olist))))
|
||||
(shell ld " /DLL /OUT:" target " " olist " %JANET_PATH%\\janet.lib")
|
||||
(shell ld " " cflags " -o " target " " olist " " lflags))))
|
||||
|
||||
(defn- create-buffer-c
|
||||
"Inline raw byte file as a c file."
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# Tool to dump a marshalled version of the janet core to stdout. The
|
||||
# image should eventually allow janet to be started from a pre-compiled
|
||||
# image rather than recompiled every time from the embedded source. More
|
||||
# work will go into shrinking the image (it isn't currently that large but
|
||||
# could be smaller), creating the mechanism to load the image, and modifying
|
||||
# the build process to compile janet with a built image rather than
|
||||
# embedded source.
|
||||
|
||||
# Get image. This image contains as much of the core library and documentation that
|
||||
# can be written to an image (no cfunctions, no abstracts (stdout, stdin, stderr)),
|
||||
# everything else goes. Cfunctions and abstracts will be referenced from a register
|
||||
# table which will be generated on janet startup.
|
||||
(def image (let [env-pairs (pairs (env-lookup *env*))
|
||||
essential-pairs (filter (fn [[k v]] (or (cfunction? v) (abstract? v))) env-pairs)
|
||||
lookup (table ;(mapcat identity essential-pairs))
|
||||
reverse-lookup (invert lookup)]
|
||||
(marshal (table/getproto *env*) reverse-lookup)))
|
||||
|
||||
# Write image
|
||||
(file/write stdout image)
|
||||
(file/flush stdout)
|
||||
Reference in New Issue
Block a user