mirror of
https://github.com/janet-lang/janet
synced 2025-11-18 16:25:11 +00:00
Compare commits
65 Commits
v1.6.0
...
repl-compl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8e4c4bed0 | ||
|
|
6471b4d100 | ||
|
|
7f9b2b34d1 | ||
|
|
789c5f135a | ||
|
|
d8841de180 | ||
|
|
23c7c3bf1c | ||
|
|
3d117804dd | ||
|
|
77bb0ebe3f | ||
|
|
6d9e51e4be | ||
|
|
174ff87946 | ||
|
|
ea02b2fde9 | ||
|
|
962cd7e5f5 | ||
|
|
65be9ae095 | ||
|
|
bc2bac8cd3 | ||
|
|
b567ece401 | ||
|
|
f001b0a40c | ||
|
|
04579664fd | ||
|
|
f709d7eb40 | ||
|
|
2df8660f8b | ||
|
|
a68ee7aac6 | ||
|
|
f0e04e734c | ||
|
|
0e7cf51890 | ||
|
|
b54d9725d8 | ||
|
|
2f0570aad6 | ||
|
|
3d40c95e80 | ||
|
|
ed5027db5d | ||
|
|
c4047f3f88 | ||
|
|
ec1a06cfaf | ||
|
|
17e47a798c | ||
|
|
212aceedc6 | ||
|
|
e6f897f4ef | ||
|
|
6c7f376410 | ||
|
|
e93e237c67 | ||
|
|
a1cd759759 | ||
|
|
a2c45a697b | ||
|
|
acdbf8911c | ||
|
|
9269372768 | ||
|
|
5575e7577a | ||
|
|
ef02dacdb4 | ||
|
|
c6b639b939 | ||
|
|
0b0fb18c42 | ||
|
|
b872ee024f | ||
|
|
a15d841b5b | ||
|
|
bfb638cfc2 | ||
|
|
3a47ad5d99 | ||
|
|
e3c88295f2 | ||
|
|
75bb8fbcd1 | ||
|
|
9cb25ad7b1 | ||
|
|
f361830cb2 | ||
|
|
9dd152dc28 | ||
|
|
2ba4337e6f | ||
|
|
48fcd927ab | ||
|
|
407d8af026 | ||
|
|
d0570b55b1 | ||
|
|
a964a95c1e | ||
|
|
c2f8441572 | ||
|
|
099a957e6c | ||
|
|
a2e515ab89 | ||
|
|
2bebace8eb | ||
|
|
5142722da3 | ||
|
|
52dd0f132a | ||
|
|
022be217a2 | ||
|
|
5528bca7a9 | ||
|
|
ae474bc8d0 | ||
|
|
ddc4274314 |
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,6 +1,27 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
### Unreleased
|
||||
- Remove `==`, `not==`, `order<`, `order>`, `order<=`, and `order>=`. Instead, use the normal
|
||||
comparison and equality functions.
|
||||
- Let abstract types define a hash function and comparison/equality semantics. This lets
|
||||
abstract types much better represent value types. This adds more fields to abstract types, which
|
||||
will generate warnings when compiled against other versions.
|
||||
- Remove Emscripten build. Instead, use the amalgamated source code with a custom toolchain.
|
||||
- Update documentation.
|
||||
- Add `module/add-paths`
|
||||
- Add `file/temp`
|
||||
- Small bug fixes
|
||||
- Allow signaling from C functions (yielding) via janet\_signalv. This
|
||||
makes it easy to write C functions that work with event loops, such as
|
||||
in libuv or embedded in a game.
|
||||
- Add `defer`
|
||||
- Add `assert`
|
||||
- Add `when-with`
|
||||
- Add `if-with`
|
||||
- Fix thread module issue where sometimes decoding a message failed.
|
||||
- Fix segfault regression when macros are called with bad arity.
|
||||
|
||||
### 1.6.0 - 2019-12-22
|
||||
- Add `thread/` module to the core.
|
||||
- Allow seeding RNGs with any sequence of bytes. This provides
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019 Calvin Rose and contributors
|
||||
Copyright (c) 2020 Calvin Rose and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
42
Makefile
42
Makefile
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose
|
||||
# Copyright (c) 2020 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
|
||||
@@ -37,7 +37,7 @@ MANPATH?=$(PREFIX)/share/man/man1/
|
||||
PKG_CONFIG_PATH?=$(LIBDIR)/pkgconfig
|
||||
DEBUGGER=gdb
|
||||
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fPIC -O2 -fvisibility=hidden \
|
||||
CFLAGS=-std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fPIC -O2 -fvisibility=hidden -march=native \
|
||||
-DJANET_BUILD=$(JANET_BUILD)
|
||||
LDFLAGS=-rdynamic
|
||||
|
||||
@@ -67,7 +67,8 @@ all: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY)
|
||||
|
||||
JANET_HEADERS=src/include/janet.h src/conf/janetconf.h
|
||||
|
||||
JANET_LOCAL_HEADERS=src/core/util.h \
|
||||
JANET_LOCAL_HEADERS=src/core/features.h \
|
||||
src/core/util.h \
|
||||
src/core/state.h \
|
||||
src/core/gc.h \
|
||||
src/core/vector.h \
|
||||
@@ -121,8 +122,10 @@ JANET_BOOT_SOURCES=src/boot/array_test.c \
|
||||
src/boot/number_test.c \
|
||||
src/boot/system_test.c \
|
||||
src/boot/table_test.c
|
||||
JANET_BOOT_HEADERS=src/boot/tests.h
|
||||
|
||||
JANET_MAINCLIENT_SOURCES=src/mainclient/line.c src/mainclient/main.c
|
||||
JANET_MAINCLIENT_HEADERS=src/mainclient/line.h
|
||||
|
||||
JANET_WEBCLIENT_SOURCES=src/webclient/main.c
|
||||
|
||||
@@ -133,6 +136,8 @@ JANET_WEBCLIENT_SOURCES=src/webclient/main.c
|
||||
JANET_BOOT_OBJECTS=$(patsubst src/%.c,build/%.boot.o,$(JANET_CORE_SOURCES) $(JANET_BOOT_SOURCES)) \
|
||||
build/boot.gen.o
|
||||
|
||||
$(JANET_BOOT_OBJECTS): $(JANET_BOOT_HEADERS)
|
||||
|
||||
build/%.boot.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(CC) $(CFLAGS) -DJANET_BOOTSTRAP -o $@ -c $<
|
||||
|
||||
@@ -150,6 +155,8 @@ build/core_image.c: build/janet_boot
|
||||
JANET_CORE_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_CORE_SOURCES)) build/core_image.o
|
||||
JANET_MAINCLIENT_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_MAINCLIENT_SOURCES))
|
||||
|
||||
$(JANET_MAINCLIENT_OBJECTS): $(JANET_MAINCLIENT_HEADERS)
|
||||
|
||||
# Compile the core image generated by the bootstrap build
|
||||
build/core_image.o: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
@@ -166,35 +173,6 @@ $(JANET_LIBRARY): $(JANET_CORE_OBJECTS)
|
||||
$(JANET_STATIC_LIBRARY): $(JANET_CORE_OBJECTS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
######################
|
||||
##### Emscripten #####
|
||||
######################
|
||||
|
||||
EMCC=emcc
|
||||
EMCFLAGS=-std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -O2 \
|
||||
-s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s AGGRESSIVE_VARIABLE_ELIMINATION=1 \
|
||||
-DJANET_BUILD=$(JANET_BUILD)
|
||||
JANET_EMTARGET=build/janet.js
|
||||
JANET_WEB_SOURCES=$(JANET_CORE_SOURCES) $(JANET_WEBCLIENT_SOURCES)
|
||||
JANET_EMOBJECTS=$(patsubst src/%.c,build/%.bc,$(JANET_WEB_SOURCES)) \
|
||||
build/webinit.gen.bc build/core_image.bc
|
||||
|
||||
%.gen.bc: %.gen.c
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
build/core_image.bc: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
build/%.bc: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
$(EMCC) $(EMCFLAGS) -o $@ -c $<
|
||||
|
||||
$(JANET_EMTARGET): $(JANET_EMOBJECTS)
|
||||
$(EMCC) $(EMCFLAGS) -shared -o $@ $^
|
||||
|
||||
emscripten: $(JANET_EMTARGET)
|
||||
|
||||
#############################
|
||||
##### Generated C files #####
|
||||
#############################
|
||||
|
||||
11
README.md
11
README.md
@@ -21,7 +21,7 @@ janet could be embedded into other programs. Try janet in your browser at
|
||||
|
||||
## Use Cases
|
||||
|
||||
Janet makes a good system scripting language, or a language to embed in other programs. Think Lua or Guile.
|
||||
Janet makes a good system scripting language, or a language to embed in other programs, like Lua or Guile.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -114,15 +114,6 @@ gmake repl
|
||||
3. Run `build_win` to compile janet.
|
||||
4. Run `build_win test` to make sure everything is working.
|
||||
|
||||
### Emscripten
|
||||
|
||||
To build janet for the web via [Emscripten](https://kripken.github.io/emscripten-site/), make sure you
|
||||
have `emcc` installed and on your path. On a linux or macOS system, use `make emscripten` to build
|
||||
`janet.js` and `janet.wasm` - both are needed to run janet in a browser or in node.
|
||||
The JavaScript build is what runs the repl on the main website,
|
||||
but really serves mainly as a proof of concept. Janet will run slower in a browser.
|
||||
Building with emscripten on windows is currently unsupported.
|
||||
|
||||
### Meson
|
||||
|
||||
Janet also has a build file for [Meson](https://mesonbuild.com/), a cross platform build
|
||||
|
||||
@@ -20,17 +20,17 @@ init:
|
||||
|
||||
install:
|
||||
- set JANET_BUILD=%appveyor_repo_commit:~0,7%
|
||||
- choco install nsis -y -pre
|
||||
- choco install nsis -y -pre --version 3.05
|
||||
# Replace makensis.exe and files with special long string build. This should
|
||||
# prevent issues when setting PATH during installation.
|
||||
- 7z e "tools\nsis-3.04-strlen_8192.zip" -o"C:\Program Files (x86)\NSIS\" -y
|
||||
- 7z e "tools\nsis-3.05-strlen_8192.zip" -o"C:\Program Files (x86)\NSIS\" -y
|
||||
- build_win all
|
||||
- refreshenv
|
||||
# We need to reload vcvars after refreshing
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %platform%
|
||||
- build_win test-install
|
||||
- set janet_outname=%appveyor_repo_tag_name%
|
||||
- if "%janet_outname%"=="" set janet_outname=v1.6.0
|
||||
- if "%janet_outname%"=="" set janet_outname=v1.6.1
|
||||
build: off
|
||||
|
||||
artifacts:
|
||||
|
||||
29
auxbin/jpm
29
auxbin/jpm
@@ -29,7 +29,7 @@
|
||||
|
||||
(defn- rule-impl
|
||||
[target deps thunk &opt phony]
|
||||
(put (getrules) target @[(array/slice deps) thunk phony]))
|
||||
(put (getrules) target @[(array/slice deps) @[thunk] phony]))
|
||||
|
||||
(defmacro rule
|
||||
"Add a rule to the rule graph."
|
||||
@@ -53,8 +53,9 @@
|
||||
(defn- add-thunk
|
||||
[target more]
|
||||
(def item (gettarget target))
|
||||
(def [_ thunk] item)
|
||||
(put item 1 (fn [] (more) (thunk))))
|
||||
(def [_ thunks] item)
|
||||
(array/push thunks more)
|
||||
item)
|
||||
|
||||
(defmacro add-body
|
||||
"Add recipe code to an existing rule. This makes existing rules do more but
|
||||
@@ -83,10 +84,10 @@
|
||||
(if (os/stat target :mode)
|
||||
(break target)
|
||||
(error (string "No rule for file " target " found."))))
|
||||
(def [deps thunk phony] item)
|
||||
(def [deps thunks 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))
|
||||
(each thunk thunks (thunk)))
|
||||
(unless phony target))
|
||||
|
||||
#
|
||||
@@ -587,16 +588,20 @@ int main(int argc, const char **argv) {
|
||||
(rm manifest)
|
||||
(print "Uninstalled."))
|
||||
|
||||
(defn- rimraf
|
||||
"Hard delete directory tree"
|
||||
[path]
|
||||
(if is-win
|
||||
# windows get rid of read-only files
|
||||
(os/shell `rmdir /S /Q "` path `"`))
|
||||
(rm path))
|
||||
|
||||
(defn clear-cache
|
||||
"Clear the global git cache."
|
||||
[]
|
||||
(def cache (find-cache))
|
||||
(print "clearing " cache "...")
|
||||
(if is-win
|
||||
# Git for windows decided that .git should be hidden and everything in it read-only.
|
||||
# This means we can't delete things easily.
|
||||
(os/shell (string `rmdir /S /Q "` cache `"`))
|
||||
(rm cache)))
|
||||
(rimraf cache))
|
||||
|
||||
(def- default-pkglist (or (os/getenv "JANET_PKGLIST") "https://github.com/janet-lang/pkgs.git"))
|
||||
|
||||
@@ -631,7 +636,9 @@ int main(int argc, const char **argv) {
|
||||
(when (mkdir module-dir)
|
||||
(set fresh true)
|
||||
(print "cloning repository " repo " to " module-dir)
|
||||
(os/execute ["git" "clone" repo module-dir] :p))
|
||||
(unless (zero? (os/execute ["git" "clone" repo module-dir] :p))
|
||||
(rimraf module-dir)
|
||||
(error (string "could not clone git dependency " repo))))
|
||||
(def olddir (os/cwd))
|
||||
(try
|
||||
(with-dyns [:rules @{}
|
||||
|
||||
@@ -93,7 +93,7 @@ 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
|
||||
janet.exe tools\amalg.janet src\core\features.h 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
|
||||
janet.exe tools\removecr.janet build\janet.c
|
||||
|
||||
@rem Gen shell.c
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
Unicode True
|
||||
|
||||
!echo "Program Files: ${PROGRAMFILES}"
|
||||
!addplugindir "tools\"
|
||||
|
||||
# Version
|
||||
!define PRODUCT_VERSION "${VERSION}.0"
|
||||
VIProductVersion "${PRODUCT_VERSION}"
|
||||
@@ -20,7 +25,6 @@ VIFileVersion "${PRODUCT_VERSION}"
|
||||
# Includes
|
||||
!include "MultiUser.nsh"
|
||||
!include "MUI2.nsh"
|
||||
!include ".\tools\EnvVarUpdate.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
|
||||
# Basics
|
||||
@@ -124,6 +128,15 @@ section "Janet" BfWSection
|
||||
# Start Menu
|
||||
createShortCut "$SMPROGRAMS\Janet.lnk" "$INSTDIR\bin\janet.exe" "" "$INSTDIR\logo.ico"
|
||||
|
||||
# Update path
|
||||
${If} $MultiUser.InstallMode == "AllUsers"
|
||||
EnVar::SetHKLM
|
||||
${Else}
|
||||
EnVar::SetHKCU
|
||||
${EndIf}
|
||||
EnVar::AddValue "PATH" "$INSTDIR\bin"
|
||||
Pop $0
|
||||
|
||||
# Set up Environment variables
|
||||
!insertmacro WriteEnv JANET_PATH "$INSTDIR\Library"
|
||||
!insertmacro WriteEnv JANET_HEADERPATH "$INSTDIR\C"
|
||||
@@ -132,13 +145,6 @@ section "Janet" BfWSection
|
||||
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
# Update path
|
||||
${If} $MultiUser.InstallMode == "AllUsers"
|
||||
${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR\bin" ; Append
|
||||
${Else}
|
||||
${EnvVarUpdate} $0 "PATH" "A" "HKCU" "$INSTDIR\bin" ; Append
|
||||
${EndIf}
|
||||
|
||||
# Registry information for add/remove programs
|
||||
WriteRegStr SHCTX "${UNINST_KEY}" "DisplayName" "Janet"
|
||||
WriteRegStr SHCTX "${UNINST_KEY}" "InstallLocation" "$INSTDIR"
|
||||
@@ -185,10 +191,12 @@ section "uninstall"
|
||||
|
||||
# Unset PATH
|
||||
${If} $MultiUser.InstallMode == "AllUsers"
|
||||
${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$INSTDIR\bin" ; Remove
|
||||
EnVar::SetHKLM
|
||||
${Else}
|
||||
${un.EnvVarUpdate} $0 "PATH" "R" "HKCU" "$INSTDIR\bin" ; Remove
|
||||
EnVar::SetHKCU
|
||||
${EndIf}
|
||||
EnVar::DeleteValue "PATH" "$INSTDIR\bin"
|
||||
Pop $0
|
||||
|
||||
# make sure windows knows about the change
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
|
||||
10
meson.build
10
meson.build
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose and contributors
|
||||
# Copyright (c) 2020 Calvin Rose and contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
project('janet', 'c',
|
||||
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
version : '1.6.0')
|
||||
version : '1.6.1-dev')
|
||||
|
||||
# Global settings
|
||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||
@@ -62,6 +62,7 @@ conf.set('JANET_NO_PEG', not get_option('peg'))
|
||||
conf.set('JANET_REDUCED_OS', get_option('reduced_os'))
|
||||
conf.set('JANET_NO_TYPED_ARRAY', not get_option('typed_array'))
|
||||
conf.set('JANET_NO_INT_TYPES', not get_option('int_types'))
|
||||
conf.set('JANET_NO_PRF', not get_option('prf'))
|
||||
conf.set('JANET_RECURSION_GUARD', get_option('recursion_guard'))
|
||||
conf.set('JANET_MAX_PROTO_DEPTH', get_option('max_proto_depth'))
|
||||
conf.set('JANET_MAX_MACRO_EXPAND', get_option('max_macro_expand'))
|
||||
@@ -88,6 +89,7 @@ boot_gen = gen.process('src/boot/boot.janet', extra_args: 'janet_gen_boot')
|
||||
# Order is important here, as some headers
|
||||
# depend on other headers for the amalg target
|
||||
core_headers = [
|
||||
'src/core/features.h',
|
||||
'src/core/util.h',
|
||||
'src/core/state.h',
|
||||
'src/core/gc.h',
|
||||
@@ -257,5 +259,5 @@ install_headers(['src/include/janet.h', jconf], subdir: 'janet')
|
||||
janet_binscripts = [
|
||||
'auxbin/jpm'
|
||||
]
|
||||
install_data(sources : janet_binscripts, install_dir : 'bin')
|
||||
install_data(sources : ['tools/.keep'], install_dir : 'lib/janet')
|
||||
install_data(sources : janet_binscripts, install_dir : get_option('bindir'))
|
||||
install_data(sources : ['tools/.keep'], install_dir : join_paths(get_option('libdir'), 'janet'))
|
||||
|
||||
@@ -10,6 +10,7 @@ option('assembler', type : 'boolean', value : true)
|
||||
option('peg', type : 'boolean', value : true)
|
||||
option('typed_array', type : 'boolean', value : true)
|
||||
option('int_types', type : 'boolean', value : true)
|
||||
option('prf', type : 'boolean', value : true)
|
||||
|
||||
option('recursion_guard', type : 'integer', min : 10, max : 8000, value : 1024)
|
||||
option('max_proto_depth', type : 'integer', min : 10, max : 8000, value : 200)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -74,12 +74,12 @@
|
||||
|
||||
# Basic predicates
|
||||
(defn nan? "Check if x is NaN" [x] (not= x x))
|
||||
(defn even? "Check if x is even." [x] (== 0 (% x 2)))
|
||||
(defn even? "Check if x is even." [x] (= 0 (% x 2)))
|
||||
(defn odd? "Check if x is odd." [x] (not= 0 (% x 2)))
|
||||
(defn zero? "Check if x is zero." [x] (== x 0))
|
||||
(defn zero? "Check if x is zero." [x] (= x 0))
|
||||
(defn pos? "Check if x is greater than 0." [x] (> x 0))
|
||||
(defn neg? "Check if x is less than 0." [x] (< x 0))
|
||||
(defn one? "Check if x is equal to 1." [x] (== x 1))
|
||||
(defn one? "Check if x is equal to 1." [x] (= x 1))
|
||||
(defn number? "Check if x is a number." [x] (= (type x) :number))
|
||||
(defn fiber? "Check if x is a fiber." [x] (= (type x) :fiber))
|
||||
(defn string? "Check if x is a string." [x] (= (type x) :string))
|
||||
@@ -131,6 +131,11 @@
|
||||
(defmacro /= "Shorthand for (set x (/ x n))." [x n] ~(set ,x (,/ ,x ,n)))
|
||||
(defmacro %= "Shorthand for (set x (% x n))." [x n] ~(set ,x (,% ,x ,n)))
|
||||
|
||||
(defn assert
|
||||
"Throw an error if x is not truthy."
|
||||
[x &opt err]
|
||||
(if x x (error (if err err "assert failure"))))
|
||||
|
||||
(defmacro default
|
||||
"Define a default value for an optional argument.
|
||||
Expands to (def sym (if (= nil sym) val sym))"
|
||||
@@ -219,7 +224,7 @@
|
||||
r (gensym)]
|
||||
~(let [,f (,fiber/new (fn [] ,body) :ie)
|
||||
,r (,resume ,f)]
|
||||
(if (= (,fiber/status ,f) :error)
|
||||
(if (,= (,fiber/status ,f) :error)
|
||||
(do (def ,err ,r) ,(if fib ~(def ,fib ,f)) ,;(tuple/slice catch 1))
|
||||
,r))))
|
||||
|
||||
@@ -276,20 +281,45 @@
|
||||
(++ i))
|
||||
~(let (,;accum) ,;body))
|
||||
|
||||
(defmacro defer
|
||||
"Run form unconditionally after form, even if the body throws an error."
|
||||
[form & body]
|
||||
(with-syms [f r]
|
||||
~(do
|
||||
(def ,f (,fiber/new (fn [] ,;body) :ie))
|
||||
(def ,r (,resume ,f))
|
||||
,form
|
||||
(if (= (,fiber/status ,f) :dead)
|
||||
,r
|
||||
(propagate ,r ,f)))))
|
||||
|
||||
(defmacro with
|
||||
"Evaluate body with some resource, which will be automatically cleaned up
|
||||
if there is an error in body. binding is bound to the expression ctor, and
|
||||
dtor is a function or callable that is passed the binding. If no destructor
|
||||
(dtor) is given, will call :close on the resource."
|
||||
[[binding ctor dtor] & body]
|
||||
(with-syms [res f]
|
||||
~(let [,binding ,ctor
|
||||
,f (,fiber/new (fn [] ,;body) :ie)
|
||||
,res (,resume ,f)]
|
||||
(,(or dtor :close) ,binding)
|
||||
(if (,= (,fiber/status ,f) :error)
|
||||
(,propagate ,res ,f)
|
||||
,res))))
|
||||
~(do
|
||||
(def ,binding ,ctor)
|
||||
(defer (,(or dtor :close) ,binding)
|
||||
,;body)))
|
||||
|
||||
(defmacro when-with
|
||||
"Similar to with, but if binding is false or nil, returns
|
||||
nil without evaluating the body. Otherwise, the same as with."
|
||||
[[binding ctor dtor] & body]
|
||||
~(if-let [,binding ,ctor]
|
||||
(defer (,(or dtor :close) ,binding)
|
||||
,;body)))
|
||||
|
||||
(defmacro if-with
|
||||
"Similar to with, but if binding is false or nil, evaluates
|
||||
the falsey path. Otherwise, evaluates the truthy path. In both cases,
|
||||
ctor is bound to binding."
|
||||
[[binding ctor dtor] truthy &opt falsey ]
|
||||
~(if-let [,binding ,ctor]
|
||||
(defer (,(or dtor :close) ,binding) ,truthy)
|
||||
,falsey))
|
||||
|
||||
(defn- for-template
|
||||
[binding start stop step comparison delta body]
|
||||
@@ -554,12 +584,12 @@
|
||||
(defn max-order
|
||||
"Returns the maximum of the arguments according to a total
|
||||
order over all values."
|
||||
[& args] (extreme order> args))
|
||||
[& args] (extreme > args))
|
||||
|
||||
(defn min-order
|
||||
"Returns the minimum of the arguments according to a total
|
||||
order over all values."
|
||||
[& args] (extreme order< args))
|
||||
[& args] (extreme < args))
|
||||
|
||||
(defn first
|
||||
"Get the first element from an indexed data structure."
|
||||
@@ -605,11 +635,11 @@
|
||||
a)
|
||||
|
||||
(fn sort [a &opt by]
|
||||
(sort-help a 0 (- (length a) 1) (or by order<)))))
|
||||
(sort-help a 0 (- (length a) 1) (or by <)))))
|
||||
|
||||
(defn sorted
|
||||
"Returns a new sorted array without modifying the old one."
|
||||
[ind by]
|
||||
[ind &opt by]
|
||||
(sort (array/slice ind) by))
|
||||
|
||||
(defn reduce
|
||||
@@ -1427,7 +1457,7 @@
|
||||
(if-let [[path line col] sm]
|
||||
(string " " path " on line " line ", column " col "\n") "")
|
||||
(if (or d sm) "\n" "")
|
||||
(if d (doc-format d) "no documentation found.")
|
||||
(if d (doc-format d) " no documentation found.")
|
||||
"\n\n"))))
|
||||
|
||||
# else
|
||||
@@ -1520,7 +1550,8 @@
|
||||
'quote identity
|
||||
'quasiquote expandqq
|
||||
'var expanddef
|
||||
'while expandall})
|
||||
'while expandall
|
||||
'break expandall})
|
||||
|
||||
(defn dotup [t]
|
||||
(def h (in t 0))
|
||||
@@ -1778,7 +1809,7 @@
|
||||
:source where
|
||||
:expander expand} opts)
|
||||
(default env (fiber/getenv (fiber/current)))
|
||||
(default chunks (fn [buf p] (getline "" buf)))
|
||||
(default chunks (fn [buf p] (getline "" buf env)))
|
||||
(default onstatus debug/stacktrace)
|
||||
(default on-compile-error bad-compile)
|
||||
(default on-parse-error bad-parse)
|
||||
@@ -1924,27 +1955,33 @@
|
||||
from searching that path template if the filter doesn't match the input
|
||||
path. The filter can be a string or a predicate function, and
|
||||
is often a file extension, including the period."
|
||||
@[# Relative to (dyn :current-file "./."). Path must start with .
|
||||
[":cur:/:all:.jimage" :image check-.]
|
||||
[":cur:/:all:.janet" :source check-.]
|
||||
[":cur:/:all:/init.janet" :source check-.]
|
||||
[":cur:/:all::native:" :native check-.]
|
||||
|
||||
# As a path from (os/cwd)
|
||||
[":all:.jimage" :image not-check-.]
|
||||
[":all:.janet" :source not-check-.]
|
||||
[":all:/init.janet" :source not-check-.]
|
||||
[":all::native:" :native not-check-.]
|
||||
|
||||
# System paths
|
||||
[":sys:/:all:.jimage" :image not-check-.]
|
||||
[":sys:/:all:.janet" :source not-check-.]
|
||||
[":sys:/:all:/init.janet" :source not-check-.]
|
||||
[":sys:/:all::native:" :native not-check-.]])
|
||||
@[])
|
||||
|
||||
(setdyn :syspath (boot/opts "JANET_PATH"))
|
||||
(setdyn :headerpath (boot/opts "JANET_HEADERPATH"))
|
||||
|
||||
(defn module/add-paths
|
||||
"Add paths to module/paths for a given loader such that
|
||||
the generated paths behave like other module types, including
|
||||
relative imports and syspath imports. ext is the file extension
|
||||
to associate with this module type, including the dot. loader is the
|
||||
keyword name of a loader that is module/loaders. Returns the modified module/paths."
|
||||
[ext loader]
|
||||
(defn- find-prefix
|
||||
[pre]
|
||||
(or (find-index |(string/has-prefix? pre ($ 0)) module/paths) 0))
|
||||
(array/insert module/paths 0 [(string ":cur:/:all:" ext) loader check-.])
|
||||
(def all-index (find-prefix ":all:"))
|
||||
(array/insert module/paths all-index [(string ":all:" ext) loader not-check-.])
|
||||
(def sys-index (find-prefix ":sys:"))
|
||||
(array/insert module/paths sys-index [(string ":sys:/:all:" ext) loader not-check-.])
|
||||
module/paths)
|
||||
|
||||
(module/add-paths ":native:" :native)
|
||||
(module/add-paths "/init.janet" :source)
|
||||
(module/add-paths ".janet" :source)
|
||||
(module/add-paths ".jimage" :image)
|
||||
|
||||
# Version of fexists that works even with a reduced OS
|
||||
(if-let [has-stat (_env 'os/stat)]
|
||||
(let [stat (has-stat :value)]
|
||||
@@ -2098,7 +2135,7 @@
|
||||
use the name of the module as a prefix. One can also use :export true
|
||||
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."
|
||||
to be called. Dynamic bindings will NOT be imported."
|
||||
[path & args]
|
||||
(def argm (map (fn [x]
|
||||
(if (keyword? x)
|
||||
@@ -2131,7 +2168,7 @@
|
||||
((parser/where p) 0)
|
||||
":"
|
||||
(parser/state p :delimiters) "> ")
|
||||
buf)))
|
||||
buf env)))
|
||||
(defn make-onsignal
|
||||
[e level]
|
||||
|
||||
@@ -2146,7 +2183,7 @@
|
||||
(def status (parser/state p :delimiters))
|
||||
(def c ((parser/where p) 0))
|
||||
(def prompt (string "debug[" level "]:" c ":" status "> "))
|
||||
(getline prompt buf))
|
||||
(getline prompt buf nextenv))
|
||||
(print "entering debug[" level "] - (quit) to exit")
|
||||
(repl debugger-chunks (make-onsignal nextenv (+ 1 level)) nextenv)
|
||||
(print "exiting debug[" level "]")
|
||||
@@ -2272,23 +2309,24 @@
|
||||
|
||||
(when (and (not *compile-only*) (or *should-repl* *no-file*))
|
||||
(if-not *quiet*
|
||||
(print "Janet " janet/version "-" janet/build " Copyright (C) 2017-2019 Calvin Rose"))
|
||||
(print "Janet " janet/version "-" janet/build " Copyright (C) 2017-2020 Calvin Rose"))
|
||||
(defn noprompt [_] "")
|
||||
(defn getprompt [p]
|
||||
(def [line] (parser/where p))
|
||||
(string "janet:" line ":" (parser/state p :delimiters) "> "))
|
||||
(def prompter (if *quiet* noprompt getprompt))
|
||||
(defn getstdin [prompt buf]
|
||||
(defn getstdin [prompt buf _]
|
||||
(file/write stdout prompt)
|
||||
(file/flush stdout)
|
||||
(file/read stdin :line buf))
|
||||
(def env (make-env))
|
||||
(def getter (if *raw-stdin* getstdin getline))
|
||||
(defn getchunk [buf p]
|
||||
(getter (prompter p) buf))
|
||||
(getter (prompter p) buf env))
|
||||
(def onsig (if *quiet* (fn [x &] x) nil))
|
||||
(setdyn :pretty-format (if *colorize* "%.20Q" "%.20q"))
|
||||
(setdyn :err-color (if *colorize* true))
|
||||
(repl getchunk onsig)))
|
||||
(repl getchunk onsig env)))
|
||||
|
||||
|
||||
###
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
#define JANET_VERSION_MAJOR 1
|
||||
#define JANET_VERSION_MINOR 6
|
||||
#define JANET_VERSION_PATCH 0
|
||||
#define JANET_VERSION_EXTRA ""
|
||||
#define JANET_VERSION "1.6.0"
|
||||
#define JANET_VERSION_PATCH 1
|
||||
#define JANET_VERSION_EXTRA "-dev"
|
||||
#define JANET_VERSION "1.6.1-dev"
|
||||
|
||||
/* #define JANET_BUILD "local" */
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
/* #define JANET_NO_PEG */
|
||||
/* #define JANET_NO_TYPED_ARRAY */
|
||||
/* #define JANET_NO_INT_TYPES */
|
||||
/* #define JANET_NO_PRF */
|
||||
/* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */
|
||||
/* #define JANET_RECURSION_GUARD 1024 */
|
||||
/* #define JANET_MAX_PROTO_DEPTH 200 */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -35,7 +36,7 @@ JanetArray *janet_array(int32_t capacity) {
|
||||
Janet *data = NULL;
|
||||
if (capacity > 0) {
|
||||
janet_vm_next_collection += capacity * sizeof(Janet);
|
||||
data = (Janet *) malloc(sizeof(Janet) * capacity);
|
||||
data = (Janet *) malloc(sizeof(Janet) * (size_t) capacity);
|
||||
if (NULL == data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ JanetArray *janet_array_n(const Janet *elements, int32_t n) {
|
||||
JanetArray *array = janet_gcalloc(JANET_MEMORY_ARRAY, sizeof(JanetArray));
|
||||
array->capacity = n;
|
||||
array->count = n;
|
||||
array->data = malloc(sizeof(Janet) * n);
|
||||
array->data = malloc(sizeof(Janet) * (size_t) n);
|
||||
if (!array->data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -92,6 +93,9 @@ void janet_array_setcount(JanetArray *array, int32_t count) {
|
||||
|
||||
/* Push a value to the top of the array */
|
||||
void janet_array_push(JanetArray *array, Janet x) {
|
||||
if (array->count == INT32_MAX) {
|
||||
janet_panic("array overflow");
|
||||
}
|
||||
int32_t newcount = array->count + 1;
|
||||
janet_array_ensure(array, newcount, 2);
|
||||
array->data[array->count] = x;
|
||||
@@ -162,9 +166,12 @@ static Janet cfun_array_peek(int32_t argc, Janet *argv) {
|
||||
static Janet cfun_array_push(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, -1);
|
||||
JanetArray *array = janet_getarray(argv, 0);
|
||||
if (INT32_MAX - argc + 1 <= array->count) {
|
||||
janet_panic("array overflow");
|
||||
}
|
||||
int32_t newcount = array->count - 1 + argc;
|
||||
janet_array_ensure(array, newcount, 2);
|
||||
if (argc > 1) memcpy(array->data + array->count, argv + 1, (argc - 1) * sizeof(Janet));
|
||||
if (argc > 1) memcpy(array->data + array->count, argv + 1, (size_t)(argc - 1) * sizeof(Janet));
|
||||
array->count = newcount;
|
||||
return argv[0];
|
||||
}
|
||||
@@ -224,6 +231,9 @@ static Janet cfun_array_insert(int32_t argc, Janet *argv) {
|
||||
janet_panicf("insertion index %d out of range [0,%d]", at, array->count);
|
||||
chunksize = (argc - 2) * sizeof(Janet);
|
||||
restsize = (array->count - at) * sizeof(Janet);
|
||||
if (INT32_MAX - (argc - 2) < array->count) {
|
||||
janet_panic("array overflow");
|
||||
}
|
||||
janet_array_ensure(array, array->count + argc - 2, 2);
|
||||
memmove(array->data + at + argc - 2,
|
||||
array->data + at,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -77,14 +78,12 @@ static const JanetInstructionDef janet_ops[] = {
|
||||
{"divim", JOP_DIVIDE_IMMEDIATE},
|
||||
{"eq", JOP_EQUALS},
|
||||
{"eqim", JOP_EQUALS_IMMEDIATE},
|
||||
{"eqn", JOP_NUMERIC_EQUAL},
|
||||
{"err", JOP_ERROR},
|
||||
{"get", JOP_GET},
|
||||
{"geti", JOP_GET_INDEX},
|
||||
{"gt", JOP_GREATER_THAN},
|
||||
{"gten", JOP_NUMERIC_GREATER_THAN_EQUAL},
|
||||
{"gte", JOP_GREATER_THAN_EQUAL},
|
||||
{"gtim", JOP_GREATER_THAN_IMMEDIATE},
|
||||
{"gtn", JOP_NUMERIC_GREATER_THAN},
|
||||
{"in", JOP_IN},
|
||||
{"jmp", JOP_JUMP},
|
||||
{"jmpif", JOP_JUMP_IF},
|
||||
@@ -98,9 +97,8 @@ static const JanetInstructionDef janet_ops[] = {
|
||||
{"ldu", JOP_LOAD_UPVALUE},
|
||||
{"len", JOP_LENGTH},
|
||||
{"lt", JOP_LESS_THAN},
|
||||
{"lten", JOP_NUMERIC_LESS_THAN_EQUAL},
|
||||
{"lte", JOP_LESS_THAN_EQUAL},
|
||||
{"ltim", JOP_LESS_THAN_IMMEDIATE},
|
||||
{"ltn", JOP_NUMERIC_LESS_THAN},
|
||||
{"mkarr", JOP_MAKE_ARRAY},
|
||||
{"mkbtp", JOP_MAKE_BRACKET_TUPLE},
|
||||
{"mkbuf", JOP_MAKE_BUFFER},
|
||||
@@ -582,7 +580,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
|
||||
x = janet_get1(s, janet_csymbolv("constants"));
|
||||
if (janet_indexed_view(x, &arr, &count)) {
|
||||
def->constants_length = count;
|
||||
def->constants = malloc(sizeof(Janet) * count);
|
||||
def->constants = malloc(sizeof(Janet) * (size_t) count);
|
||||
if (NULL == def->constants) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -661,7 +659,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
|
||||
}
|
||||
/* Allocate bytecode array */
|
||||
def->bytecode_length = blength;
|
||||
def->bytecode = malloc(sizeof(uint32_t) * blength);
|
||||
def->bytecode = malloc(sizeof(uint32_t) * (size_t) blength);
|
||||
if (NULL == def->bytecode) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -703,7 +701,7 @@ static JanetAssembleResult janet_asm1(JanetAssembler *parent, Janet source, int
|
||||
x = janet_get1(s, janet_csymbolv("sourcemap"));
|
||||
if (janet_indexed_view(x, &arr, &count)) {
|
||||
janet_asm_assert(&a, count == def->bytecode_length, "sourcemap must have the same length as the bytecode");
|
||||
def->sourcemap = malloc(sizeof(JanetSourceMapping) * count);
|
||||
def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) count);
|
||||
for (i = 0; i < count; i++) {
|
||||
const Janet *tup;
|
||||
Janet entry = arr[i];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -32,7 +33,7 @@ JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) {
|
||||
uint8_t *data = NULL;
|
||||
if (capacity > 0) {
|
||||
janet_vm_next_collection += capacity;
|
||||
data = malloc(sizeof(uint8_t) * capacity);
|
||||
data = malloc(sizeof(uint8_t) * (size_t) capacity);
|
||||
if (NULL == data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth)
|
||||
int64_t big_capacity = ((int64_t) capacity) * growth;
|
||||
capacity = big_capacity > INT32_MAX ? INT32_MAX : (int32_t) big_capacity;
|
||||
janet_vm_next_collection += capacity - buffer->capacity;
|
||||
new_data = realloc(old, capacity * sizeof(uint8_t));
|
||||
new_data = realloc(old, (size_t) capacity * sizeof(uint8_t));
|
||||
if (NULL == new_data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -93,11 +94,8 @@ enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT] = {
|
||||
JINT_S, /* JOP_MAKE_TABLE */
|
||||
JINT_S, /* JOP_MAKE_TUPLE */
|
||||
JINT_S, /* JOP_MAKE_BRACKET_TUPLE */
|
||||
JINT_SSS, /* JOP_NUMERIC_LESS_THAN */
|
||||
JINT_SSS, /* JOP_NUMERIC_LESS_THAN_EQUAL */
|
||||
JINT_SSS, /* JOP_NUMERIC_GREATER_THAN */
|
||||
JINT_SSS, /* JOP_NUMERIC_GREATER_THAN_EQUAL */
|
||||
JINT_SSS /* JOP_NUMERIC_EQUAL */
|
||||
JINT_SSS, /* JOP_GREATER_THAN_EQUAL */
|
||||
JINT_SSS /* JOP_LESS_THAN_EQUAL */
|
||||
};
|
||||
|
||||
/* Verify some bytecode */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,25 +21,31 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#include "fiber.h"
|
||||
#endif
|
||||
|
||||
void janet_panicv(Janet message) {
|
||||
void janet_signalv(JanetSignal sig, Janet message) {
|
||||
if (janet_vm_return_reg != NULL) {
|
||||
*janet_vm_return_reg = message;
|
||||
janet_vm_fiber->flags |= JANET_FIBER_DID_LONGJUMP;
|
||||
#if defined(JANET_BSD) || defined(JANET_APPLE)
|
||||
_longjmp(*janet_vm_jmp_buf, 1);
|
||||
_longjmp(*janet_vm_jmp_buf, sig);
|
||||
#else
|
||||
longjmp(*janet_vm_jmp_buf, 1);
|
||||
longjmp(*janet_vm_jmp_buf, sig);
|
||||
#endif
|
||||
} else {
|
||||
fputs((const char *)janet_formatc("janet top level panic - %v\n", message), stdout);
|
||||
fputs((const char *)janet_formatc("janet top level signal - %v\n", message), stdout);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void janet_panicv(Janet message) {
|
||||
janet_signalv(JANET_SIGNAL_ERROR, message);
|
||||
}
|
||||
|
||||
void janet_panicf(const char *format, ...) {
|
||||
va_list args;
|
||||
const uint8_t *ret;
|
||||
@@ -149,6 +155,13 @@ DEFINE_OPTLEN(buffer, BUFFER, JanetBuffer *)
|
||||
DEFINE_OPTLEN(table, TABLE, JanetTable *)
|
||||
DEFINE_OPTLEN(array, ARRAY, JanetArray *)
|
||||
|
||||
const char *janet_optcstring(const Janet *argv, int32_t argc, int32_t n, const char *dflt) {
|
||||
if (n >= argc || janet_checktype(argv[n], JANET_NIL)) {
|
||||
return dflt;
|
||||
}
|
||||
return janet_getcstring(argv, n);
|
||||
}
|
||||
|
||||
#undef DEFINE_GETTER
|
||||
#undef DEFINE_OPT
|
||||
#undef DEFINE_OPTLEN
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "compile.h"
|
||||
#include "emit.h"
|
||||
@@ -235,41 +236,23 @@ static JanetSlot compreduce(
|
||||
return t;
|
||||
}
|
||||
|
||||
static JanetSlot do_order_gt(JanetFopts opts, JanetSlot *args) {
|
||||
static JanetSlot do_gt(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_GREATER_THAN, 0);
|
||||
}
|
||||
static JanetSlot do_order_lt(JanetFopts opts, JanetSlot *args) {
|
||||
static JanetSlot do_lt(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_LESS_THAN, 0);
|
||||
}
|
||||
static JanetSlot do_order_gte(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_LESS_THAN, 1);
|
||||
}
|
||||
static JanetSlot do_order_lte(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_GREATER_THAN, 1);
|
||||
}
|
||||
static JanetSlot do_order_eq(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_EQUALS, 0);
|
||||
}
|
||||
static JanetSlot do_order_neq(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_EQUALS, 1);
|
||||
}
|
||||
static JanetSlot do_gt(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_GREATER_THAN, 0);
|
||||
}
|
||||
static JanetSlot do_lt(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_LESS_THAN, 0);
|
||||
}
|
||||
static JanetSlot do_gte(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_GREATER_THAN_EQUAL, 0);
|
||||
return compreduce(opts, args, JOP_GREATER_THAN_EQUAL, 0);
|
||||
}
|
||||
static JanetSlot do_lte(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_LESS_THAN_EQUAL, 0);
|
||||
return compreduce(opts, args, JOP_LESS_THAN_EQUAL, 0);
|
||||
}
|
||||
static JanetSlot do_eq(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_EQUAL, 0);
|
||||
return compreduce(opts, args, JOP_EQUALS, 0);
|
||||
}
|
||||
static JanetSlot do_neq(JanetFopts opts, JanetSlot *args) {
|
||||
return compreduce(opts, args, JOP_NUMERIC_EQUAL, 1);
|
||||
return compreduce(opts, args, JOP_EQUALS, 1);
|
||||
}
|
||||
|
||||
/* Arranged by tag */
|
||||
@@ -293,12 +276,6 @@ static const JanetFunOptimizer optimizers[] = {
|
||||
{NULL, do_rshift},
|
||||
{NULL, do_rshiftu},
|
||||
{fixarity1, do_bnot},
|
||||
{NULL, do_order_gt},
|
||||
{NULL, do_order_lt},
|
||||
{NULL, do_order_gte},
|
||||
{NULL, do_order_lte},
|
||||
{NULL, do_order_eq},
|
||||
{NULL, do_order_neq},
|
||||
{NULL, do_gt},
|
||||
{NULL, do_lt},
|
||||
{NULL, do_gte},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "compile.h"
|
||||
#include "emit.h"
|
||||
@@ -582,18 +583,21 @@ static int macroexpand1(
|
||||
es = janet_formatc("macro arity mismatch, expected at most %d, got %d", maxar, arity);
|
||||
c->result.macrofiber = NULL;
|
||||
janetc_error(c, es);
|
||||
return 0;
|
||||
}
|
||||
/* Set env */
|
||||
fiberp->env = c->env;
|
||||
int lock = janet_gclock();
|
||||
JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &x);
|
||||
Janet tempOut;
|
||||
JanetSignal status = janet_continue(fiberp, janet_wrap_nil(), &tempOut);
|
||||
janet_gcunlock(lock);
|
||||
if (status != JANET_SIGNAL_OK) {
|
||||
const uint8_t *es = janet_formatc("(macro) %V", x);
|
||||
const uint8_t *es = janet_formatc("(macro) %V", tempOut);
|
||||
c->result.macrofiber = fiberp;
|
||||
janetc_error(c, es);
|
||||
return 0;
|
||||
} else {
|
||||
*out = x;
|
||||
*out = tempOut;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -704,7 +708,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
|
||||
/* Copy bytecode (only last chunk) */
|
||||
def->bytecode_length = janet_v_count(c->buffer) - scope->bytecode_start;
|
||||
if (def->bytecode_length) {
|
||||
size_t s = sizeof(int32_t) * def->bytecode_length;
|
||||
size_t s = sizeof(int32_t) * (size_t) def->bytecode_length;
|
||||
def->bytecode = malloc(s);
|
||||
if (NULL == def->bytecode) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
@@ -712,7 +716,7 @@ JanetFuncDef *janetc_pop_funcdef(JanetCompiler *c) {
|
||||
memcpy(def->bytecode, c->buffer + scope->bytecode_start, s);
|
||||
janet_v__cnt(c->buffer) = scope->bytecode_start;
|
||||
if (NULL != c->mapbuffer && c->source) {
|
||||
size_t s = sizeof(JanetSourceMapping) * def->bytecode_length;
|
||||
size_t s = sizeof(JanetSourceMapping) * (size_t) def->bytecode_length;
|
||||
def->sourcemap = malloc(s);
|
||||
if (NULL == def->sourcemap) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -24,6 +24,7 @@
|
||||
#define JANET_COMPILE_H
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "regalloc.h"
|
||||
#endif
|
||||
@@ -48,20 +49,14 @@
|
||||
#define JANET_FUN_RSHIFT 17
|
||||
#define JANET_FUN_RSHIFTU 18
|
||||
#define JANET_FUN_BNOT 19
|
||||
#define JANET_FUN_ORDER_GT 20
|
||||
#define JANET_FUN_ORDER_LT 21
|
||||
#define JANET_FUN_ORDER_GTE 22
|
||||
#define JANET_FUN_ORDER_LTE 23
|
||||
#define JANET_FUN_ORDER_EQ 24
|
||||
#define JANET_FUN_ORDER_NEQ 25
|
||||
#define JANET_FUN_GT 26
|
||||
#define JANET_FUN_LT 27
|
||||
#define JANET_FUN_GTE 28
|
||||
#define JANET_FUN_LTE 29
|
||||
#define JANET_FUN_EQ 30
|
||||
#define JANET_FUN_NEQ 31
|
||||
#define JANET_FUN_PROP 32
|
||||
#define JANET_FUN_GET 33
|
||||
#define JANET_FUN_GT 20
|
||||
#define JANET_FUN_LT 21
|
||||
#define JANET_FUN_GTE 22
|
||||
#define JANET_FUN_LTE 23
|
||||
#define JANET_FUN_EQ 24
|
||||
#define JANET_FUN_NEQ 25
|
||||
#define JANET_FUN_PROP 26
|
||||
#define JANET_FUN_GET 27
|
||||
|
||||
/* Compiler typedefs */
|
||||
typedef struct JanetCompiler JanetCompiler;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include <math.h>
|
||||
#include "compile.h"
|
||||
@@ -401,17 +402,19 @@ static Janet janet_core_gccollect(int32_t argc, Janet *argv) {
|
||||
|
||||
static Janet janet_core_gcsetinterval(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
int32_t val = janet_getinteger(argv, 0);
|
||||
if (val < 0)
|
||||
janet_panic("expected non-negative integer");
|
||||
janet_vm_gc_interval = val;
|
||||
size_t s = janet_getsize(argv, 0);
|
||||
/* limit interval to 48 bits */
|
||||
if (s > 0xFFFFFFFFFFFFUl) {
|
||||
janet_panic("interval too large");
|
||||
}
|
||||
janet_vm_gc_interval = s;
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static Janet janet_core_gcinterval(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 0);
|
||||
return janet_wrap_number(janet_vm_gc_interval);
|
||||
return janet_wrap_number((double) janet_vm_gc_interval);
|
||||
}
|
||||
|
||||
static Janet janet_core_type(int32_t argc, Janet *argv) {
|
||||
@@ -1090,45 +1093,23 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
||||
"for positive shifts the return value will always be positive."));
|
||||
|
||||
/* Variadic comparators */
|
||||
templatize_comparator(env, JANET_FUN_ORDER_GT, "order>", 0, JOP_GREATER_THAN,
|
||||
JDOC("(order> & xs)\n\n"
|
||||
"Check if xs is strictly descending according to a total order "
|
||||
"over all values. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_ORDER_LT, "order<", 0, JOP_LESS_THAN,
|
||||
JDOC("(order< & xs)\n\n"
|
||||
"Check if xs is strictly increasing according to a total order "
|
||||
"over all values. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_ORDER_GTE, "order>=", 1, JOP_LESS_THAN,
|
||||
JDOC("(order>= & xs)\n\n"
|
||||
"Check if xs is not increasing according to a total order "
|
||||
"over all values. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_ORDER_LTE, "order<=", 1, JOP_GREATER_THAN,
|
||||
JDOC("(order<= & xs)\n\n"
|
||||
"Check if xs is not decreasing according to a total order "
|
||||
"over all values. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_ORDER_EQ, "=", 0, JOP_EQUALS,
|
||||
JDOC("(= & xs)\n\n"
|
||||
"Returns true if all values in xs are the same, false otherwise."));
|
||||
templatize_comparator(env, JANET_FUN_ORDER_NEQ, "not=", 1, JOP_EQUALS,
|
||||
JDOC("(not= & xs)\n\n"
|
||||
"Return true if any values in xs are not equal, otherwise false."));
|
||||
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_NUMERIC_GREATER_THAN,
|
||||
templatize_comparator(env, JANET_FUN_GT, ">", 0, JOP_GREATER_THAN,
|
||||
JDOC("(> & xs)\n\n"
|
||||
"Check if xs is in numerically descending order. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_NUMERIC_LESS_THAN,
|
||||
templatize_comparator(env, JANET_FUN_LT, "<", 0, JOP_LESS_THAN,
|
||||
JDOC("(< & xs)\n\n"
|
||||
"Check if xs is in numerically ascending order. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_NUMERIC_GREATER_THAN_EQUAL,
|
||||
templatize_comparator(env, JANET_FUN_GTE, ">=", 0, JOP_GREATER_THAN_EQUAL,
|
||||
JDOC("(>= & xs)\n\n"
|
||||
"Check if xs is in numerically non-ascending order. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_NUMERIC_LESS_THAN_EQUAL,
|
||||
templatize_comparator(env, JANET_FUN_LTE, "<=", 0, JOP_LESS_THAN_EQUAL,
|
||||
JDOC("(<= & xs)\n\n"
|
||||
"Check if xs is in numerically non-descending order. Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_EQ, "==", 0, JOP_NUMERIC_EQUAL,
|
||||
JDOC("(== & xs)\n\n"
|
||||
templatize_comparator(env, JANET_FUN_EQ, "=", 0, JOP_EQUALS,
|
||||
JDOC("(= & xs)\n\n"
|
||||
"Check if all values in xs are numerically equal (4.0 == 4). Returns a boolean."));
|
||||
templatize_comparator(env, JANET_FUN_NEQ, "not==", 1, JOP_NUMERIC_EQUAL,
|
||||
JDOC("(not== & xs)\n\n"
|
||||
templatize_comparator(env, JANET_FUN_NEQ, "not=", 1, JOP_EQUALS,
|
||||
JDOC("(not= & xs)\n\n"
|
||||
"Check if any values in xs are not numerically equal (3.0 not== 4). Returns a boolean."));
|
||||
|
||||
/* Platform detection */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "state.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "emit.h"
|
||||
#include "vector.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
32
src/core/features.h
Normal file
32
src/core/features.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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.
|
||||
*/
|
||||
|
||||
/* Feature test macros */
|
||||
|
||||
#ifndef JANET_FEATURES_H_defined
|
||||
#define JANET_FEATURES_H_defined
|
||||
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "fiber.h"
|
||||
#include "state.h"
|
||||
@@ -34,7 +35,7 @@ static void fiber_reset(JanetFiber *fiber) {
|
||||
fiber->stackstart = JANET_FRAME_SIZE;
|
||||
fiber->stacktop = JANET_FRAME_SIZE;
|
||||
fiber->child = NULL;
|
||||
fiber->flags = JANET_FIBER_MASK_YIELD;
|
||||
fiber->flags = JANET_FIBER_MASK_YIELD | JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
|
||||
fiber->env = NULL;
|
||||
janet_fiber_set_status(fiber, JANET_STATUS_NEW);
|
||||
}
|
||||
@@ -46,7 +47,7 @@ static JanetFiber *fiber_alloc(int32_t capacity) {
|
||||
capacity = 32;
|
||||
}
|
||||
fiber->capacity = capacity;
|
||||
data = malloc(sizeof(Janet) * capacity);
|
||||
data = malloc(sizeof(Janet) * (size_t) capacity);
|
||||
if (NULL == data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -210,7 +211,7 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
||||
static void janet_env_detach(JanetFuncEnv *env) {
|
||||
/* Check for closure environment */
|
||||
if (env) {
|
||||
size_t s = sizeof(Janet) * env->length;
|
||||
size_t s = sizeof(Janet) * (size_t) env->length;
|
||||
Janet *vmem = malloc(s);
|
||||
janet_vm_next_collection += (uint32_t) s;
|
||||
if (NULL == vmem) {
|
||||
@@ -368,7 +369,7 @@ static Janet cfun_fiber_new(int32_t argc, Janet *argv) {
|
||||
if (argc == 2) {
|
||||
int32_t i;
|
||||
JanetByteView view = janet_getbytes(argv, 1);
|
||||
fiber->flags = 0;
|
||||
fiber->flags = JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
|
||||
janet_fiber_set_status(fiber, JANET_STATUS_NEW);
|
||||
for (i = 0; i < view.len; i++) {
|
||||
if (view.bytes[i] >= '0' && view.bytes[i] <= '9') {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -27,6 +27,34 @@
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
/* Fiber signal masks. */
|
||||
#define JANET_FIBER_MASK_ERROR 2
|
||||
#define JANET_FIBER_MASK_DEBUG 4
|
||||
#define JANET_FIBER_MASK_YIELD 8
|
||||
|
||||
#define JANET_FIBER_MASK_USER0 (16 << 0)
|
||||
#define JANET_FIBER_MASK_USER1 (16 << 1)
|
||||
#define JANET_FIBER_MASK_USER2 (16 << 2)
|
||||
#define JANET_FIBER_MASK_USER3 (16 << 3)
|
||||
#define JANET_FIBER_MASK_USER4 (16 << 4)
|
||||
#define JANET_FIBER_MASK_USER5 (16 << 5)
|
||||
#define JANET_FIBER_MASK_USER6 (16 << 6)
|
||||
#define JANET_FIBER_MASK_USER7 (16 << 7)
|
||||
#define JANET_FIBER_MASK_USER8 (16 << 8)
|
||||
#define JANET_FIBER_MASK_USER9 (16 << 9)
|
||||
|
||||
#define JANET_FIBER_MASK_USERN(N) (16 << (N))
|
||||
#define JANET_FIBER_MASK_USER 0x3FF0
|
||||
|
||||
#define JANET_FIBER_STATUS_MASK 0xFF0000
|
||||
#define JANET_FIBER_STATUS_OFFSET 16
|
||||
|
||||
#define JANET_FIBER_BREAKPOINT 0x1000000
|
||||
#define JANET_FIBER_RESUME_NO_USEVAL 0x2000000
|
||||
#define JANET_FIBER_RESUME_NO_SKIP 0x4000000
|
||||
#define JANET_FIBER_DID_LONGJUMP 0x8000000
|
||||
#define JANET_FIBER_FLAG_MASK 0xF000000
|
||||
|
||||
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
|
||||
|
||||
#define janet_fiber_set_status(f, s) do {\
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#include "symcache.h"
|
||||
@@ -30,14 +31,14 @@
|
||||
|
||||
/* GC State */
|
||||
JANET_THREAD_LOCAL void *janet_vm_blocks;
|
||||
JANET_THREAD_LOCAL uint32_t janet_vm_gc_interval;
|
||||
JANET_THREAD_LOCAL uint32_t janet_vm_next_collection;
|
||||
JANET_THREAD_LOCAL size_t janet_vm_gc_interval;
|
||||
JANET_THREAD_LOCAL size_t janet_vm_next_collection;
|
||||
JANET_THREAD_LOCAL int janet_vm_gc_suspend = 0;
|
||||
|
||||
/* Roots */
|
||||
JANET_THREAD_LOCAL Janet *janet_vm_roots;
|
||||
JANET_THREAD_LOCAL uint32_t janet_vm_root_count;
|
||||
JANET_THREAD_LOCAL uint32_t janet_vm_root_capacity;
|
||||
JANET_THREAD_LOCAL size_t janet_vm_root_count;
|
||||
JANET_THREAD_LOCAL size_t janet_vm_root_capacity;
|
||||
|
||||
/* Scratch Memory */
|
||||
#ifdef JANET_64
|
||||
@@ -64,9 +65,9 @@ static void janet_mark_string(const uint8_t *str);
|
||||
static void janet_mark_fiber(JanetFiber *fiber);
|
||||
static void janet_mark_abstract(void *adata);
|
||||
|
||||
/* Local state that is only temporary */
|
||||
/* Local state that is only temporary for gc */
|
||||
static JANET_THREAD_LOCAL uint32_t depth = JANET_RECURSION_GUARD;
|
||||
static JANET_THREAD_LOCAL uint32_t orig_rootcount;
|
||||
static JANET_THREAD_LOCAL size_t orig_rootcount;
|
||||
|
||||
/* Mark a value */
|
||||
void janet_mark(Janet x) {
|
||||
@@ -347,7 +348,7 @@ void *janet_gcalloc(enum JanetMemoryType type, size_t size) {
|
||||
mem->flags = type;
|
||||
|
||||
/* Prepend block to heap list */
|
||||
janet_vm_next_collection += (int32_t) size;
|
||||
janet_vm_next_collection += size;
|
||||
mem->next = janet_vm_blocks;
|
||||
janet_vm_blocks = mem;
|
||||
|
||||
@@ -390,9 +391,9 @@ void janet_collect(void) {
|
||||
* and all of its children. If gcroot is called on a value n times, unroot
|
||||
* must also be called n times to remove it as a gc root. */
|
||||
void janet_gcroot(Janet root) {
|
||||
uint32_t newcount = janet_vm_root_count + 1;
|
||||
size_t newcount = janet_vm_root_count + 1;
|
||||
if (newcount > janet_vm_root_capacity) {
|
||||
uint32_t newcap = 2 * newcount;
|
||||
size_t newcap = 2 * newcount;
|
||||
janet_vm_roots = realloc(janet_vm_roots, sizeof(Janet) * newcap);
|
||||
if (NULL == janet_vm_roots) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
@@ -490,6 +491,16 @@ void *janet_smalloc(size_t size) {
|
||||
return (char *)mem + SCRATCH_HDR_SIZE;
|
||||
}
|
||||
|
||||
void *janet_scalloc(size_t nmemb, size_t size) {
|
||||
if (nmemb && size > (size_t) -1 / size) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
size_t n = nmemb * size;
|
||||
void *p = janet_smalloc(n);
|
||||
memset(p, 0, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *janet_srealloc(void *mem, size_t size) {
|
||||
if (NULL == mem) return janet_smalloc(size);
|
||||
mem = (char *)mem - SCRATCH_HDR_SIZE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -24,6 +24,7 @@
|
||||
#define JANET_GC_H
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose & contributors
|
||||
* Copyright (c) 2020 Calvin Rose & contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -39,6 +40,24 @@
|
||||
static int it_s64_get(void *p, Janet key, Janet *out);
|
||||
static int it_u64_get(void *p, Janet key, Janet *out);
|
||||
|
||||
static int32_t janet_int64_hash(void *p1, size_t size) {
|
||||
(void) size;
|
||||
int32_t *words = p1;
|
||||
return words[0] ^ words[1];
|
||||
}
|
||||
|
||||
static int janet_int64_compare(void *p1, void *p2) {
|
||||
int64_t x = *((int64_t *)p1);
|
||||
int64_t y = *((int64_t *)p2);
|
||||
return x == y ? 0 : x < y ? -1 : 1;
|
||||
}
|
||||
|
||||
static int janet_uint64_compare(void *p1, void *p2) {
|
||||
uint64_t x = *((uint64_t *)p1);
|
||||
uint64_t y = *((uint64_t *)p2);
|
||||
return x == y ? 0 : x < y ? -1 : 1;
|
||||
}
|
||||
|
||||
static void int64_marshal(void *p, JanetMarshalContext *ctx) {
|
||||
janet_marshal_abstract(ctx, p);
|
||||
janet_marshal_int64(ctx, *((int64_t *)p));
|
||||
@@ -70,7 +89,9 @@ static const JanetAbstractType it_s64_type = {
|
||||
NULL,
|
||||
int64_marshal,
|
||||
int64_unmarshal,
|
||||
it_s64_tostring
|
||||
it_s64_tostring,
|
||||
janet_int64_compare,
|
||||
janet_int64_hash
|
||||
};
|
||||
|
||||
static const JanetAbstractType it_u64_type = {
|
||||
@@ -81,7 +102,9 @@ static const JanetAbstractType it_u64_type = {
|
||||
NULL,
|
||||
int64_marshal,
|
||||
int64_unmarshal,
|
||||
it_u64_tostring
|
||||
it_u64_tostring,
|
||||
janet_uint64_compare,
|
||||
janet_int64_hash
|
||||
};
|
||||
|
||||
int64_t janet_unwrap_s64(Janet x) {
|
||||
@@ -297,7 +320,7 @@ static JanetMethod it_s64_methods[] = {
|
||||
{">", cfun_it_s64_gt},
|
||||
{"<=", cfun_it_s64_le},
|
||||
{">=", cfun_it_s64_ge},
|
||||
{"==", cfun_it_s64_eq},
|
||||
{"=", cfun_it_s64_eq},
|
||||
{"!=", cfun_it_s64_ne},
|
||||
{"&", cfun_it_s64_and},
|
||||
{"|", cfun_it_s64_or},
|
||||
@@ -329,7 +352,7 @@ static JanetMethod it_u64_methods[] = {
|
||||
{">", cfun_it_u64_gt},
|
||||
{"<=", cfun_it_u64_le},
|
||||
{">=", cfun_it_u64_ge},
|
||||
{"==", cfun_it_u64_eq},
|
||||
{"=", cfun_it_u64_eq},
|
||||
{"!=", cfun_it_u64_ne},
|
||||
{"&", cfun_it_u64_and},
|
||||
{"|", cfun_it_u64_or},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -49,6 +50,8 @@ JanetAbstractType cfun_io_filetype = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -134,6 +137,15 @@ static Janet cfun_io_popen(int32_t argc, Janet *argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static Janet cfun_io_temp(int32_t argc, Janet *argv) {
|
||||
(void)argv;
|
||||
janet_fixarity(argc, 0);
|
||||
FILE *tmp = tmpfile();
|
||||
if (!tmp)
|
||||
janet_panicf("unable to create temporary file - %s", strerror(errno));
|
||||
return janet_makefile(tmp, JANET_FILE_WRITE | JANET_FILE_READ | JANET_FILE_BINARY);
|
||||
}
|
||||
|
||||
static Janet cfun_io_fopen(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
const uint8_t *fname = janet_getstring(argv, 0);
|
||||
@@ -565,6 +577,12 @@ static const JanetReg io_cfuns[] = {
|
||||
JDOC("(eprinf fmt & xs)\n\n"
|
||||
"Like eprintf but with no trailing newline.")
|
||||
},
|
||||
{
|
||||
"file/temp", cfun_io_temp,
|
||||
JDOC("(file/temp)\n\n"
|
||||
"Open an anonymous temporary file that is removed on close."
|
||||
"Raises an error on failure.")
|
||||
},
|
||||
{
|
||||
"file/open", cfun_io_fopen,
|
||||
JDOC("(file/open path &opt mode)\n\n"
|
||||
@@ -604,7 +622,8 @@ static const JanetReg io_cfuns[] = {
|
||||
JDOC("(file/close f)\n\n"
|
||||
"Close a file and release all related resources. When you are "
|
||||
"done reading a file, close it to prevent a resource leak and let "
|
||||
"other processes read the file.")
|
||||
"other processes read the file. If the file is the result of a file/popen "
|
||||
"call, close waits for and returns the process exit status.")
|
||||
},
|
||||
{
|
||||
"file/read", cfun_io_fread,
|
||||
@@ -660,6 +679,20 @@ FILE *janet_getfile(const Janet *argv, int32_t n, int *flags) {
|
||||
return iof->file;
|
||||
}
|
||||
|
||||
Janet janet_makefile(FILE *f, int flags) {
|
||||
return makef(f, flags);
|
||||
}
|
||||
|
||||
JanetAbstract janet_checkfile(Janet j) {
|
||||
return janet_checkabstract(j, &cfun_io_filetype);
|
||||
}
|
||||
|
||||
FILE *janet_unwrapfile(Janet j, int *flags) {
|
||||
IOFile *iof = janet_unwrap_abstract(j);
|
||||
if (NULL != flags) *flags = iof->flags;
|
||||
return iof->file;
|
||||
}
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_io(JanetTable *env) {
|
||||
janet_core_cfuns(env, NULL, io_cfuns);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#include "vector.h"
|
||||
@@ -692,7 +693,7 @@ static const uint8_t *unmarshal_one_env(
|
||||
janet_panic("invalid funcenv length");
|
||||
} else {
|
||||
/* Off stack variant */
|
||||
env->as.values = malloc(sizeof(Janet) * length);
|
||||
env->as.values = malloc(sizeof(Janet) * (size_t) length);
|
||||
if (!env->as.values) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -797,7 +798,7 @@ static const uint8_t *unmarshal_one_def(
|
||||
|
||||
/* Unmarshal environments */
|
||||
if (def->flags & JANET_FUNCDEF_FLAG_HASENVS) {
|
||||
def->environments = calloc(1, sizeof(int32_t) * environments_length);
|
||||
def->environments = calloc(1, sizeof(int32_t) * (size_t) environments_length);
|
||||
if (!def->environments) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -811,7 +812,7 @@ static const uint8_t *unmarshal_one_def(
|
||||
|
||||
/* Unmarshal sub funcdefs */
|
||||
if (def->flags & JANET_FUNCDEF_FLAG_HASDEFS) {
|
||||
def->defs = calloc(1, sizeof(JanetFuncDef *) * defs_length);
|
||||
def->defs = calloc(1, sizeof(JanetFuncDef *) * (size_t) defs_length);
|
||||
if (!def->defs) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -826,7 +827,7 @@ static const uint8_t *unmarshal_one_def(
|
||||
/* Unmarshal source maps if needed */
|
||||
if (def->flags & JANET_FUNCDEF_FLAG_HASSOURCEMAP) {
|
||||
int32_t current = 0;
|
||||
def->sourcemap = malloc(sizeof(JanetSourceMapping) * bytecode_length);
|
||||
def->sourcemap = malloc(sizeof(JanetSourceMapping) * (size_t) bytecode_length);
|
||||
if (!def->sourcemap) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,13 +20,14 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
static JANET_THREAD_LOCAL JanetRNG janet_vm_rng = {0, 0, 0, 0, 0};
|
||||
|
||||
static int janet_rng_get(void *p, Janet key, Janet *out);
|
||||
@@ -59,6 +60,8 @@ static JanetAbstractType JanetRNG_type = {
|
||||
NULL,
|
||||
janet_rng_marshal,
|
||||
janet_rng_unmarshal,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -51,6 +52,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
extern char **environ;
|
||||
#ifdef JANET_THREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* For macos */
|
||||
@@ -65,6 +69,34 @@ extern char **environ;
|
||||
void arc4random_buf(void *buf, size_t nbytes);
|
||||
#endif
|
||||
|
||||
/* Access to some global variables should be synchronized if not in single threaded mode, as
|
||||
* setenv/getenv are not thread safe. */
|
||||
#ifdef JANET_THREADS
|
||||
# ifdef JANET_WINDOWS
|
||||
static int env_lock_initialized = 0;
|
||||
static CRITICAL_SECTION env_lock;
|
||||
static void janet_lock_environ(void) {
|
||||
EnterCriticalSection(&env_lock);
|
||||
}
|
||||
static void janet_unlock_environ(void) {
|
||||
LeaveCriticalSection(&env_lock);
|
||||
}
|
||||
# else
|
||||
static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static void janet_lock_environ(void) {
|
||||
pthread_mutex_lock(&env_lock);
|
||||
}
|
||||
static void janet_unlock_environ(void) {
|
||||
pthread_mutex_unlock(&env_lock);
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
static void janet_lock_environ(void) {
|
||||
}
|
||||
static void janet_unlock_environ(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* JANET_REDCUED_OS */
|
||||
|
||||
/* Core OS functions */
|
||||
@@ -129,13 +161,16 @@ static Janet os_arch(int32_t argc, Janet *argv) {
|
||||
|
||||
static Janet os_exit(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 1);
|
||||
int status;
|
||||
if (argc == 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
status = EXIT_SUCCESS;
|
||||
} else if (janet_checkint(argv[0])) {
|
||||
exit(janet_unwrap_integer(argv[0]));
|
||||
status = janet_unwrap_integer(argv[0]);
|
||||
} else {
|
||||
exit(EXIT_FAILURE);
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
janet_deinit();
|
||||
exit(status);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
@@ -144,7 +179,7 @@ static Janet os_exit(int32_t argc, Janet *argv) {
|
||||
|
||||
static Janet os_getenv(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 1);
|
||||
janet_arity(argc, 1, 2);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
@@ -156,7 +191,7 @@ static char **os_execute_env(int32_t argc, const Janet *argv) {
|
||||
char **envp = NULL;
|
||||
if (argc > 2) {
|
||||
JanetDictView dict = janet_getdictionary(argv, 2);
|
||||
envp = janet_smalloc(sizeof(char *) * (dict.len + 1));
|
||||
envp = janet_smalloc(sizeof(char *) * ((size_t)dict.len + 1));
|
||||
int32_t j = 0;
|
||||
for (int32_t i = 0; i < dict.cap; i++) {
|
||||
const JanetKV *kv = dict.kvs + i;
|
||||
@@ -175,7 +210,7 @@ static char **os_execute_env(int32_t argc, const Janet *argv) {
|
||||
}
|
||||
}
|
||||
if (skip) continue;
|
||||
char *envitem = janet_smalloc(klen + vlen + 2);
|
||||
char *envitem = janet_smalloc((size_t) klen + (size_t) vlen + 2);
|
||||
memcpy(envitem, keys, klen);
|
||||
envitem[klen] = '=';
|
||||
memcpy(envitem + klen + 1, vals, vlen);
|
||||
@@ -337,7 +372,7 @@ static Janet os_execute(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_integer(status);
|
||||
#else
|
||||
|
||||
const char **child_argv = janet_smalloc(sizeof(char *) * (exargs.len + 1));
|
||||
const char **child_argv = janet_smalloc(sizeof(char *) * ((size_t) exargs.len + 1));
|
||||
for (int32_t i = 0; i < exargs.len; i++)
|
||||
child_argv[i] = janet_getcstring(exargs.items, i);
|
||||
child_argv[exargs.len] = NULL;
|
||||
@@ -385,6 +420,7 @@ static Janet os_environ(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 0);
|
||||
int32_t nenv = 0;
|
||||
janet_lock_environ();
|
||||
char **env = environ;
|
||||
while (*env++)
|
||||
nenv += 1;
|
||||
@@ -392,7 +428,10 @@ static Janet os_environ(int32_t argc, Janet *argv) {
|
||||
for (int32_t i = 0; i < nenv; i++) {
|
||||
char *e = environ[i];
|
||||
char *eq = strchr(e, '=');
|
||||
if (!eq) janet_panic("no '=' in environ");
|
||||
if (!eq) {
|
||||
janet_unlock_environ();
|
||||
janet_panic("no '=' in environ");
|
||||
}
|
||||
char *v = eq + 1;
|
||||
int32_t full_len = (int32_t) strlen(e);
|
||||
int32_t val_len = (int32_t) strlen(v);
|
||||
@@ -402,16 +441,22 @@ static Janet os_environ(int32_t argc, Janet *argv) {
|
||||
janet_stringv((const uint8_t *)v, val_len)
|
||||
);
|
||||
}
|
||||
janet_unlock_environ();
|
||||
return janet_wrap_table(t);
|
||||
}
|
||||
|
||||
static Janet os_getenv(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
janet_arity(argc, 1, 2);
|
||||
const char *cstr = janet_getcstring(argv, 0);
|
||||
const char *res = getenv(cstr);
|
||||
return res
|
||||
? janet_cstringv(res)
|
||||
: janet_wrap_nil();
|
||||
janet_lock_environ();
|
||||
Janet ret = res
|
||||
? janet_cstringv(res)
|
||||
: argc == 2
|
||||
? argv[1]
|
||||
: janet_wrap_nil();
|
||||
janet_unlock_environ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Janet os_setenv(int32_t argc, Janet *argv) {
|
||||
@@ -424,11 +469,14 @@ static Janet os_setenv(int32_t argc, Janet *argv) {
|
||||
#endif
|
||||
janet_arity(argc, 1, 2);
|
||||
const char *ks = janet_getcstring(argv, 0);
|
||||
if (argc == 1 || janet_checktype(argv[1], JANET_NIL)) {
|
||||
const char *vs = janet_optcstring(argv, argc, 1, NULL);
|
||||
janet_lock_environ();
|
||||
if (NULL == vs) {
|
||||
UNSETENV(ks);
|
||||
} else {
|
||||
SETENV(ks, janet_getcstring(argv, 1));
|
||||
SETENV(ks, vs);
|
||||
}
|
||||
janet_unlock_environ();
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
@@ -925,7 +973,7 @@ static const JanetReg os_cfuns[] = {
|
||||
},
|
||||
{
|
||||
"os/getenv", os_getenv,
|
||||
JDOC("(os/getenv variable)\n\n"
|
||||
JDOC("(os/getenv variable &opt dflt)\n\n"
|
||||
"Get the string value of an environment variable.")
|
||||
},
|
||||
{
|
||||
@@ -1082,5 +1130,13 @@ static const JanetReg os_cfuns[] = {
|
||||
|
||||
/* Module entry point */
|
||||
void janet_lib_os(JanetTable *env) {
|
||||
#if !defined(JANET_REDUCED_OS) && defined(JANET_WINDOWS) && defined(JANET_THREADS)
|
||||
/* During start up, the top-most abstract machine (thread)
|
||||
* in the thread tree sets up the critical section. */
|
||||
if (!env_lock_initialized) {
|
||||
InitializeCriticalSection(&env_lock);
|
||||
env_lock_initialized = 1;
|
||||
}
|
||||
#endif
|
||||
janet_core_cfuns(env, NULL, os_cfuns);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -740,6 +741,8 @@ static JanetAbstractType janet_parse_parsertype = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -793,6 +796,7 @@ static Janet cfun_parse_insert(int32_t argc, Janet *argv) {
|
||||
p->column--;
|
||||
s = p->states + p->statecount - 1;
|
||||
}
|
||||
if (s->flags & PFLAG_COMMENT) s--;
|
||||
if (s->flags & PFLAG_CONTAINER) {
|
||||
s->argn++;
|
||||
if (p->statecount == 1) p->pending++;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
@@ -727,6 +728,13 @@ static void spec_opt(Builder *b, int32_t argc, const Janet *argv) {
|
||||
emit_3(r, RULE_BETWEEN, 0, 1, subrule);
|
||||
}
|
||||
|
||||
static void spec_repeat(Builder *b, int32_t argc, const Janet *argv) {
|
||||
peg_fixarity(b, argc, 2);
|
||||
Reserve r = reserve(b, 4);
|
||||
int32_t n = peg_getnat(b, argv[0]);
|
||||
uint32_t subrule = peg_compile1(b, argv[1]);
|
||||
emit_3(r, RULE_BETWEEN, n, n, subrule);
|
||||
}
|
||||
|
||||
/* Rule of the form [rule] */
|
||||
static void spec_onerule(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
|
||||
@@ -869,6 +877,7 @@ static const SpecialPair peg_specials[] = {
|
||||
{"position", spec_position},
|
||||
{"quote", spec_capture},
|
||||
{"range", spec_range},
|
||||
{"repeat", spec_repeat},
|
||||
{"replace", spec_replace},
|
||||
{"sequence", spec_sequence},
|
||||
{"set", spec_set},
|
||||
@@ -1045,7 +1054,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
size_t bytecode_start = size_padded(sizeof(Peg), sizeof(uint32_t));
|
||||
size_t bytecode_size = bytecode_len * sizeof(uint32_t);
|
||||
size_t constants_start = size_padded(bytecode_start + bytecode_size, sizeof(Janet));
|
||||
size_t total_size = constants_start + sizeof(Janet) * num_constants;
|
||||
size_t total_size = constants_start + sizeof(Janet) * (size_t) num_constants;
|
||||
|
||||
/* DOS prevention? I.E. we could read bytecode and constants before
|
||||
* hand so we don't allocated a ton of memory on bad, short input */
|
||||
@@ -1203,6 +1212,8 @@ static const JanetAbstractType peg_type = {
|
||||
NULL,
|
||||
peg_marshal,
|
||||
peg_unmarshal,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
142
src/core/pp.c
142
src/core/pp.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,16 +20,17 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#include "state.h"
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Implements a pretty printer for Janet. The pretty printer
|
||||
* is simple and not that flexible, but fast. */
|
||||
|
||||
@@ -180,49 +181,42 @@ static void janet_escape_buffer_b(JanetBuffer *buffer, JanetBuffer *bx) {
|
||||
janet_escape_string_impl(buffer, bx->data, bx->count);
|
||||
}
|
||||
|
||||
void janet_description_b(JanetBuffer *buffer, Janet x) {
|
||||
void janet_to_string_b(JanetBuffer *buffer, Janet x) {
|
||||
switch (janet_type(x)) {
|
||||
case JANET_NIL:
|
||||
janet_buffer_push_cstring(buffer, "nil");
|
||||
return;
|
||||
break;
|
||||
case JANET_BOOLEAN:
|
||||
janet_buffer_push_cstring(buffer,
|
||||
janet_unwrap_boolean(x) ? "true" : "false");
|
||||
return;
|
||||
break;
|
||||
case JANET_NUMBER:
|
||||
number_to_string_b(buffer, janet_unwrap_number(x));
|
||||
return;
|
||||
case JANET_KEYWORD:
|
||||
janet_buffer_push_u8(buffer, ':');
|
||||
/* fallthrough */
|
||||
break;
|
||||
case JANET_STRING:
|
||||
case JANET_SYMBOL:
|
||||
case JANET_KEYWORD:
|
||||
janet_buffer_push_bytes(buffer,
|
||||
janet_unwrap_string(x),
|
||||
janet_string_length(janet_unwrap_string(x)));
|
||||
return;
|
||||
case JANET_STRING:
|
||||
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
||||
return;
|
||||
break;
|
||||
case JANET_BUFFER: {
|
||||
JanetBuffer *b = janet_unwrap_buffer(x);
|
||||
if (b == buffer) {
|
||||
/* Ensures buffer won't resize while escaping */
|
||||
janet_buffer_ensure(b, 5 * b->count + 3, 1);
|
||||
}
|
||||
janet_escape_buffer_b(buffer, b);
|
||||
return;
|
||||
JanetBuffer *to = janet_unwrap_buffer(x);
|
||||
/* Prevent resizing buffer while appending */
|
||||
if (buffer == to) janet_buffer_extra(buffer, to->count);
|
||||
janet_buffer_push_bytes(buffer, to->data, to->count);
|
||||
break;
|
||||
}
|
||||
case JANET_ABSTRACT: {
|
||||
void *p = janet_unwrap_abstract(x);
|
||||
const JanetAbstractType *at = janet_abstract_type(p);
|
||||
if (at->tostring) {
|
||||
at->tostring(p, buffer);
|
||||
JanetAbstract p = janet_unwrap_abstract(x);
|
||||
const JanetAbstractType *t = janet_abstract_type(p);
|
||||
if (t->tostring != NULL) {
|
||||
t->tostring(p, buffer);
|
||||
} else {
|
||||
const char *n = at->name;
|
||||
string_description_b(buffer, n, janet_unwrap_abstract(x));
|
||||
string_description_b(buffer, t->name, p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case JANET_CFUNCTION: {
|
||||
Janet check = janet_table_get(janet_vm_registry, x);
|
||||
if (janet_checktype(check, JANET_SYMBOL)) {
|
||||
@@ -254,26 +248,42 @@ void janet_description_b(JanetBuffer *buffer, Janet x) {
|
||||
}
|
||||
}
|
||||
|
||||
void janet_to_string_b(JanetBuffer *buffer, Janet x) {
|
||||
|
||||
void janet_description_b(JanetBuffer *buffer, Janet x) {
|
||||
switch (janet_type(x)) {
|
||||
default:
|
||||
janet_description_b(buffer, x);
|
||||
break;
|
||||
case JANET_BUFFER: {
|
||||
JanetBuffer *to = janet_unwrap_buffer(x);
|
||||
/* Prevent resizing buffer while appending */
|
||||
if (buffer == to) janet_buffer_extra(buffer, to->count);
|
||||
janet_buffer_push_bytes(buffer, to->data, to->count);
|
||||
break;
|
||||
}
|
||||
case JANET_STRING:
|
||||
case JANET_SYMBOL:
|
||||
case JANET_KEYWORD:
|
||||
janet_buffer_push_bytes(buffer,
|
||||
janet_unwrap_string(x),
|
||||
janet_string_length(janet_unwrap_string(x)));
|
||||
janet_buffer_push_u8(buffer, ':');
|
||||
break;
|
||||
case JANET_STRING:
|
||||
janet_escape_string_b(buffer, janet_unwrap_string(x));
|
||||
return;
|
||||
case JANET_BUFFER: {
|
||||
JanetBuffer *b = janet_unwrap_buffer(x);
|
||||
if (b == buffer) {
|
||||
/* Ensures buffer won't resize while escaping */
|
||||
janet_buffer_ensure(b, 5 * b->count + 3, 1);
|
||||
}
|
||||
janet_escape_buffer_b(buffer, b);
|
||||
return;
|
||||
}
|
||||
case JANET_ABSTRACT: {
|
||||
JanetAbstract p = janet_unwrap_abstract(x);
|
||||
const JanetAbstractType *t = janet_abstract_type(p);
|
||||
if (t->tostring != NULL) {
|
||||
janet_buffer_push_cstring(buffer, "<");
|
||||
janet_buffer_push_cstring(buffer, t->name);
|
||||
janet_buffer_push_cstring(buffer, " ");
|
||||
t->tostring(p, buffer);
|
||||
janet_buffer_push_cstring(buffer, ">");
|
||||
} else {
|
||||
string_description_b(buffer, t->name, p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
janet_to_string_b(buffer, x);
|
||||
}
|
||||
|
||||
const uint8_t *janet_description(Janet x) {
|
||||
@@ -330,6 +340,7 @@ static void print_newline(struct pretty *S, int just_a_space) {
|
||||
|
||||
/* Color coding for types */
|
||||
static const char janet_cycle_color[] = "\x1B[36m";
|
||||
static const char janet_class_color[] = "\x1B[34m";
|
||||
static const char *janet_pretty_colors[] = {
|
||||
"\x1B[32m",
|
||||
"\x1B[36m",
|
||||
@@ -351,6 +362,8 @@ static const char *janet_pretty_colors[] = {
|
||||
|
||||
#define JANET_PRETTY_DICT_ONELINE 4
|
||||
#define JANET_PRETTY_IND_ONELINE 10
|
||||
#define JANET_PRETTY_DICT_LIMIT 16
|
||||
#define JANET_PRETTY_ARRAY_LIMIT 16
|
||||
|
||||
/* Helper for pretty printing */
|
||||
static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
@@ -417,9 +430,22 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
if (!isarray && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_IND_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_IND_ONELINE) print_newline(S, 0);
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i) print_newline(S, len < JANET_PRETTY_IND_ONELINE);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
if (len > JANET_PRETTY_ARRAY_LIMIT) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i) print_newline(S, 0);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
}
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
for (i = 0; i < 3; i++) {
|
||||
print_newline(S, 0);
|
||||
janet_pretty_one(S, arr[len - 3 + i], 0);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i) print_newline(S, len < JANET_PRETTY_IND_ONELINE);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
S->indent -= 2;
|
||||
@@ -437,10 +463,17 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
JanetTable *t = janet_unwrap_table(x);
|
||||
JanetTable *proto = t->proto;
|
||||
if (NULL != proto) {
|
||||
Janet name = janet_table_get(proto, janet_csymbolv(":name"));
|
||||
if (janet_checktype(name, JANET_SYMBOL)) {
|
||||
const uint8_t *sym = janet_unwrap_symbol(name);
|
||||
janet_buffer_push_bytes(S->buffer, sym, janet_string_length(sym));
|
||||
Janet name = janet_table_get(proto, janet_ckeywordv("name"));
|
||||
const uint8_t *n;
|
||||
int32_t len;
|
||||
if (janet_bytes_view(name, &n, &len)) {
|
||||
if (S->flags & JANET_PRETTY_COLOR) {
|
||||
janet_buffer_push_cstring(S->buffer, janet_class_color);
|
||||
}
|
||||
janet_buffer_push_bytes(S->buffer, n, len);
|
||||
if (S->flags & JANET_PRETTY_COLOR) {
|
||||
janet_buffer_push_cstring(S->buffer, "\x1B[0m");
|
||||
}
|
||||
}
|
||||
}
|
||||
janet_buffer_push_cstring(S->buffer, "{");
|
||||
@@ -454,8 +487,9 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
int32_t i = 0, len = 0, cap = 0;
|
||||
int first_kv_pair = 1;
|
||||
const JanetKV *kvs = NULL;
|
||||
int counter = 0;
|
||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||
if (!istable && len >= JANET_PRETTY_DICT_ONELINE)
|
||||
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||
for (i = 0; i < cap; i++) {
|
||||
@@ -468,6 +502,12 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
janet_pretty_one(S, kvs[i].key, 0);
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
janet_pretty_one(S, kvs[i].value, 1);
|
||||
counter++;
|
||||
if (counter == 10) {
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "regalloc.h"
|
||||
#include "util.h"
|
||||
@@ -66,7 +67,7 @@ void janetc_regalloc_clone(JanetcRegisterAllocator *dest, JanetcRegisterAllocato
|
||||
dest->count = src->count;
|
||||
dest->capacity = src->capacity;
|
||||
dest->max = src->max;
|
||||
size = sizeof(uint32_t) * dest->capacity;
|
||||
size = sizeof(uint32_t) * (size_t) dest->capacity;
|
||||
dest->regtemps = 0;
|
||||
if (size) {
|
||||
dest->chunks = malloc(size);
|
||||
@@ -86,7 +87,7 @@ static void pushchunk(JanetcRegisterAllocator *ra) {
|
||||
int32_t newcount = ra->count + 1;
|
||||
if (newcount > ra->capacity) {
|
||||
int32_t newcapacity = newcount * 2;
|
||||
ra->chunks = realloc(ra->chunks, newcapacity * sizeof(uint32_t));
|
||||
ra->chunks = realloc(ra->chunks, (size_t) newcapacity * sizeof(uint32_t));
|
||||
if (!ra->chunks) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "compile.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -59,14 +59,14 @@ extern JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted;
|
||||
|
||||
/* Garbage collection */
|
||||
extern JANET_THREAD_LOCAL void *janet_vm_blocks;
|
||||
extern JANET_THREAD_LOCAL uint32_t janet_vm_gc_interval;
|
||||
extern JANET_THREAD_LOCAL uint32_t janet_vm_next_collection;
|
||||
extern JANET_THREAD_LOCAL size_t janet_vm_gc_interval;
|
||||
extern JANET_THREAD_LOCAL size_t janet_vm_next_collection;
|
||||
extern JANET_THREAD_LOCAL int janet_vm_gc_suspend;
|
||||
|
||||
/* GC roots */
|
||||
extern JANET_THREAD_LOCAL Janet *janet_vm_roots;
|
||||
extern JANET_THREAD_LOCAL uint32_t janet_vm_root_count;
|
||||
extern JANET_THREAD_LOCAL uint32_t janet_vm_root_capacity;
|
||||
extern JANET_THREAD_LOCAL size_t janet_vm_root_count;
|
||||
extern JANET_THREAD_LOCAL size_t janet_vm_root_capacity;
|
||||
|
||||
/* Scratch memory */
|
||||
extern JANET_THREAD_LOCAL void **janet_scratch_mem;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,18 +20,19 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
#include "state.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Begin building a string */
|
||||
uint8_t *janet_string_begin(int32_t length) {
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_STRING, sizeof(JanetStringHead) + length + 1);
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_STRING, sizeof(JanetStringHead) + (size_t) length + 1);
|
||||
head->length = length;
|
||||
uint8_t *data = (uint8_t *)head->data;
|
||||
data[length] = 0;
|
||||
@@ -46,7 +47,7 @@ const uint8_t *janet_string_end(uint8_t *str) {
|
||||
|
||||
/* Load a buffer as a string */
|
||||
const uint8_t *janet_string(const uint8_t *buf, int32_t len) {
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_STRING, sizeof(JanetStringHead) + len + 1);
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_STRING, sizeof(JanetStringHead) + (size_t) len + 1);
|
||||
head->length = len;
|
||||
head->hash = janet_string_calchash(buf, len);
|
||||
uint8_t *data = (uint8_t *)head->data;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -40,14 +40,15 @@
|
||||
* '0xdeadbeef'.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Lookup table for getting values of characters when parsing numbers. Handles
|
||||
* digits 0-9 and a-z (and A-Z). A-Z have values of 10 to 35. */
|
||||
static uint8_t digit_lookup[128] = {
|
||||
@@ -86,7 +87,7 @@ static uint32_t *bignat_extra(struct BigNat *mant, int32_t n) {
|
||||
int32_t newn = oldn + n;
|
||||
if (mant->cap < newn) {
|
||||
int32_t newcap = 2 * newn;
|
||||
uint32_t *mem = realloc(mant->digits, newcap * sizeof(uint32_t));
|
||||
uint32_t *mem = realloc(mant->digits, (size_t) newcap * sizeof(uint32_t));
|
||||
if (NULL == mem) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -33,7 +34,7 @@ JanetKV *janet_struct_begin(int32_t count) {
|
||||
int32_t capacity = janet_tablen(2 * count);
|
||||
if (capacity < 0) capacity = janet_tablen(count + 1);
|
||||
|
||||
size_t size = sizeof(JanetStructHead) + capacity * sizeof(JanetKV);
|
||||
size_t size = sizeof(JanetStructHead) + (size_t) capacity * sizeof(JanetKV);
|
||||
JanetStructHead *head = janet_gcalloc(JANET_MEMORY_STRUCT, size);
|
||||
head->length = count;
|
||||
head->capacity = capacity;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -25,9 +25,8 @@
|
||||
* checks, all symbols are interned so that there is a single copy of it in the
|
||||
* whole program. Equality is then just a pointer check. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#include "gc.h"
|
||||
@@ -35,6 +34,8 @@
|
||||
#include "symcache.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Cache state */
|
||||
JANET_THREAD_LOCAL const uint8_t **janet_vm_cache = NULL;
|
||||
JANET_THREAD_LOCAL uint32_t janet_vm_cache_capacity = 0;
|
||||
@@ -44,7 +45,7 @@ JANET_THREAD_LOCAL uint32_t janet_vm_cache_deleted = 0;
|
||||
/* Initialize the cache (allocate cache memory) */
|
||||
void janet_symcache_init() {
|
||||
janet_vm_cache_capacity = 1024;
|
||||
janet_vm_cache = calloc(1, janet_vm_cache_capacity * sizeof(const uint8_t *));
|
||||
janet_vm_cache = calloc(1, (size_t) janet_vm_cache_capacity * sizeof(const uint8_t *));
|
||||
if (NULL == janet_vm_cache) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -121,7 +122,7 @@ notfound:
|
||||
static void janet_cache_resize(uint32_t newCapacity) {
|
||||
uint32_t i, oldCapacity;
|
||||
const uint8_t **oldCache = janet_vm_cache;
|
||||
const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t *));
|
||||
const uint8_t **newCache = calloc(1, (size_t) newCapacity * sizeof(const uint8_t *));
|
||||
if (newCache == NULL) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -178,7 +179,7 @@ const uint8_t *janet_symbol(const uint8_t *str, int32_t len) {
|
||||
const uint8_t **bucket = janet_symcache_findmem(str, len, hash, &success);
|
||||
if (success)
|
||||
return *bucket;
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_SYMBOL, sizeof(JanetStringHead) + len + 1);
|
||||
JanetStringHead *head = janet_gcalloc(JANET_MEMORY_SYMBOL, sizeof(JanetStringHead) + (size_t) len + 1);
|
||||
head->hash = hash;
|
||||
head->length = len;
|
||||
newstr = (uint8_t *)(head->data);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -24,6 +24,7 @@
|
||||
#define JANET_SYMCACHE_H_defined
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -31,7 +32,7 @@
|
||||
|
||||
static void *janet_memalloc_empty_local(int32_t count) {
|
||||
int32_t i;
|
||||
void *mem = janet_smalloc(count * sizeof(JanetKV));
|
||||
void *mem = janet_smalloc((size_t) count * sizeof(JanetKV));
|
||||
JanetKV *mmem = (JanetKV *)mem;
|
||||
for (i = 0; i < count; i++) {
|
||||
JanetKV *kv = mmem + i;
|
||||
@@ -240,7 +241,7 @@ JanetTable *janet_table_clone(JanetTable *table) {
|
||||
if (NULL == newTable->data) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(newTable->data, table->data, table->capacity * sizeof(JanetKV));
|
||||
memcpy(newTable->data, table->data, (size_t) table->capacity * sizeof(JanetKV));
|
||||
return newTable;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "gc.h"
|
||||
#include "util.h"
|
||||
@@ -50,9 +51,6 @@ struct JanetMailbox {
|
||||
pthread_cond_t cond;
|
||||
#endif
|
||||
|
||||
/* Receiving messages - (only by owner thread) */
|
||||
JanetTable *decode;
|
||||
|
||||
/* Setup procedure - requires a parent mailbox
|
||||
* to receive thunk from */
|
||||
JanetMailbox *parent;
|
||||
@@ -74,9 +72,18 @@ struct JanetMailbox {
|
||||
|
||||
static JANET_THREAD_LOCAL JanetMailbox *janet_vm_mailbox = NULL;
|
||||
static JANET_THREAD_LOCAL JanetThread *janet_vm_thread_current = NULL;
|
||||
static JANET_THREAD_LOCAL JanetTable *janet_vm_thread_decode = NULL;
|
||||
|
||||
static JanetTable *janet_thread_get_decode(void) {
|
||||
if (janet_vm_thread_decode == NULL) {
|
||||
janet_vm_thread_decode = janet_get_core_table("load-image-dict");
|
||||
janet_gcroot(janet_wrap_table(janet_vm_thread_decode));
|
||||
}
|
||||
return janet_vm_thread_decode;
|
||||
}
|
||||
|
||||
static JanetMailbox *janet_mailbox_create(JanetMailbox *parent, int refCount, uint16_t capacity) {
|
||||
JanetMailbox *mailbox = malloc(sizeof(JanetMailbox) + sizeof(JanetBuffer) * capacity);
|
||||
JanetMailbox *mailbox = malloc(sizeof(JanetMailbox) + sizeof(JanetBuffer) * (size_t) capacity);
|
||||
if (NULL == mailbox) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -355,7 +362,7 @@ int janet_thread_receive(Janet *msg_out, double timeout) {
|
||||
const uint8_t *nextItem = NULL;
|
||||
Janet item = janet_unmarshal(
|
||||
msgbuf->data, msgbuf->count,
|
||||
0, mailbox->decode, &nextItem);
|
||||
0, janet_thread_get_decode(), &nextItem);
|
||||
*msg_out = item;
|
||||
|
||||
/* Cleanup */
|
||||
@@ -393,6 +400,8 @@ static JanetAbstractType Thread_AT = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -420,7 +429,6 @@ static int thread_worker(JanetMailbox *mailbox) {
|
||||
|
||||
/* Get dictionaries for default encode/decode */
|
||||
JanetTable *encode = janet_get_core_table("make-image-dict");
|
||||
mailbox->decode = janet_get_core_table("load-image-dict");
|
||||
|
||||
/* Create parent thread */
|
||||
JanetThread *parent = janet_make_thread(mailbox->parent, encode);
|
||||
@@ -504,6 +512,8 @@ void janet_threads_init(void) {
|
||||
if (NULL == janet_vm_mailbox) {
|
||||
janet_vm_mailbox = janet_mailbox_create(NULL, 1, 10);
|
||||
}
|
||||
janet_vm_thread_decode = NULL;
|
||||
janet_vm_thread_current = NULL;
|
||||
}
|
||||
|
||||
void janet_threads_deinit(void) {
|
||||
@@ -512,6 +522,7 @@ void janet_threads_deinit(void) {
|
||||
janet_mailbox_ref_with_lock(janet_vm_mailbox, -1);
|
||||
janet_vm_mailbox = NULL;
|
||||
janet_vm_thread_current = NULL;
|
||||
janet_vm_thread_decode = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "symcache.h"
|
||||
#include "gc.h"
|
||||
@@ -31,7 +32,7 @@
|
||||
* which should be filled with Janets. The memory will not be collected until
|
||||
* janet_tuple_end is called. */
|
||||
Janet *janet_tuple_begin(int32_t length) {
|
||||
size_t size = sizeof(JanetTupleHead) + (length * sizeof(Janet));
|
||||
size_t size = sizeof(JanetTupleHead) + ((size_t) length * sizeof(Janet));
|
||||
JanetTupleHead *head = janet_gcalloc(JANET_MEMORY_TUPLE, size);
|
||||
head->sm_line = -1;
|
||||
head->sm_column = -1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose & contributors
|
||||
* Copyright (c) 2020 Calvin Rose & contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -118,6 +119,8 @@ static const JanetAbstractType ta_buffer_type = {
|
||||
NULL,
|
||||
ta_buffer_marshal,
|
||||
ta_buffer_unmarshal,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -282,6 +285,8 @@ static const JanetAbstractType ta_view_type = {
|
||||
ta_setter,
|
||||
ta_view_marshal,
|
||||
ta_view_unmarshal,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
166
src/core/util.c
166
src/core/util.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,15 +20,16 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#include "state.h"
|
||||
#include "gc.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Base 64 lookup table for digits */
|
||||
const char janet_base64[65] =
|
||||
"0123456789"
|
||||
@@ -93,7 +94,7 @@ const char *const janet_status_names[16] = {
|
||||
"alive"
|
||||
};
|
||||
|
||||
/* Calculate hash for string */
|
||||
#ifdef JANET_NO_PRF
|
||||
|
||||
int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
||||
const uint8_t *end = str + len;
|
||||
@@ -103,6 +104,118 @@ int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
||||
return (int32_t) hash;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
Public domain siphash implementation sourced from:
|
||||
|
||||
https://raw.githubusercontent.com/veorq/SipHash/master/halfsiphash.c
|
||||
|
||||
We have made a few alterations, such as hardcoding the output size
|
||||
and then removing dead code.
|
||||
*/
|
||||
#define cROUNDS 2
|
||||
#define dROUNDS 4
|
||||
|
||||
#define ROTL(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
|
||||
|
||||
#define U8TO32_LE(p) \
|
||||
(((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
|
||||
((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
|
||||
|
||||
#define SIPROUND \
|
||||
do { \
|
||||
v0 += v1; \
|
||||
v1 = ROTL(v1, 5); \
|
||||
v1 ^= v0; \
|
||||
v0 = ROTL(v0, 16); \
|
||||
v2 += v3; \
|
||||
v3 = ROTL(v3, 8); \
|
||||
v3 ^= v2; \
|
||||
v0 += v3; \
|
||||
v3 = ROTL(v3, 7); \
|
||||
v3 ^= v0; \
|
||||
v2 += v1; \
|
||||
v1 = ROTL(v1, 13); \
|
||||
v1 ^= v2; \
|
||||
v2 = ROTL(v2, 16); \
|
||||
} while (0)
|
||||
|
||||
static uint32_t halfsiphash(const uint8_t *in, const size_t inlen, const uint8_t *k) {
|
||||
|
||||
uint32_t v0 = 0;
|
||||
uint32_t v1 = 0;
|
||||
uint32_t v2 = UINT32_C(0x6c796765);
|
||||
uint32_t v3 = UINT32_C(0x74656462);
|
||||
uint32_t k0 = U8TO32_LE(k);
|
||||
uint32_t k1 = U8TO32_LE(k + 4);
|
||||
uint32_t m;
|
||||
int i;
|
||||
const uint8_t *end = in + inlen - (inlen % sizeof(uint32_t));
|
||||
const int left = inlen & 3;
|
||||
uint32_t b = ((uint32_t)inlen) << 24;
|
||||
v3 ^= k1;
|
||||
v2 ^= k0;
|
||||
v1 ^= k1;
|
||||
v0 ^= k0;
|
||||
|
||||
for (; in != end; in += 4) {
|
||||
m = U8TO32_LE(in);
|
||||
v3 ^= m;
|
||||
|
||||
for (i = 0; i < cROUNDS; ++i)
|
||||
SIPROUND;
|
||||
|
||||
v0 ^= m;
|
||||
}
|
||||
|
||||
switch (left) {
|
||||
case 3:
|
||||
b |= ((uint32_t)in[2]) << 16;
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
b |= ((uint32_t)in[1]) << 8;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
b |= ((uint32_t)in[0]);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
|
||||
v3 ^= b;
|
||||
|
||||
for (i = 0; i < cROUNDS; ++i)
|
||||
SIPROUND;
|
||||
|
||||
v0 ^= b;
|
||||
|
||||
v2 ^= 0xff;
|
||||
|
||||
for (i = 0; i < dROUNDS; ++i)
|
||||
SIPROUND;
|
||||
|
||||
b = v1 ^ v3;
|
||||
return b;
|
||||
}
|
||||
/* end of siphash */
|
||||
|
||||
static uint8_t hash_key[16] = {0};
|
||||
|
||||
void janet_init_hash_key(uint8_t new_key[16]) {
|
||||
memcpy(hash_key, new_key, sizeof(hash_key));
|
||||
}
|
||||
|
||||
/* Calculate hash for string */
|
||||
|
||||
int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
||||
uint32_t hash;
|
||||
hash = halfsiphash(str, len, hash_key);
|
||||
return (int32_t)hash;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Computes hash of an array of values */
|
||||
int32_t janet_array_calchash(const Janet *array, int32_t len) {
|
||||
const Janet *end = array + len;
|
||||
@@ -262,27 +375,44 @@ void janet_var(JanetTable *env, const char *name, Janet val, const char *doc) {
|
||||
|
||||
/* Load many cfunctions at once */
|
||||
void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns) {
|
||||
uint8_t *longname_buffer = NULL;
|
||||
size_t prefixlen = 0;
|
||||
size_t bufsize = 0;
|
||||
if (NULL != regprefix) {
|
||||
prefixlen = strlen(regprefix);
|
||||
bufsize = prefixlen + 256;
|
||||
longname_buffer = malloc(bufsize);
|
||||
if (NULL == longname_buffer) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(longname_buffer, regprefix, prefixlen);
|
||||
longname_buffer[prefixlen] = '/';
|
||||
prefixlen++;
|
||||
}
|
||||
while (cfuns->name) {
|
||||
Janet name = janet_csymbolv(cfuns->name);
|
||||
Janet longname = name;
|
||||
if (regprefix) {
|
||||
int32_t reglen = 0;
|
||||
Janet name;
|
||||
if (NULL != regprefix) {
|
||||
int32_t nmlen = 0;
|
||||
while (regprefix[reglen]) reglen++;
|
||||
while (cfuns->name[nmlen]) nmlen++;
|
||||
int32_t symlen = reglen + 1 + nmlen;
|
||||
uint8_t *longname_buffer = malloc(symlen);
|
||||
memcpy(longname_buffer, regprefix, reglen);
|
||||
longname_buffer[reglen] = '/';
|
||||
memcpy(longname_buffer + reglen + 1, cfuns->name, nmlen);
|
||||
longname = janet_wrap_symbol(janet_symbol(longname_buffer, symlen));
|
||||
free(longname_buffer);
|
||||
int32_t totallen = (int32_t) prefixlen + nmlen;
|
||||
if ((size_t) totallen > bufsize) {
|
||||
bufsize = (size_t)(totallen) + 128;
|
||||
longname_buffer = realloc(longname_buffer, bufsize);
|
||||
if (NULL == longname_buffer) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
memcpy(longname_buffer + prefixlen, cfuns->name, nmlen);
|
||||
name = janet_wrap_symbol(janet_symbol(longname_buffer, totallen));
|
||||
} else {
|
||||
name = janet_csymbolv(cfuns->name);
|
||||
}
|
||||
Janet fun = janet_wrap_cfunction(cfuns->cfun);
|
||||
janet_def(env, cfuns->name, fun, cfuns->documentation);
|
||||
janet_table_put(janet_vm_registry, fun, longname);
|
||||
janet_table_put(janet_vm_registry, fun, name);
|
||||
cfuns++;
|
||||
}
|
||||
free(longname_buffer);
|
||||
}
|
||||
|
||||
/* Abstract type introspection */
|
||||
@@ -295,6 +425,8 @@ static const JanetAbstractType type_wrap = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -23,13 +23,14 @@
|
||||
#ifndef JANET_UTIL_H_defined
|
||||
#define JANET_UTIL_H_defined
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Handle runtime errors */
|
||||
#ifndef janet_exit
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
@@ -28,6 +29,20 @@
|
||||
* Define a number of functions that can be used internally on ANY Janet.
|
||||
*/
|
||||
|
||||
/* Compare two abstract values */
|
||||
static int janet_compare_abstract(JanetAbstract xx, JanetAbstract yy) {
|
||||
if (xx == yy) return 0;
|
||||
const JanetAbstractType *xt = janet_abstract_type(xx);
|
||||
const JanetAbstractType *yt = janet_abstract_type(yy);
|
||||
if (xt != yt) {
|
||||
return xt > yt ? 1 : -1;
|
||||
}
|
||||
if (xt->compare == NULL) {
|
||||
return xx > yy ? 1 : -1;
|
||||
}
|
||||
return xt->compare(xx, yy);
|
||||
}
|
||||
|
||||
/* Check if two values are equal. This is strict equality with no conversion. */
|
||||
int janet_equals(Janet x, Janet y) {
|
||||
int result = 0;
|
||||
@@ -53,6 +68,9 @@ int janet_equals(Janet x, Janet y) {
|
||||
case JANET_STRUCT:
|
||||
result = janet_struct_equal(janet_unwrap_struct(x), janet_unwrap_struct(y));
|
||||
break;
|
||||
case JANET_ABSTRACT:
|
||||
result = !janet_compare_abstract(janet_unwrap_abstract(x), janet_unwrap_abstract(y));
|
||||
break;
|
||||
default:
|
||||
/* compare pointers */
|
||||
result = (janet_unwrap_pointer(x) == janet_unwrap_pointer(y));
|
||||
@@ -83,6 +101,15 @@ int32_t janet_hash(Janet x) {
|
||||
case JANET_STRUCT:
|
||||
hash = janet_struct_hash(janet_unwrap_struct(x));
|
||||
break;
|
||||
case JANET_ABSTRACT: {
|
||||
JanetAbstract xx = janet_unwrap_abstract(x);
|
||||
const JanetAbstractType *at = janet_abstract_type(xx);
|
||||
if (at->hash != NULL) {
|
||||
hash = at->hash(xx, janet_abstract_size(xx));
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* fallthrough */
|
||||
default:
|
||||
/* TODO - test performance with different hash functions */
|
||||
if (sizeof(double) == sizeof(void *)) {
|
||||
@@ -104,7 +131,7 @@ int32_t janet_hash(Janet x) {
|
||||
|
||||
/* Compares x to y. If they are equal returns 0. If x is less, returns -1.
|
||||
* If y is less, returns 1. All types are comparable
|
||||
* and should have strict ordering. */
|
||||
* and should have strict ordering, excepts NaNs. */
|
||||
int janet_compare(Janet x, Janet y) {
|
||||
if (janet_type(x) == janet_type(y)) {
|
||||
switch (janet_type(x)) {
|
||||
@@ -112,20 +139,13 @@ int janet_compare(Janet x, Janet y) {
|
||||
return 0;
|
||||
case JANET_BOOLEAN:
|
||||
return janet_unwrap_boolean(x) - janet_unwrap_boolean(y);
|
||||
case JANET_NUMBER:
|
||||
/* Check for NaNs to ensure total order */
|
||||
if (janet_unwrap_number(x) != janet_unwrap_number(x))
|
||||
return janet_unwrap_number(y) != janet_unwrap_number(y)
|
||||
? 0
|
||||
: -1;
|
||||
if (janet_unwrap_number(y) != janet_unwrap_number(y))
|
||||
return 1;
|
||||
|
||||
if (janet_unwrap_number(x) == janet_unwrap_number(y)) {
|
||||
return 0;
|
||||
} else {
|
||||
return janet_unwrap_number(x) > janet_unwrap_number(y) ? 1 : -1;
|
||||
}
|
||||
case JANET_NUMBER: {
|
||||
double xx = janet_unwrap_number(x);
|
||||
double yy = janet_unwrap_number(y);
|
||||
return xx == yy
|
||||
? 0
|
||||
: (xx < yy) ? -1 : 1;
|
||||
}
|
||||
case JANET_STRING:
|
||||
case JANET_SYMBOL:
|
||||
case JANET_KEYWORD:
|
||||
@@ -134,6 +154,8 @@ int janet_compare(Janet x, Janet y) {
|
||||
return janet_tuple_compare(janet_unwrap_tuple(x), janet_unwrap_tuple(y));
|
||||
case JANET_STRUCT:
|
||||
return janet_struct_compare(janet_unwrap_struct(x), janet_unwrap_struct(y));
|
||||
case JANET_ABSTRACT:
|
||||
return janet_compare_abstract(janet_unwrap_abstract(x), janet_unwrap_abstract(y));
|
||||
default:
|
||||
if (janet_unwrap_string(x) == janet_unwrap_string(y)) {
|
||||
return 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include "vector.h"
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -40,18 +41,14 @@ void *janet_v_grow(void *v, int32_t increment, int32_t itemsize) {
|
||||
/* Convert a buffer to normal allocated memory (forget capacity) */
|
||||
void *janet_v_flattenmem(void *v, int32_t itemsize) {
|
||||
int32_t *p;
|
||||
int32_t sizen;
|
||||
if (NULL == v) return NULL;
|
||||
sizen = itemsize * janet_v__cnt(v);
|
||||
p = malloc(sizen);
|
||||
size_t size = (size_t) itemsize * janet_v__cnt(v);
|
||||
p = malloc(size);
|
||||
if (NULL != p) {
|
||||
memcpy(p, v, sizen);
|
||||
memcpy(p, v, size);
|
||||
return p;
|
||||
} else {
|
||||
{
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
return NULL;
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -24,6 +24,7 @@
|
||||
#define JANET_VECTOR_H_defined
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
|
||||
126
src/core/vm.c
126
src/core/vm.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "state.h"
|
||||
#include "fiber.h"
|
||||
@@ -149,7 +150,6 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
stack[A] = janet_mcall(#op, 2, _argv);\
|
||||
vm_pcnext();\
|
||||
} else {\
|
||||
vm_assert_type(op1, JANET_NUMBER);\
|
||||
vm_assert_type(op2, JANET_NUMBER);\
|
||||
double x1 = janet_unwrap_number(op1);\
|
||||
double x2 = janet_unwrap_number(op2);\
|
||||
@@ -158,7 +158,6 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
}\
|
||||
}
|
||||
#define vm_binop(op) _vm_binop(op, janet_wrap_number)
|
||||
#define vm_numcomp(op) _vm_binop(op, janet_wrap_boolean)
|
||||
#define _vm_bitop(op, type1)\
|
||||
{\
|
||||
Janet op1 = stack[B];\
|
||||
@@ -172,6 +171,21 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
}
|
||||
#define vm_bitop(op) _vm_bitop(op, int32_t)
|
||||
#define vm_bitopu(op) _vm_bitop(op, uint32_t)
|
||||
#define vm_compop(op) \
|
||||
{\
|
||||
Janet op1 = stack[B];\
|
||||
Janet op2 = stack[C];\
|
||||
if (!janet_checktype(op1, JANET_NUMBER) || !janet_checktype(op2, JANET_NUMBER)) {\
|
||||
vm_commit();\
|
||||
stack[A] = janet_wrap_boolean(janet_compare(op1, op2) op 0);\
|
||||
vm_pcnext();\
|
||||
} else {\
|
||||
double x1 = janet_unwrap_number(op1);\
|
||||
double x2 = janet_unwrap_number(op2);\
|
||||
stack[A] = janet_wrap_boolean(x1 op x2);\
|
||||
vm_pcnext();\
|
||||
}\
|
||||
}
|
||||
|
||||
/* Trace a function call */
|
||||
static void vm_do_trace(JanetFunction *func) {
|
||||
@@ -218,7 +232,7 @@ static Janet resolve_method(Janet name, JanetFiber *fiber) {
|
||||
}
|
||||
|
||||
/* Interpreter main loop */
|
||||
static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) {
|
||||
static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
||||
|
||||
/* opcode -> label lookup if using clang/GCC */
|
||||
#ifdef JANET_USE_COMPUTED_GOTOS
|
||||
@@ -288,11 +302,11 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
&&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_JOP_GREATER_THAN_EQUAL,
|
||||
&&label_JOP_LESS_THAN_EQUAL,
|
||||
&&label_unknown_op,
|
||||
&&label_unknown_op,
|
||||
&&label_unknown_op,
|
||||
&&label_unknown_op,
|
||||
&&label_unknown_op,
|
||||
&&label_unknown_op,
|
||||
@@ -487,29 +501,38 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
register JanetFunction *func;
|
||||
vm_restore();
|
||||
|
||||
/* Only should be hit if the fiber is either waiting for a child, or
|
||||
* waiting to be resumed. In those cases, use input and increment pc. We
|
||||
* DO NOT use input when resuming a fiber that has been interrupted at a
|
||||
* breakpoint. */
|
||||
uint8_t first_opcode;
|
||||
if (status != JANET_STATUS_NEW &&
|
||||
((*pc & 0xFF) == JOP_SIGNAL ||
|
||||
(*pc & 0xFF) == JOP_PROPAGATE ||
|
||||
(*pc & 0xFF) == JOP_RESUME)) {
|
||||
stack[A] = in;
|
||||
pc++;
|
||||
first_opcode = *pc & 0xFF;
|
||||
} else if (status == JANET_STATUS_DEBUG) {
|
||||
first_opcode = *pc & 0x7F;
|
||||
} else {
|
||||
first_opcode = *pc & 0xFF;
|
||||
if (fiber->flags & JANET_FIBER_DID_LONGJUMP) {
|
||||
if (janet_fiber_frame(fiber)->func == NULL) {
|
||||
/* Inside a c function */
|
||||
janet_fiber_popframe(fiber);
|
||||
vm_restore();
|
||||
}
|
||||
/* Check if we were at a tail call instruction. If so, do implicit return */
|
||||
if ((*pc & 0xFF) == JOP_TAILCALL) {
|
||||
/* Tail call resume */
|
||||
int entrance_frame = janet_stack_frame(stack)->flags & JANET_STACKFRAME_ENTRANCE;
|
||||
janet_fiber_popframe(fiber);
|
||||
if (entrance_frame) {
|
||||
fiber->flags &= ~JANET_FIBER_FLAG_MASK;
|
||||
vm_return(JANET_SIGNAL_OK, in);
|
||||
}
|
||||
vm_restore();
|
||||
}
|
||||
}
|
||||
|
||||
if (!(fiber->flags & JANET_FIBER_RESUME_NO_USEVAL)) stack[A] = in;
|
||||
if (!(fiber->flags & JANET_FIBER_RESUME_NO_SKIP)) pc++;
|
||||
|
||||
uint8_t first_opcode = *pc & ((fiber->flags & JANET_FIBER_BREAKPOINT) ? 0x7F : 0xFF);
|
||||
|
||||
fiber->flags &= ~JANET_FIBER_FLAG_MASK;
|
||||
|
||||
/* Main interpreter loop. Semantically is a switch on
|
||||
* (*pc & 0xFF) inside of an infinite loop. */
|
||||
VM_START();
|
||||
|
||||
VM_DEFAULT();
|
||||
fiber->flags |= JANET_FIBER_BREAKPOINT | JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
|
||||
vm_return(JANET_SIGNAL_DEBUG, janet_wrap_nil());
|
||||
|
||||
VM_OP(JOP_NOOP)
|
||||
@@ -557,21 +580,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
VM_OP(JOP_MULTIPLY)
|
||||
vm_binop(*);
|
||||
|
||||
VM_OP(JOP_NUMERIC_LESS_THAN)
|
||||
vm_numcomp( <);
|
||||
|
||||
VM_OP(JOP_NUMERIC_LESS_THAN_EQUAL)
|
||||
vm_numcomp( <=);
|
||||
|
||||
VM_OP(JOP_NUMERIC_GREATER_THAN)
|
||||
vm_numcomp( >);
|
||||
|
||||
VM_OP(JOP_NUMERIC_GREATER_THAN_EQUAL)
|
||||
vm_numcomp( >=);
|
||||
|
||||
VM_OP(JOP_NUMERIC_EQUAL)
|
||||
vm_numcomp( ==);
|
||||
|
||||
VM_OP(JOP_DIVIDE_IMMEDIATE)
|
||||
vm_binop_immediate( /);
|
||||
|
||||
@@ -641,16 +649,20 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
vm_next();
|
||||
|
||||
VM_OP(JOP_LESS_THAN)
|
||||
stack[A] = janet_wrap_boolean(janet_compare(stack[B], stack[C]) < 0);
|
||||
vm_pcnext();
|
||||
vm_compop( <);
|
||||
|
||||
VM_OP(JOP_LESS_THAN_EQUAL)
|
||||
vm_compop( <=);
|
||||
|
||||
VM_OP(JOP_LESS_THAN_IMMEDIATE)
|
||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) < CS);
|
||||
vm_pcnext();
|
||||
|
||||
VM_OP(JOP_GREATER_THAN)
|
||||
stack[A] = janet_wrap_boolean(janet_compare(stack[B], stack[C]) > 0);
|
||||
vm_pcnext();
|
||||
vm_compop( >);
|
||||
|
||||
VM_OP(JOP_GREATER_THAN_EQUAL)
|
||||
vm_compop( >=);
|
||||
|
||||
VM_OP(JOP_GREATER_THAN_IMMEDIATE)
|
||||
stack[A] = janet_wrap_boolean(janet_unwrap_integer(stack[B]) > CS);
|
||||
@@ -735,7 +747,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
vm_assert(defindex < func->def->defs_length, "invalid funcdef");
|
||||
fd = func->def->defs[defindex];
|
||||
elen = fd->environments_length;
|
||||
fn = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + (elen * sizeof(JanetFuncEnv *)));
|
||||
fn = janet_gcalloc(JANET_MEMORY_FUNCTION, sizeof(JanetFunction) + ((size_t) elen * sizeof(JanetFuncEnv *)));
|
||||
fn->def = fd;
|
||||
{
|
||||
int32_t i;
|
||||
@@ -873,8 +885,9 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
JanetFiber *child = janet_unwrap_fiber(stack[B]);
|
||||
fiber->child = child;
|
||||
JanetSignal sig = janet_continue(child, stack[C], &retreg);
|
||||
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig)))
|
||||
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
||||
vm_return(sig, retreg);
|
||||
}
|
||||
fiber->child = NULL;
|
||||
stack = fiber->data + fiber->frame;
|
||||
stack[A] = retreg;
|
||||
@@ -898,18 +911,22 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
|
||||
janet_panicf("cannot propagate from fiber with status :%s",
|
||||
janet_status_names[sub_status]);
|
||||
}
|
||||
janet_vm_fiber->child = f;
|
||||
fiber->child = f;
|
||||
vm_return((int) sub_status, stack[B]);
|
||||
}
|
||||
|
||||
VM_OP(JOP_PUT)
|
||||
vm_commit();
|
||||
fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL;
|
||||
janet_put(stack[A], stack[B], stack[C]);
|
||||
fiber->flags &= ~JANET_FIBER_RESUME_NO_USEVAL;
|
||||
vm_checkgc_pcnext();
|
||||
|
||||
VM_OP(JOP_PUT_INDEX)
|
||||
vm_commit();
|
||||
fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL;
|
||||
janet_putindex(stack[A], C, stack[B]);
|
||||
fiber->flags &= ~JANET_FIBER_RESUME_NO_USEVAL;
|
||||
vm_checkgc_pcnext();
|
||||
|
||||
VM_OP(JOP_IN)
|
||||
@@ -1091,9 +1108,8 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
||||
int handle = janet_gclock();
|
||||
|
||||
/* Run vm */
|
||||
JanetSignal signal = run_vm(janet_vm_fiber,
|
||||
janet_wrap_nil(),
|
||||
JANET_STATUS_ALIVE);
|
||||
janet_vm_fiber->flags |= JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP;
|
||||
JanetSignal signal = run_vm(janet_vm_fiber, janet_wrap_nil());
|
||||
|
||||
/* Teardown */
|
||||
janet_vm_stackn = oldn;
|
||||
@@ -1153,14 +1169,16 @@ JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out) {
|
||||
|
||||
/* Run loop */
|
||||
JanetSignal signal;
|
||||
int jmpsig;
|
||||
#if defined(JANET_BSD) || defined(JANET_APPLE)
|
||||
if (_setjmp(buf)) {
|
||||
jmpsig = _setjmp(buf);
|
||||
#else
|
||||
if (setjmp(buf)) {
|
||||
jmpsig = setjmp(buf);
|
||||
#endif
|
||||
signal = JANET_SIGNAL_ERROR;
|
||||
if (jmpsig) {
|
||||
signal = (JanetSignal) jmpsig;
|
||||
} else {
|
||||
signal = run_vm(fiber, in, old_status);
|
||||
signal = run_vm(fiber, in);
|
||||
}
|
||||
|
||||
/* Tear down fiber */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -21,8 +21,9 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include <math.h>
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include <math.h>
|
||||
#include "util.h"
|
||||
#include "state.h"
|
||||
#endif
|
||||
@@ -161,8 +162,8 @@ Janet(janet_wrap_number)(double x) {
|
||||
|
||||
void *janet_memalloc_empty(int32_t count) {
|
||||
int32_t i;
|
||||
void *mem = malloc(count * sizeof(JanetKV));
|
||||
janet_vm_next_collection += count * sizeof(JanetKV);
|
||||
void *mem = malloc((size_t) count * sizeof(JanetKV));
|
||||
janet_vm_next_collection += (size_t) count * sizeof(JanetKV);
|
||||
if (NULL == mem) {
|
||||
JANET_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -49,7 +49,6 @@ extern "C" {
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || \
|
||||
defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#define JANET_BSD 1
|
||||
#define _BSD_SOURCE 1
|
||||
#endif
|
||||
|
||||
/* Check for Mac */
|
||||
@@ -76,7 +75,6 @@ extern "C" {
|
||||
|| defined(sun) || defined(__sun) /* Solaris */ \
|
||||
|| defined(unix) || defined(__unix) || defined(__unix__)
|
||||
#define JANET_POSIX 1
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define JANET_WEB 1
|
||||
#elif defined(WIN32) || defined(_WIN32)
|
||||
@@ -256,6 +254,11 @@ typedef struct {
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef JANET_BSD
|
||||
int _setjmp(jmp_buf);
|
||||
JANET_NO_RETURN void _longjmp(jmp_buf, int);
|
||||
#endif
|
||||
|
||||
/* Names of all of the types */
|
||||
JANET_API extern const char *const janet_type_names[16];
|
||||
JANET_API extern const char *const janet_signal_names[14];
|
||||
@@ -693,28 +696,6 @@ struct JanetGCObject {
|
||||
JanetGCObject *next;
|
||||
};
|
||||
|
||||
/* Fiber signal masks. */
|
||||
#define JANET_FIBER_MASK_ERROR 2
|
||||
#define JANET_FIBER_MASK_DEBUG 4
|
||||
#define JANET_FIBER_MASK_YIELD 8
|
||||
|
||||
#define JANET_FIBER_MASK_USER0 (16 << 0)
|
||||
#define JANET_FIBER_MASK_USER1 (16 << 1)
|
||||
#define JANET_FIBER_MASK_USER2 (16 << 2)
|
||||
#define JANET_FIBER_MASK_USER3 (16 << 3)
|
||||
#define JANET_FIBER_MASK_USER4 (16 << 4)
|
||||
#define JANET_FIBER_MASK_USER5 (16 << 5)
|
||||
#define JANET_FIBER_MASK_USER6 (16 << 6)
|
||||
#define JANET_FIBER_MASK_USER7 (16 << 7)
|
||||
#define JANET_FIBER_MASK_USER8 (16 << 8)
|
||||
#define JANET_FIBER_MASK_USER9 (16 << 9)
|
||||
|
||||
#define JANET_FIBER_MASK_USERN(N) (16 << (N))
|
||||
#define JANET_FIBER_MASK_USER 0x3FF0
|
||||
|
||||
#define JANET_FIBER_STATUS_MASK 0xFF0000
|
||||
#define JANET_FIBER_STATUS_OFFSET 16
|
||||
|
||||
/* A lightweight green thread in janet. Does not correspond to
|
||||
* operating system threads. */
|
||||
struct JanetFiber {
|
||||
@@ -924,6 +905,8 @@ struct JanetAbstractType {
|
||||
void (*marshal)(void *p, JanetMarshalContext *ctx);
|
||||
void *(*unmarshal)(JanetMarshalContext *ctx);
|
||||
void (*tostring)(void *p, JanetBuffer *buffer);
|
||||
int (*compare)(void *lhs, void *rhs);
|
||||
int32_t (*hash)(void *p, size_t len);
|
||||
};
|
||||
|
||||
struct JanetReg {
|
||||
@@ -1075,11 +1058,8 @@ enum JanetOpCode {
|
||||
JOP_MAKE_TABLE,
|
||||
JOP_MAKE_TUPLE,
|
||||
JOP_MAKE_BRACKET_TUPLE,
|
||||
JOP_NUMERIC_LESS_THAN,
|
||||
JOP_NUMERIC_LESS_THAN_EQUAL,
|
||||
JOP_NUMERIC_GREATER_THAN,
|
||||
JOP_NUMERIC_GREATER_THAN_EQUAL,
|
||||
JOP_NUMERIC_EQUAL,
|
||||
JOP_GREATER_THAN_EQUAL,
|
||||
JOP_LESS_THAN_EQUAL,
|
||||
JOP_INSTRUCTION_COUNT
|
||||
};
|
||||
|
||||
@@ -1322,6 +1302,9 @@ JANET_API int janet_verify(JanetFuncDef *def);
|
||||
JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x);
|
||||
|
||||
/* Misc */
|
||||
#ifndef JANET_NO_PRF
|
||||
JANET_API void janet_init_hash_key(uint8_t key[16]);
|
||||
#endif
|
||||
JANET_API int janet_equals(Janet x, Janet y);
|
||||
JANET_API int32_t janet_hash(Janet x);
|
||||
JANET_API int janet_compare(Janet x, Janet y);
|
||||
@@ -1353,6 +1336,7 @@ JANET_API void janet_stacktrace(JanetFiber *fiber, Janet err);
|
||||
typedef void (*ScratchFinalizer)(void *);
|
||||
JANET_API void *janet_smalloc(size_t size);
|
||||
JANET_API void *janet_srealloc(void *mem, size_t size);
|
||||
JANET_API void *janet_scalloc(size_t nmemb, size_t size);
|
||||
JANET_API void janet_sfinalizer(void *mem, ScratchFinalizer finalizer);
|
||||
JANET_API void janet_sfree(void *mem);
|
||||
|
||||
@@ -1376,15 +1360,16 @@ JANET_API Janet janet_resolve_core(const char *name);
|
||||
|
||||
/* Allow setting entry name for static libraries */
|
||||
#ifndef JANET_ENTRY_NAME
|
||||
#define JANET_ENTRY_NAME _janet_init
|
||||
#endif
|
||||
|
||||
#define JANET_MODULE_ENTRY \
|
||||
JANET_API JanetBuildConfig _janet_mod_config(void) { \
|
||||
return janet_config_current(); \
|
||||
} \
|
||||
JANET_API void JANET_ENTRY_NAME
|
||||
JANET_API void _janet_init
|
||||
#else
|
||||
#define JANET_MODULE_ENTRY JANET_API void JANET_ENTRY_NAME
|
||||
#endif
|
||||
|
||||
JANET_NO_RETURN JANET_API void janet_signalv(JanetSignal signal, Janet message);
|
||||
JANET_NO_RETURN JANET_API void janet_panicv(Janet message);
|
||||
JANET_NO_RETURN JANET_API void janet_panic(const char *message);
|
||||
JANET_NO_RETURN JANET_API void janet_panics(JanetString message);
|
||||
@@ -1465,8 +1450,11 @@ JANET_API void janet_setdyn(const char *name, Janet value);
|
||||
#define JANET_FILE_SERIALIZABLE 128
|
||||
#define JANET_FILE_PIPED 256
|
||||
|
||||
JANET_API Janet janet_makefile(FILE *f, int flags);
|
||||
JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int *flags);
|
||||
JANET_API FILE *janet_dynfile(const char *name, FILE *def);
|
||||
JANET_API JanetAbstract janet_checkfile(Janet j);
|
||||
JANET_API FILE *janet_unwrapfile(Janet j, int *flags);
|
||||
|
||||
/* Marshal API */
|
||||
JANET_API void janet_marshal_size(JanetMarshalContext *ctx, size_t value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,16 +20,24 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "line.h"
|
||||
#endif
|
||||
|
||||
static JANET_THREAD_LOCAL JanetTable *gbl_complete_env;
|
||||
|
||||
/* Common */
|
||||
Janet janet_line_getter(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 0, 2);
|
||||
janet_arity(argc, 0, 3);
|
||||
const char *str = (argc >= 1) ? (const char *) janet_getstring(argv, 0) : "";
|
||||
JanetBuffer *buf = (argc >= 2) ? janet_getbuffer(argv, 1) : janet_buffer(10);
|
||||
gbl_complete_env = (argc >= 3) ? janet_gettable(argv, 2) : NULL;
|
||||
janet_line_get(str, buf);
|
||||
gbl_complete_env = NULL;
|
||||
return janet_wrap_buffer(buf);
|
||||
}
|
||||
|
||||
@@ -72,6 +80,8 @@ void janet_line_get(const char *p, JanetBuffer *buffer) {
|
||||
https://github.com/antirez/linenoise/blob/master/linenoise.c
|
||||
*/
|
||||
|
||||
#include <janet.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@@ -88,6 +98,7 @@ https://github.com/antirez/linenoise/blob/master/linenoise.c
|
||||
|
||||
/* static state */
|
||||
#define JANET_LINE_MAX 1024
|
||||
#define JANET_MATCH_MAX 256
|
||||
#define JANET_HISTORY_MAX 100
|
||||
static JANET_THREAD_LOCAL int gbl_israwmode = 0;
|
||||
static JANET_THREAD_LOCAL const char *gbl_prompt = "> ";
|
||||
@@ -101,6 +112,8 @@ static JANET_THREAD_LOCAL int gbl_history_count = 0;
|
||||
static JANET_THREAD_LOCAL int gbl_historyi = 0;
|
||||
static JANET_THREAD_LOCAL int gbl_sigint_flag = 0;
|
||||
static JANET_THREAD_LOCAL struct termios gbl_termios_start;
|
||||
static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX];
|
||||
static JANET_THREAD_LOCAL int gbl_match_count = 0;
|
||||
|
||||
/* Unsupported terminal list from linenoise */
|
||||
static const char *badterms[] = {
|
||||
@@ -120,7 +133,7 @@ static char *sdup(const char *s) {
|
||||
}
|
||||
|
||||
/* Ansi terminal raw mode */
|
||||
static int rawmode() {
|
||||
static int rawmode(void) {
|
||||
struct termios t;
|
||||
if (!isatty(STDIN_FILENO)) goto fatal;
|
||||
if (tcgetattr(STDIN_FILENO, &gbl_termios_start) == -1) goto fatal;
|
||||
@@ -139,12 +152,12 @@ fatal:
|
||||
}
|
||||
|
||||
/* Disable raw mode */
|
||||
static void norawmode() {
|
||||
static void norawmode(void) {
|
||||
if (gbl_israwmode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &gbl_termios_start) != -1)
|
||||
gbl_israwmode = 0;
|
||||
}
|
||||
|
||||
static int curpos() {
|
||||
static int curpos(void) {
|
||||
char buf[32];
|
||||
int cols, rows;
|
||||
unsigned int i = 0;
|
||||
@@ -160,7 +173,7 @@ static int curpos() {
|
||||
return cols;
|
||||
}
|
||||
|
||||
static int getcols() {
|
||||
static int getcols(void) {
|
||||
struct winsize ws;
|
||||
if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
|
||||
int start, cols;
|
||||
@@ -184,13 +197,13 @@ failed:
|
||||
return 80;
|
||||
}
|
||||
|
||||
static void clear() {
|
||||
static void clear(void) {
|
||||
if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) <= 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void refresh() {
|
||||
static void refresh(void) {
|
||||
char seq[64];
|
||||
JanetBuffer b;
|
||||
|
||||
@@ -223,23 +236,25 @@ static void refresh() {
|
||||
janet_buffer_deinit(&b);
|
||||
}
|
||||
|
||||
static int insert(char c) {
|
||||
static int insert(char c, int draw) {
|
||||
if (gbl_len < JANET_LINE_MAX - 1) {
|
||||
if (gbl_len == gbl_pos) {
|
||||
gbl_buf[gbl_pos++] = c;
|
||||
gbl_buf[++gbl_len] = '\0';
|
||||
if (gbl_plen + gbl_len < gbl_cols) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write(STDOUT_FILENO, &c, 1) == -1) return -1;
|
||||
} else {
|
||||
refresh();
|
||||
if (draw) {
|
||||
if (gbl_plen + gbl_len < gbl_cols) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write(STDOUT_FILENO, &c, 1) == -1) return -1;
|
||||
} else {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memmove(gbl_buf + gbl_pos + 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
|
||||
gbl_buf[gbl_pos++] = c;
|
||||
gbl_buf[++gbl_len] = '\0';
|
||||
refresh();
|
||||
if (draw) refresh();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -266,7 +281,7 @@ static void historymove(int delta) {
|
||||
}
|
||||
}
|
||||
|
||||
static void addhistory() {
|
||||
static void addhistory(void) {
|
||||
int i, len;
|
||||
char *newline = sdup(gbl_buf);
|
||||
if (!newline) return;
|
||||
@@ -283,28 +298,28 @@ static void addhistory() {
|
||||
gbl_history[0] = newline;
|
||||
}
|
||||
|
||||
static void replacehistory() {
|
||||
static void replacehistory(void) {
|
||||
char *newline = sdup(gbl_buf);
|
||||
if (!newline) return;
|
||||
free(gbl_history[0]);
|
||||
gbl_history[0] = newline;
|
||||
}
|
||||
|
||||
static void kleft() {
|
||||
static void kleft(void) {
|
||||
if (gbl_pos > 0) {
|
||||
gbl_pos--;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static void kright() {
|
||||
static void kright(void) {
|
||||
if (gbl_pos != gbl_len) {
|
||||
gbl_pos++;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static void kbackspace() {
|
||||
static void kbackspace(void) {
|
||||
if (gbl_pos > 0) {
|
||||
memmove(gbl_buf + gbl_pos - 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
|
||||
gbl_pos--;
|
||||
@@ -313,7 +328,7 @@ static void kbackspace() {
|
||||
}
|
||||
}
|
||||
|
||||
static void kdelete() {
|
||||
static void kdelete(void) {
|
||||
if (gbl_pos != gbl_len) {
|
||||
memmove(gbl_buf + gbl_pos, gbl_buf + gbl_pos + 1, gbl_len - gbl_pos);
|
||||
gbl_buf[--gbl_len] = '\0';
|
||||
@@ -321,6 +336,167 @@ static void kdelete() {
|
||||
}
|
||||
}
|
||||
|
||||
/* See tools/symchargen.c */
|
||||
static int is_symbol_char_gen(uint8_t c) {
|
||||
if (c & 0x80) return 1;
|
||||
if (c >= 'a' && c <= 'z') return 1;
|
||||
if (c >= 'A' && c <= 'Z') return 1;
|
||||
if (c >= '0' && c <= '9') return 1;
|
||||
return (c == '!' ||
|
||||
c == '$' ||
|
||||
c == '%' ||
|
||||
c == '&' ||
|
||||
c == '*' ||
|
||||
c == '+' ||
|
||||
c == '-' ||
|
||||
c == '.' ||
|
||||
c == '/' ||
|
||||
c == ':' ||
|
||||
c == '<' ||
|
||||
c == '?' ||
|
||||
c == '=' ||
|
||||
c == '>' ||
|
||||
c == '@' ||
|
||||
c == '^' ||
|
||||
c == '_');
|
||||
}
|
||||
|
||||
static JanetByteView get_symprefix(void) {
|
||||
/* Calculate current partial symbol. Maybe we could actually hook up the Janet
|
||||
* parser here...*/
|
||||
int i;
|
||||
JanetByteView ret;
|
||||
ret.len = 0;
|
||||
for (i = gbl_pos - 1; i >= 0; i--) {
|
||||
uint8_t c = (uint8_t) gbl_buf[i];
|
||||
if (!is_symbol_char_gen(c)) break;
|
||||
ret.len++;
|
||||
}
|
||||
/* Will be const for duration of match checking */
|
||||
ret.bytes = (const uint8_t *)(gbl_buf + i + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int compare_bytes(JanetByteView a, JanetByteView b) {
|
||||
int32_t minlen = a.len < b.len ? a.len : b.len;
|
||||
int result = strncmp((const char *) a.bytes, (const char *) b.bytes, minlen);
|
||||
if (result) return result;
|
||||
return a.len < b.len ? -1 : a.len > b.len ? 1 : 0;
|
||||
}
|
||||
|
||||
static void check_match(JanetByteView src, const uint8_t *testsym, int32_t testlen) {
|
||||
JanetByteView test;
|
||||
test.bytes = testsym;
|
||||
test.len = testlen;
|
||||
if (src.len > test.len || strncmp((const char *) src.bytes, (const char *) test.bytes, src.len)) return;
|
||||
JanetByteView mm = test;
|
||||
for (int i = 0; i < gbl_match_count; i++) {
|
||||
if (compare_bytes(mm, gbl_matches[i]) < 0) {
|
||||
JanetByteView temp = mm;
|
||||
mm = gbl_matches[i];
|
||||
gbl_matches[i] = temp;
|
||||
}
|
||||
}
|
||||
if (gbl_match_count == JANET_MATCH_MAX) return;
|
||||
gbl_matches[gbl_match_count++] = mm;
|
||||
}
|
||||
|
||||
static void check_cmatch(JanetByteView src, const char *cstr) {
|
||||
check_match(src, (const uint8_t *) cstr, (int32_t) strlen(cstr));
|
||||
}
|
||||
|
||||
static JanetByteView longest_common_prefix(void) {
|
||||
JanetByteView bv;
|
||||
if (gbl_match_count == 0) {
|
||||
bv.len = 0;
|
||||
bv.bytes = NULL;
|
||||
} else {
|
||||
bv = gbl_matches[0];
|
||||
for (int i = 0; i < gbl_match_count; i++) {
|
||||
JanetByteView other = gbl_matches[i];
|
||||
int32_t minlen = other.len < bv.len ? other.len : bv.len;
|
||||
for (bv.len = 0; bv.len < minlen; bv.len++) {
|
||||
if (bv.bytes[bv.len] != other.bytes[bv.len]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bv;
|
||||
}
|
||||
|
||||
static void check_specials(JanetByteView src) {
|
||||
check_cmatch(src, "break");
|
||||
check_cmatch(src, "def");
|
||||
check_cmatch(src, "do");
|
||||
check_cmatch(src, "fn");
|
||||
check_cmatch(src, "if");
|
||||
check_cmatch(src, "quasiquote");
|
||||
check_cmatch(src, "quote");
|
||||
check_cmatch(src, "set");
|
||||
check_cmatch(src, "splice");
|
||||
check_cmatch(src, "unquote");
|
||||
check_cmatch(src, "var");
|
||||
check_cmatch(src, "while");
|
||||
}
|
||||
|
||||
/* TODO - check against special forms and print in alphabetical order */
|
||||
static void kshowcomp(void) {
|
||||
JanetTable *env = gbl_complete_env;
|
||||
if (env == NULL) {
|
||||
insert(' ', 0);
|
||||
insert(' ', 0);
|
||||
return;
|
||||
}
|
||||
|
||||
JanetByteView prefix = get_symprefix();
|
||||
if (prefix.len == 0) return;
|
||||
|
||||
/* Find all matches */
|
||||
gbl_match_count = 0;
|
||||
while (NULL != env) {
|
||||
JanetKV *kvend = env->data + env->capacity;
|
||||
for (JanetKV *kv = env->data; kv < kvend; kv++) {
|
||||
if (!janet_checktype(kv->key, JANET_SYMBOL)) continue;
|
||||
const uint8_t *sym = janet_unwrap_symbol(kv->key);
|
||||
check_match(prefix, sym, janet_string_length(sym));
|
||||
}
|
||||
env = env->proto;
|
||||
}
|
||||
|
||||
check_specials(prefix);
|
||||
|
||||
JanetByteView lcp = longest_common_prefix();
|
||||
for (int i = prefix.len; i < lcp.len; i++) {
|
||||
insert(lcp.bytes[i], 0);
|
||||
}
|
||||
|
||||
int32_t maxlen = 0;
|
||||
for (int i = 0; i < gbl_match_count; i++)
|
||||
if (gbl_matches[i].len > maxlen)
|
||||
maxlen = gbl_matches[i].len;
|
||||
|
||||
int num_cols = getcols();
|
||||
if (gbl_match_count >= 2) {
|
||||
|
||||
norawmode();
|
||||
|
||||
/* Second pass, print */
|
||||
int col_width = maxlen + 4;
|
||||
int cols = num_cols / col_width;
|
||||
if (cols == 0) cols = 1;
|
||||
int current_col = 0;
|
||||
for (int i = 0; i < gbl_match_count; i++) {
|
||||
if (current_col == 0) printf("\n");
|
||||
printf("%-*s", col_width, (const char *) gbl_matches[i].bytes);
|
||||
current_col = (current_col + 1) % cols;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
rawmode();
|
||||
}
|
||||
}
|
||||
|
||||
static int line() {
|
||||
gbl_cols = getcols();
|
||||
gbl_plen = 0;
|
||||
@@ -342,11 +518,11 @@ static int line() {
|
||||
|
||||
switch (c) {
|
||||
default:
|
||||
if (insert(c)) return -1;
|
||||
if (insert(c, 1)) return -1;
|
||||
break;
|
||||
case 9: /* tab */
|
||||
if (insert(' ')) return -1;
|
||||
if (insert(' ')) return -1;
|
||||
kshowcomp();
|
||||
refresh();
|
||||
break;
|
||||
case 13: /* enter */
|
||||
return 0;
|
||||
@@ -360,9 +536,17 @@ static int line() {
|
||||
break;
|
||||
case 4: /* ctrl-d, eof */
|
||||
return -1;
|
||||
case 1: /* ctrl-a */
|
||||
gbl_pos = 0;
|
||||
refresh();
|
||||
break;
|
||||
case 2: /* ctrl-b */
|
||||
kleft();
|
||||
break;
|
||||
case 5: /* ctrl-e */
|
||||
gbl_pos = gbl_len;
|
||||
refresh();
|
||||
break;
|
||||
case 6: /* ctrl-f */
|
||||
kright();
|
||||
break;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -23,6 +23,10 @@
|
||||
#ifndef JANET_LINE_H_defined
|
||||
#define JANET_LINE_H_defined
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include <janet.h>
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
@@ -20,6 +20,10 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include <janet.h>
|
||||
#include "line.h"
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <janet.h>
|
||||
#include <emscripten.h>
|
||||
|
||||
extern const unsigned char *janet_gen_webinit;
|
||||
extern int32_t janet_gen_webinit_size;
|
||||
|
||||
static JanetFiber *repl_fiber = NULL;
|
||||
static JanetBuffer *line_buffer = NULL;
|
||||
static const uint8_t *line_prompt = NULL;
|
||||
|
||||
/* Yield to JS event loop from janet. Takes a repl prompt
|
||||
* and a buffer to fill with input data. */
|
||||
static Janet repl_yield(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
line_prompt = janet_getstring(argv, 0);
|
||||
line_buffer = janet_getbuffer(argv, 1);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
/* Re-enter the loop */
|
||||
static int enter_loop(void) {
|
||||
Janet ret;
|
||||
JanetSignal status = janet_continue(repl_fiber, janet_wrap_nil(), &ret);
|
||||
if (status == JANET_SIGNAL_ERROR) {
|
||||
janet_stacktrace(repl_fiber, ret);
|
||||
janet_deinit();
|
||||
repl_fiber = NULL;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allow JS interoperation from within janet */
|
||||
static Janet cfun_js(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetByteView bytes = janet_getbytes(argv, 0);
|
||||
emscripten_run_script((const char *)bytes.bytes);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
/* Initialize the repl */
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void repl_init(void) {
|
||||
int status;
|
||||
JanetTable *env;
|
||||
|
||||
/* Set up VM */
|
||||
janet_init();
|
||||
janet_register("repl-yield", repl_yield);
|
||||
janet_register("js", cfun_js);
|
||||
env = janet_core_env(NULL);
|
||||
|
||||
janet_def(env, "repl-yield", janet_wrap_cfunction(repl_yield), NULL);
|
||||
janet_def(env, "js", janet_wrap_cfunction(cfun_js), NULL);
|
||||
|
||||
/* Run startup script */
|
||||
Janet ret;
|
||||
status = janet_dobytes(env, janet_gen_webinit, janet_gen_webinit_size, "webinit.janet", &ret);
|
||||
if (status == JANET_SIGNAL_ERROR) {
|
||||
printf("start up error.\n");
|
||||
janet_deinit();
|
||||
repl_fiber = NULL;
|
||||
return;
|
||||
}
|
||||
janet_gcroot(ret);
|
||||
repl_fiber = janet_unwrap_fiber(ret);
|
||||
|
||||
/* Start repl */
|
||||
if (enter_loop()) return;
|
||||
}
|
||||
|
||||
/* Deinitialize the repl */
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void repl_deinit(void) {
|
||||
if (!repl_fiber) {
|
||||
return;
|
||||
}
|
||||
repl_fiber = NULL;
|
||||
line_buffer = NULL;
|
||||
janet_deinit();
|
||||
}
|
||||
|
||||
/* Get the prompt to show in the repl */
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
const char *repl_prompt(void) {
|
||||
return line_prompt ? ((const char *)line_prompt) : "";
|
||||
}
|
||||
|
||||
/* Restart the repl calling from JS. Pass in the input for the next line. */
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void repl_input(char *input) {
|
||||
|
||||
/* Create the repl if we haven't yet */
|
||||
if (!repl_fiber) {
|
||||
printf("initialize the repl first");
|
||||
}
|
||||
|
||||
/* Now fill the pending line_buffer and resume the repl loop */
|
||||
if (line_buffer) {
|
||||
janet_buffer_push_cstring(line_buffer, input);
|
||||
line_buffer = NULL;
|
||||
enter_loop();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2017-2019 (C) Calvin Rose
|
||||
|
||||
(print (string "Janet " janet/version "-" janet/build " Copyright (C) 2017-2019 Calvin Rose"))
|
||||
|
||||
(fiber/new (fn webrepl []
|
||||
(setdyn :pretty-format "%.20P")
|
||||
(repl (fn get-line [buf p]
|
||||
(def [offset] (parser/where p))
|
||||
(def prompt (string "janet:" offset ":" (parser/state p :delimiters) "> "))
|
||||
(repl-yield prompt buf)
|
||||
(yield)
|
||||
buf))))
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
(var numchecks 0)
|
||||
(var start-time 0)
|
||||
|
||||
(defn assert [x e]
|
||||
(defn assert
|
||||
"Override's the default assert with some nice error handling."
|
||||
[x e]
|
||||
(++ num-tests-run)
|
||||
(when x (++ num-tests-passed))
|
||||
(if x
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
:name "testmod"
|
||||
:source @["testmod.c"])
|
||||
|
||||
(declare-native
|
||||
:name "testmod2"
|
||||
:source @["testmod2.c"])
|
||||
|
||||
(declare-executable
|
||||
:name "testexec"
|
||||
:entry "testexec.janet")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(use build/testmod)
|
||||
(use build/testmod2)
|
||||
|
||||
(defn main [&]
|
||||
(print "Hello from executable!")
|
||||
(print (get5)))
|
||||
(print (+ (get5) (get6))))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose and contributors
|
||||
* Copyright (c) 2020 Calvin Rose and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
|
||||
40
test/install/testmod2.c
Normal file
40
test/install/testmod2.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Calvin Rose and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in 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 very simple native module */
|
||||
|
||||
#include <janet.h>
|
||||
|
||||
static Janet cfun_get_six(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 0);
|
||||
return janet_wrap_number(6.0);
|
||||
}
|
||||
|
||||
static const JanetReg array_cfuns[] = {
|
||||
{"get6", cfun_get_six, NULL},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
JANET_MODULE_ENTRY(JanetTable *env) {
|
||||
janet_cfuns(env, NULL, array_cfuns);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose
|
||||
# Copyright (c) 2020 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
|
||||
@@ -37,18 +37,18 @@
|
||||
(assert (= 7 (% 20 13)) "modulo 1")
|
||||
(assert (= -7 (% -20 13)) "modulo 2")
|
||||
|
||||
(assert (order< 1.0 nil false true
|
||||
(fiber/new (fn [] 1))
|
||||
"hi"
|
||||
(quote hello)
|
||||
:hello
|
||||
(array 1 2 3)
|
||||
(tuple 1 2 3)
|
||||
(table "a" "b" "c" "d")
|
||||
(struct 1 2 3 4)
|
||||
(buffer "hi")
|
||||
(fn [x] (+ x x))
|
||||
print) "type ordering")
|
||||
(assert (< 1.0 nil false true
|
||||
(fiber/new (fn [] 1))
|
||||
"hi"
|
||||
(quote hello)
|
||||
:hello
|
||||
(array 1 2 3)
|
||||
(tuple 1 2 3)
|
||||
(table "a" "b" "c" "d")
|
||||
(struct 1 2 3 4)
|
||||
(buffer "hi")
|
||||
(fn [x] (+ x x))
|
||||
print) "type ordering")
|
||||
|
||||
(assert (= (string (buffer "123" "456")) (string @"123456")) "buffer literal")
|
||||
(assert (= (get {} 1) nil) "get nil from empty struct")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose
|
||||
# Copyright (c) 2020 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
|
||||
@@ -232,11 +232,11 @@
|
||||
(assert (= 4 ((get closures 4))) "closure in loop 4")
|
||||
|
||||
# More numerical tests
|
||||
(assert (== 1 1.0) "numerical equal 1")
|
||||
(assert (== 0 0.0) "numerical equal 2")
|
||||
(assert (== 0 -0.0) "numerical equal 3")
|
||||
(assert (== 2_147_483_647 2_147_483_647.0) "numerical equal 4")
|
||||
(assert (== -2_147_483_648 -2_147_483_648.0) "numerical equal 5")
|
||||
(assert (= 1 1.0) "numerical equal 1")
|
||||
(assert (= 0 0.0) "numerical equal 2")
|
||||
(assert (= 0 -0.0) "numerical equal 3")
|
||||
(assert (= 2_147_483_647 2_147_483_647.0) "numerical equal 4")
|
||||
(assert (= -2_147_483_648 -2_147_483_648.0) "numerical equal 5")
|
||||
|
||||
# Array tests
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#' Copyright (c) 2019 Calvin Rose
|
||||
#' Copyright (c) 2020 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose
|
||||
# Copyright (c) 2020 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
|
||||
@@ -203,12 +203,12 @@
|
||||
(defn check-match
|
||||
[pat text should-match]
|
||||
(def result (peg/match pat text))
|
||||
(assert (= (not should-match) (not result)) text))
|
||||
(assert (= (not should-match) (not result)) (string "check-match " text)))
|
||||
|
||||
(defn check-deep
|
||||
[pat text what]
|
||||
(def result (peg/match pat text))
|
||||
(assert (deep= result what) text))
|
||||
(assert (deep= result what) (string "check-deep " text)))
|
||||
|
||||
# Just numbers
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose
|
||||
# Copyright (c) 2020 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose & contributors
|
||||
# Copyright (c) 2020 Calvin Rose & contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose & contributors
|
||||
# Copyright (c) 2020 Calvin Rose & contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -62,8 +62,8 @@
|
||||
# just to big
|
||||
(def d (u64 "123456789123456789123456789"))))
|
||||
|
||||
(assert (:== (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) "0xfffffffffffffff") "bigint operations")
|
||||
(assert (let [a (u64 0xff)] (:== (:+ a a a a) (:* a 2 2))) "bigint operations")
|
||||
(assert (= (:/ (u64 "0xffff_ffff_ffff_ffff") 8 2) (u64 "0xfffffffffffffff")) "bigint operations 1")
|
||||
(assert (let [a (u64 0xff)] (= (:+ a a a a) (:* a 2 2))) "bigint operations 2")
|
||||
|
||||
(assert (= (string (i64 -123)) "-123") "i64 prints reasonably")
|
||||
(assert (= (string (u64 123)) "123") "u64 prints reasonably")
|
||||
@@ -73,7 +73,7 @@
|
||||
(:/ (int/s64 "-0x8000_0000_0000_0000") -1))
|
||||
|
||||
# in place operators
|
||||
(assert (let [a (u64 1e10)] (:+! a 1000000 "1000000" "0xffff") (:== a 10002065535)) "in place operators")
|
||||
(assert (let [a (u64 1e10)] (:+! a 1000000 "1000000" "0xffff") (:= a 10002065535)) "in place operators")
|
||||
|
||||
# int64 typed arrays
|
||||
(assert (let [t (tarray/new :int64 10)
|
||||
@@ -84,10 +84,10 @@
|
||||
(set (t 3) (t 0))
|
||||
(set (t 4) (u64 1000))
|
||||
(and
|
||||
(:== (t 0) (t 1))
|
||||
(:== (t 1) (t 2))
|
||||
(:== (t 2) (t 3))
|
||||
(:== (t 3) (t 4))
|
||||
(= (t 0) (t 1))
|
||||
(= (t 1) (t 2))
|
||||
(= (t 2) (t 3))
|
||||
(= (t 3) (t 4))
|
||||
))
|
||||
"int64 typed arrays")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2019 Calvin Rose & contributors
|
||||
# Copyright (c) 2020 Calvin Rose & contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -277,4 +277,26 @@
|
||||
|
||||
(assert (= (constantly) (constantly)) "comptime 1")
|
||||
|
||||
(assert-error "arity issue in macro" (eval '(each [])))
|
||||
(assert-error "comptime issue" (eval '(comptime (error "oops"))))
|
||||
|
||||
(with [f (file/temp)]
|
||||
(file/write f "foo\n")
|
||||
(file/flush f)
|
||||
(file/seek f :set 0)
|
||||
(assert (= (string (file/read f :all)) "foo\n") "temp files work"))
|
||||
|
||||
(var counter 0)
|
||||
(when-with [x nil |$]
|
||||
(++ counter))
|
||||
(when-with [x 10 |$]
|
||||
(+= counter 10))
|
||||
|
||||
(assert (= 10 counter) "when-with 1")
|
||||
|
||||
(if-with [x nil |$] (++ counter) (+= counter 10))
|
||||
(if-with [x true |$] (+= counter 20) (+= counter 30))
|
||||
|
||||
(assert (= 40 counter) "if-with 1")
|
||||
|
||||
(end-suite)
|
||||
|
||||
BIN
tools/EnVar.dll
Normal file
BIN
tools/EnVar.dll
Normal file
Binary file not shown.
@@ -1,327 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@@ -5,6 +5,7 @@
|
||||
(print "/* Generated from janet version " janet/version "-" janet/build " */")
|
||||
(print "#define JANET_BUILD \"" janet/build "\"")
|
||||
(print ```#define JANET_AMALG```)
|
||||
(print ```#define _POSIX_C_SOURCE 200112L```)
|
||||
(print ```#include "janet.h"```)
|
||||
|
||||
# Body
|
||||
|
||||
Binary file not shown.
BIN
tools/nsis-3.05-strlen_8192.zip
Normal file
BIN
tools/nsis-3.05-strlen_8192.zip
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Calvin Rose
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
Reference in New Issue
Block a user