mirror of
https://github.com/janet-lang/janet
synced 2025-11-22 18:24:49 +00:00
Compare commits
93 Commits
v0.5.0
...
posix_spaw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26513a7a16 | ||
|
|
d005ac6888 | ||
|
|
7fdb098a20 | ||
|
|
a4a200e037 | ||
|
|
15d95d8803 | ||
|
|
46950a8cb3 | ||
|
|
4867cab569 | ||
|
|
c8cf7c2445 | ||
|
|
1b63215aad | ||
|
|
bcbe42ab23 | ||
|
|
c8c6419013 | ||
|
|
e8516c29e0 | ||
|
|
12247bd958 | ||
|
|
9d30d5f6e3 | ||
|
|
ba0956488d | ||
|
|
31f502b508 | ||
|
|
efaaead378 | ||
|
|
4d47d92a4a | ||
|
|
b39ad97a87 | ||
|
|
af23040d9c | ||
|
|
fd2d706e33 | ||
|
|
178d175bcf | ||
|
|
7a7f586094 | ||
|
|
5124587c96 | ||
|
|
6c897b1a37 | ||
|
|
c6ac53f4be | ||
|
|
2d7812a06c | ||
|
|
db55277b58 | ||
|
|
75818217a6 | ||
|
|
486b80fa7b | ||
|
|
873054d055 | ||
|
|
f12f896020 | ||
|
|
09ab391d13 | ||
|
|
7569930b0c | ||
|
|
e7189438dd | ||
|
|
3c304ddc35 | ||
|
|
1696de233c | ||
|
|
ce9cd4fcef | ||
|
|
698e89aba4 | ||
|
|
4c8dd4b96c | ||
|
|
11998b3913 | ||
|
|
840610facf | ||
|
|
0280deccae | ||
|
|
4d5a95784a | ||
|
|
b43d93cf55 | ||
|
|
3f137ed0b1 | ||
|
|
5deb13d73e | ||
|
|
82a1c8635e | ||
|
|
010e2e4652 | ||
|
|
ddedae6831 | ||
|
|
6c63c4f129 | ||
|
|
802686e3df | ||
|
|
3be79e8735 | ||
|
|
a303704a7d | ||
|
|
b5e6c0b8fc | ||
|
|
98c46fcfb1 | ||
|
|
409da697dd | ||
|
|
91c3685705 | ||
|
|
411fc77ecf | ||
|
|
0378ba78cc | ||
|
|
55d8e8b56b | ||
|
|
97ad4c4f89 | ||
|
|
8de999c8f7 | ||
|
|
f444bd25ef | ||
|
|
43c0db4b0e | ||
|
|
8f168c600d | ||
|
|
ec43afb426 | ||
|
|
880049c0ee | ||
|
|
2b7ac16784 | ||
|
|
56d903d75b | ||
|
|
7054e878fb | ||
|
|
dde5351d11 | ||
|
|
7d49e3e6f1 | ||
|
|
30cb01e2f0 | ||
|
|
018e836ef5 | ||
|
|
7b25125431 | ||
|
|
0aa2f68793 | ||
|
|
516e031f67 | ||
|
|
3331f2fa02 | ||
|
|
dd1a199ebd | ||
|
|
f35b5765d6 | ||
|
|
8359044408 | ||
|
|
9f3dde3cc7 | ||
|
|
ad0f7d9b0d | ||
|
|
f647ac5631 | ||
|
|
e4c5eb4c76 | ||
|
|
dc9fc9c3f5 | ||
|
|
3b6a51df24 | ||
|
|
f2313b9959 | ||
|
|
805b3bbb88 | ||
|
|
232ea22dc5 | ||
|
|
3388acd2db | ||
|
|
52ab9fb475 |
@@ -1,11 +1,11 @@
|
|||||||
image: freebsd/latest
|
image: freebsd/latest
|
||||||
packages:
|
packages:
|
||||||
- gmake
|
- gmake
|
||||||
- gcc
|
|
||||||
tasks:
|
tasks:
|
||||||
- build: |
|
- build: |
|
||||||
cd janet
|
cd janet
|
||||||
gmake CC=gcc
|
gmake
|
||||||
gmake test CC=gcc
|
gmake test
|
||||||
sudo gmake install CC=gcc
|
sudo gmake install
|
||||||
gmake test-install CC=gcc
|
gmake test-install
|
||||||
|
gmake test-amalg
|
||||||
|
|||||||
11
.builds/.openbsd.yaml
Normal file
11
.builds/.openbsd.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
image: openbsd/6.5
|
||||||
|
packages:
|
||||||
|
- gmake
|
||||||
|
tasks:
|
||||||
|
- build: |
|
||||||
|
cd janet
|
||||||
|
gmake
|
||||||
|
gmake test
|
||||||
|
doas gmake install
|
||||||
|
gmake test-install
|
||||||
|
gmake test-amalg
|
||||||
@@ -4,6 +4,7 @@ script:
|
|||||||
- make test
|
- make test
|
||||||
- sudo make install
|
- sudo make install
|
||||||
- make test-install
|
- make test-install
|
||||||
|
- make test-amalg
|
||||||
- make build/janet-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.tar.gz
|
- make build/janet-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.tar.gz
|
||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
|
|||||||
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,6 +1,33 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
- Add API compatibility checking for modules. This will let native modules not load
|
||||||
|
when the host program is not of a compatible version or configuration.
|
||||||
|
- Change signature of `os/execute` to be much more flexible.
|
||||||
|
|
||||||
|
## 0.6.0 - 2019-05-29
|
||||||
|
- `file/close` returns exit code when closing file opened with `file/popen`.
|
||||||
|
- Add `os/rename`
|
||||||
|
- Update windows installer to include tools like `jpm`.
|
||||||
|
- Add `jpm` tool for building and managing projects.
|
||||||
|
- Change interface to `cook` tool.
|
||||||
|
- Add optional filters to `module/paths` to further refine import methods.
|
||||||
|
- Add keyword arguments via `&keys` in parameter list.
|
||||||
|
- Add `-k` flag for flychecking source.
|
||||||
|
- Change signature to `compile` function.
|
||||||
|
- Add `module/loaders` for custom loading functions.
|
||||||
|
- Add external unification to `match` macro.
|
||||||
|
- Add static library to main build.
|
||||||
|
- Add `janet/*headerpath*` and change location of installed headers.
|
||||||
|
- Let `partition` take strings.
|
||||||
|
- Haiku OS support
|
||||||
|
- Add `string/trim`, `string/trimr`, and `string/triml`.
|
||||||
|
- Add `dofile` function.
|
||||||
|
- Numbers require at least 1 significant digit.
|
||||||
|
- `file/read` will return nil on end of file.
|
||||||
|
- Fix various bugs.
|
||||||
|
|
||||||
## 0.5.0 - 2019-05-09
|
## 0.5.0 - 2019-05-09
|
||||||
- Fix some bugs with buffers.
|
- Fix some bugs with buffers.
|
||||||
- Add `trace` and `untrace` to the core library.
|
- Add `trace` and `untrace` to the core library.
|
||||||
@@ -61,7 +88,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Disallow NaNs as table or struct keys
|
- Disallow NaNs as table or struct keys
|
||||||
- Update module resolution paths and format
|
- Update module resolution paths and format
|
||||||
|
|
||||||
## 0.3.0 - 2019-26-01
|
## 0.3.0 - 2019-01-26
|
||||||
- Add amalgamated build to janet for easier embedding.
|
- Add amalgamated build to janet for easier embedding.
|
||||||
- Add os/date function
|
- Add os/date function
|
||||||
- Add slurp and spit to core library.
|
- Add slurp and spit to core library.
|
||||||
|
|||||||
91
Makefile
91
Makefile
@@ -31,8 +31,10 @@ JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 1)\""
|
|||||||
CLIBS=-lm
|
CLIBS=-lm
|
||||||
JANET_TARGET=build/janet
|
JANET_TARGET=build/janet
|
||||||
JANET_LIBRARY=build/libjanet.so
|
JANET_LIBRARY=build/libjanet.so
|
||||||
|
JANET_STATIC_LIBRARY=build/libjanet.a
|
||||||
JANET_PATH?=$(PREFIX)/lib/janet
|
JANET_PATH?=$(PREFIX)/lib/janet
|
||||||
MANPATH?=$(PREFIX)/share/man/man1/
|
MANPATH?=$(PREFIX)/share/man/man1/
|
||||||
|
PKG_CONFIG_PATH?=$(PREFIX)/lib/pkgconfig
|
||||||
DEBUGGER=gdb
|
DEBUGGER=gdb
|
||||||
|
|
||||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -O2 -fvisibility=hidden \
|
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -fpic -O2 -fvisibility=hidden \
|
||||||
@@ -47,9 +49,12 @@ else ifeq ($(UNAME), Linux)
|
|||||||
CLIBS:=$(CLIBS) -lrt -ldl
|
CLIBS:=$(CLIBS) -lrt -ldl
|
||||||
endif
|
endif
|
||||||
# For other unix likes, add flags here!
|
# For other unix likes, add flags here!
|
||||||
|
ifeq ($(UNAME),Haiku)
|
||||||
|
LDFLAGS=-Wl,--export-dynamic
|
||||||
|
endif
|
||||||
|
|
||||||
$(shell mkdir -p build/core build/mainclient build/webclient build/boot)
|
$(shell mkdir -p build/core build/mainclient build/webclient build/boot)
|
||||||
all: $(JANET_TARGET) $(JANET_LIBRARY)
|
all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY)
|
||||||
|
|
||||||
######################
|
######################
|
||||||
##### Name Files #####
|
##### Name Files #####
|
||||||
@@ -130,7 +135,7 @@ build/janet_boot: $(JANET_BOOT_OBJECTS)
|
|||||||
|
|
||||||
# Now the reason we bootstrap in the first place
|
# Now the reason we bootstrap in the first place
|
||||||
build/core_image.c: build/janet_boot
|
build/core_image.c: build/janet_boot
|
||||||
build/janet_boot $@ JANET_PATH $(JANET_PATH)
|
build/janet_boot $@ JANET_PATH $(JANET_PATH) JANET_HEADERPATH $(INCLUDEDIR)/janet
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
##### The main interpreter program and shared object #####
|
##### The main interpreter program and shared object #####
|
||||||
@@ -152,6 +157,9 @@ $(JANET_TARGET): $(JANET_CORE_OBJECTS) $(JANET_MAINCLIENT_OBJECTS)
|
|||||||
$(JANET_LIBRARY): $(JANET_CORE_OBJECTS)
|
$(JANET_LIBRARY): $(JANET_CORE_OBJECTS)
|
||||||
$(CC) $(LDFLAGS) $(CFLAGS) -shared -o $@ $^ $(CLIBS)
|
$(CC) $(LDFLAGS) $(CFLAGS) -shared -o $@ $^ $(CLIBS)
|
||||||
|
|
||||||
|
$(JANET_STATIC_LIBRARY): $(JANET_CORE_OBJECTS)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
######################
|
######################
|
||||||
##### Emscripten #####
|
##### Emscripten #####
|
||||||
######################
|
######################
|
||||||
@@ -245,7 +253,7 @@ dist: build/janet-dist.tar.gz
|
|||||||
|
|
||||||
build/janet-%.tar.gz: $(JANET_TARGET) \
|
build/janet-%.tar.gz: $(JANET_TARGET) \
|
||||||
src/include/janet.h src/include/janetconf.h \
|
src/include/janet.h src/include/janetconf.h \
|
||||||
janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) \
|
janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) \
|
||||||
build/doc.html README.md build/janet.c
|
build/doc.html README.md build/janet.c
|
||||||
tar -czvf $@ $^
|
tar -czvf $@ $^
|
||||||
|
|
||||||
@@ -258,6 +266,47 @@ docs: build/doc.html
|
|||||||
build/doc.html: $(JANET_TARGET) tools/gendoc.janet
|
build/doc.html: $(JANET_TARGET) tools/gendoc.janet
|
||||||
$(JANET_TARGET) tools/gendoc.janet > build/doc.html
|
$(JANET_TARGET) tools/gendoc.janet > build/doc.html
|
||||||
|
|
||||||
|
########################
|
||||||
|
##### Installation #####
|
||||||
|
########################
|
||||||
|
|
||||||
|
SONAME=libjanet.so.1
|
||||||
|
|
||||||
|
.PHONY: $(PKG_CONFIG_PATH)/janet.pc
|
||||||
|
$(PKG_CONFIG_PATH)/janet.pc: $(JANET_TARGET)
|
||||||
|
mkdir -p $(PKG_CONFIG_PATH)
|
||||||
|
echo 'prefix=$(PREFIX)' > $@
|
||||||
|
echo 'exec_prefix=$${prefix}' >> $@
|
||||||
|
echo 'includedir=$(INCLUDEDIR)/janet' >> $@
|
||||||
|
echo 'libdir=$(LIBDIR)' >> $@
|
||||||
|
echo "" >> $@
|
||||||
|
echo "Name: janet" >> $@
|
||||||
|
echo "Url: https://janet-lang.org" >> $@
|
||||||
|
echo "Description: Library for the Janet programming language." >> $@
|
||||||
|
$(JANET_TARGET) -e '(print "Version: " janet/version)' >> $@
|
||||||
|
echo 'Cflags: -I$${includedir}' >> $@
|
||||||
|
echo 'Libs: -L$${libdir} -ljanet $(LDFLAGS)' >> $@
|
||||||
|
echo 'Libs.private: $(CLIBS)' >> $@
|
||||||
|
|
||||||
|
install: $(JANET_TARGET) $(PKG_CONFIG_PATH)/janet.pc
|
||||||
|
mkdir -p $(BINDIR)
|
||||||
|
cp $(JANET_TARGET) $(BINDIR)/janet
|
||||||
|
mkdir -p $(INCLUDEDIR)/janet
|
||||||
|
cp -rf $(JANET_HEADERS) $(INCLUDEDIR)/janet
|
||||||
|
mkdir -p $(JANET_PATH)
|
||||||
|
mkdir -p $(LIBDIR)
|
||||||
|
cp $(JANET_LIBRARY) $(LIBDIR)/libjanet.so.$(shell $(JANET_TARGET) -e '(print janet/version)')
|
||||||
|
cp $(JANET_STATIC_LIBRARY) $(LIBDIR)/libjanet.a
|
||||||
|
ln -sf $(SONAME) $(LIBDIR)/libjanet.so
|
||||||
|
ln -sf libjanet.so.$(shell $(JANET_TARGET) -e '(print janet/version)') $(LIBDIR)/$(SONAME)
|
||||||
|
cp tools/cook.janet $(JANET_PATH)
|
||||||
|
cp tools/jpm $(BINDIR)/jpm
|
||||||
|
cp tools/highlight.janet $(JANET_PATH)
|
||||||
|
cp tools/bars.janet $(JANET_PATH)
|
||||||
|
mkdir -p $(MANPATH)
|
||||||
|
cp janet.1 $(MANPATH)
|
||||||
|
-ldconfig $(LIBDIR)
|
||||||
|
|
||||||
#################
|
#################
|
||||||
##### Other #####
|
##### Other #####
|
||||||
#################
|
#################
|
||||||
@@ -272,32 +321,18 @@ build/janet.tmLanguage: tools/tm_lang_gen.janet $(JANET_TARGET)
|
|||||||
clean:
|
clean:
|
||||||
-rm -rf build vgcore.* callgrind.*
|
-rm -rf build vgcore.* callgrind.*
|
||||||
|
|
||||||
build/version.txt: $(JANET_TARGET)
|
|
||||||
$(JANET_TARGET) -e '(print janet/version)' > $@
|
|
||||||
|
|
||||||
SONAME=libjanet.so.0
|
|
||||||
install: $(JANET_TARGET) build/version.txt
|
|
||||||
mkdir -p $(BINDIR)
|
|
||||||
cp $(JANET_TARGET) $(BINDIR)/janet
|
|
||||||
mkdir -p $(INCLUDEDIR)
|
|
||||||
cp $(JANET_HEADERS) $(INCLUDEDIR)
|
|
||||||
mkdir -p $(LIBDIR)
|
|
||||||
cp $(JANET_LIBRARY) $(LIBDIR)/libjanet.so.$(shell cat build/version.txt)
|
|
||||||
ln -sf $(SONAME) $(LIBDIR)/libjanet.so
|
|
||||||
ln -sf libjanet.so.$(shell cat build/version.txt) $(LIBDIR)/$(SONAME)
|
|
||||||
mkdir -p $(INCLUDEDIR)/janet
|
|
||||||
mkdir -p $(JANET_PATH)
|
|
||||||
ln -sf $(INCLUDEDIR)/janet.h $(JANET_PATH)/janet.h
|
|
||||||
ln -sf $(INCLUDEDIR)/janetconf.h $(JANET_PATH)/janetconf.h
|
|
||||||
cp tools/cook.janet $(JANET_PATH)
|
|
||||||
cp tools/highlight.janet $(JANET_PATH)
|
|
||||||
cp tools/bars.janet $(JANET_PATH)
|
|
||||||
mkdir -p $(MANPATH)
|
|
||||||
cp janet.1 $(MANPATH)
|
|
||||||
-ldconfig $(LIBDIR)
|
|
||||||
|
|
||||||
test-install:
|
test-install:
|
||||||
cd test/install && rm -rf build && janet build && janet build
|
cd test/install && rm -rf build && jpm build && jpm test
|
||||||
|
|
||||||
|
build/embed_janet.o: build/janet.c $(JANET_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
build/embed_main.o: test/amalg/main.c $(JANET_HEADERS)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
build/embed_test: build/embed_janet.o build/embed_main.o
|
||||||
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(CLIBS)
|
||||||
|
|
||||||
|
test-amalg: build/embed_test
|
||||||
|
./build/embed_test
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
-rm $(BINDIR)/../$(JANET_TARGET)
|
-rm $(BINDIR)/../$(JANET_TARGET)
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -3,6 +3,7 @@
|
|||||||
[](https://ci.appveyor.com/project/bakpakin/janet/branch/master)
|
[](https://ci.appveyor.com/project/bakpakin/janet/branch/master)
|
||||||
[](https://travis-ci.org/janet-lang/janet)
|
[](https://travis-ci.org/janet-lang/janet)
|
||||||
[](https://builds.sr.ht/~bakpakin/janet/.freebsd.yaml?)
|
[](https://builds.sr.ht/~bakpakin/janet/.freebsd.yaml?)
|
||||||
|
[](https://builds.sr.ht/~bakpakin/janet/.openbsd.yaml?)
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">
|
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">
|
||||||
|
|
||||||
@@ -79,15 +80,28 @@ make test
|
|||||||
make repl
|
make repl
|
||||||
```
|
```
|
||||||
|
|
||||||
### FreeBSD
|
### 32-bit Haiku
|
||||||
|
|
||||||
FreeBSD build instructions are the same as the unix-like build instuctions,
|
32-bit Haiku build instructions are the same as the unix-like build instructions,
|
||||||
but you need `gmake` and `gcc` to compile.
|
but you need to specify an alternative compiler, such as `gcc-x86`.
|
||||||
|
|
||||||
```
|
```
|
||||||
cd somewhere/my/projects/janet
|
cd somewhere/my/projects/janet
|
||||||
gmake CC=gcc
|
make CC=gcc-x86
|
||||||
gmake test CC=gcc
|
make test
|
||||||
|
make repl
|
||||||
|
```
|
||||||
|
|
||||||
|
### FreeBSD
|
||||||
|
|
||||||
|
FreeBSD build instructions are the same as the unix-like build instuctions,
|
||||||
|
but you need `gmake` to compile. Alternatively, install directly from
|
||||||
|
packages, using `pkg install lang/janet`.
|
||||||
|
|
||||||
|
```
|
||||||
|
cd somewhere/my/projects/janet
|
||||||
|
gmake
|
||||||
|
gmake test
|
||||||
gmake repl
|
gmake repl
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -172,6 +186,16 @@ See the examples directory for some example janet code.
|
|||||||
Feel free to ask questions and join discussion on the [Janet Gitter Channel](https://gitter.im/janet-language/community).
|
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/)
|
Alternatively, check out [the #janet channel on Freenode](https://webchat.freenode.net/)
|
||||||
|
|
||||||
|
## FAQ
|
||||||
|
|
||||||
|
### Why is my terminal is spitting out junk when I run the repl?
|
||||||
|
|
||||||
|
Make sure your terminal supports ANSI escape codes. Most modern terminals will
|
||||||
|
support these, but some older terminals, windows consoles, or embedded terminals
|
||||||
|
will not. If your terminal does not support ANSI escape codes, run the repl with
|
||||||
|
the `-n` flag, which disables color output. You can also try the `-s` if further issues
|
||||||
|
ensue.
|
||||||
|
|
||||||
## Why Janet
|
## Why Janet
|
||||||
|
|
||||||
Janet is named after the almost omniscient and friendly artificial being in [The Good Place](https://en.wikipedia.org/wiki/The_Good_Place).
|
Janet is named after the almost omniscient and friendly artificial being in [The Good Place](https://en.wikipedia.org/wiki/The_Good_Place).
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ install:
|
|||||||
- build_win
|
- build_win
|
||||||
- build_win test
|
- build_win test
|
||||||
- choco install nsis -y -pre
|
- choco install nsis -y -pre
|
||||||
- call "C:\Program Files (x86)\NSIS\makensis.exe" janet-installer.nsi
|
|
||||||
- build_win dist
|
- build_win dist
|
||||||
- copy janet-install.exe dist\install.exe
|
- call "C:\Program Files (x86)\NSIS\makensis.exe" janet-installer.nsi
|
||||||
|
|
||||||
build: off
|
build: off
|
||||||
|
|
||||||
@@ -33,9 +32,9 @@ only_commits:
|
|||||||
- src/
|
- src/
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: dist
|
- path: janet-installer.exe
|
||||||
name: janet-windows
|
name: janet-windows-installer.exe
|
||||||
type: Zip
|
type: File
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
description: 'The Janet Programming Language.'
|
description: 'The Janet Programming Language.'
|
||||||
|
|||||||
BIN
assets/icon.ico
Normal file
BIN
assets/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
11
assets/icon_svg.svg
Normal file
11
assets/icon_svg.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="64px" height="64px" viewBox="0 0 640 640" preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g id="layer101" fill="#d45500" stroke="none">
|
||||||
|
<path d="M145 531 c-46 -31 -58 -75 -30 -118 21 -32 30 -22 44 47 7 30 19 62 27 71 26 29 1 29 -41 0z"/>
|
||||||
|
<path d="M341 534 c-23 -29 -26 -50 -11 -88 10 -28 64 -60 86 -52 12 5 12 2 0 -22 -24 -47 -51 -64 -116 -71 -51 -6 -65 -12 -85 -37 -14 -16 -24 -32 -25 -36 0 -12 -35 -9 -48 4 -7 7 -12 24 -12 38 0 41 -11 43 -47 8 -47 -46 -46 -90 5 -138 20 -19 49 -51 63 -70 l27 -35 88 0 c49 0 106 4 127 8 46 10 106 62 143 125 25 42 28 58 30 142 0 52 4 103 9 113 11 27 -14 75 -49 93 -41 21 -115 44 -143 44 -12 0 -31 -12 -42 -26z m89 -119 c0 -3 -2 -5 -5 -5 -3 0 -5 2 -5 5 0 3 2 5 5 5 3 0 5 -2 5 -5z"/>
|
||||||
|
</g>
|
||||||
|
<g id="layer102" fill="#deaa87" stroke="none">
|
||||||
|
<path d="M186 549 c-33 -31 -38 -43 -56 -137 -26 -135 -26 -163 3 -190 33 -31 49 -28 85 17 28 35 36 39 87 43 46 4 61 10 90 38 18 18 39 46 46 62 10 25 9 32 -5 46 -17 16 -19 16 -29 1 -8 -14 -15 -15 -34 -6 -27 12 -40 65 -24 96 10 17 8 23 -12 36 -13 8 -44 18 -69 21 -42 6 -49 4 -82 -27z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -53,7 +53,7 @@ for %%f in (src\boot\*.c) do (
|
|||||||
)
|
)
|
||||||
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
build\janet_boot build\core_image.c JANET_PATH "C:/Janet/Library"
|
build\janet_boot build\core_image.c
|
||||||
|
|
||||||
@rem Build the core image
|
@rem Build the core image
|
||||||
@%JANET_COMPILE% /Fobuild\core_image.obj build\core_image.c
|
@%JANET_COMPILE% /Fobuild\core_image.obj build\core_image.c
|
||||||
@@ -65,6 +65,9 @@ for %%f in (src\core\*.c) do (
|
|||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@rem Build the resources
|
||||||
|
rc /nologo /fobuild\janet_win.res janet_win.rc
|
||||||
|
|
||||||
@rem Build the main client
|
@rem Build the main client
|
||||||
for %%f in (src\mainclient\*.c) do (
|
for %%f in (src\mainclient\*.c) do (
|
||||||
@%JANET_COMPILE% /Fobuild\mainclient\%%~nf.obj %%f
|
@%JANET_COMPILE% /Fobuild\mainclient\%%~nf.obj %%f
|
||||||
@@ -72,9 +75,17 @@ for %%f in (src\mainclient\*.c) do (
|
|||||||
)
|
)
|
||||||
|
|
||||||
@rem Link everything to main client
|
@rem Link everything to main client
|
||||||
%JANET_LINK% /out:janet.exe build\core\*.obj build\mainclient\*.obj build\core_image.obj
|
%JANET_LINK% /out:janet.exe build\core\*.obj build\mainclient\*.obj build\core_image.obj build\janet_win.res
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
|
|
||||||
|
@rem Gen amlag
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
set "amalg_files="
|
||||||
|
for %%f in (src\core\*.c) do (
|
||||||
|
set "amalg_files=!amalg_files! %%f"
|
||||||
|
)
|
||||||
|
janet.exe tools\amalg.janet src\core\util.h src\core\state.h src\core\gc.h src\core\vector.h src\core\fiber.h src\core\regalloc.h src\core\compile.h src\core\emit.h src\core\symcache.h %amalg_files% build\core_image.c > build\janet.c
|
||||||
|
|
||||||
echo === Successfully built janet.exe for Windows ===
|
echo === Successfully built janet.exe for Windows ===
|
||||||
echo === Run 'build_win test' to run tests. ==
|
echo === Run 'build_win test' to run tests. ==
|
||||||
echo === Run 'build_win clean' to delete build artifacts. ===
|
echo === Run 'build_win clean' to delete build artifacts. ===
|
||||||
@@ -113,13 +124,7 @@ exit /b 0
|
|||||||
mkdir dist
|
mkdir dist
|
||||||
janet.exe tools\gendoc.janet > dist\doc.html
|
janet.exe tools\gendoc.janet > dist\doc.html
|
||||||
|
|
||||||
@rem Gen amlag
|
copy build\janet.c dist\janet.c
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
set "amalg_files="
|
|
||||||
for %%f in (src\core\*.c) do (
|
|
||||||
set "amalg_files=!amalg_files! %%f"
|
|
||||||
)
|
|
||||||
janet.exe tools\amalg.janet src\core\util.h src\core\state.h src\core\gc.h src\core\vector.h src\core\fiber.h src\core\regalloc.h src\core\compile.h src\core\emit.h src\core\symcache.h %amalg_files% build\core_image.c > dist\janet.c
|
|
||||||
copy janet.exe dist\janet.exe
|
copy janet.exe dist\janet.exe
|
||||||
copy LICENSE dist\LICENSE
|
copy LICENSE dist\LICENSE
|
||||||
copy README.md dist\README.md
|
copy README.md dist\README.md
|
||||||
@@ -129,6 +134,8 @@ copy src\include\janet.h dist\janet.h
|
|||||||
copy src\include\janetconf.h dist\janetconf.h
|
copy src\include\janetconf.h dist\janetconf.h
|
||||||
copy tools\cook.janet dist\cook.janet
|
copy tools\cook.janet dist\cook.janet
|
||||||
copy tools\highlight.janet dist\highlight.janet
|
copy tools\highlight.janet dist\highlight.janet
|
||||||
|
copy tools\jpm dist\jpm
|
||||||
|
copy tools\jpm.bat dist\jpm.bat
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:TESTFAIL
|
:TESTFAIL
|
||||||
|
|||||||
@@ -13,4 +13,4 @@
|
|||||||
(if isprime? (array/push list i)))
|
(if isprime? (array/push list i)))
|
||||||
list)
|
list)
|
||||||
|
|
||||||
(print (string/pretty (primes 100)))
|
(pp (primes 100))
|
||||||
|
|||||||
29
examples/urlloader.janet
Normal file
29
examples/urlloader.janet
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# An example of using Janet's extensible module system
|
||||||
|
# to import files from URL. To try this, run `janet -l examples/urlloader.janet`
|
||||||
|
# from the repl, and then:
|
||||||
|
#
|
||||||
|
# (import https://raw.githubusercontent.com/janet-lang/janet/master/examples/colors.janet :as c)
|
||||||
|
#
|
||||||
|
# This will import a file using curl. You can then try
|
||||||
|
#
|
||||||
|
# (print (c/color :green "Hello!"))
|
||||||
|
#
|
||||||
|
# This is a bit of a toy example (it just shells out to curl), but it is very
|
||||||
|
# powerful and will work well in many cases.
|
||||||
|
|
||||||
|
(defn- load-url
|
||||||
|
[url args]
|
||||||
|
(def f (file/popen (string "curl " url)))
|
||||||
|
(def res (dofile f :source url ;args))
|
||||||
|
(try (file/close f) ([err] nil))
|
||||||
|
res)
|
||||||
|
|
||||||
|
(defn- check-http-url
|
||||||
|
[path]
|
||||||
|
(if (or (string/has-prefix? "http://" path)
|
||||||
|
(string/has-prefix? "https://" path))
|
||||||
|
path))
|
||||||
|
|
||||||
|
# Add the module loader and path tuple to right places
|
||||||
|
(array/push module/paths [check-http-url :janet-http])
|
||||||
|
(put module/loaders :janet-http load-url)
|
||||||
@@ -1,55 +1,157 @@
|
|||||||
|
# Version
|
||||||
|
!define VERSION "0.6.0"
|
||||||
|
!define PRODUCT_VERSION "${VERSION}.0"
|
||||||
|
VIProductVersion "${PRODUCT_VERSION}"
|
||||||
|
VIFileVersion "${PRODUCT_VERSION}"
|
||||||
|
|
||||||
|
# Use the modern UI
|
||||||
!define MULTIUSER_EXECUTIONLEVEL Highest
|
!define MULTIUSER_EXECUTIONLEVEL Highest
|
||||||
!define MULTIUSER_MUI
|
!define MULTIUSER_MUI
|
||||||
!define MULTIUSER_INSTALLMODE_COMMANDLINE
|
!define MULTIUSER_INSTALLMODE_COMMANDLINE
|
||||||
!define MULTIUSER_INSTALLMODE_INSTDIR "janet"
|
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "Software\Janet\${VERSION}"
|
||||||
|
!define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME ""
|
||||||
|
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "Software\Janet\${VERSION}"
|
||||||
|
!define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME ""
|
||||||
|
!define MULTIUSER_INSTALLMODE_INSTDIR "Janet-${VERSION}"
|
||||||
!include "MultiUser.nsh"
|
!include "MultiUser.nsh"
|
||||||
!include "MUI2.nsh"
|
!include "MUI2.nsh"
|
||||||
|
!include ".\tools\EnvVarUpdate.nsh"
|
||||||
|
|
||||||
|
# Basics
|
||||||
Name "Janet"
|
Name "Janet"
|
||||||
OutFile "janet-install.exe"
|
OutFile "janet-v${VERSION}-windows-installer.exe"
|
||||||
|
|
||||||
|
# Some Configuration
|
||||||
|
!define APPNAME "Janet"
|
||||||
|
!define DESCRIPTION "The Janet Programming Language"
|
||||||
|
!define HELPURL "http://janet-lang.org"
|
||||||
|
BrandingText "The Janet Programming Language"
|
||||||
|
|
||||||
|
# MUI Configuration
|
||||||
|
!define MUI_ICON "assets\icon.ico"
|
||||||
|
!define MUI_UNICON "assets\icon.ico"
|
||||||
|
!define MUI_HEADERIMAGE
|
||||||
|
!define MUI_HEADERIMAGE_BITMAP "assets\janet-w200.png"
|
||||||
|
!define MUI_HEADERIMAGE_RIGHT
|
||||||
!define MUI_ABORTWARNING
|
!define MUI_ABORTWARNING
|
||||||
|
|
||||||
|
# Show a welcome page first
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
!insertmacro MUI_PAGE_LICENSE "LICENSE"
|
!insertmacro MUI_PAGE_LICENSE "LICENSE"
|
||||||
!insertmacro MUI_PAGE_COMPONENTS
|
|
||||||
|
# Pick Install Directory
|
||||||
!insertmacro MULTIUSER_PAGE_INSTALLMODE
|
!insertmacro MULTIUSER_PAGE_INSTALLMODE
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
|
||||||
|
# Done
|
||||||
!insertmacro MUI_PAGE_FINISH
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
# Need to set a language.
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
|
||||||
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
Section "Janet" BfWSection
|
function .onInit
|
||||||
SetOutPath $INSTDIR
|
!insertmacro MULTIUSER_INIT
|
||||||
File "janet.exe"
|
functionEnd
|
||||||
WriteUninstaller "$INSTDIR\janet-uninstall.exe"
|
|
||||||
|
|
||||||
# Start Menu
|
section "Janet" BfWSection
|
||||||
CreateShortCut "$SMPROGRAMS\Janet.lnk" "$INSTDIR\janet.exe" "" ""
|
createDirectory "$INSTDIR\Library"
|
||||||
SectionEnd
|
createDirectory "$INSTDIR\C"
|
||||||
|
createDirectory "$INSTDIR\bin"
|
||||||
|
setOutPath "$INSTDIR"
|
||||||
|
|
||||||
Function .onInit
|
file /oname=bin\janet.exe dist\janet.exe
|
||||||
!insertmacro MULTIUSER_INIT
|
file /oname=logo.ico assets\icon.ico
|
||||||
!insertmacro MUI_LANGDLL_DISPLAY
|
|
||||||
FunctionEnd
|
|
||||||
|
|
||||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
file /oname=Library\cook.janet dist\cook.janet
|
||||||
!insertmacro MUI_DESCRIPTION_TEXT ${BfWSection} "The Janet programming language."
|
|
||||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
|
||||||
|
|
||||||
Section "Uninstall"
|
file /oname=C\janet.h dist\janet.h
|
||||||
Delete "$INSTDIR\janet.exe"
|
file /oname=C\janetconf.h dist\janetconf.h
|
||||||
Delete "$INSTDIR\janet-uninstall.exe"
|
file /oname=C\janet.lib dist\janet.lib
|
||||||
RMDir "$INSTDIR"
|
file /oname=C\janet.exp dist\janet.exp
|
||||||
SectionEnd
|
file /oname=C\janet.c dist\janet.c
|
||||||
|
|
||||||
Function un.onInit
|
file /oname=bin\jpm.janet dist\jpm
|
||||||
!insertmacro MULTIUSER_UNINIT
|
file /oname=bin\jpm.bat dist\jpm.bat
|
||||||
!insertmacro MUI_UNGETLANGUAGE
|
|
||||||
FunctionEnd
|
# Uninstaller - See function un.onInit and section "uninstall" for configuration
|
||||||
|
writeUninstaller "$INSTDIR\uninstall.exe"
|
||||||
|
|
||||||
|
# Start Menu
|
||||||
|
createShortCut "$SMPROGRAMS\Janet.lnk" "$INSTDIR\bin\janet.exe" "" "$INSTDIR\logo.ico"
|
||||||
|
|
||||||
|
# HKLM (all users) vs HKCU (current user)
|
||||||
|
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_PATH "$INSTDIR\Library"
|
||||||
|
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_HEADERPATH "$INSTDIR\C"
|
||||||
|
WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_BINPATH "$INSTDIR\bin"
|
||||||
|
|
||||||
|
WriteRegExpandStr HKCU "Environment" JANET_PATH "$INSTDIR\Library"
|
||||||
|
WriteRegExpandStr HKCU "Environment" JANET_HEADERPATH "$INSTDIR\C"
|
||||||
|
WriteRegExpandStr HKCU "Environment" JANET_BINPATH "$INSTDIR\bin"
|
||||||
|
|
||||||
|
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||||
|
|
||||||
|
# Update path
|
||||||
|
${EnvVarUpdate} $0 "PATH" "A" "HKCU" "$INSTDIR\bin" ; Append
|
||||||
|
${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR\bin" ; Append
|
||||||
|
|
||||||
|
# Registry information for add/remove programs
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "DisplayName" "Janet"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "UninstallString" "$INSTDIR\uninstall.exe"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "QuietUninstallString" "$INSTDIR\uninstall.exe /S"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "InstallLocation" "$INSTDIR"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "DisplayIcon" "$INSTDIR\logo.ico"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "Publisher" "Janet-Lang.org"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "HelpLink" "${HELPURL}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "URLUpdateInfo" "${HELPURL}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "URLInfoAbout" "${HELPURL}"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "DisplayVersion" "0.6.0"
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "VersionMajor" 0
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "VersionMinor" 6
|
||||||
|
# There is no option for modifying or repairing the install
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "NoModify" 1
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "NoRepair" 1
|
||||||
|
# Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet" "EstimatedSize" 1000
|
||||||
|
sectionEnd
|
||||||
|
|
||||||
|
# Uninstaller
|
||||||
|
|
||||||
|
function un.onInit
|
||||||
|
!insertmacro MULTIUSER_UNINIT
|
||||||
|
functionEnd
|
||||||
|
|
||||||
|
section "uninstall"
|
||||||
|
|
||||||
|
# Remove Start Menu launcher
|
||||||
|
delete "$SMPROGRAMS\Janet.lnk"
|
||||||
|
|
||||||
|
# Remove files
|
||||||
|
delete "$INSTDIR\logo.ico"
|
||||||
|
rmdir /r "$INSTDIR\Library"
|
||||||
|
rmdir /r "$INSTDIR\bin"
|
||||||
|
rmdir /r "$INSTDIR\C"
|
||||||
|
|
||||||
|
# Remove env vars
|
||||||
|
|
||||||
|
DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_PATH
|
||||||
|
DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_HEADERPATH
|
||||||
|
DeleteRegValue HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" JANET_BINPATH
|
||||||
|
|
||||||
|
DeleteRegValue HKCU "Environment" JANET_PATH
|
||||||
|
DeleteRegValue HKCU "Environment" JANET_HEADERPATH
|
||||||
|
DeleteRegValue HKCU "Environment" JANET_BINPATH
|
||||||
|
|
||||||
|
# Unset PATH
|
||||||
|
${un.EnvVarUpdate} $0 "PATH" "R" "HKCU" "$INSTDIR\bin" ; Remove
|
||||||
|
${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$INSTDIR\bin" ; Remove
|
||||||
|
|
||||||
|
# make sure windows knows about the change
|
||||||
|
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||||
|
|
||||||
|
# Always delete uninstaller as the last action
|
||||||
|
delete "$INSTDIR\uninstall.exe"
|
||||||
|
|
||||||
|
# Remove uninstaller information from the registry
|
||||||
|
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Janet"
|
||||||
|
sectionEnd
|
||||||
|
|||||||
6
janet.1
6
janet.1
@@ -3,7 +3,7 @@
|
|||||||
janet \- run the Janet language abstract machine
|
janet \- run the Janet language abstract machine
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B janet
|
.B janet
|
||||||
[\fB\-hvsrpnq\fR]
|
[\fB\-hvsrpnqk\fR]
|
||||||
[\fB\-e\fR \fISOURCE\fR]
|
[\fB\-e\fR \fISOURCE\fR]
|
||||||
[\fB\-l\fR \fIMODULE\fR]
|
[\fB\-l\fR \fIMODULE\fR]
|
||||||
[\fB\-m\fR \fIPATH\fR]
|
[\fB\-m\fR \fIPATH\fR]
|
||||||
@@ -67,6 +67,10 @@ after an error. Persistent mode can be good for debugging and testing.
|
|||||||
.BR \-q
|
.BR \-q
|
||||||
Quiet output. Don't print a repl prompt or expression results to stdout.
|
Quiet output. Don't print a repl prompt or expression results to stdout.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR \-k
|
||||||
|
Don't execute a script, only compile it to check for errors. Useful for linting scripts.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR \-m\ syspath
|
.BR \-m\ syspath
|
||||||
Set the variable module/*syspath* to the string syspath so that Janet will load system modules
|
Set the variable module/*syspath* to the string syspath so that Janet will load system modules
|
||||||
|
|||||||
1
janet_win.rc
Normal file
1
janet_win.rc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
IDI_MYICON ICON "assets\icon.ico"
|
||||||
10
meson.build
10
meson.build
@@ -22,6 +22,7 @@ project('janet', 'c', default_options : ['c_std=c99'])
|
|||||||
|
|
||||||
# Global settings
|
# Global settings
|
||||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||||
|
header_path = join_paths(get_option('prefix'), get_option('includedir'), 'janet')
|
||||||
|
|
||||||
# Link math library on all systems
|
# Link math library on all systems
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
@@ -29,7 +30,7 @@ m_dep = cc.find_library('m', required : false)
|
|||||||
dl_dep = cc.find_library('dl', required : false)
|
dl_dep = cc.find_library('dl', required : false)
|
||||||
|
|
||||||
# Some options
|
# Some options
|
||||||
add_project_arguments('-DJANET_BUILD="meson"', language : 'c')
|
add_project_link_arguments('-rdynamic', language : 'c')
|
||||||
|
|
||||||
# Include directories
|
# Include directories
|
||||||
incdir = include_directories('src/include')
|
incdir = include_directories('src/include')
|
||||||
@@ -119,7 +120,7 @@ janet_boot = executable('janet-boot', core_src, boot_src, boot_gen,
|
|||||||
core_image = custom_target('core_image',
|
core_image = custom_target('core_image',
|
||||||
input : [janet_boot],
|
input : [janet_boot],
|
||||||
output : 'core_image.gen.c',
|
output : 'core_image.gen.c',
|
||||||
command : [janet_boot, '@OUTPUT@', 'JANET_PATH', janet_path])
|
command : [janet_boot, '@OUTPUT@', 'JANET_PATH', janet_path, 'JANET_HEADERPATH', header_path])
|
||||||
|
|
||||||
libjanet = shared_library('janet', core_src, core_image,
|
libjanet = shared_library('janet', core_src, core_image,
|
||||||
include_directories : incdir,
|
include_directories : incdir,
|
||||||
@@ -129,6 +130,7 @@ janet_mainclient = executable('janet', core_src, core_image, init_gen, mainclien
|
|||||||
include_directories : incdir,
|
include_directories : incdir,
|
||||||
dependencies : [m_dep, dl_dep],
|
dependencies : [m_dep, dl_dep],
|
||||||
install : true)
|
install : true)
|
||||||
|
janet_jpm = install_data('tools/jpm', install_dir : 'bin')
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
docs = custom_target('docs',
|
docs = custom_target('docs',
|
||||||
@@ -169,10 +171,8 @@ run_target('repl', command : [janet_mainclient])
|
|||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
install_man('janet.1')
|
install_man('janet.1')
|
||||||
install_headers('src/include/janet.h', 'src/include/janetconf.h')
|
install_headers('src/include/janet.h', 'src/include/janetconf.h', subdir: 'janet')
|
||||||
janet_libs = [
|
janet_libs = [
|
||||||
'src/include/janet.h',
|
|
||||||
'src/include/janetconf.h',
|
|
||||||
'tools/bars.janet',
|
'tools/bars.janet',
|
||||||
'tools/cook.janet',
|
'tools/cook.janet',
|
||||||
'tools/highlight.janet'
|
'tools/highlight.janet'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# The core janet library
|
# The core janet library
|
||||||
# Copyright 2019 (C) Calvin Rose
|
# Copyright 2019 © Calvin Rose
|
||||||
|
|
||||||
###
|
###
|
||||||
###
|
###
|
||||||
@@ -136,12 +136,12 @@
|
|||||||
|
|
||||||
(defmacro comment
|
(defmacro comment
|
||||||
"Ignores the body of the comment."
|
"Ignores the body of the comment."
|
||||||
[])
|
[&])
|
||||||
|
|
||||||
(defmacro if-not
|
(defmacro if-not
|
||||||
"Shorthand for (if (not ... "
|
"Shorthand for (if (not condition) else then)."
|
||||||
[condition exp-1 &opt exp-2]
|
[condition then &opt else]
|
||||||
~(if ,condition ,exp-2 ,exp-1))
|
~(if ,condition ,else ,then))
|
||||||
|
|
||||||
(defmacro when
|
(defmacro when
|
||||||
"Evaluates the body when the condition is true. Otherwise returns nil."
|
"Evaluates the body when the condition is true. Otherwise returns nil."
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
~(if ,condition (do ,;body)))
|
~(if ,condition (do ,;body)))
|
||||||
|
|
||||||
(defmacro unless
|
(defmacro unless
|
||||||
"Shorthand for (when (not ... "
|
"Shorthand for (when (not condition) ;body). "
|
||||||
[condition & body]
|
[condition & body]
|
||||||
~(if ,condition nil (do ,;body)))
|
~(if ,condition nil (do ,;body)))
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
(defmacro case
|
(defmacro case
|
||||||
"Select the body that equals the dispatch value. When pairs
|
"Select the body that equals the dispatch value. When pairs
|
||||||
has an odd number of arguments, the last is the default expression.
|
has an odd number of arguments, the last is the default expression.
|
||||||
If no match is found, returns nil"
|
If no match is found, returns nil."
|
||||||
[dispatch & pairs]
|
[dispatch & pairs]
|
||||||
(def atm (idempotent? dispatch))
|
(def atm (idempotent? dispatch))
|
||||||
(def sym (if atm dispatch (gensym)))
|
(def sym (if atm dispatch (gensym)))
|
||||||
@@ -416,7 +416,7 @@
|
|||||||
~(fiber/new (fn [] (loop ,head (yield (do ,;body)))) :yi))
|
~(fiber/new (fn [] (loop ,head (yield (do ,;body)))) :yi))
|
||||||
|
|
||||||
(defmacro coro
|
(defmacro coro
|
||||||
"A wrapper for making fibers. Same as (fiber/new (fn [] ...body) :yi)."
|
"A wrapper for making fibers. Same as (fiber/new (fn [] ;body) :yi)."
|
||||||
[& body]
|
[& body]
|
||||||
(tuple fiber/new (tuple 'fn '[] ;body) :yi))
|
(tuple fiber/new (tuple 'fn '[] ;body) :yi))
|
||||||
|
|
||||||
@@ -678,7 +678,7 @@
|
|||||||
|
|
||||||
(defn find
|
(defn find
|
||||||
"Find the first value in an indexed collection that satisfies a predicate. Returns
|
"Find the first value in an indexed collection that satisfies a predicate. Returns
|
||||||
nil if not found. Note their is no way to differentiate a nil from the indexed collection
|
nil if not found. Note there is no way to differentiate a nil from the indexed collection
|
||||||
and a not found. Consider find-index if this is an issue."
|
and a not found. Consider find-index if this is an issue."
|
||||||
[pred ind]
|
[pred ind]
|
||||||
(def i (find-index pred ind))
|
(def i (find-index pred ind))
|
||||||
@@ -1047,11 +1047,12 @@
|
|||||||
(var i 0) (var nextn n)
|
(var i 0) (var nextn n)
|
||||||
(def len (length ind))
|
(def len (length ind))
|
||||||
(def ret (array/new (math/ceil (/ len n))))
|
(def ret (array/new (math/ceil (/ len n))))
|
||||||
|
(def slicer (if (bytes? ind) string/slice tuple/slice))
|
||||||
(while (<= nextn len)
|
(while (<= nextn len)
|
||||||
(array/push ret (tuple/slice ind i nextn))
|
(array/push ret (slicer ind i nextn))
|
||||||
(set i nextn)
|
(set i nextn)
|
||||||
(+= nextn n))
|
(+= nextn n))
|
||||||
(if (not= i len) (array/push ret (tuple/slice ind i)))
|
(if (not= i len) (array/push ret (slicer ind i)))
|
||||||
ret)
|
ret)
|
||||||
|
|
||||||
###
|
###
|
||||||
@@ -1126,10 +1127,13 @@
|
|||||||
~(if (= nil (def ,pattern ,expr)) ,sentinel ,(onmatch))))
|
~(if (= nil (def ,pattern ,expr)) ,sentinel ,(onmatch))))
|
||||||
|
|
||||||
(tuple? pattern)
|
(tuple? pattern)
|
||||||
(match-1
|
(if (and (= (pattern 0) 'quote) (symbol? (pattern 1)))
|
||||||
(get pattern 0) expr
|
# Unification with external values
|
||||||
(fn []
|
~(if (= ,(pattern 1) ,expr) ,(onmatch) ,sentinel)
|
||||||
~(if (and ,;(tuple/slice pattern 1)) ,(onmatch) ,sentinel)) seen)
|
(match-1
|
||||||
|
(get pattern 0) expr
|
||||||
|
(fn []
|
||||||
|
~(if (and ,;(tuple/slice pattern 1)) ,(onmatch) ,sentinel)) seen))
|
||||||
|
|
||||||
(array? pattern)
|
(array? pattern)
|
||||||
(do
|
(do
|
||||||
@@ -1454,6 +1458,7 @@
|
|||||||
:env - the environment to compile against - default is the current env\n\t
|
:env - the environment to compile against - default is the current env\n\t
|
||||||
:source - string path of source for better errors - default is \"<anonymous>\"\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-compile-error - callback when compilation fails - default is bad-compile\n\t
|
||||||
|
:compile-only - only compile the souce, do not execute it - default is false\n\t
|
||||||
:on-status - callback when a value is evaluated - default is debug/stacktrace\n\t
|
:on-status - callback when a value is evaluated - default is debug/stacktrace\n\t
|
||||||
:fiber-flags - what flags to wrap the compilation fiber with. Default is :ia."
|
:fiber-flags - what flags to wrap the compilation fiber with. Default is :ia."
|
||||||
[opts]
|
[opts]
|
||||||
@@ -1464,9 +1469,11 @@
|
|||||||
:on-compile-error on-compile-error
|
:on-compile-error on-compile-error
|
||||||
:on-parse-error on-parse-error
|
:on-parse-error on-parse-error
|
||||||
:fiber-flags guard
|
:fiber-flags guard
|
||||||
|
:compile-only compile-only
|
||||||
:source where} opts)
|
:source where} opts)
|
||||||
(default env (fiber/getenv (fiber/current)))
|
(default env (fiber/getenv (fiber/current)))
|
||||||
(default chunks getline)
|
(default chunks (fn [buf p] (getline "" buf)))
|
||||||
|
(default compile-only false)
|
||||||
(default onstatus debug/stacktrace)
|
(default onstatus debug/stacktrace)
|
||||||
(default on-compile-error bad-compile)
|
(default on-compile-error bad-compile)
|
||||||
(default on-parse-error bad-parse)
|
(default on-parse-error bad-parse)
|
||||||
@@ -1486,7 +1493,7 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(def res (compile source env where))
|
(def res (compile source env where))
|
||||||
(if (= (type res) :function)
|
(if (= (type res) :function)
|
||||||
(res)
|
(unless compile-only (res))
|
||||||
(do
|
(do
|
||||||
(set good false)
|
(set good false)
|
||||||
(def {:error err :start start :end end :fiber errf} res)
|
(def {:error err :start start :end end :fiber errf} res)
|
||||||
@@ -1578,8 +1585,13 @@
|
|||||||
:native: becomes the dynamic library file extension, usually dll
|
:native: becomes the dynamic library file extension, usually dll
|
||||||
or so. Each element is a two element tuple, containing the path
|
or so. Each element is a two element tuple, containing the path
|
||||||
template and a keyword :source, :native, or :image indicating how
|
template and a keyword :source, :native, or :image indicating how
|
||||||
require should load files found at these paths."
|
require should load files found at these paths.\n\nA tuple can also
|
||||||
@[[":all:" :source]
|
contain a third element, specifying a filter that prevents module/find
|
||||||
|
from searching that path template if the filter doesn't match the input
|
||||||
|
path. The filter is often a file extension, including the period."
|
||||||
|
@[[":all:" :native (if (= (os/which) :windows) ".dll" ".so")]
|
||||||
|
[":all:" :image ".jimage"]
|
||||||
|
[":all:" :source]
|
||||||
["./:all:.janet" :source]
|
["./:all:.janet" :source]
|
||||||
["./:all:/init.janet" :source]
|
["./:all:/init.janet" :source]
|
||||||
[":sys:/:all:.janet" :source]
|
[":sys:/:all:.janet" :source]
|
||||||
@@ -1593,9 +1605,15 @@
|
|||||||
(var module/*syspath*
|
(var module/*syspath*
|
||||||
"The path where globally installed libraries are located.
|
"The path where globally installed libraries are located.
|
||||||
The default is set at build time and is /usr/local/lib/janet on linux/posix, and
|
The default is set at build time and is /usr/local/lib/janet on linux/posix, and
|
||||||
on Windows is C:/Janet/Library."
|
on Windows is the empty string."
|
||||||
(or (process/opts "JANET_PATH") ""))
|
(or (process/opts "JANET_PATH") ""))
|
||||||
|
|
||||||
|
(var module/*headerpath*
|
||||||
|
"The path where the janet headers are installed. Useful for building
|
||||||
|
native modules or compiling code at runtime. Default on linux/posix is
|
||||||
|
/usr/local/include/janet, and on Windows is the empty string."
|
||||||
|
(or (process/opts "JANET_HEADERPATH") ""))
|
||||||
|
|
||||||
# Version of fexists that works even with a reduced OS
|
# Version of fexists that works even with a reduced OS
|
||||||
(if-let [has-stat (_env 'os/stat)]
|
(if-let [has-stat (_env 'os/stat)]
|
||||||
(let [stat (has-stat :value)]
|
(let [stat (has-stat :value)]
|
||||||
@@ -1610,6 +1628,21 @@
|
|||||||
(file/close f)
|
(file/close f)
|
||||||
res))))
|
res))))
|
||||||
|
|
||||||
|
(def nati (if (= :windows (os/which)) "dll" "so"))
|
||||||
|
(defn- expand-path-name
|
||||||
|
[template name path]
|
||||||
|
(->> template
|
||||||
|
(string/replace ":name:" name)
|
||||||
|
(string/replace ":sys:" module/*syspath*)
|
||||||
|
(string/replace ":native:" nati)
|
||||||
|
(string/replace ":all:" path)))
|
||||||
|
(defn- mod-filter
|
||||||
|
[x path]
|
||||||
|
(case (type x)
|
||||||
|
:nil path
|
||||||
|
:string (string/has-suffix? x path)
|
||||||
|
(x path)))
|
||||||
|
|
||||||
(defn module/find
|
(defn module/find
|
||||||
"Try to match a module or path name from the patterns in module/paths.
|
"Try to match a module or path name from the patterns in module/paths.
|
||||||
Returns a tuple (fullpath kind) where the kind is one of :source, :native,
|
Returns a tuple (fullpath kind) where the kind is one of :source, :native,
|
||||||
@@ -1617,25 +1650,32 @@
|
|||||||
an error message."
|
an error message."
|
||||||
[path]
|
[path]
|
||||||
(def parts (string/split "/" path))
|
(def parts (string/split "/" path))
|
||||||
(def name (get parts (- (length parts) 1)))
|
(def name (last parts))
|
||||||
(def nati (if (= :windows (os/which)) "dll" "so"))
|
(var ret nil)
|
||||||
(defn make-full
|
(each [p mod-kind checker] module/paths
|
||||||
[[p mod-kind]]
|
(when (mod-filter checker path)
|
||||||
(def fullpath (->> p
|
(if (function? p)
|
||||||
(string/replace ":name:" name)
|
(when-let [res (p path)]
|
||||||
(string/replace ":sys:" module/*syspath*)
|
(set ret [res mod-kind])
|
||||||
(string/replace ":native:" nati)
|
(break))
|
||||||
(string/replace ":all:" path)))
|
(do
|
||||||
[fullpath mod-kind])
|
(def fullpath (expand-path-name p name path))
|
||||||
(defn check-path [x] (if (fexists (x 0)) x))
|
(when (fexists fullpath)
|
||||||
(def paths (map make-full module/paths))
|
(set ret [fullpath mod-kind])
|
||||||
(def res (find check-path paths))
|
(break))))))
|
||||||
(if res res [nil (string "could not find module "
|
(if ret ret
|
||||||
path
|
(let [expander (fn [[t _ chk]]
|
||||||
":\n "
|
(when (string? t)
|
||||||
;(interpose "\n " (map 0 paths)))]))
|
(when (mod-filter chk path)
|
||||||
|
(expand-path-name t name path))))
|
||||||
|
paths (filter identity (map expander module/paths))
|
||||||
|
str-parts (interpose "\n " paths)]
|
||||||
|
[nil (string "could not find module " path ":\n " ;str-parts)])))
|
||||||
|
|
||||||
(put _env 'fexists nil)
|
(put _env 'fexists nil)
|
||||||
|
(put _env 'nati nil)
|
||||||
|
(put _env 'expand-path-name nil)
|
||||||
|
(put _env 'mod-filter nil)
|
||||||
|
|
||||||
(def module/cache
|
(def module/cache
|
||||||
"Table mapping loaded module identifiers to their environments."
|
"Table mapping loaded module identifiers to their environments."
|
||||||
@@ -1646,47 +1686,64 @@
|
|||||||
circular dependencies."
|
circular dependencies."
|
||||||
@{})
|
@{})
|
||||||
|
|
||||||
|
(defn dofile
|
||||||
|
"Evaluate a file and return the resulting environment."
|
||||||
|
[path & args]
|
||||||
|
(def {:exit exit-on-error
|
||||||
|
:source source
|
||||||
|
:env env
|
||||||
|
:compile-only compile-only} (table ;args))
|
||||||
|
(def f (if (= (type path) :core/file)
|
||||||
|
path
|
||||||
|
(file/open path)))
|
||||||
|
(default env (make-env))
|
||||||
|
(defn chunks [buf _] (file/read f 2048 buf))
|
||||||
|
(defn bp [&opt x y]
|
||||||
|
(def ret (bad-parse x y))
|
||||||
|
(if exit-on-error (os/exit 1))
|
||||||
|
ret)
|
||||||
|
(defn bc [&opt x y z]
|
||||||
|
(def ret (bad-compile x y z))
|
||||||
|
(if exit-on-error (os/exit 1))
|
||||||
|
ret)
|
||||||
|
(run-context {:env env
|
||||||
|
:chunks chunks
|
||||||
|
:on-parse-error bp
|
||||||
|
:on-compile-error bc
|
||||||
|
:on-status (fn [f x]
|
||||||
|
(when (not= (fiber/status f) :dead)
|
||||||
|
(debug/stacktrace f x)
|
||||||
|
(if exit-on-error (os/exit 1))))
|
||||||
|
:compile-only compile-only
|
||||||
|
:source (or source (if (= f path) "<anonymous>" path))})
|
||||||
|
(when (not= f path) (file/close f))
|
||||||
|
env)
|
||||||
|
|
||||||
|
(def module/loaders
|
||||||
|
"A table of loading method names to loading functions.
|
||||||
|
This table lets require and import load many different kinds
|
||||||
|
of files as module."
|
||||||
|
@{:native (fn [path &] (native path (make-env)))
|
||||||
|
:source (fn [path args]
|
||||||
|
(put module/loading path true)
|
||||||
|
(def newenv (dofile path ;args))
|
||||||
|
(put module/loading path nil)
|
||||||
|
newenv)
|
||||||
|
:image (fn [path &] (load-image (slurp path)))})
|
||||||
|
|
||||||
(defn require
|
(defn require
|
||||||
"Require a module with the given name. Will search all of the paths in
|
"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
|
module/paths, then the path as a raw file path. Returns the new environment
|
||||||
returned from compiling and running the file."
|
returned from compiling and running the file."
|
||||||
[path & args]
|
[path & args]
|
||||||
(def {:exit exit-on-error} (table ;args))
|
|
||||||
(if-let [check (get module/cache path)]
|
(if-let [check (get module/cache path)]
|
||||||
check
|
check
|
||||||
(do
|
(do
|
||||||
(def [fullpath mod-kind] (module/find path))
|
(def [fullpath mod-kind] (module/find path))
|
||||||
(unless fullpath (error mod-kind))
|
(unless fullpath (error mod-kind))
|
||||||
(def env
|
(def loader (module/loaders mod-kind))
|
||||||
(case mod-kind
|
(unless loader (error (string "module type " mod-kind " unknown")))
|
||||||
:source (do
|
(def env (loader fullpath args))
|
||||||
# Normal janet module
|
|
||||||
(def f (file/open fullpath))
|
|
||||||
(def newenv (make-env))
|
|
||||||
(put module/loading fullpath true)
|
|
||||||
(defn chunks [buf _] (file/read f 2048 buf))
|
|
||||||
(defn bp [&opt x y]
|
|
||||||
(def ret (bad-parse x y))
|
|
||||||
(if exit-on-error (os/exit 1))
|
|
||||||
ret)
|
|
||||||
(defn bc [&opt x y z]
|
|
||||||
(def ret (bad-compile x y z))
|
|
||||||
(if exit-on-error (os/exit 1))
|
|
||||||
ret)
|
|
||||||
(run-context {:env newenv
|
|
||||||
:chunks chunks
|
|
||||||
:on-parse-error bp
|
|
||||||
:on-compile-error bc
|
|
||||||
:on-status (fn [f x]
|
|
||||||
(when (not= (fiber/status f) :dead)
|
|
||||||
(debug/stacktrace f x)
|
|
||||||
(if exit-on-error (os/exit 1))))
|
|
||||||
:source fullpath})
|
|
||||||
(file/close f)
|
|
||||||
(put module/loading fullpath nil)
|
|
||||||
(table/setproto newenv nil))
|
|
||||||
:native (native fullpath (make-env))
|
|
||||||
:image (load-image (slurp fullpath))))
|
|
||||||
(put module/cache fullpath env)
|
(put module/cache fullpath env)
|
||||||
(put module/cache path env)
|
(put module/cache path env)
|
||||||
env)))
|
env)))
|
||||||
@@ -1710,7 +1767,9 @@
|
|||||||
symbols into the current environment, prepending a given prefix as needed.
|
symbols into the current environment, prepending a given prefix as needed.
|
||||||
(use the :as or :prefix option to set a prefix). If no prefix is provided,
|
(use the :as or :prefix option to set a prefix). If no prefix is provided,
|
||||||
use the name of the module as a prefix. One can also use :export true
|
use the name of the module as a prefix. One can also use :export true
|
||||||
to re-export the imported symbols."
|
to re-export the imported symbols. If :exit true is given as an argument,
|
||||||
|
any errors encountered at the top level in the module will cause (os/exit 1)
|
||||||
|
to be called."
|
||||||
[path & args]
|
[path & args]
|
||||||
(def argm (map (fn [x]
|
(def argm (map (fn [x]
|
||||||
(if (keyword? x)
|
(if (keyword? x)
|
||||||
@@ -1727,6 +1786,11 @@
|
|||||||
[&opt chunks onsignal env]
|
[&opt chunks onsignal env]
|
||||||
(def level (+ (dyn :debug-level 0) 1))
|
(def level (+ (dyn :debug-level 0) 1))
|
||||||
(default env (make-env))
|
(default env (make-env))
|
||||||
|
(default chunks (fn [buf p] (getline (string "repl:"
|
||||||
|
(parser/where p)
|
||||||
|
":"
|
||||||
|
(parser/state p) "> ")
|
||||||
|
buf)))
|
||||||
(default onsignal (fn [f x]
|
(default onsignal (fn [f x]
|
||||||
(case (fiber/status f)
|
(case (fiber/status f)
|
||||||
:dead (do
|
:dead (do
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ static const JanetReg array_cfuns[] = {
|
|||||||
{
|
{
|
||||||
"array/ensure", cfun_array_ensure,
|
"array/ensure", cfun_array_ensure,
|
||||||
JDOC("(array/ensure arr capacity)\n\n"
|
JDOC("(array/ensure arr capacity)\n\n"
|
||||||
"Ensures that the memory backing the array has enough memory for capacity "
|
"Ensures that the memory backing the array is large enough for capacity "
|
||||||
"items. Capacity must be an integer. If the backing capacity is already enough, "
|
"items. Capacity must be an integer. If the backing capacity is already enough, "
|
||||||
"then this function does nothing. Otherwise, the backing memory will be reallocated "
|
"then this function does nothing. Otherwise, the backing memory will be reallocated "
|
||||||
"so that there is enough space.")
|
"so that there is enough space.")
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "emit.h"
|
#include "emit.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "state.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JanetFopts janetc_fopts_default(JanetCompiler *c) {
|
JanetFopts janetc_fopts_default(JanetCompiler *c) {
|
||||||
@@ -716,8 +717,12 @@ JanetCompileResult janet_compile(Janet source, JanetTable *env, const uint8_t *w
|
|||||||
|
|
||||||
/* C Function for compiling */
|
/* C Function for compiling */
|
||||||
static Janet cfun(int32_t argc, Janet *argv) {
|
static Janet cfun(int32_t argc, Janet *argv) {
|
||||||
janet_arity(argc, 2, 3);
|
janet_arity(argc, 1, 3);
|
||||||
JanetTable *env = janet_gettable(argv, 1);
|
JanetTable *env = argc > 1 ? janet_gettable(argv, 1) : janet_vm_fiber->env;
|
||||||
|
if (NULL == env) {
|
||||||
|
env = janet_table(0);
|
||||||
|
janet_vm_fiber->env = env;
|
||||||
|
}
|
||||||
const uint8_t *source = NULL;
|
const uint8_t *source = NULL;
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
source = janet_getstring(argv, 2);
|
source = janet_getstring(argv, 2);
|
||||||
@@ -740,7 +745,7 @@ static Janet cfun(int32_t argc, Janet *argv) {
|
|||||||
static const JanetReg compile_cfuns[] = {
|
static const JanetReg compile_cfuns[] = {
|
||||||
{
|
{
|
||||||
"compile", cfun,
|
"compile", cfun,
|
||||||
JDOC("(compile ast env [, source])\n\n"
|
JDOC("(compile ast &opt env source)\n\n"
|
||||||
"Compiles an Abstract Syntax Tree (ast) into a janet function. "
|
"Compiles an Abstract Syntax Tree (ast) into a janet function. "
|
||||||
"Pair the compile function with parsing functionality to implement "
|
"Pair the compile function with parsing functionality to implement "
|
||||||
"eval. Returns a janet function and does not modify ast. Throws an "
|
"eval. Returns a janet function and does not modify ast. Throws an "
|
||||||
|
|||||||
@@ -57,13 +57,37 @@ typedef void *Clib;
|
|||||||
JanetModule janet_native(const char *name, const uint8_t **error) {
|
JanetModule janet_native(const char *name, const uint8_t **error) {
|
||||||
Clib lib = load_clib(name);
|
Clib lib = load_clib(name);
|
||||||
JanetModule init;
|
JanetModule init;
|
||||||
|
JanetModconf getter;
|
||||||
if (!lib) {
|
if (!lib) {
|
||||||
*error = janet_cstring(error_clib());
|
*error = janet_cstring(error_clib());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
init = (JanetModule) symbol_clib(lib, "_janet_init");
|
init = (JanetModule) symbol_clib(lib, "_janet_init");
|
||||||
if (!init) {
|
if (!init) {
|
||||||
*error = janet_cstring("could not find _janet_init symbol");
|
*error = janet_cstring("could not find the _janet_init symbol");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
getter = (JanetModconf) symbol_clib(lib, "_janet_mod_config");
|
||||||
|
if (!getter) {
|
||||||
|
*error = janet_cstring("could not find the _janet_mod_config symbol");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
JanetBuildConfig modconf = getter();
|
||||||
|
JanetBuildConfig host = janet_config_current();
|
||||||
|
if (host.major != modconf.major ||
|
||||||
|
host.minor < modconf.minor ||
|
||||||
|
host.bits != modconf.bits) {
|
||||||
|
char errbuf[128];
|
||||||
|
sprintf(errbuf, "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
|
||||||
|
host.major,
|
||||||
|
host.minor,
|
||||||
|
host.patch,
|
||||||
|
host.bits,
|
||||||
|
modconf.major,
|
||||||
|
modconf.minor,
|
||||||
|
modconf.patch,
|
||||||
|
modconf.bits);
|
||||||
|
*error = janet_cstring(errbuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return init;
|
return init;
|
||||||
@@ -653,7 +677,7 @@ static void make_apply(JanetTable *env) {
|
|||||||
"be an array-like. Each element in this last argument is then also pushed as an argument to "
|
"be an array-like. Each element in this last argument is then also pushed as an argument to "
|
||||||
"f. For example:\n\n"
|
"f. For example:\n\n"
|
||||||
"\t(apply + 1000 (range 10))\n\n"
|
"\t(apply + 1000 (range 10))\n\n"
|
||||||
"sums the first 10 integers and 1000.)"));
|
"sums the first 10 integers and 1000."));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32_t error_asm[] = {
|
static const uint32_t error_asm[] = {
|
||||||
@@ -830,6 +854,9 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
|||||||
JDOC("The version number of the running janet program."));
|
JDOC("The version number of the running janet program."));
|
||||||
janet_def(env, "janet/build", janet_cstringv(JANET_BUILD),
|
janet_def(env, "janet/build", janet_cstringv(JANET_BUILD),
|
||||||
JDOC("The build identifier of the running janet program."));
|
JDOC("The build identifier of the running janet program."));
|
||||||
|
janet_def(env, "janet/config-bits", janet_wrap_integer(JANET_CURRENT_CONFIG_BITS),
|
||||||
|
JDOC("The flag set of config options from janetconf.h which is used to check "
|
||||||
|
"if native modules are compatible with the host program."));
|
||||||
|
|
||||||
/* Allow references to the environment */
|
/* Allow references to the environment */
|
||||||
janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope."));
|
janet_def(env, "_env", janet_wrap_table(env), JDOC("The environment table for the current scope."));
|
||||||
|
|||||||
@@ -239,11 +239,11 @@ void janetc_copy(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Process: src -> near -> dest */
|
/* Process: src -> near -> dest */
|
||||||
int32_t near = janetc_allocnear(c, JANETC_REGTEMP_3);
|
int32_t nearreg = janetc_allocnear(c, JANETC_REGTEMP_3);
|
||||||
janetc_movenear(c, near, src);
|
janetc_movenear(c, nearreg, src);
|
||||||
janetc_moveback(c, dest, near);
|
janetc_moveback(c, dest, nearreg);
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
janetc_regalloc_freetemp(&c->scope->ra, near, JANETC_REGTEMP_3);
|
janetc_regalloc_freetemp(&c->scope->ra, nearreg, JANETC_REGTEMP_3);
|
||||||
|
|
||||||
}
|
}
|
||||||
/* Instruction templated emitters */
|
/* Instruction templated emitters */
|
||||||
|
|||||||
@@ -127,6 +127,16 @@ void janet_fiber_pushn(JanetFiber *fiber, const Janet *arr, int32_t n) {
|
|||||||
fiber->stacktop = newtop;
|
fiber->stacktop = newtop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a struct with n values. If n is odd, the last value is ignored. */
|
||||||
|
static Janet make_struct_n(const Janet *args, int32_t n) {
|
||||||
|
int32_t i = 0;
|
||||||
|
JanetKV *st = janet_struct_begin(n & (~1));
|
||||||
|
for (; i < n; i += 2) {
|
||||||
|
janet_struct_put(st, args[i], args[i + 1]);
|
||||||
|
}
|
||||||
|
return janet_wrap_struct(janet_struct_end(st));
|
||||||
|
}
|
||||||
|
|
||||||
/* Push a stack frame to a fiber */
|
/* Push a stack frame to a fiber */
|
||||||
int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
||||||
JanetStackFrame *newframe;
|
JanetStackFrame *newframe;
|
||||||
@@ -164,12 +174,19 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
|||||||
/* Check varargs */
|
/* Check varargs */
|
||||||
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
||||||
int32_t tuplehead = fiber->frame + func->def->arity;
|
int32_t tuplehead = fiber->frame + func->def->arity;
|
||||||
|
int st = func->def->flags & JANET_FUNCDEF_FLAG_STRUCTARG;
|
||||||
if (tuplehead >= oldtop) {
|
if (tuplehead >= oldtop) {
|
||||||
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(NULL, 0));
|
fiber->data[tuplehead] = st
|
||||||
|
? make_struct_n(NULL, 0)
|
||||||
|
: janet_wrap_tuple(janet_tuple_n(NULL, 0));
|
||||||
} else {
|
} else {
|
||||||
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(
|
fiber->data[tuplehead] = st
|
||||||
|
? make_struct_n(
|
||||||
fiber->data + tuplehead,
|
fiber->data + tuplehead,
|
||||||
oldtop - tuplehead));
|
oldtop - tuplehead)
|
||||||
|
: janet_wrap_tuple(janet_tuple_n(
|
||||||
|
fiber->data + tuplehead,
|
||||||
|
oldtop - tuplehead));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,14 +237,21 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
|
|||||||
/* Check varargs */
|
/* Check varargs */
|
||||||
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
if (func->def->flags & JANET_FUNCDEF_FLAG_VARARG) {
|
||||||
int32_t tuplehead = fiber->stackstart + func->def->arity;
|
int32_t tuplehead = fiber->stackstart + func->def->arity;
|
||||||
|
int st = func->def->flags & JANET_FUNCDEF_FLAG_STRUCTARG;
|
||||||
if (tuplehead >= fiber->stacktop) {
|
if (tuplehead >= fiber->stacktop) {
|
||||||
if (tuplehead >= fiber->capacity) janet_fiber_setcapacity(fiber, 2 * (tuplehead + 1));
|
if (tuplehead >= fiber->capacity) janet_fiber_setcapacity(fiber, 2 * (tuplehead + 1));
|
||||||
for (i = fiber->stacktop; i < tuplehead; ++i) fiber->data[i] = janet_wrap_nil();
|
for (i = fiber->stacktop; i < tuplehead; ++i) fiber->data[i] = janet_wrap_nil();
|
||||||
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(NULL, 0));
|
fiber->data[tuplehead] = st
|
||||||
|
? make_struct_n(NULL, 0)
|
||||||
|
: janet_wrap_tuple(janet_tuple_n(NULL, 0));
|
||||||
} else {
|
} else {
|
||||||
fiber->data[tuplehead] = janet_wrap_tuple(janet_tuple_n(
|
fiber->data[tuplehead] = st
|
||||||
|
? make_struct_n(
|
||||||
fiber->data + tuplehead,
|
fiber->data + tuplehead,
|
||||||
fiber->stacktop - tuplehead));
|
fiber->stacktop - tuplehead)
|
||||||
|
: janet_wrap_tuple(janet_tuple_n(
|
||||||
|
fiber->data + tuplehead,
|
||||||
|
fiber->stacktop - tuplehead));
|
||||||
}
|
}
|
||||||
stacksize = tuplehead - fiber->stackstart + 1;
|
stacksize = tuplehead - fiber->stackstart + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef JANET_WINDOWS
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IO_WRITE 1
|
#define IO_WRITE 1
|
||||||
#define IO_READ 2
|
#define IO_READ 2
|
||||||
#define IO_APPEND 4
|
#define IO_APPEND 4
|
||||||
@@ -160,7 +164,7 @@ static Janet cfun_io_fopen(int32_t argc, Janet *argv) {
|
|||||||
return f ? makef(f, flags) : janet_wrap_nil();
|
return f ? makef(f, flags) : janet_wrap_nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read up to n bytes into buffer. Return error string if error. */
|
/* Read up to n bytes into buffer. */
|
||||||
static void read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) {
|
static void read_chunk(IOFile *iof, JanetBuffer *buffer, int32_t nBytesMax) {
|
||||||
if (!(iof->flags & (IO_READ | IO_UPDATE)))
|
if (!(iof->flags & (IO_READ | IO_UPDATE)))
|
||||||
janet_panic("file is not readable");
|
janet_panic("file is not readable");
|
||||||
@@ -183,6 +187,7 @@ static Janet cfun_io_fread(int32_t argc, Janet *argv) {
|
|||||||
} else {
|
} else {
|
||||||
buffer = janet_getbuffer(argv, 2);
|
buffer = janet_getbuffer(argv, 2);
|
||||||
}
|
}
|
||||||
|
int32_t bufstart = buffer->count;
|
||||||
if (janet_checktype(argv[1], JANET_KEYWORD)) {
|
if (janet_checktype(argv[1], JANET_KEYWORD)) {
|
||||||
const uint8_t *sym = janet_unwrap_keyword(argv[1]);
|
const uint8_t *sym = janet_unwrap_keyword(argv[1]);
|
||||||
if (!janet_cstrcmp(sym, "all")) {
|
if (!janet_cstrcmp(sym, "all")) {
|
||||||
@@ -207,6 +212,8 @@ static Janet cfun_io_fread(int32_t argc, Janet *argv) {
|
|||||||
fseek(iof->file, 0, SEEK_SET);
|
fseek(iof->file, 0, SEEK_SET);
|
||||||
read_chunk(iof, buffer, (int32_t) fsize);
|
read_chunk(iof, buffer, (int32_t) fsize);
|
||||||
}
|
}
|
||||||
|
/* Never return nil for :all */
|
||||||
|
return janet_wrap_buffer(buffer);
|
||||||
} else if (!janet_cstrcmp(sym, "line")) {
|
} else if (!janet_cstrcmp(sym, "line")) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int x = fgetc(iof->file);
|
int x = fgetc(iof->file);
|
||||||
@@ -221,6 +228,7 @@ static Janet cfun_io_fread(int32_t argc, Janet *argv) {
|
|||||||
if (len < 0) janet_panic("expected positive integer");
|
if (len < 0) janet_panic("expected positive integer");
|
||||||
read_chunk(iof, buffer, len);
|
read_chunk(iof, buffer, len);
|
||||||
}
|
}
|
||||||
|
if (bufstart == buffer->count) return janet_wrap_nil();
|
||||||
return janet_wrap_buffer(buffer);
|
return janet_wrap_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,13 +289,17 @@ static Janet cfun_io_fclose(int32_t argc, Janet *argv) {
|
|||||||
if (iof->flags & IO_PIPED) {
|
if (iof->flags & IO_PIPED) {
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
#define pclose _pclose
|
#define pclose _pclose
|
||||||
|
#define WEXITSTATUS(x) x
|
||||||
#endif
|
#endif
|
||||||
if (pclose(iof->file)) janet_panic("could not close file");
|
int status = pclose(iof->file);
|
||||||
|
iof->flags |= IO_CLOSED;
|
||||||
|
if (status == -1) janet_panic("could not close file");
|
||||||
|
return janet_wrap_integer(WEXITSTATUS(status));
|
||||||
} else {
|
} else {
|
||||||
if (fclose(iof->file)) janet_panic("could not close file");
|
if (fclose(iof->file)) janet_panic("could not close file");
|
||||||
|
iof->flags |= IO_CLOSED;
|
||||||
|
return janet_wrap_nil();
|
||||||
}
|
}
|
||||||
iof->flags |= IO_CLOSED;
|
|
||||||
return argv[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Seek a file */
|
/* Seek a file */
|
||||||
|
|||||||
243
src/core/os.c
243
src/core/os.c
@@ -41,7 +41,9 @@
|
|||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <sys/utime.h>
|
#include <sys/utime.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
#include <process.h>
|
||||||
#else
|
#else
|
||||||
|
#include <spawn.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@@ -88,7 +90,7 @@ static Janet os_exit(int32_t argc, Janet *argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JANET_REDUCED_OS
|
#ifdef JANET_REDUCED_OS
|
||||||
/* Provide a dud os/getenv so init.janet works, but nothing else */
|
/* Provide a dud os/getenv so boot.janet and init.janet work, but nothing else */
|
||||||
|
|
||||||
static Janet os_getenv(int32_t argc, Janet *argv) {
|
static Janet os_getenv(int32_t argc, Janet *argv) {
|
||||||
(void) argv;
|
(void) argv;
|
||||||
@@ -99,97 +101,152 @@ static Janet os_getenv(int32_t argc, Janet *argv) {
|
|||||||
#else
|
#else
|
||||||
/* Provide full os functionality */
|
/* Provide full os functionality */
|
||||||
|
|
||||||
#ifdef JANET_WINDOWS
|
#define JANET_OS_EFLAG_E 0x1
|
||||||
static Janet os_execute(int32_t argc, Janet *argv) {
|
#define JANET_OS_EFLAG_P 0x2
|
||||||
janet_arity(argc, 1, -1);
|
|
||||||
JanetBuffer *buffer = janet_buffer(10);
|
/* Get flags */
|
||||||
for (int32_t i = 0; i < argc; i++) {
|
/* Unfortunately, execvpe is linux (glibc) only. Instead, we can switch
|
||||||
const uint8_t *argstring = janet_getstring(argv, i);
|
* between the more portable execve, execvp, or execv.
|
||||||
janet_buffer_push_bytes(buffer, argstring, janet_string_length(argstring));
|
* Use the :e or :p flag for execve and execvp respectively. Eventually
|
||||||
if (i != argc - 1) {
|
* :ep or :pe could be execvpe. */
|
||||||
janet_buffer_push_u8(buffer, ' ');
|
static int os_execute_flags(int32_t argc, const Janet *argv) {
|
||||||
|
if (argc < 2) return 0;
|
||||||
|
int flags = 0;
|
||||||
|
if (argc > 1) {
|
||||||
|
const uint8_t *f = janet_getkeyword(argv, 1);
|
||||||
|
int32_t len = janet_string_length(f);
|
||||||
|
for (int32_t i = 0; i < len; i++) {
|
||||||
|
if (f[i] == 'e') flags |= JANET_OS_EFLAG_E;
|
||||||
|
if (f[i] == 'p') flags |= JANET_OS_EFLAG_P;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
janet_buffer_push_u8(buffer, 0);
|
return flags;
|
||||||
|
|
||||||
/* Convert to wide chars */
|
|
||||||
wchar_t *sys_str = malloc(buffer->count * sizeof(wchar_t));
|
|
||||||
if (NULL == sys_str) {
|
|
||||||
JANET_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
int nwritten = MultiByteToWideChar(
|
|
||||||
CP_UTF8,
|
|
||||||
MB_PRECOMPOSED,
|
|
||||||
buffer->data,
|
|
||||||
buffer->count,
|
|
||||||
sys_str,
|
|
||||||
buffer->count);
|
|
||||||
if (nwritten == 0) {
|
|
||||||
free(sys_str);
|
|
||||||
janet_panic("could not create process");
|
|
||||||
}
|
|
||||||
|
|
||||||
STARTUPINFO si;
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
|
|
||||||
ZeroMemory(&si, sizeof(si));
|
|
||||||
si.cb = sizeof(si);
|
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
|
||||||
|
|
||||||
// Start the child process.
|
|
||||||
if (!CreateProcess(NULL,
|
|
||||||
(LPSTR) sys_str,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
FALSE,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&si,
|
|
||||||
&pi)) {
|
|
||||||
free(sys_str);
|
|
||||||
janet_panic("could not create process");
|
|
||||||
}
|
|
||||||
free(sys_str);
|
|
||||||
|
|
||||||
// Wait until child process exits.
|
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
||||||
|
|
||||||
// Close process and thread handles.
|
|
||||||
WORD status;
|
|
||||||
GetExitCodeProcess(pi.hProcess, (LPDWORD)&status);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
return janet_wrap_integer(status);
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
/* Get env for os_execute (execv family of functions, as well as CreateProcess) */
|
||||||
|
static char **os_execute_env(int32_t argc, const Janet *argv) {
|
||||||
|
char **envp = NULL;
|
||||||
|
if (argc > 2) {
|
||||||
|
JanetDictView dict = janet_getdictionary(argv, 2);
|
||||||
|
envp = malloc(sizeof(char *) * (dict.len + 1));
|
||||||
|
if (NULL == envp) {
|
||||||
|
JANET_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
int32_t j = 0;
|
||||||
|
for (int32_t i = 0; i < dict.cap; i++) {
|
||||||
|
const JanetKV *kv = dict.kvs + i;
|
||||||
|
if (!janet_checktype(kv->key, JANET_STRING)) continue;
|
||||||
|
if (!janet_checktype(kv->value, JANET_STRING)) continue;
|
||||||
|
const uint8_t *keys = janet_unwrap_string(kv->key);
|
||||||
|
const uint8_t *vals = janet_unwrap_string(kv->value);
|
||||||
|
int32_t klen = janet_string_length(keys);
|
||||||
|
int32_t vlen = janet_string_length(vals);
|
||||||
|
/* Check keys has no embedded 0s or =s. */
|
||||||
|
int skip = 0;
|
||||||
|
for (int32_t k = 0; k < klen; k++) {
|
||||||
|
if (keys[k] == '\0' || keys[k] == '=') {
|
||||||
|
skip = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) continue;
|
||||||
|
char *envitem = malloc(klen + vlen + 2);
|
||||||
|
if (NULL == envitem) {
|
||||||
|
JANET_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
memcpy(envitem, keys, klen);
|
||||||
|
envitem[klen] = '=';
|
||||||
|
memcpy(envitem + klen + 1, vals, vlen);
|
||||||
|
envitem[klen + vlen + 1] = 0;
|
||||||
|
envp[j++] = envitem;
|
||||||
|
}
|
||||||
|
envp[j] = NULL;
|
||||||
|
}
|
||||||
|
return envp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free memory from os_execute */
|
||||||
|
static void os_execute_cleanup(char **envp, const char **child_argv) {
|
||||||
|
free((void *)child_argv);
|
||||||
|
if (NULL != envp) {
|
||||||
|
char **envitem = envp;
|
||||||
|
while (*envitem != NULL) {
|
||||||
|
free(*envitem);
|
||||||
|
envitem++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(envp);
|
||||||
|
}
|
||||||
|
|
||||||
static Janet os_execute(int32_t argc, Janet *argv) {
|
static Janet os_execute(int32_t argc, Janet *argv) {
|
||||||
janet_arity(argc, 1, -1);
|
janet_arity(argc, 1, 3);
|
||||||
const char **child_argv = malloc(sizeof(char *) * (argc + 1));
|
|
||||||
|
/* Get arguments */
|
||||||
|
JanetView exargs = janet_getindexed(argv, 0);
|
||||||
|
const char **child_argv = malloc(sizeof(char *) * (exargs.len + 1));
|
||||||
int status = 0;
|
int status = 0;
|
||||||
if (NULL == child_argv) {
|
if (NULL == child_argv) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
for (int32_t i = 0; i < argc; i++) {
|
for (int32_t i = 0; i < exargs.len; i++) {
|
||||||
child_argv[i] = janet_getcstring(argv, i);
|
child_argv[i] = janet_getcstring(exargs.items, i);
|
||||||
}
|
}
|
||||||
child_argv[argc] = NULL;
|
child_argv[exargs.len] = NULL;
|
||||||
|
|
||||||
/* Fork child process */
|
/* Get flags */
|
||||||
pid_t pid = fork();
|
int flags = os_execute_flags(argc, argv);
|
||||||
if (pid < 0) {
|
|
||||||
janet_panic("failed to execute");
|
/* Get environment */
|
||||||
} else if (pid == 0) {
|
char **envp = os_execute_env(argc, argv);
|
||||||
if (-1 == execve(child_argv[0], (char **)child_argv, NULL)) {
|
|
||||||
exit(1);
|
/* Coerce to form that works for spawn. I'm fairly confident no implementation
|
||||||
}
|
* of posix_spawn would modify the argv array passed in. */
|
||||||
|
char *const *cargv = (char *const *)child_argv;
|
||||||
|
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
|
||||||
|
/* Use _spawn family of functions. */
|
||||||
|
/* Windows docs say do this before any spawns. */
|
||||||
|
_flushall();
|
||||||
|
|
||||||
|
if (flags & (JANET_OS_EFLAG_P | JANET_OS_EFLAG_E)) {
|
||||||
|
status = (int) _spawnvpe(_P_WAIT, child_argv[0], cargv, envp);
|
||||||
|
} else if (flags & JANET_OS_EFLAG_P) {
|
||||||
|
status = (int) _spawnvp(_P_WAIT, child_argv[0], cargv);
|
||||||
|
} else if (flags & JANET_OS_EFLAG_E) {
|
||||||
|
status = (int) _spawnve(_P_WAIT, child_argv[0], cargv, envp);
|
||||||
|
} else {
|
||||||
|
status = (int) _spawnv(_P_WAIT, child_argv[0], cargv);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_execute_cleanup(envp, child_argv);
|
||||||
|
return janet_wrap_integer(status);
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Use posix_spawn to spawn new process */
|
||||||
|
pid_t pid;
|
||||||
|
if (flags & JANET_OS_EFLAG_P) {
|
||||||
|
status = posix_spawnp(&pid,
|
||||||
|
child_argv[0], NULL, NULL, cargv,
|
||||||
|
(flags & JANET_OS_EFLAG_E) ? envp : NULL);
|
||||||
|
} else {
|
||||||
|
status = posix_spawn(&pid,
|
||||||
|
child_argv[0], NULL, NULL, cargv,
|
||||||
|
(flags & JANET_OS_EFLAG_E) ? envp : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for child */
|
||||||
|
if (status) {
|
||||||
|
os_execute_cleanup(envp, child_argv);
|
||||||
|
janet_panic(strerror(status));
|
||||||
} else {
|
} else {
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
}
|
}
|
||||||
free(child_argv);
|
|
||||||
return janet_wrap_integer(status);
|
os_execute_cleanup(envp, child_argv);
|
||||||
}
|
return janet_wrap_integer(WEXITSTATUS(status));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static Janet os_shell(int32_t argc, Janet *argv) {
|
static Janet os_shell(int32_t argc, Janet *argv) {
|
||||||
janet_arity(argc, 0, 1);
|
janet_arity(argc, 0, 1);
|
||||||
@@ -607,6 +664,17 @@ static Janet os_dir(int32_t argc, Janet *argv) {
|
|||||||
return janet_wrap_array(paths);
|
return janet_wrap_array(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Janet os_rename(int32_t argc, Janet *argv) {
|
||||||
|
janet_fixarity(argc, 2);
|
||||||
|
const char *src = janet_getcstring(argv, 0);
|
||||||
|
const char *dest = janet_getcstring(argv, 1);
|
||||||
|
int status = rename(src, dest);
|
||||||
|
if (status) {
|
||||||
|
janet_panic(strerror(errno));
|
||||||
|
}
|
||||||
|
return janet_wrap_nil();
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* JANET_REDUCED_OS */
|
#endif /* JANET_REDUCED_OS */
|
||||||
|
|
||||||
static const JanetReg os_cfuns[] = {
|
static const JanetReg os_cfuns[] = {
|
||||||
@@ -632,7 +700,7 @@ static const JanetReg os_cfuns[] = {
|
|||||||
#ifndef JANET_REDUCED_OS
|
#ifndef JANET_REDUCED_OS
|
||||||
{
|
{
|
||||||
"os/dir", os_dir,
|
"os/dir", os_dir,
|
||||||
JDOC("(os/stat dir [, array])\n\n"
|
JDOC("(os/dir dir [, array])\n\n"
|
||||||
"Iterate over files and subdirectories in a directory. Returns an array of paths parts, "
|
"Iterate over files and subdirectories in a directory. Returns an array of paths parts, "
|
||||||
"with only the filename or directory name and no prefix.")
|
"with only the filename or directory name and no prefix.")
|
||||||
},
|
},
|
||||||
@@ -690,9 +758,15 @@ static const JanetReg os_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"os/execute", os_execute,
|
"os/execute", os_execute,
|
||||||
JDOC("(os/execute program & args)\n\n"
|
JDOC("(os/execute args &opts flags env)\n\n"
|
||||||
"Execute a program on the system and pass it string arguments. Returns "
|
"Execute a program on the system and pass it string arguments. Flags "
|
||||||
"the exit status of the program.")
|
"is a keyword that modifies how the program will execute.\n\n"
|
||||||
|
"\t:e - enables passing an environment to the program. Without :e, the "
|
||||||
|
"current environment is inherited.\n"
|
||||||
|
"\t:p - allows searching the current PATH for the binary to execute. "
|
||||||
|
"Without this flag, binaries must use absolute paths.\n\n"
|
||||||
|
"env is a table or struct mapping environment variables to values. "
|
||||||
|
"Returns the exit status of the program.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"os/shell", os_shell,
|
"os/shell", os_shell,
|
||||||
@@ -742,6 +816,11 @@ static const JanetReg os_cfuns[] = {
|
|||||||
"\t:year-day - day of the year [0-365]\n"
|
"\t:year-day - day of the year [0-365]\n"
|
||||||
"\t:dst - If Day Light Savings is in effect")
|
"\t:dst - If Day Light Savings is in effect")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"os/rename", os_rename,
|
||||||
|
JDOC("(os/rename oldname newname)\n\n"
|
||||||
|
"Rename a file on disk to a new path. Returns nil.")
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ static const JanetReg parse_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"parser/eof", cfun_parse_eof,
|
"parser/eof", cfun_parse_eof,
|
||||||
JDOC("(parser/insert parser)\n\n"
|
JDOC("(parser/eof parser)\n\n"
|
||||||
"Indicate that the end of file was reached to the parser. This puts the parser in the :dead state.")
|
"Indicate that the end of file was reached to the parser. This puts the parser in the :dead state.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -197,16 +197,15 @@ void janet_description_b(JanetBuffer *buffer, Janet x) {
|
|||||||
case JANET_STRING:
|
case JANET_STRING:
|
||||||
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
||||||
return;
|
return;
|
||||||
case JANET_BUFFER:
|
case JANET_BUFFER: {
|
||||||
{
|
JanetBuffer *b = janet_unwrap_buffer(x);
|
||||||
JanetBuffer *b = janet_unwrap_buffer(x);
|
if (b == buffer) {
|
||||||
if (b == buffer) {
|
/* Ensures buffer won't resize while escaping */
|
||||||
/* Ensures buffer won't resize while escaping */
|
janet_buffer_ensure(b, 5 * b->count + 3, 1);
|
||||||
janet_buffer_ensure(b, 5 * b->count + 3, 1);
|
|
||||||
}
|
|
||||||
janet_escape_buffer_b(buffer, b);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
janet_escape_buffer_b(buffer, b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
case JANET_ABSTRACT: {
|
case JANET_ABSTRACT: {
|
||||||
void *p = janet_unwrap_abstract(x);
|
void *p = janet_unwrap_abstract(x);
|
||||||
const JanetAbstractType *at = janet_abstract_type(p);
|
const JanetAbstractType *at = janet_abstract_type(p);
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ static int destructure(JanetCompiler *c,
|
|||||||
/* Create a source map for definitions. */
|
/* Create a source map for definitions. */
|
||||||
static const Janet *janetc_make_sourcemap(JanetCompiler *c) {
|
static const Janet *janetc_make_sourcemap(JanetCompiler *c) {
|
||||||
Janet *tup = janet_tuple_begin(3);
|
Janet *tup = janet_tuple_begin(3);
|
||||||
tup[0] = janet_wrap_string(c->source);
|
tup[0] = c->source ? janet_wrap_string(c->source) : janet_wrap_nil();
|
||||||
tup[1] = janet_wrap_integer(c->current_mapping.start);
|
tup[1] = janet_wrap_integer(c->current_mapping.start);
|
||||||
tup[2] = janet_wrap_integer(c->current_mapping.end);
|
tup[2] = janet_wrap_integer(c->current_mapping.end);
|
||||||
return janet_tuple_end(tup);
|
return janet_tuple_end(tup);
|
||||||
@@ -652,6 +652,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
|
|
||||||
/* Function flags */
|
/* Function flags */
|
||||||
int vararg = 0;
|
int vararg = 0;
|
||||||
|
int structarg = 0;
|
||||||
int allow_extra = 0;
|
int allow_extra = 0;
|
||||||
int selfref = 0;
|
int selfref = 0;
|
||||||
int seenamp = 0;
|
int seenamp = 0;
|
||||||
@@ -712,6 +713,19 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
min_arity = i;
|
min_arity = i;
|
||||||
arity--;
|
arity--;
|
||||||
seenopt = 1;
|
seenopt = 1;
|
||||||
|
} else if (!janet_cstrcmp(janet_unwrap_symbol(param), "&keys")) {
|
||||||
|
if (seenamp) {
|
||||||
|
errmsg = "&keys in unexpected location";
|
||||||
|
goto error;
|
||||||
|
} else if (i == paramcount - 2) {
|
||||||
|
vararg = 1;
|
||||||
|
structarg = 1;
|
||||||
|
arity -= 2;
|
||||||
|
} else {
|
||||||
|
errmsg = "&keys in unexpected location";
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
seenamp = 1;
|
||||||
} else {
|
} else {
|
||||||
janetc_nameslot(c, janet_unwrap_symbol(param), janetc_farslot(c));
|
janetc_nameslot(c, janet_unwrap_symbol(param), janetc_farslot(c));
|
||||||
}
|
}
|
||||||
@@ -749,6 +763,7 @@ static JanetSlot janetc_fn(JanetFopts opts, int32_t argn, const Janet *argv) {
|
|||||||
def->min_arity = min_arity;
|
def->min_arity = min_arity;
|
||||||
def->max_arity = max_arity;
|
def->max_arity = max_arity;
|
||||||
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
if (vararg) def->flags |= JANET_FUNCDEF_FLAG_VARARG;
|
||||||
|
if (structarg) def->flags |= JANET_FUNCDEF_FLAG_STRUCTARG;
|
||||||
|
|
||||||
if (selfref) def->name = janet_unwrap_symbol(head);
|
if (selfref) def->name = janet_unwrap_symbol(head);
|
||||||
defindex = janetc_addfuncdef(c, def);
|
defindex = janetc_addfuncdef(c, def);
|
||||||
|
|||||||
@@ -290,8 +290,8 @@ static Janet cfun_string_hassuffix(int32_t argc, Janet *argv) {
|
|||||||
return str.len < suffix.len
|
return str.len < suffix.len
|
||||||
? janet_wrap_false()
|
? janet_wrap_false()
|
||||||
: janet_wrap_boolean(memcmp(suffix.bytes,
|
: janet_wrap_boolean(memcmp(suffix.bytes,
|
||||||
str.bytes + str.len - suffix.len,
|
str.bytes + str.len - suffix.len,
|
||||||
suffix.len) == 0);
|
suffix.len) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Janet cfun_string_findall(int32_t argc, Janet *argv) {
|
static Janet cfun_string_findall(int32_t argc, Janet *argv) {
|
||||||
@@ -467,6 +467,60 @@ static Janet cfun_string_format(int32_t argc, Janet *argv) {
|
|||||||
return janet_stringv(buffer->data, buffer->count);
|
return janet_stringv(buffer->data, buffer->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int trim_help_checkset(JanetByteView set, uint8_t x) {
|
||||||
|
for (int32_t j = 0; j < set.len; j++)
|
||||||
|
if (set.bytes[j] == x)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t trim_help_leftedge(JanetByteView str, JanetByteView set) {
|
||||||
|
for (int32_t i = 0; i < str.len; i++)
|
||||||
|
if (!trim_help_checkset(set, str.bytes[i]))
|
||||||
|
return i;
|
||||||
|
return str.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t trim_help_rightedge(JanetByteView str, JanetByteView set) {
|
||||||
|
for (int32_t i = str.len - 1; i >= 0; i--)
|
||||||
|
if (!trim_help_checkset(set, str.bytes[i]))
|
||||||
|
return i + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trim_help_args(int32_t argc, Janet *argv, JanetByteView *str, JanetByteView *set) {
|
||||||
|
janet_arity(argc, 1, 2);
|
||||||
|
*str = janet_getbytes(argv, 0);
|
||||||
|
if (argc >= 2) {
|
||||||
|
*set = janet_getbytes(argv, 1);
|
||||||
|
} else {
|
||||||
|
set->bytes = (const uint8_t *)(" \t\r\n\v\f");
|
||||||
|
set->len = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Janet cfun_string_trim(int32_t argc, Janet *argv) {
|
||||||
|
JanetByteView str, set;
|
||||||
|
trim_help_args(argc, argv, &str, &set);
|
||||||
|
int32_t left_edge = trim_help_leftedge(str, set);
|
||||||
|
int32_t right_edge = trim_help_rightedge(str, set);
|
||||||
|
return janet_stringv(str.bytes + left_edge, right_edge - left_edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Janet cfun_string_triml(int32_t argc, Janet *argv) {
|
||||||
|
JanetByteView str, set;
|
||||||
|
trim_help_args(argc, argv, &str, &set);
|
||||||
|
int32_t left_edge = trim_help_leftedge(str, set);
|
||||||
|
return janet_stringv(str.bytes + left_edge, str.len - left_edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Janet cfun_string_trimr(int32_t argc, Janet *argv) {
|
||||||
|
JanetByteView str, set;
|
||||||
|
trim_help_args(argc, argv, &str, &set);
|
||||||
|
int32_t right_edge = trim_help_rightedge(str, set);
|
||||||
|
return janet_stringv(str.bytes, right_edge);
|
||||||
|
}
|
||||||
|
|
||||||
static const JanetReg string_cfuns[] = {
|
static const JanetReg string_cfuns[] = {
|
||||||
{
|
{
|
||||||
"string/slice", cfun_string_slice,
|
"string/slice", cfun_string_slice,
|
||||||
@@ -488,8 +542,8 @@ static const JanetReg string_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"string/from-bytes", cfun_string_frombytes,
|
"string/from-bytes", cfun_string_frombytes,
|
||||||
JDOC("(string/from-bytes byte-array)\n\n"
|
JDOC("(string/from-bytes &byte-vals)\n\n"
|
||||||
"Creates a string from an array of integers with byte values. All integers "
|
"Creates a string from integer params with byte values. All integers "
|
||||||
"will be coerced to the range of 1 byte 0-255.")
|
"will be coerced to the range of 1 byte 0-255.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -574,6 +628,24 @@ static const JanetReg string_cfuns[] = {
|
|||||||
"Similar to snprintf, but specialized for operating with janet. Returns "
|
"Similar to snprintf, but specialized for operating with janet. Returns "
|
||||||
"a new string.")
|
"a new string.")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"string/trim", cfun_string_trim,
|
||||||
|
JDOC("(string/trim str [,set])\n\n"
|
||||||
|
"Trim leading and trailing whitespace from a byte sequence. If the argument "
|
||||||
|
"set is provided, consider only characters in set to be whitespace.")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"string/triml", cfun_string_triml,
|
||||||
|
JDOC("(string/triml str [,set])\n\n"
|
||||||
|
"Trim leading whitespace from a byte sequence. If the argument "
|
||||||
|
"set is provided, consider only characters in set to be whitespace.")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"string/trimr", cfun_string_trimr,
|
||||||
|
JDOC("(string/trimr str [,set])\n\n"
|
||||||
|
"Trim trailing whitespace from a byte sequence. If the argument "
|
||||||
|
"set is provided, consider only characters in set to be whitespace.")
|
||||||
|
},
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -291,8 +291,9 @@ int janet_scan_number(
|
|||||||
if (*str == '.') {
|
if (*str == '.') {
|
||||||
if (seenpoint) goto error;
|
if (seenpoint) goto error;
|
||||||
seenpoint = 1;
|
seenpoint = 1;
|
||||||
|
} else {
|
||||||
|
seenadigit = 1;
|
||||||
}
|
}
|
||||||
seenadigit = 1;
|
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,23 @@ static Janet cfun_tuple_type(int32_t argc, Janet *argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Janet cfun_tuple_sourcemap(int32_t argc, Janet *argv) {
|
||||||
|
janet_fixarity(argc, 1);
|
||||||
|
const Janet *tup = janet_gettuple(argv, 0);
|
||||||
|
Janet contents[2];
|
||||||
|
contents[0] = janet_wrap_integer(janet_tuple_head(tup)->sm_start);
|
||||||
|
contents[1] = janet_wrap_integer(janet_tuple_head(tup)->sm_end);
|
||||||
|
return janet_wrap_tuple(janet_tuple_n(contents, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Janet cfun_tuple_setmap(int32_t argc, Janet *argv) {
|
||||||
|
janet_fixarity(argc, 3);
|
||||||
|
const Janet *tup = janet_gettuple(argv, 0);
|
||||||
|
janet_tuple_head(tup)->sm_start = janet_getinteger(argv, 1);
|
||||||
|
janet_tuple_head(tup)->sm_end = janet_getinteger(argv, 2);
|
||||||
|
return argv[0];
|
||||||
|
}
|
||||||
|
|
||||||
static const JanetReg tuple_cfuns[] = {
|
static const JanetReg tuple_cfuns[] = {
|
||||||
{
|
{
|
||||||
"tuple/brackets", cfun_tuple_brackets,
|
"tuple/brackets", cfun_tuple_brackets,
|
||||||
@@ -138,6 +155,20 @@ static const JanetReg tuple_cfuns[] = {
|
|||||||
"the time, but will print differently and be treated differently by "
|
"the time, but will print differently and be treated differently by "
|
||||||
"the compiler.")
|
"the compiler.")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"tuple/sourcemap", cfun_tuple_sourcemap,
|
||||||
|
JDOC("(tuple/sourcemap tup)\n\n"
|
||||||
|
"Returns the sourcemap metadata attached to a tuple. "
|
||||||
|
"The mapping is represented by a pair of byte offsets into the "
|
||||||
|
"the source code representing the start and end byte indices where "
|
||||||
|
"the tuple is. ")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tuple/setmap", cfun_tuple_setmap,
|
||||||
|
JDOC("(tuple/setmap tup start end)\n\n"
|
||||||
|
"Set the sourcemap metadata on a tuple. start and end should "
|
||||||
|
"be integers representing byte offsets into the file. Returns tup.")
|
||||||
|
},
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#ifndef JANET_UTIL_H_defined
|
#ifndef JANET_UTIL_H_defined
|
||||||
#define JANET_UTIL_H_defined
|
#define JANET_UTIL_H_defined
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#ifndef JANET_AMALG
|
#ifndef JANET_AMALG
|
||||||
#include <janet.h>
|
#include <janet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
149
src/core/vm.c
149
src/core/vm.c
@@ -57,83 +57,13 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
|||||||
/* How we dispatch instructions. By default, we use
|
/* How we dispatch instructions. By default, we use
|
||||||
* a switch inside an infinite loop. For GCC/clang, we use
|
* a switch inside an infinite loop. For GCC/clang, we use
|
||||||
* computed gotos. */
|
* computed gotos. */
|
||||||
#ifdef ____GNUC__
|
#ifdef __GNUC__
|
||||||
#define VM_START() { goto *op_lookup[first_opcode];
|
#define VM_START() { goto *op_lookup[first_opcode];
|
||||||
#define VM_END() }
|
#define VM_END() }
|
||||||
#define VM_OP(op) label_##op :
|
#define VM_OP(op) label_##op :
|
||||||
#define VM_DEFAULT() label_unknown_op:
|
#define VM_DEFAULT() label_unknown_op:
|
||||||
#define vm_next() goto *op_lookup[*pc & 0xFF]
|
#define vm_next() goto *op_lookup[*pc & 0xFF]
|
||||||
static void *op_lookup[255] = {
|
#define opcode (*pc & 0xFF)
|
||||||
&&label_JOP_NOOP,
|
|
||||||
&&label_JOP_ERROR,
|
|
||||||
&&label_JOP_TYPECHECK,
|
|
||||||
&&label_JOP_RETURN,
|
|
||||||
&&label_JOP_RETURN_NIL,
|
|
||||||
&&label_JOP_ADD_IMMEDIATE,
|
|
||||||
&&label_JOP_ADD,
|
|
||||||
&&label_JOP_SUBTRACT,
|
|
||||||
&&label_JOP_MULTIPLY_IMMEDIATE,
|
|
||||||
&&label_JOP_MULTIPLY,
|
|
||||||
&&label_JOP_DIVIDE_IMMEDIATE,
|
|
||||||
&&label_JOP_DIVIDE,
|
|
||||||
&&label_JOP_BAND,
|
|
||||||
&&label_JOP_BOR,
|
|
||||||
&&label_JOP_BXOR,
|
|
||||||
&&label_JOP_BNOT,
|
|
||||||
&&label_JOP_SHIFT_LEFT,
|
|
||||||
&&label_JOP_SHIFT_LEFT_IMMEDIATE,
|
|
||||||
&&label_JOP_SHIFT_RIGHT,
|
|
||||||
&&label_JOP_SHIFT_RIGHT_IMMEDIATE,
|
|
||||||
&&label_JOP_SHIFT_RIGHT_UNSIGNED,
|
|
||||||
&&label_JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE,
|
|
||||||
&&label_JOP_MOVE_FAR,
|
|
||||||
&&label_JOP_MOVE_NEAR,
|
|
||||||
&&label_JOP_JUMP,
|
|
||||||
&&label_JOP_JUMP_IF,
|
|
||||||
&&label_JOP_JUMP_IF_NOT,
|
|
||||||
&&label_JOP_GREATER_THAN,
|
|
||||||
&&label_JOP_GREATER_THAN_IMMEDIATE,
|
|
||||||
&&label_JOP_LESS_THAN,
|
|
||||||
&&label_JOP_LESS_THAN_IMMEDIATE,
|
|
||||||
&&label_JOP_EQUALS,
|
|
||||||
&&label_JOP_EQUALS_IMMEDIATE,
|
|
||||||
&&label_JOP_COMPARE,
|
|
||||||
&&label_JOP_LOAD_NIL,
|
|
||||||
&&label_JOP_LOAD_TRUE,
|
|
||||||
&&label_JOP_LOAD_FALSE,
|
|
||||||
&&label_JOP_LOAD_INTEGER,
|
|
||||||
&&label_JOP_LOAD_CONSTANT,
|
|
||||||
&&label_JOP_LOAD_UPVALUE,
|
|
||||||
&&label_JOP_LOAD_SELF,
|
|
||||||
&&label_JOP_SET_UPVALUE,
|
|
||||||
&&label_JOP_CLOSURE,
|
|
||||||
&&label_JOP_PUSH,
|
|
||||||
&&label_JOP_PUSH_2,
|
|
||||||
&&label_JOP_PUSH_3,
|
|
||||||
&&label_JOP_PUSH_ARRAY,
|
|
||||||
&&label_JOP_CALL,
|
|
||||||
&&label_JOP_TAILCALL,
|
|
||||||
&&label_JOP_RESUME,
|
|
||||||
&&label_JOP_SIGNAL,
|
|
||||||
&&label_JOP_GET,
|
|
||||||
&&label_JOP_PUT,
|
|
||||||
&&label_JOP_GET_INDEX,
|
|
||||||
&&label_JOP_PUT_INDEX,
|
|
||||||
&&label_JOP_LENGTH,
|
|
||||||
&&label_JOP_MAKE_ARRAY,
|
|
||||||
&&label_JOP_MAKE_BUFFER,
|
|
||||||
&&label_JOP_MAKE_STRING,
|
|
||||||
&&label_JOP_MAKE_STRUCT,
|
|
||||||
&&label_JOP_MAKE_TABLE,
|
|
||||||
&&label_JOP_MAKE_TUPLE,
|
|
||||||
&&label_JOP_MAKE_BRACKET_TUPLE,
|
|
||||||
&&label_JOP_NUMERIC_LESS_THAN,
|
|
||||||
&&label_JOP_NUMERIC_LESS_THAN_EQUAL,
|
|
||||||
&&label_JOP_NUMERIC_GREATER_THAN,
|
|
||||||
&&label_JOP_NUMERIC_GREATER_THAN_EQUAL,
|
|
||||||
&&label_JOP_NUMERIC_EQUAL,
|
|
||||||
&&label_unknown_op
|
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
#define VM_START() uint8_t opcode = first_opcode; for (;;) {switch(opcode) {
|
#define VM_START() uint8_t opcode = first_opcode; for (;;) {switch(opcode) {
|
||||||
#define VM_END() }}
|
#define VM_END() }}
|
||||||
@@ -261,6 +191,81 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
|||||||
/* Interpreter main loop */
|
/* Interpreter main loop */
|
||||||
static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) {
|
static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) {
|
||||||
|
|
||||||
|
/* opcode -> label lookup if using clang/GCC */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
static void *op_lookup[255] = {
|
||||||
|
&&label_JOP_NOOP,
|
||||||
|
&&label_JOP_ERROR,
|
||||||
|
&&label_JOP_TYPECHECK,
|
||||||
|
&&label_JOP_RETURN,
|
||||||
|
&&label_JOP_RETURN_NIL,
|
||||||
|
&&label_JOP_ADD_IMMEDIATE,
|
||||||
|
&&label_JOP_ADD,
|
||||||
|
&&label_JOP_SUBTRACT,
|
||||||
|
&&label_JOP_MULTIPLY_IMMEDIATE,
|
||||||
|
&&label_JOP_MULTIPLY,
|
||||||
|
&&label_JOP_DIVIDE_IMMEDIATE,
|
||||||
|
&&label_JOP_DIVIDE,
|
||||||
|
&&label_JOP_BAND,
|
||||||
|
&&label_JOP_BOR,
|
||||||
|
&&label_JOP_BXOR,
|
||||||
|
&&label_JOP_BNOT,
|
||||||
|
&&label_JOP_SHIFT_LEFT,
|
||||||
|
&&label_JOP_SHIFT_LEFT_IMMEDIATE,
|
||||||
|
&&label_JOP_SHIFT_RIGHT,
|
||||||
|
&&label_JOP_SHIFT_RIGHT_IMMEDIATE,
|
||||||
|
&&label_JOP_SHIFT_RIGHT_UNSIGNED,
|
||||||
|
&&label_JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE,
|
||||||
|
&&label_JOP_MOVE_FAR,
|
||||||
|
&&label_JOP_MOVE_NEAR,
|
||||||
|
&&label_JOP_JUMP,
|
||||||
|
&&label_JOP_JUMP_IF,
|
||||||
|
&&label_JOP_JUMP_IF_NOT,
|
||||||
|
&&label_JOP_GREATER_THAN,
|
||||||
|
&&label_JOP_GREATER_THAN_IMMEDIATE,
|
||||||
|
&&label_JOP_LESS_THAN,
|
||||||
|
&&label_JOP_LESS_THAN_IMMEDIATE,
|
||||||
|
&&label_JOP_EQUALS,
|
||||||
|
&&label_JOP_EQUALS_IMMEDIATE,
|
||||||
|
&&label_JOP_COMPARE,
|
||||||
|
&&label_JOP_LOAD_NIL,
|
||||||
|
&&label_JOP_LOAD_TRUE,
|
||||||
|
&&label_JOP_LOAD_FALSE,
|
||||||
|
&&label_JOP_LOAD_INTEGER,
|
||||||
|
&&label_JOP_LOAD_CONSTANT,
|
||||||
|
&&label_JOP_LOAD_UPVALUE,
|
||||||
|
&&label_JOP_LOAD_SELF,
|
||||||
|
&&label_JOP_SET_UPVALUE,
|
||||||
|
&&label_JOP_CLOSURE,
|
||||||
|
&&label_JOP_PUSH,
|
||||||
|
&&label_JOP_PUSH_2,
|
||||||
|
&&label_JOP_PUSH_3,
|
||||||
|
&&label_JOP_PUSH_ARRAY,
|
||||||
|
&&label_JOP_CALL,
|
||||||
|
&&label_JOP_TAILCALL,
|
||||||
|
&&label_JOP_RESUME,
|
||||||
|
&&label_JOP_SIGNAL,
|
||||||
|
&&label_JOP_GET,
|
||||||
|
&&label_JOP_PUT,
|
||||||
|
&&label_JOP_GET_INDEX,
|
||||||
|
&&label_JOP_PUT_INDEX,
|
||||||
|
&&label_JOP_LENGTH,
|
||||||
|
&&label_JOP_MAKE_ARRAY,
|
||||||
|
&&label_JOP_MAKE_BUFFER,
|
||||||
|
&&label_JOP_MAKE_STRING,
|
||||||
|
&&label_JOP_MAKE_STRUCT,
|
||||||
|
&&label_JOP_MAKE_TABLE,
|
||||||
|
&&label_JOP_MAKE_TUPLE,
|
||||||
|
&&label_JOP_MAKE_BRACKET_TUPLE,
|
||||||
|
&&label_JOP_NUMERIC_LESS_THAN,
|
||||||
|
&&label_JOP_NUMERIC_LESS_THAN_EQUAL,
|
||||||
|
&&label_JOP_NUMERIC_GREATER_THAN,
|
||||||
|
&&label_JOP_NUMERIC_GREATER_THAN_EQUAL,
|
||||||
|
&&label_JOP_NUMERIC_EQUAL,
|
||||||
|
&&label_unknown_op
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Interpreter state */
|
/* Interpreter state */
|
||||||
register Janet *stack;
|
register Janet *stack;
|
||||||
register uint32_t *pc;
|
register uint32_t *pc;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ extern "C" {
|
|||||||
|| defined(__FreeBSD__) || defined(__DragonFly__) \
|
|| defined(__FreeBSD__) || defined(__DragonFly__) \
|
||||||
|| defined(__FreeBSD_kernel__) \
|
|| defined(__FreeBSD_kernel__) \
|
||||||
|| defined(__GNU__) /* GNU/Hurd */ \
|
|| defined(__GNU__) /* GNU/Hurd */ \
|
||||||
|
|| defined(__HAIKU__) \
|
||||||
|| defined(__linux__) \
|
|| defined(__linux__) \
|
||||||
|| defined(__NetBSD__) \
|
|| defined(__NetBSD__) \
|
||||||
|| defined(__OpenBSD__) \
|
|| defined(__OpenBSD__) \
|
||||||
@@ -183,15 +184,38 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Alignment for pointers */
|
/* Runtime config constants */
|
||||||
#ifndef JANET_WALIGN
|
#ifdef JANET_NO_NANBOX
|
||||||
#ifdef JANET_32
|
#define JANET_NANBOX_BIT 0
|
||||||
#define JANET_WALIGN 4
|
|
||||||
#else
|
#else
|
||||||
#define JANET_WALIGN 8
|
#define JANET_NANBOX_BIT 0x1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef JANET_SINGLE_THREADED
|
||||||
|
#define JANET_SINGLE_THREADED_BIT 0x2
|
||||||
|
#else
|
||||||
|
#define JANET_SINGLE_THREADED_BIT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define JANET_CURRENT_CONFIG_BITS \
|
||||||
|
(JANET_SINGLE_THREADED_BIT | \
|
||||||
|
JANET_NANBOX_BIT)
|
||||||
|
|
||||||
|
/* Represents the settings used to compile Janet, as well as the version */
|
||||||
|
typedef struct {
|
||||||
|
unsigned major;
|
||||||
|
unsigned minor;
|
||||||
|
unsigned patch;
|
||||||
|
unsigned bits;
|
||||||
|
} JanetBuildConfig;
|
||||||
|
|
||||||
|
/* Get config of current compilation unit. */
|
||||||
|
#define janet_config_current() ((JanetBuildConfig){ \
|
||||||
|
JANET_VERSION_MAJOR, \
|
||||||
|
JANET_VERSION_MINOR, \
|
||||||
|
JANET_VERSION_PATCH, \
|
||||||
|
JANET_CURRENT_CONFIG_BITS })
|
||||||
|
|
||||||
/***** END SECTION CONFIG *****/
|
/***** END SECTION CONFIG *****/
|
||||||
|
|
||||||
/***** START SECTION TYPES *****/
|
/***** START SECTION TYPES *****/
|
||||||
@@ -326,12 +350,12 @@ typedef enum JanetType {
|
|||||||
#define JANET_TFLAG_ABSTRACT (1 << JANET_ABSTRACT)
|
#define JANET_TFLAG_ABSTRACT (1 << JANET_ABSTRACT)
|
||||||
#define JANET_TFLAG_POINTER (1 << JANET_POINTER)
|
#define JANET_TFLAG_POINTER (1 << JANET_POINTER)
|
||||||
|
|
||||||
/* Some abstractions */
|
|
||||||
#define JANET_TFLAG_BYTES (JANET_TFLAG_STRING | JANET_TFLAG_SYMBOL | JANET_TFLAG_BUFFER | JANET_TFLAG_KEYWORD)
|
#define JANET_TFLAG_BYTES (JANET_TFLAG_STRING | JANET_TFLAG_SYMBOL | JANET_TFLAG_BUFFER | JANET_TFLAG_KEYWORD)
|
||||||
#define JANET_TFLAG_INDEXED (JANET_TFLAG_ARRAY | JANET_TFLAG_TUPLE)
|
#define JANET_TFLAG_INDEXED (JANET_TFLAG_ARRAY | JANET_TFLAG_TUPLE)
|
||||||
#define JANET_TFLAG_DICTIONARY (JANET_TFLAG_TABLE | JANET_TFLAG_STRUCT)
|
#define JANET_TFLAG_DICTIONARY (JANET_TFLAG_TABLE | JANET_TFLAG_STRUCT)
|
||||||
#define JANET_TFLAG_LENGTHABLE (JANET_TFLAG_BYTES | JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY)
|
#define JANET_TFLAG_LENGTHABLE (JANET_TFLAG_BYTES | JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY)
|
||||||
#define JANET_TFLAG_CALLABLE (JANET_TFLAG_FUNCTION | JANET_TFLAG_CFUNCTION)
|
#define JANET_TFLAG_CALLABLE (JANET_TFLAG_FUNCTION | JANET_TFLAG_CFUNCTION | \
|
||||||
|
JANET_TFLAG_LENGTHABLE | JANET_TFLAG_ABSTRACT)
|
||||||
|
|
||||||
/* We provide three possible implementations of Janets. The preferred
|
/* We provide three possible implementations of Janets. The preferred
|
||||||
* nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the
|
* nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the
|
||||||
@@ -761,6 +785,7 @@ struct JanetAbstractHead {
|
|||||||
#define JANET_FUNCDEF_FLAG_HASDEFS 0x200000
|
#define JANET_FUNCDEF_FLAG_HASDEFS 0x200000
|
||||||
#define JANET_FUNCDEF_FLAG_HASENVS 0x400000
|
#define JANET_FUNCDEF_FLAG_HASENVS 0x400000
|
||||||
#define JANET_FUNCDEF_FLAG_HASSOURCEMAP 0x800000
|
#define JANET_FUNCDEF_FLAG_HASSOURCEMAP 0x800000
|
||||||
|
#define JANET_FUNCDEF_FLAG_STRUCTARG 0x1000000
|
||||||
#define JANET_FUNCDEF_FLAG_TAG 0xFFFF
|
#define JANET_FUNCDEF_FLAG_TAG 0xFFFF
|
||||||
|
|
||||||
/* Source mapping structure for a bytecode instruction */
|
/* Source mapping structure for a bytecode instruction */
|
||||||
@@ -1191,6 +1216,7 @@ JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size);
|
|||||||
|
|
||||||
/* Native */
|
/* Native */
|
||||||
typedef void (*JanetModule)(JanetTable *);
|
typedef void (*JanetModule)(JanetTable *);
|
||||||
|
typedef JanetBuildConfig(*JanetModconf)(void);
|
||||||
JANET_API JanetModule janet_native(const char *name, const uint8_t **error);
|
JANET_API JanetModule janet_native(const char *name, const uint8_t **error);
|
||||||
|
|
||||||
/* Marshaling */
|
/* Marshaling */
|
||||||
@@ -1261,7 +1287,12 @@ JANET_API void janet_register(const char *name, JanetCFunction cfun);
|
|||||||
|
|
||||||
/* New C API */
|
/* New C API */
|
||||||
|
|
||||||
#define JANET_MODULE_ENTRY JANET_API void _janet_init
|
#define JANET_MODULE_ENTRY \
|
||||||
|
JANET_API JanetBuildConfig _janet_mod_config(void) { \
|
||||||
|
return janet_config_current(); \
|
||||||
|
} \
|
||||||
|
JANET_API void _janet_init
|
||||||
|
|
||||||
JANET_API void janet_panicv(Janet message);
|
JANET_API void janet_panicv(Janet message);
|
||||||
JANET_API void janet_panic(const char *message);
|
JANET_API void janet_panic(const char *message);
|
||||||
JANET_API void janet_panics(const uint8_t *message);
|
JANET_API void janet_panics(const uint8_t *message);
|
||||||
|
|||||||
@@ -25,23 +25,29 @@
|
|||||||
#ifndef JANETCONF_H
|
#ifndef JANETCONF_H
|
||||||
#define JANETCONF_H
|
#define JANETCONF_H
|
||||||
|
|
||||||
#define JANET_VERSION "0.5.0"
|
#define JANET_VERSION_MAJOR 0
|
||||||
|
#define JANET_VERSION_MINOR 6
|
||||||
|
#define JANET_VERSION_PATCH 0
|
||||||
|
#define JANET_VERSION_EXTRA "-dev"
|
||||||
|
#define JANET_VERSION "0.6.0-dev"
|
||||||
|
|
||||||
/* #define JANET_BUILD "local" */
|
/* #define JANET_BUILD "local" */
|
||||||
|
|
||||||
|
/* These settings all affect linking, so use cautiously. */
|
||||||
/* #define JANET_SINGLE_THREADED */
|
/* #define JANET_SINGLE_THREADED */
|
||||||
/* #define JANET_NO_DYNAMIC_MODULES */
|
/* #define JANET_NO_DYNAMIC_MODULES */
|
||||||
|
/* #define JANET_NO_NANBOX */
|
||||||
|
/* #define JANET_API __attribute__((visibility ("default"))) */
|
||||||
|
|
||||||
/* #define JANET_NO_ASSEMBLER */
|
/* #define JANET_NO_ASSEMBLER */
|
||||||
/* #define JANET_NO_PEG */
|
/* #define JANET_NO_PEG */
|
||||||
/* #define JANET_NO_TYPED_ARRAY */
|
/* #define JANET_NO_TYPED_ARRAY */
|
||||||
/* #define JANET_NO_INT_TYPES */
|
/* #define JANET_NO_INT_TYPES */
|
||||||
/* #define JANET_REDUCED_OS */
|
/* #define JANET_REDUCED_OS */
|
||||||
/* #define JANET_API __attribute__((visibility ("default"))) */
|
|
||||||
/* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */
|
/* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */
|
||||||
/* #define JANET_RECURSION_GUARD 1024 */
|
/* #define JANET_RECURSION_GUARD 1024 */
|
||||||
/* #define JANET_MAX_PROTO_DEPTH 200 */
|
/* #define JANET_MAX_PROTO_DEPTH 200 */
|
||||||
/* #define JANET_MAX_MACRO_EXPAND 200 */
|
/* #define JANET_MAX_MACRO_EXPAND 200 */
|
||||||
/* #define JANET_STACK_MAX 16384 */
|
/* #define JANET_STACK_MAX 16384 */
|
||||||
/* #define JANET_NO_NANBOX */
|
|
||||||
/* #define JANET_WALIGN 8 */
|
|
||||||
|
|
||||||
#endif /* end of include guard: JANETCONF_H */
|
#endif /* end of include guard: JANETCONF_H */
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
(var *handleopts* true)
|
(var *handleopts* true)
|
||||||
(var *exit-on-error* true)
|
(var *exit-on-error* true)
|
||||||
(var *colorize* true)
|
(var *colorize* true)
|
||||||
|
(var *compile-only* false)
|
||||||
|
|
||||||
(if-let [jp (os/getenv "JANET_PATH")] (set module/*syspath* jp))
|
(if-let [jp (os/getenv "JANET_PATH")] (set module/*syspath* jp))
|
||||||
|
(if-let [jp (os/getenv "JANET_HEADERPATH")] (set module/*headerpath* jp))
|
||||||
|
|
||||||
# Flag handlers
|
# Flag handlers
|
||||||
(def handlers :private
|
(def handlers :private
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
-r : Enter the repl after running all scripts
|
-r : Enter the repl after running all scripts
|
||||||
-p : Keep on executing if there is a top level error (persistent)
|
-p : Keep on executing if there is a top level error (persistent)
|
||||||
-q : Hide prompt, logo, and repl output (quiet)
|
-q : Hide prompt, logo, and repl output (quiet)
|
||||||
|
-k : Compile scripts but do not execute
|
||||||
-m syspath : Set system path for loading global modules
|
-m syspath : Set system path for loading global modules
|
||||||
-c source output : Compile janet source code into an image
|
-c source output : Compile janet source code into an image
|
||||||
-n : Disable ANSI color output in the repl
|
-n : Disable ANSI color output in the repl
|
||||||
@@ -37,6 +40,7 @@
|
|||||||
"r" (fn [&] (set *should-repl* true) 1)
|
"r" (fn [&] (set *should-repl* true) 1)
|
||||||
"p" (fn [&] (set *exit-on-error* false) 1)
|
"p" (fn [&] (set *exit-on-error* false) 1)
|
||||||
"q" (fn [&] (set *quiet* true) 1)
|
"q" (fn [&] (set *quiet* true) 1)
|
||||||
|
"k" (fn [&] (set *compile-only* true) (set *exit-on-error* false) 1)
|
||||||
"n" (fn [&] (set *colorize* false) 1)
|
"n" (fn [&] (set *colorize* false) 1)
|
||||||
"m" (fn [i &] (set module/*syspath* (get process/args (+ i 1))) 2)
|
"m" (fn [i &] (set module/*syspath* (get process/args (+ i 1))) 2)
|
||||||
"c" (fn [i &]
|
"c" (fn [i &]
|
||||||
@@ -67,10 +71,10 @@
|
|||||||
(+= i (dohandler (string/slice arg 1 2) i))
|
(+= i (dohandler (string/slice arg 1 2) i))
|
||||||
(do
|
(do
|
||||||
(set *no-file* false)
|
(set *no-file* false)
|
||||||
(import* arg :prefix "" :exit *exit-on-error*)
|
(import* arg :prefix "" :exit *exit-on-error* :compile-only *compile-only*)
|
||||||
(set i lenargs))))
|
(set i lenargs))))
|
||||||
|
|
||||||
(when (or *should-repl* *no-file*)
|
(when (and (not *compile-only*) (or *should-repl* *no-file*))
|
||||||
(if-not *quiet*
|
(if-not *quiet*
|
||||||
(print "Janet " janet/version "-" janet/build " Copyright (C) 2017-2019 Calvin Rose"))
|
(print "Janet " janet/version "-" janet/build " Copyright (C) 2017-2019 Calvin Rose"))
|
||||||
(defn noprompt [_] "")
|
(defn noprompt [_] "")
|
||||||
|
|||||||
@@ -23,6 +23,13 @@
|
|||||||
#include <janet.h>
|
#include <janet.h>
|
||||||
#include "line.h"
|
#include "line.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const unsigned char *janet_gen_init;
|
extern const unsigned char *janet_gen_init;
|
||||||
extern int32_t janet_gen_init_size;
|
extern int32_t janet_gen_init_size;
|
||||||
|
|
||||||
@@ -31,6 +38,15 @@ int main(int argc, char **argv) {
|
|||||||
JanetArray *args;
|
JanetArray *args;
|
||||||
JanetTable *env;
|
JanetTable *env;
|
||||||
|
|
||||||
|
/* Enable color console on windows 10 console. */
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
DWORD dwMode = 0;
|
||||||
|
GetConsoleMode(hOut, &dwMode);
|
||||||
|
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
SetConsoleMode(hOut, dwMode);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set up VM */
|
/* Set up VM */
|
||||||
janet_init();
|
janet_init();
|
||||||
|
|
||||||
|
|||||||
36
test/amalg/main.c
Normal file
36
test/amalg/main.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* A simple client for checking if the amalgamated Janet source compiles
|
||||||
|
* correctly. */
|
||||||
|
|
||||||
|
#include <janet.h>
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
(void) argc;
|
||||||
|
(void) argv;
|
||||||
|
janet_init();
|
||||||
|
JanetTable *env = janet_core_env(NULL);
|
||||||
|
janet_dostring(env, "(print `hello, world!`)", "main", NULL);
|
||||||
|
janet_deinit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
(import cook)
|
|
||||||
|
|
||||||
(cook/make-native
|
|
||||||
:name "testmod"
|
|
||||||
:source @["testmod.c"])
|
|
||||||
|
|
||||||
(import build/testmod :as testmod)
|
|
||||||
|
|
||||||
(if (not= 5 (testmod/get5)) (error "testmod/get5 failed"))
|
|
||||||
|
|
||||||
(print "OK!")
|
|
||||||
7
test/install/project.janet
Normal file
7
test/install/project.janet
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
(declare-project
|
||||||
|
:name "testmod")
|
||||||
|
|
||||||
|
(declare-native
|
||||||
|
:name "testmod"
|
||||||
|
:source @["testmod.c"])
|
||||||
|
|
||||||
3
test/install/test/test1.janet
Normal file
3
test/install/test/test1.janet
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(import build/testmod :as testmod)
|
||||||
|
|
||||||
|
(if (not= 5 (testmod/get5)) (error "testmod/get5 failed"))
|
||||||
@@ -300,5 +300,8 @@
|
|||||||
(assert (= (length {1 2 3 nil}) 1) "nil value struct literal")
|
(assert (= (length {1 2 3 nil}) 1) "nil value struct literal")
|
||||||
(assert (= (length @{1 2 3 nil}) 1) "nil value table literal")
|
(assert (= (length @{1 2 3 nil}) 1) "nil value table literal")
|
||||||
|
|
||||||
|
# Regression Test
|
||||||
|
(assert (= 1 (((compile '(fn [] 1) @{})))) "regression test")
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,16 @@
|
|||||||
(assert (= (string/join @["one" "two" "three"] ", ") "one, two, three") "string/join 2")
|
(assert (= (string/join @["one" "two" "three"] ", ") "one, two, three") "string/join 2")
|
||||||
(assert (= (string/join @["one" "two" "three"]) "onetwothree") "string/join 3")
|
(assert (= (string/join @["one" "two" "three"]) "onetwothree") "string/join 3")
|
||||||
(assert (= (string/join @[] "hi") "") "string/join 4")
|
(assert (= (string/join @[] "hi") "") "string/join 4")
|
||||||
|
(assert (= (string/trim " abcd ") "abcd") "string/trim 1")
|
||||||
|
(assert (= (string/trim "abcd \t\t\r\f") "abcd") "string/trim 2")
|
||||||
|
(assert (= (string/trim "\n\n\t abcd") "abcd") "string/trim 3")
|
||||||
|
(assert (= (string/trim "") "") "string/trim 4")
|
||||||
|
(assert (= (string/triml " abcd ") "abcd ") "string/triml 1")
|
||||||
|
(assert (= (string/triml "\tabcd \t\t\r\f") "abcd \t\t\r\f") "string/triml 2")
|
||||||
|
(assert (= (string/triml "abcd ") "abcd ") "string/triml 3")
|
||||||
|
(assert (= (string/trimr " abcd ") " abcd") "string/trimr 1")
|
||||||
|
(assert (= (string/trimr "\tabcd \t\t\r\f") "\tabcd") "string/trimr 2")
|
||||||
|
(assert (= (string/trimr " abcd") " abcd") "string/trimr 3")
|
||||||
(assert (deep= (string/split "," "one,two,three") @["one" "two" "three"]) "string/split 1")
|
(assert (deep= (string/split "," "one,two,three") @["one" "two" "three"]) "string/split 1")
|
||||||
(assert (deep= (string/split "," "onetwothree") @["onetwothree"]) "string/split 2")
|
(assert (deep= (string/split "," "onetwothree") @["onetwothree"]) "string/split 2")
|
||||||
(assert (deep= (string/find-all "e" "onetwothree") @[2 9 10]) "string/find-all 1")
|
(assert (deep= (string/find-all "e" "onetwothree") @[2 9 10]) "string/find-all 1")
|
||||||
|
|||||||
@@ -96,4 +96,17 @@
|
|||||||
(setdyn :a 100)
|
(setdyn :a 100)
|
||||||
(assert (= 100 (dyn :a)) "dyn usage 4")
|
(assert (= 100 (dyn :a)) "dyn usage 4")
|
||||||
|
|
||||||
|
# Keyword arguments
|
||||||
|
(defn myfn [x y z &keys {:a a :b b :c c}]
|
||||||
|
(+ x y z a b c))
|
||||||
|
|
||||||
|
(assert (= (+ ;(range 6)) (myfn 0 1 2 :a 3 :b 4 :c 5)) "keyword args 1")
|
||||||
|
(assert (= (+ ;(range 6)) (myfn 0 1 2 :a 1 :b 6 :c 5 :d 11)) "keyword args 2")
|
||||||
|
|
||||||
|
# Comment macro
|
||||||
|
(comment 1)
|
||||||
|
(comment 1 2)
|
||||||
|
(comment 1 2 3)
|
||||||
|
(comment 1 2 3 4)
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
327
tools/EnvVarUpdate.nsh
Normal file
327
tools/EnvVarUpdate.nsh
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
/**
|
||||||
|
* EnvVarUpdate.nsh
|
||||||
|
* : Environmental Variables: append, prepend, and remove entries
|
||||||
|
*
|
||||||
|
* WARNING: If you use StrFunc.nsh header then include it before this file
|
||||||
|
* with all required definitions. This is to avoid conflicts
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
|
||||||
|
*
|
||||||
|
* Credits:
|
||||||
|
* Version 1.0
|
||||||
|
* * Cal Turney (turnec2)
|
||||||
|
* * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
|
||||||
|
* function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
|
||||||
|
* WriteEnvStr, and un.DeleteEnvStr
|
||||||
|
* * Diego Pedroso (deguix) for StrTok
|
||||||
|
* * Kevin English (kenglish_hi) for StrContains
|
||||||
|
* * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry
|
||||||
|
* (dandaman32) for StrReplace
|
||||||
|
*
|
||||||
|
* Version 1.1 (compatibility with StrFunc.nsh)
|
||||||
|
* * techtonik
|
||||||
|
*
|
||||||
|
* http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
!ifndef ENVVARUPDATE_FUNCTION
|
||||||
|
!define ENVVARUPDATE_FUNCTION
|
||||||
|
!verbose push
|
||||||
|
!verbose 3
|
||||||
|
!include "LogicLib.nsh"
|
||||||
|
!include "WinMessages.NSH"
|
||||||
|
!include "StrFunc.nsh"
|
||||||
|
|
||||||
|
; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
|
||||||
|
!macro _IncludeStrFunction StrFuncName
|
||||||
|
!ifndef ${StrFuncName}_INCLUDED
|
||||||
|
${${StrFuncName}}
|
||||||
|
!endif
|
||||||
|
!ifndef Un${StrFuncName}_INCLUDED
|
||||||
|
${Un${StrFuncName}}
|
||||||
|
!endif
|
||||||
|
!define un.${StrFuncName} "${Un${StrFuncName}}"
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
!insertmacro _IncludeStrFunction StrTok
|
||||||
|
!insertmacro _IncludeStrFunction StrStr
|
||||||
|
!insertmacro _IncludeStrFunction StrRep
|
||||||
|
|
||||||
|
; ---------------------------------- Macro Definitions ----------------------------------------
|
||||||
|
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
|
||||||
|
Push "${EnvVarName}"
|
||||||
|
Push "${Action}"
|
||||||
|
Push "${RegLoc}"
|
||||||
|
Push "${PathString}"
|
||||||
|
Call EnvVarUpdate
|
||||||
|
Pop "${ResultVar}"
|
||||||
|
!macroend
|
||||||
|
!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
|
||||||
|
|
||||||
|
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
|
||||||
|
Push "${EnvVarName}"
|
||||||
|
Push "${Action}"
|
||||||
|
Push "${RegLoc}"
|
||||||
|
Push "${PathString}"
|
||||||
|
Call un.EnvVarUpdate
|
||||||
|
Pop "${ResultVar}"
|
||||||
|
!macroend
|
||||||
|
!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
|
||||||
|
; ---------------------------------- Macro Definitions end-------------------------------------
|
||||||
|
|
||||||
|
;----------------------------------- EnvVarUpdate start----------------------------------------
|
||||||
|
!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
|
||||||
|
!define hkcu_current_user 'HKCU "Environment"'
|
||||||
|
|
||||||
|
!macro EnvVarUpdate UN
|
||||||
|
|
||||||
|
Function ${UN}EnvVarUpdate
|
||||||
|
|
||||||
|
Push $0
|
||||||
|
Exch 4
|
||||||
|
Exch $1
|
||||||
|
Exch 3
|
||||||
|
Exch $2
|
||||||
|
Exch 2
|
||||||
|
Exch $3
|
||||||
|
Exch
|
||||||
|
Exch $4
|
||||||
|
Push $5
|
||||||
|
Push $6
|
||||||
|
Push $7
|
||||||
|
Push $8
|
||||||
|
Push $9
|
||||||
|
Push $R0
|
||||||
|
|
||||||
|
/* After this point:
|
||||||
|
-------------------------
|
||||||
|
$0 = ResultVar (returned)
|
||||||
|
$1 = EnvVarName (input)
|
||||||
|
$2 = Action (input)
|
||||||
|
$3 = RegLoc (input)
|
||||||
|
$4 = PathString (input)
|
||||||
|
$5 = Orig EnvVar (read from registry)
|
||||||
|
$6 = Len of $0 (temp)
|
||||||
|
$7 = tempstr1 (temp)
|
||||||
|
$8 = Entry counter (temp)
|
||||||
|
$9 = tempstr2 (temp)
|
||||||
|
$R0 = tempChar (temp) */
|
||||||
|
|
||||||
|
; Step 1: Read contents of EnvVarName from RegLoc
|
||||||
|
;
|
||||||
|
; Check for empty EnvVarName
|
||||||
|
${If} $1 == ""
|
||||||
|
SetErrors
|
||||||
|
DetailPrint "ERROR: EnvVarName is blank"
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Check for valid Action
|
||||||
|
${If} $2 != "A"
|
||||||
|
${AndIf} $2 != "P"
|
||||||
|
${AndIf} $2 != "R"
|
||||||
|
SetErrors
|
||||||
|
DetailPrint "ERROR: Invalid Action - must be A, P, or R"
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${If} $3 == HKLM
|
||||||
|
ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5
|
||||||
|
${ElseIf} $3 == HKCU
|
||||||
|
ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5
|
||||||
|
${Else}
|
||||||
|
SetErrors
|
||||||
|
DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Check for empty PathString
|
||||||
|
${If} $4 == ""
|
||||||
|
SetErrors
|
||||||
|
DetailPrint "ERROR: PathString is blank"
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Make sure we've got some work to do
|
||||||
|
${If} $5 == ""
|
||||||
|
${AndIf} $2 == "R"
|
||||||
|
SetErrors
|
||||||
|
DetailPrint "$1 is empty - Nothing to remove"
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Step 2: Scrub EnvVar
|
||||||
|
;
|
||||||
|
StrCpy $0 $5 ; Copy the contents to $0
|
||||||
|
; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
|
||||||
|
; after the last one are not removed here but instead in Step 3)
|
||||||
|
${If} $0 != "" ; If EnvVar is not empty ...
|
||||||
|
${Do}
|
||||||
|
${${UN}StrStr} $7 $0 " ;"
|
||||||
|
${If} $7 == ""
|
||||||
|
${ExitDo}
|
||||||
|
${EndIf}
|
||||||
|
${${UN}StrRep} $0 $0 " ;" ";" ; Remove '<space>;'
|
||||||
|
${Loop}
|
||||||
|
${Do}
|
||||||
|
${${UN}StrStr} $7 $0 "; "
|
||||||
|
${If} $7 == ""
|
||||||
|
${ExitDo}
|
||||||
|
${EndIf}
|
||||||
|
${${UN}StrRep} $0 $0 "; " ";" ; Remove ';<space>'
|
||||||
|
${Loop}
|
||||||
|
${Do}
|
||||||
|
${${UN}StrStr} $7 $0 ";;"
|
||||||
|
${If} $7 == ""
|
||||||
|
${ExitDo}
|
||||||
|
${EndIf}
|
||||||
|
${${UN}StrRep} $0 $0 ";;" ";"
|
||||||
|
${Loop}
|
||||||
|
|
||||||
|
; Remove a leading or trailing semicolon from EnvVar
|
||||||
|
StrCpy $7 $0 1 0
|
||||||
|
${If} $7 == ";"
|
||||||
|
StrCpy $0 $0 "" 1 ; Change ';<EnvVar>' to '<EnvVar>'
|
||||||
|
${EndIf}
|
||||||
|
StrLen $6 $0
|
||||||
|
IntOp $6 $6 - 1
|
||||||
|
StrCpy $7 $0 1 $6
|
||||||
|
${If} $7 == ";"
|
||||||
|
StrCpy $0 $0 $6 ; Change ';<EnvVar>' to '<EnvVar>'
|
||||||
|
${EndIf}
|
||||||
|
; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
/* Step 3. Remove all instances of the target path/string (even if "A" or "P")
|
||||||
|
$6 = bool flag (1 = found and removed PathString)
|
||||||
|
$7 = a string (e.g. path) delimited by semicolon(s)
|
||||||
|
$8 = entry counter starting at 0
|
||||||
|
$9 = copy of $0
|
||||||
|
$R0 = tempChar */
|
||||||
|
|
||||||
|
${If} $5 != "" ; If EnvVar is not empty ...
|
||||||
|
StrCpy $9 $0
|
||||||
|
StrCpy $0 ""
|
||||||
|
StrCpy $8 0
|
||||||
|
StrCpy $6 0
|
||||||
|
|
||||||
|
${Do}
|
||||||
|
${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter
|
||||||
|
|
||||||
|
${If} $7 == "" ; If we've run out of entries,
|
||||||
|
${ExitDo} ; were done
|
||||||
|
${EndIf} ;
|
||||||
|
|
||||||
|
; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
|
||||||
|
${Do}
|
||||||
|
StrCpy $R0 $7 1
|
||||||
|
${If} $R0 != " "
|
||||||
|
${ExitDo}
|
||||||
|
${EndIf}
|
||||||
|
StrCpy $7 $7 "" 1 ; Remove leading space
|
||||||
|
${Loop}
|
||||||
|
${Do}
|
||||||
|
StrCpy $R0 $7 1 -1
|
||||||
|
${If} $R0 != " "
|
||||||
|
${ExitDo}
|
||||||
|
${EndIf}
|
||||||
|
StrCpy $7 $7 -1 ; Remove trailing space
|
||||||
|
${Loop}
|
||||||
|
${If} $7 == $4 ; If string matches, remove it by not appending it
|
||||||
|
StrCpy $6 1 ; Set 'found' flag
|
||||||
|
${ElseIf} $7 != $4 ; If string does NOT match
|
||||||
|
${AndIf} $0 == "" ; and the 1st string being added to $0,
|
||||||
|
StrCpy $0 $7 ; copy it to $0 without a prepended semicolon
|
||||||
|
${ElseIf} $7 != $4 ; If string does NOT match
|
||||||
|
${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0,
|
||||||
|
StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon
|
||||||
|
${EndIf} ;
|
||||||
|
|
||||||
|
IntOp $8 $8 + 1 ; Bump counter
|
||||||
|
${Loop} ; Check for duplicates until we run out of paths
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Step 4: Perform the requested Action
|
||||||
|
;
|
||||||
|
${If} $2 != "R" ; If Append or Prepend
|
||||||
|
${If} $6 == 1 ; And if we found the target
|
||||||
|
DetailPrint "Target is already present in $1. It will be removed and"
|
||||||
|
${EndIf}
|
||||||
|
${If} $0 == "" ; If EnvVar is (now) empty
|
||||||
|
StrCpy $0 $4 ; just copy PathString to EnvVar
|
||||||
|
${If} $6 == 0 ; If found flag is either 0
|
||||||
|
${OrIf} $6 == "" ; or blank (if EnvVarName is empty)
|
||||||
|
DetailPrint "$1 was empty and has been updated with the target"
|
||||||
|
${EndIf}
|
||||||
|
${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty),
|
||||||
|
StrCpy $0 $0;$4 ; append PathString
|
||||||
|
${If} $6 == 1
|
||||||
|
DetailPrint "appended to $1"
|
||||||
|
${Else}
|
||||||
|
DetailPrint "Target was appended to $1"
|
||||||
|
${EndIf}
|
||||||
|
${Else} ; If Prepend (and EnvVar is not empty),
|
||||||
|
StrCpy $0 $4;$0 ; prepend PathString
|
||||||
|
${If} $6 == 1
|
||||||
|
DetailPrint "prepended to $1"
|
||||||
|
${Else}
|
||||||
|
DetailPrint "Target was prepended to $1"
|
||||||
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
${Else} ; If Action = Remove
|
||||||
|
${If} $6 == 1 ; and we found the target
|
||||||
|
DetailPrint "Target was found and removed from $1"
|
||||||
|
${Else}
|
||||||
|
DetailPrint "Target was NOT found in $1 (nothing to remove)"
|
||||||
|
${EndIf}
|
||||||
|
${If} $0 == ""
|
||||||
|
DetailPrint "$1 is now empty"
|
||||||
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change
|
||||||
|
;
|
||||||
|
ClearErrors
|
||||||
|
${If} $3 == HKLM
|
||||||
|
WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section
|
||||||
|
${ElseIf} $3 == HKCU
|
||||||
|
WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
IfErrors 0 +4
|
||||||
|
MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
|
||||||
|
DetailPrint "Could not write updated $1 to $3"
|
||||||
|
Goto EnvVarUpdate_Restore_Vars
|
||||||
|
|
||||||
|
; "Export" our change
|
||||||
|
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||||
|
|
||||||
|
EnvVarUpdate_Restore_Vars:
|
||||||
|
;
|
||||||
|
; Restore the user's variables and return ResultVar
|
||||||
|
Pop $R0
|
||||||
|
Pop $9
|
||||||
|
Pop $8
|
||||||
|
Pop $7
|
||||||
|
Pop $6
|
||||||
|
Pop $5
|
||||||
|
Pop $4
|
||||||
|
Pop $3
|
||||||
|
Pop $2
|
||||||
|
Pop $1
|
||||||
|
Push $0 ; Push my $0 (ResultVar)
|
||||||
|
Exch
|
||||||
|
Pop $0 ; Restore his $0
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!macroend ; EnvVarUpdate UN
|
||||||
|
!insertmacro EnvVarUpdate ""
|
||||||
|
!insertmacro EnvVarUpdate "un."
|
||||||
|
;----------------------------------- EnvVarUpdate end----------------------------------------
|
||||||
|
|
||||||
|
!verbose pop
|
||||||
|
!endif
|
||||||
366
tools/cook.janet
366
tools/cook.janet
@@ -1,5 +1,13 @@
|
|||||||
# Library to help build janet natives and other
|
### cook.janet
|
||||||
# build artifacts.
|
###
|
||||||
|
### Library to help build janet natives and other
|
||||||
|
### build artifacts.
|
||||||
|
###
|
||||||
|
### Copyright 2019 © Calvin Rose
|
||||||
|
|
||||||
|
#
|
||||||
|
# Basic Path Settings
|
||||||
|
#
|
||||||
|
|
||||||
# Windows is the OS outlier
|
# Windows is the OS outlier
|
||||||
(def- is-win (= (os/which) :windows))
|
(def- is-win (= (os/which) :windows))
|
||||||
@@ -8,18 +16,142 @@
|
|||||||
(def- objext (if is-win ".obj" ".o"))
|
(def- objext (if is-win ".obj" ".o"))
|
||||||
(def- modext (if is-win ".dll" ".so"))
|
(def- modext (if is-win ".dll" ".so"))
|
||||||
|
|
||||||
(def prefix (or (os/getenv "PREFIX") "/usr/local"))
|
#
|
||||||
|
# Rule Engine
|
||||||
|
#
|
||||||
|
|
||||||
|
(defn- getrules []
|
||||||
|
(def rules (dyn :rules))
|
||||||
|
(if rules rules (setdyn :rules @{})))
|
||||||
|
|
||||||
|
(defn- gettarget [target]
|
||||||
|
(def item ((getrules) target))
|
||||||
|
(unless item (error (string "No rule for target " target)))
|
||||||
|
item)
|
||||||
|
|
||||||
|
(defn- rule-impl
|
||||||
|
[target deps thunk &opt phony]
|
||||||
|
(put (getrules) target @[(array/slice deps) thunk phony]))
|
||||||
|
|
||||||
|
(defmacro rule
|
||||||
|
"Add a rule to the rule graph."
|
||||||
|
[target deps & body]
|
||||||
|
~(,rule-impl ,target ,deps (fn [] nil ,;body)))
|
||||||
|
|
||||||
|
(defmacro phony
|
||||||
|
"Add a phony rule to the rule graph. A phony rule will run every time
|
||||||
|
(it is always considered out of date). Phony rules are good for defining
|
||||||
|
user facing tasks."
|
||||||
|
[target deps & body]
|
||||||
|
~(,rule-impl ,target ,deps (fn [] nil ,;body) true))
|
||||||
|
|
||||||
|
(defn add-dep
|
||||||
|
"Add a dependency to an existing rule. Useful for extending phony
|
||||||
|
rules or extending the dependency graph of existing rules."
|
||||||
|
[target dep]
|
||||||
|
(def [deps] (gettarget target))
|
||||||
|
(array/push deps dep))
|
||||||
|
|
||||||
|
(defn- add-thunk
|
||||||
|
[target more]
|
||||||
|
(def item (gettarget target))
|
||||||
|
(def [_ thunk] item)
|
||||||
|
(put item 1 (fn [] (more) (thunk))))
|
||||||
|
|
||||||
|
(defmacro add-body
|
||||||
|
"Add recipe code to an existing rule. This makes existing rules do more but
|
||||||
|
does not modify the dependency graph."
|
||||||
|
[target & body]
|
||||||
|
~(,add-thunk ,target (fn [] ,;body)))
|
||||||
|
|
||||||
|
(defn- needs-build
|
||||||
|
[dest src]
|
||||||
|
(let [mod-dest (os/stat dest :modified)
|
||||||
|
mod-src (os/stat src :modified)]
|
||||||
|
(< mod-dest mod-src)))
|
||||||
|
|
||||||
|
(defn- needs-build-some
|
||||||
|
[dest sources]
|
||||||
|
(def f (file/open dest))
|
||||||
|
(if (not f) (break true))
|
||||||
|
(file/close f)
|
||||||
|
(some (partial needs-build dest) sources))
|
||||||
|
|
||||||
|
(defn do-rule
|
||||||
|
"Evaluate a given rule."
|
||||||
|
[target]
|
||||||
|
(def item ((getrules) target))
|
||||||
|
(unless item
|
||||||
|
(if (os/stat target :mode)
|
||||||
|
(break target)
|
||||||
|
(error (string "No rule for file " target " found."))))
|
||||||
|
(def [deps thunk phony] item)
|
||||||
|
(def realdeps (seq [dep :in deps :let [x (do-rule dep)] :when x] x))
|
||||||
|
(when (or phony (needs-build-some target realdeps))
|
||||||
|
(thunk))
|
||||||
|
(unless phony target))
|
||||||
|
|
||||||
|
(def- _env (fiber/getenv (fiber/current)))
|
||||||
|
(defn- import-rules*
|
||||||
|
[path & args]
|
||||||
|
(def [realpath] (module/find path))
|
||||||
|
(def env (make-env))
|
||||||
|
(loop [k :keys _env :when (symbol? k)]
|
||||||
|
(unless ((_env k) :private) (put env k (_env k))))
|
||||||
|
(def currenv (fiber/getenv (fiber/current)))
|
||||||
|
(loop [k :keys currenv :when (keyword? k)]
|
||||||
|
(put env k (currenv k)))
|
||||||
|
(require path :env env ;args)
|
||||||
|
(when-let [rules (env :rules)] (merge-into (getrules) rules)))
|
||||||
|
|
||||||
|
(defmacro import-rules
|
||||||
|
"Import another file that defines more cook rules. This ruleset
|
||||||
|
is merged into the current ruleset."
|
||||||
|
[path & args]
|
||||||
|
~(,import-rules* ,(string path) ,;args))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
# Installation settings
|
||||||
|
(def JANET_MODPATH (or (os/getenv "JANET_MODPATH") module/*syspath*))
|
||||||
|
(def JANET_HEADERPATH (or (os/getenv "JANET_HEADERPATH") module/*headerpath*))
|
||||||
|
(def JANET_BINPATH (or (os/getenv "JANET_BINPATH") (unless is-win "/usr/local/bin")))
|
||||||
|
|
||||||
|
# Compilation settings
|
||||||
|
(def OPTIMIZE (or (os/getenv "OPTIMIZE") 2))
|
||||||
|
(def CC (or (os/getenv "CC") (if is-win "cl" "cc")))
|
||||||
|
(def LD (or (os/getenv "LINKER") (if is-win "link" CC)))
|
||||||
|
(def LDFLAGS (or (os/getenv "LFLAGS")
|
||||||
|
(if is-win " /nologo"
|
||||||
|
(string " -shared"
|
||||||
|
(if is-mac " -undefined dynamic_lookup" "")))))
|
||||||
|
(def CFLAGS (or (os/getenv "CFLAGS") (if is-win "" " -std=c99 -Wall -Wextra -fpic")))
|
||||||
|
|
||||||
|
(defn- opt
|
||||||
|
"Get an option, allowing overrides via dynamic bindings AND some
|
||||||
|
default value dflt if no dynamic binding is set."
|
||||||
|
[opts key dflt]
|
||||||
|
(def ret (or (opts key) (dyn key dflt)))
|
||||||
|
(if (= nil ret)
|
||||||
|
(error (string "option :" key " not set")))
|
||||||
|
ret)
|
||||||
|
|
||||||
|
#
|
||||||
|
# OS and shell helpers
|
||||||
|
#
|
||||||
|
|
||||||
(defn shell
|
(defn shell
|
||||||
"Do a shell command"
|
"Do a shell command"
|
||||||
[& args]
|
[& args]
|
||||||
(def cmd (string ;args))
|
(def cmd (string/join args))
|
||||||
(print cmd)
|
(print cmd)
|
||||||
(def res (os/shell cmd))
|
(def res (os/shell cmd))
|
||||||
(unless (zero? res)
|
(unless (zero? res)
|
||||||
(error (string "command exited with status " res))))
|
(error (string "command exited with status " res))))
|
||||||
|
|
||||||
(defn- rm
|
(defn rm
|
||||||
"Remove a directory and all sub directories."
|
"Remove a directory and all sub directories."
|
||||||
[path]
|
[path]
|
||||||
(if (= (os/stat path :mode) :directory)
|
(if (= (os/stat path :mode) :directory)
|
||||||
@@ -29,19 +161,14 @@
|
|||||||
(os/rmdir path))
|
(os/rmdir path))
|
||||||
(os/rm path)))
|
(os/rm path)))
|
||||||
|
|
||||||
(defn- needs-build
|
(defn copy
|
||||||
[dest src]
|
"Copy a file or directory recursively from one location to another."
|
||||||
"Check if dest is older than src. Used for checking if a file should be updated."
|
[src dest]
|
||||||
(def f (file/open dest))
|
(shell (if is-win "xcopy " "cp -rf ") `"` src `" "` dest (if is-win `" /y /e` `"`)))
|
||||||
(if (not f) (break true))
|
|
||||||
(file/close f)
|
|
||||||
(let [mod-dest (os/stat dest :modified)
|
|
||||||
mod-src (os/stat src :modified)]
|
|
||||||
(< mod-dest mod-src)))
|
|
||||||
|
|
||||||
(defn- needs-build-some
|
#
|
||||||
[f others]
|
# C Compilation
|
||||||
(some (partial needs-build f) others))
|
#
|
||||||
|
|
||||||
(defn- embed-name
|
(defn- embed-name
|
||||||
"Rename a janet symbol for embedding."
|
"Rename a janet symbol for embedding."
|
||||||
@@ -82,10 +209,10 @@
|
|||||||
(defn- make-define
|
(defn- make-define
|
||||||
"Generate strings for adding custom defines to the compiler."
|
"Generate strings for adding custom defines to the compiler."
|
||||||
[define value]
|
[define value]
|
||||||
(def prefix (if is-win "/D" "-D"))
|
(def pre (if is-win "/D" "-D"))
|
||||||
(if value
|
(if value
|
||||||
(string prefix define "=" value)
|
(string pre define "=" value)
|
||||||
(string prefix define)))
|
(string pre define)))
|
||||||
|
|
||||||
(defn- make-defines
|
(defn- make-defines
|
||||||
"Generate many defines. Takes a dictionary of defines. If a value is
|
"Generate many defines. Takes a dictionary of defines. If a value is
|
||||||
@@ -93,102 +220,149 @@
|
|||||||
[defines]
|
[defines]
|
||||||
(seq [[d v] :pairs defines] (make-define d (if (not= v true) v))))
|
(seq [[d v] :pairs defines] (make-define d (if (not= v true) v))))
|
||||||
|
|
||||||
# Defaults
|
(defn- getcflags
|
||||||
(def OPTIMIZE 2)
|
"Generate the c flags from the input options."
|
||||||
(def CC (if is-win "cl" "cc"))
|
[opts]
|
||||||
(def LD (if is-win
|
(string (opt opts :cflags CFLAGS)
|
||||||
"link"
|
(if is-win " /I\"" " \"-I")
|
||||||
(string CC
|
(opt opts :headerpath JANET_HEADERPATH)
|
||||||
" -shared"
|
`"`
|
||||||
(if is-mac " -undefined dynamic_lookup" ""))))
|
(if is-win " /O\"" " \"-O")
|
||||||
(def CFLAGS (string
|
(opt opts :optimize OPTIMIZE)
|
||||||
(if is-win "/I" "-I")
|
`"`))
|
||||||
module/*syspath*
|
|
||||||
(if is-win " /O" " -std=c99 -Wall -Wextra -fpic -O")
|
|
||||||
OPTIMIZE))
|
|
||||||
|
|
||||||
(defn- compile-c
|
(defn- compile-c
|
||||||
"Compile a C file into an object file."
|
"Compile a C file into an object file."
|
||||||
[opts src dest]
|
[opts src dest]
|
||||||
(def cc (or (opts :compiler) CC))
|
(def cc (opt opts :compiler CC))
|
||||||
(def cflags (or (opts :cflags) CFLAGS))
|
(def cflags (getcflags opts))
|
||||||
(def defines (interpose " " (make-defines (or (opts :defines) {}))))
|
(def defines (interpose " " (make-defines (opt opts :defines {}))))
|
||||||
(if (needs-build dest src)
|
(rule dest [src]
|
||||||
(if is-win
|
(if is-win
|
||||||
(shell cc " " ;defines " /nologo /c " cflags " /Fo" dest " " src)
|
(shell cc " " ;defines " /nologo /c " cflags " /Fo\"" dest `" "` src `"`)
|
||||||
(shell cc " -c " src " " ;defines " " cflags " -o " dest))))
|
(shell cc " -c '" src "' " ;defines " " cflags " -o '" dest `'`))))
|
||||||
|
|
||||||
(defn- link-c
|
(defn- link-c
|
||||||
"Link a number of object files together."
|
"Link a number of object files together."
|
||||||
[opts target & objects]
|
[opts target & objects]
|
||||||
(def ld (or (opts :linker) LD))
|
(def ld (opt opts :linker LD))
|
||||||
(def cflags (or (opts :cflags) CFLAGS))
|
(def cflags (getcflags opts))
|
||||||
(def lflags (or (opts :lflags) ""))
|
(def lflags (opt opts :lflags LDFLAGS))
|
||||||
(def olist (string/join objects " "))
|
(def olist (string/join objects `" "`))
|
||||||
(if (needs-build-some target objects)
|
(rule target objects
|
||||||
(if is-win
|
(if is-win
|
||||||
(shell ld " /DLL /OUT:" target " " olist " %JANET_PATH%\\janet.lib")
|
(shell ld " " lflags " /DLL /OUT:" target ` "` olist `" "` (opt opts :headerpath JANET_HEADERPATH) `"\\janet.lib`)
|
||||||
(shell ld " " cflags " -o " target " " olist " " lflags))))
|
(shell ld " " cflags ` -o "` target `" "` olist `" ` lflags))))
|
||||||
|
|
||||||
(defn- create-buffer-c
|
(defn- create-buffer-c
|
||||||
"Inline raw byte file as a c file."
|
"Inline raw byte file as a c file."
|
||||||
[source dest name]
|
[source dest name]
|
||||||
(when (needs-build dest source)
|
(rule dest [source]
|
||||||
(def f (file/open source :r))
|
(def f (file/open source :r))
|
||||||
(if (not f) (error (string "file " f " not found")))
|
(if (not f) (error (string "file " f " not found")))
|
||||||
(def out (file/open dest :w))
|
(def out (file/open dest :w))
|
||||||
(def chunks (seq [b :in (file/read f :all)] (string b)))
|
(def chunks (seq [b :in (file/read f :all)] (string b)))
|
||||||
(file/write out
|
(file/write out
|
||||||
"#include <janet/janet.h>\n"
|
"#include <janet.h>\n"
|
||||||
"static const unsigned char bytes[] = {"
|
"static const unsigned char bytes[] = {"
|
||||||
;(interpose ", " chunks)
|
;(interpose ", " chunks)
|
||||||
"};\n\n"
|
"};\n\n"
|
||||||
"const unsigned char *" name "_embed = bytes;\n"
|
"const unsigned char *" name "_embed = bytes;\n"
|
||||||
"size_t " name "_embed_size = sizeof(bytes);\n")
|
"size_t " name "_embed_size = sizeof(bytes);\n")
|
||||||
(file/close out)
|
(file/close out)
|
||||||
(file/close f)))
|
(file/close f)))
|
||||||
|
|
||||||
# Public
|
#
|
||||||
|
# Declaring Artifacts - used in project.janet, targets specifically
|
||||||
|
# tailored for janet.
|
||||||
|
#
|
||||||
|
|
||||||
(defn make-native
|
(defn- install-rule
|
||||||
"Build a native binary. This is a shared library that can be loaded
|
"Add install and uninstall rule for moving file from src into destdir."
|
||||||
|
[src destdir]
|
||||||
|
(def parts (string/split sep src))
|
||||||
|
(def name (last parts))
|
||||||
|
(add-body "install"
|
||||||
|
(try (os/mkdir destdir) ([err] nil))
|
||||||
|
(copy src destdir))
|
||||||
|
(add-body "uninstall"
|
||||||
|
(def path (string destdir sep name))
|
||||||
|
(print "removing " path)
|
||||||
|
(try (rm path) ([err]
|
||||||
|
(unless (= err "No such file or directory")
|
||||||
|
(error err))))))
|
||||||
|
|
||||||
|
(defn declare-native
|
||||||
|
"Declare a native binary. This is a shared library that can be loaded
|
||||||
dynamically by a janet runtime."
|
dynamically by a janet runtime."
|
||||||
[& opts]
|
[&keys opts]
|
||||||
(def opt-table (table ;opts))
|
(def sources (opts :source))
|
||||||
(os/mkdir "build")
|
(def name (opts :name))
|
||||||
(def sources (opt-table :source))
|
(def lname (lib-name name))
|
||||||
(def name (opt-table :name))
|
|
||||||
(loop [src :in sources]
|
(loop [src :in sources]
|
||||||
(compile-c opt-table src (object-name src)))
|
(compile-c opts src (object-name src)))
|
||||||
(def objects (map object-name sources))
|
(def objects (map object-name sources))
|
||||||
(when-let [embedded (opt-table :embedded)]
|
(when-let [embedded (opts :embedded)]
|
||||||
(loop [src :in embedded]
|
(loop [src :in embedded]
|
||||||
(def c-src (embed-c-name src))
|
(def c-src (embed-c-name src))
|
||||||
(def o-src (embed-o-name src))
|
(def o-src (embed-o-name src))
|
||||||
(array/push objects o-src)
|
(array/push objects o-src)
|
||||||
(create-buffer-c src c-src (embed-name src))
|
(create-buffer-c src c-src (embed-name src))
|
||||||
(compile-c opt-table c-src o-src)))
|
(compile-c opts c-src o-src)))
|
||||||
(link-c opt-table (lib-name name) ;objects))
|
(link-c opts lname ;objects)
|
||||||
|
(add-dep "build" lname)
|
||||||
|
(def path (opt opts :modpath JANET_MODPATH))
|
||||||
|
(install-rule lname path))
|
||||||
|
|
||||||
(defn clean
|
(defn declare-source
|
||||||
"Remove all built artifacts."
|
"Create a Janet modules. This does not actually build the module(s),
|
||||||
[]
|
but registers it for packaging and installation."
|
||||||
(rm "build"))
|
[&keys opts]
|
||||||
|
(def sources (opts :source))
|
||||||
|
(def path (opt opts :modpath JANET_MODPATH))
|
||||||
|
(each s sources
|
||||||
|
(install-rule s path)))
|
||||||
|
|
||||||
(defn make-archive
|
(defn declare-binscript
|
||||||
|
"Declare a janet file to be installed as an executable script."
|
||||||
|
[&keys opts]
|
||||||
|
(def main (opts :main))
|
||||||
|
(def binpath (opt opts :binpath JANET_BINPATH))
|
||||||
|
(install-rule main binpath))
|
||||||
|
|
||||||
|
(defn declare-archive
|
||||||
"Build a janet archive. This is a file that bundles together many janet
|
"Build a janet archive. This is a file that bundles together many janet
|
||||||
scripts into a janet image. This file can the be moved to any machine with
|
scripts into a janet image. This file can the be moved to any machine with
|
||||||
a janet vm and the required dependencies and run there."
|
a janet vm and the required dependencies and run there."
|
||||||
[& opts]
|
[&keys opts]
|
||||||
(def opt-table (table ;opts))
|
(def entry (opts :entry))
|
||||||
(os/mkdir "build")
|
(def name (opts :name))
|
||||||
(def entry (opt-table :entry))
|
(def iname (string "build" sep name ".jimage"))
|
||||||
(def name (opt-table :name))
|
(rule iname (or (opts :deps) [])
|
||||||
(spit (string name ".jimage") (make-image (require entry))))
|
(spit iname (make-image (require entry))))
|
||||||
|
(def path (opt opts :modpath JANET_MODPATH))
|
||||||
|
(install-rule iname path))
|
||||||
|
|
||||||
(defn make-binary
|
(defn declare-project
|
||||||
"Make a binary executable that can be run on the current platform. This function
|
"Define your project metadata. This should
|
||||||
generates a self contained binary that can be run of the same architecture as the
|
be the first declaration in a project.janet file.
|
||||||
build machine, as the current janet vm will be packaged with the output binary."
|
Also sets up basic phony targets like clean, build, test, etc."
|
||||||
[& opts]
|
[&keys meta]
|
||||||
(error "Not Yet Implemented."))
|
(setdyn :project meta)
|
||||||
|
(try (os/mkdir "build") ([err] nil))
|
||||||
|
(phony "build" [])
|
||||||
|
(phony "install" ["build"] (print "Installed."))
|
||||||
|
(phony "uninstall" [] (print "Uninstalled."))
|
||||||
|
(phony "clean" [] (rm "build") (print "Deleted build directory."))
|
||||||
|
(phony "test" ["build"]
|
||||||
|
(defn dodir
|
||||||
|
[dir]
|
||||||
|
(each sub (os/dir dir)
|
||||||
|
(def ndir (string dir sep sub))
|
||||||
|
(case (os/stat ndir :mode)
|
||||||
|
:file (when (string/has-suffix? ".janet" ndir)
|
||||||
|
(print "running " ndir " ...")
|
||||||
|
(dofile ndir :exit true))
|
||||||
|
:directory (dodir ndir))))
|
||||||
|
(dodir "test")
|
||||||
|
(print "All tests passed.")))
|
||||||
|
|||||||
41
tools/jpm
Executable file
41
tools/jpm
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env janet
|
||||||
|
|
||||||
|
# CLI tool for building janet projects. Wraps cook.
|
||||||
|
|
||||||
|
(import cook)
|
||||||
|
|
||||||
|
(def- argpeg
|
||||||
|
(peg/compile
|
||||||
|
'(* "--" '(some (if-not "=" 1)) "=" '(any 1))))
|
||||||
|
|
||||||
|
(defn- help
|
||||||
|
[]
|
||||||
|
(print "usage: jpm [targets]... --key=value ...")
|
||||||
|
(print "Available targets are:")
|
||||||
|
(each k (sort (keys (dyn :rules @{})))
|
||||||
|
(print " " k))
|
||||||
|
(print `
|
||||||
|
|
||||||
|
Keys are:
|
||||||
|
--modpath : The directory to install modules to. Defaults to $JANET_MODPATH or module/*syspath*
|
||||||
|
--headerpath : The directory containing janet headers. Defaults to $JANET_HEADERPATH or module/*headerpath*
|
||||||
|
--binpath : The directory to install binaries and scripts. Defaults to $JANET_BINPATH.
|
||||||
|
--optimize : Optimization level for natives. Defaults to $OPTIMIZE or 2.
|
||||||
|
--compiler : C compiler to use for natives. Defaults to $CC or cc.
|
||||||
|
--linker : C linker to use for linking natives. Defaults to $LINKER or cc.
|
||||||
|
--cflags : Extra compiler flags for native modules. Defaults to $CFLAGS if set.
|
||||||
|
--lflags : Extra linker flags for native modules. Defaults to $LFLAGS if set.
|
||||||
|
`))
|
||||||
|
|
||||||
|
(def args (tuple/slice process/args 2))
|
||||||
|
(def todo @[])
|
||||||
|
(each arg args
|
||||||
|
(if (string/has-prefix? "--" arg)
|
||||||
|
(let [[key value] (peg/match argpeg arg)]
|
||||||
|
(setdyn (keyword key) value))
|
||||||
|
(array/push todo arg)))
|
||||||
|
|
||||||
|
(cook/import-rules "./project.janet")
|
||||||
|
|
||||||
|
(if (empty? todo) (help))
|
||||||
|
(each rule todo (cook/do-rule rule))
|
||||||
4
tools/jpm.bat
Normal file
4
tools/jpm.bat
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
@rem Wrapper arounf jpm
|
||||||
|
|
||||||
|
janet %~dp0\jpm.janet %*
|
||||||
Reference in New Issue
Block a user