mirror of
https://github.com/janet-lang/janet
synced 2026-04-07 07:21:26 +00:00
Compare commits
24 Commits
v1.1.0
...
executable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71e5278364 | ||
|
|
d6a1faa380 | ||
|
|
166862ecff | ||
|
|
3c133bd677 | ||
|
|
b0b1024f8a | ||
|
|
cc07ff987d | ||
|
|
efc38b87de | ||
|
|
a3a3e4c0dc | ||
|
|
d46bcd5b8f | ||
|
|
dfe00fee94 | ||
|
|
9118f2ce08 | ||
|
|
a0e98b9aa8 | ||
|
|
0d3986abbb | ||
|
|
529b34d84e | ||
|
|
e0fe8476aa | ||
|
|
0ca0180f27 | ||
|
|
21a355c89f | ||
|
|
e528b86a2a | ||
|
|
2e6ee39506 | ||
|
|
894877a0e3 | ||
|
|
6887dd05f6 | ||
|
|
95dbad6ec1 | ||
|
|
ea88ae1a5b | ||
|
|
e8e4d637ef |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,6 +20,9 @@ dist
|
||||
.project
|
||||
.cproject
|
||||
|
||||
# Gnome Builder
|
||||
.buildconfig
|
||||
|
||||
# Local directory for testing
|
||||
local
|
||||
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,6 +1,21 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## Unreleased
|
||||
- Add `(dyn :executable)` at top level to get what used to be
|
||||
`(process/args 0)`.
|
||||
- Add `:linux` to platforms returned by `(os/which)`.
|
||||
- Update jpm to build standalone executables. Use `declare-executable` for this.
|
||||
- Add `use` macro.
|
||||
- Remove `process/args` in favor of `(dyn :args)`.
|
||||
- Fix bug with Nanbox implementation allowing users to created
|
||||
custom values of any type with typed array and marshal modules, which
|
||||
was unsafe.
|
||||
- Add `janet_wrap_number_safe` to API, for converting numbers to Janets
|
||||
where the number could be any 64 bit, user provided bit pattern. Certain
|
||||
NaN values (which a machine will never generate as a result of a floating
|
||||
point operation) are guarded against and converted to a default NaN value.
|
||||
|
||||
## 1.1.0 - 2019-07-08
|
||||
- Change semantics of `-l` flag to be import rather than dofile.
|
||||
- Fix compiler regression in top level defs with destructuring.
|
||||
|
||||
3
Makefile
3
Makefile
@@ -329,7 +329,8 @@ clean:
|
||||
-rm -rf build vgcore.* callgrind.*
|
||||
|
||||
test-install:
|
||||
cd test/install && rm -rf build && jpm build && jpm test
|
||||
cd test/install && rm -rf build .cache .manifests && jpm --verbose build && jpm --verbose test \
|
||||
&& build/testexec
|
||||
|
||||
build/embed_janet.o: build/janet.c $(JANET_HEADERS)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
@@ -132,6 +132,13 @@ is maybe more convenient and flexible for integrating into existing pipelines.
|
||||
Meson also provides much better IDE integration than Make or batch files, as well as support
|
||||
for cross compilation.
|
||||
|
||||
## Development
|
||||
|
||||
Janet can be hacked on with pretty much any environment you like, but for IDE
|
||||
lovers, [Gnome Builder](https://wiki.gnome.org/Apps/Builder) is probably the
|
||||
best option, as it has excellent meson integration. It also offers code completion
|
||||
for Janet's C API right out of the box, which is very useful for exploring.
|
||||
|
||||
## Installation
|
||||
|
||||
See [the Introduction](https://janet-lang.org/introduction.html) for more details. If you just want
|
||||
|
||||
@@ -33,7 +33,7 @@ only_commits:
|
||||
|
||||
artifacts:
|
||||
- path: janet-installer.exe
|
||||
name: janet-v1.1.0-windows-installer.exe
|
||||
name: janet-v1.2.0-windows-installer.exe
|
||||
type: File
|
||||
|
||||
deploy:
|
||||
|
||||
34
auxbin/jpm
34
auxbin/jpm
@@ -6,7 +6,7 @@
|
||||
|
||||
(def- argpeg
|
||||
(peg/compile
|
||||
'(* "--" '(some (if-not "=" 1)) "=" '(any 1))))
|
||||
'(* "--" '(some (if-not "=" 1)) (+ (* "=" '(any 1)) -1))))
|
||||
|
||||
(defn- local-rule
|
||||
[rule]
|
||||
@@ -16,7 +16,7 @@
|
||||
(defn- help
|
||||
[]
|
||||
(print `
|
||||
usage: jpm --key=value ... [subcommand] [args]...
|
||||
usage: jpm [--key=value, --flag] ... [subcommand] [args] ...
|
||||
|
||||
Subcommands are:
|
||||
build : build all artifacts
|
||||
@@ -32,13 +32,17 @@ Subcommands are:
|
||||
|
||||
Keys are:
|
||||
--modpath : The directory to install modules to. Defaults to $JANET_MODPATH or (dyn :syspath)
|
||||
--headerpath : The directory containing janet headers. Defaults to $JANET_HEADERPATH or (dyn :headerpath)
|
||||
--headerpath : The directory containing janet headers. Defaults to $JANET_HEADERPATH.
|
||||
--binpath : The directory to install binaries and scripts. Defaults to $JANET_BINPATH.
|
||||
--optimize : Optimization level for natives. Defaults to $OPTIMIZE or 2.
|
||||
--compiler : C compiler to use for natives. Defaults to $COMPILER or cc.
|
||||
--linker : C linker to use for linking natives. Defaults to $LINKER or cc.
|
||||
--cflags : Extra compiler flags for native modules. Defaults to $CFLAGS if set.
|
||||
--lflags : Extra linker flags for native modules. Defaults to $LFLAGS if set.
|
||||
--libpath : The directory containing janet C libraries (libjanet.*). Defaults to $JANET_LIBPATH.
|
||||
--optimize : Optimization level for natives. Defaults to 2.
|
||||
--compiler : C compiler to use for natives. Defaults to cc (cl on windows).
|
||||
--linker : C linker to use for linking natives. Defaults to cc (link on windows).
|
||||
--cflags : Extra compiler flags for native modules.
|
||||
--lflags : Extra linker flags for native modules.
|
||||
|
||||
Flags are:
|
||||
--verbose : Print shell commands as they are executed.
|
||||
`))
|
||||
|
||||
(defn build
|
||||
@@ -79,18 +83,18 @@ Keys are:
|
||||
"clear-cache" cook/clear-cache
|
||||
"uninstall" uninstall})
|
||||
|
||||
(def args (tuple/slice process/args 2))
|
||||
(def args (tuple/slice (dyn :args) 1))
|
||||
(def len (length args))
|
||||
(var i 0)
|
||||
|
||||
# Get flags
|
||||
(while (< i len)
|
||||
(def arg (args i))
|
||||
(unless (string/has-prefix? "--" arg) (break))
|
||||
(if-let [m (peg/match argpeg arg)]
|
||||
(let [[key value] m]
|
||||
(setdyn (keyword key) value))
|
||||
(print "invalid argument " arg))
|
||||
(if-let [m (peg/match argpeg (args i))]
|
||||
(if (= 2 (length m))
|
||||
(let [[key value] m]
|
||||
(setdyn (keyword key) value))
|
||||
(setdyn (keyword (m 0)) true))
|
||||
(break))
|
||||
(++ i))
|
||||
|
||||
# Run subcommand
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
(def- sep (if is-win "\\" "/"))
|
||||
(def- objext (if is-win ".obj" ".o"))
|
||||
(def- modext (if is-win ".dll" ".so"))
|
||||
(def- statext (if is-win ".lib" ".a"))
|
||||
(def- absprefix (if is-win "C:\\" "/"))
|
||||
|
||||
#
|
||||
@@ -91,55 +92,48 @@
|
||||
(thunk))
|
||||
(unless phony target))
|
||||
|
||||
(def- _env (fiber/getenv (fiber/current)))
|
||||
|
||||
(defn import-rules
|
||||
"Import another file that defines more cook rules. This ruleset
|
||||
is merged into the current ruleset."
|
||||
[path]
|
||||
(def env (make-env))
|
||||
(unless (os/stat path :mode)
|
||||
(error (string "cannot open " path)))
|
||||
(loop [k :keys _env :when (symbol? k)]
|
||||
(unless ((_env k) :private) (put env k (_env k))))
|
||||
(def currenv (fiber/getenv (fiber/current)))
|
||||
(loop [k :keys currenv :when (keyword? k)]
|
||||
(put env k (currenv k)))
|
||||
(dofile path :env env)
|
||||
(when-let [rules (env :rules)] (merge-into (getrules) rules)))
|
||||
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
# Installation settings
|
||||
(def JANET_MODPATH (or (os/getenv "JANET_MODPATH") (dyn :syspath)))
|
||||
(def JANET_HEADERPATH (os/getenv "JANET_HEADERPATH"))
|
||||
(def JANET_BINPATH (or (os/getenv "JANET_BINPATH") (unless is-win "/usr/local/bin")))
|
||||
(def JANET_HEADERPATH (or (os/getenv "JANET_HEADERPATH")
|
||||
(if-let [j JANET_MODPATH]
|
||||
(string j "/../../include/janet"))))
|
||||
(def JANET_BINPATH (or (os/getenv "JANET_BINPATH")
|
||||
(if-let [j JANET_MODPATH]
|
||||
(string j "/../../bin"))))
|
||||
(def JANET_LIBPATH (or (os/getenv "JANET_LIBPATH")
|
||||
(if-let [j JANET_MODPATH]
|
||||
(string j "/.."))))
|
||||
|
||||
# Compilation settings
|
||||
(def- OPTIMIZE (or (os/getenv "OPTIMIZE") 2))
|
||||
(def- COMPILER (or (os/getenv "COMPILER") (if is-win "cl" "cc")))
|
||||
(def- LINKER (or (os/getenv "LINKER") (if is-win "link" COMPILER)))
|
||||
(def- LFLAGS
|
||||
(if-let [lflags (os/getenv "LFLAGS")]
|
||||
(string/split " " lflags)
|
||||
(if is-win ["/nologo" "/DLL"]
|
||||
#
|
||||
# Compilation Defaults
|
||||
#
|
||||
|
||||
(def default-compiler (if is-win "cl" "cc"))
|
||||
(def default-linker (if is-win "link" "cc"))
|
||||
(def default-archiver (if is-win "lib" "ar"))
|
||||
|
||||
# Default flags for natives, but not required
|
||||
(def default-lflags [])
|
||||
(def default-cflags
|
||||
(if is-win
|
||||
[]
|
||||
["-std=c99" "-Wall" "-Wextra"]))
|
||||
|
||||
# Required flags for dynamic libraries. These
|
||||
# are used no matter what for dynamic libraries.
|
||||
(def- dynamic-cflags
|
||||
(if is-win
|
||||
["/nologo"]
|
||||
["-fpic"]))
|
||||
(def- dynamic-lflags
|
||||
(if is-win
|
||||
["/nologo" "/DLL"]
|
||||
(if is-mac
|
||||
["-shared" "-undefined" "dynamic_lookup"]
|
||||
["-shared"]))))
|
||||
(def- CFLAGS
|
||||
(if-let [cflags (os/getenv "CFLAGS")]
|
||||
(string/split " " cflags)
|
||||
(if is-win
|
||||
["/nologo"]
|
||||
["-std=c99" "-Wall" "-Wextra" "-fpic"])))
|
||||
|
||||
# Some defaults
|
||||
(def default-cflags CFLAGS)
|
||||
(def default-lflags LFLAGS)
|
||||
(def default-cc COMPILER)
|
||||
(def default-ld LINKER)
|
||||
["-shared"])))
|
||||
|
||||
(defn- opt
|
||||
"Get an option, allowing overrides via dynamic bindings AND some
|
||||
@@ -150,13 +144,54 @@
|
||||
(error (string "option :" key " not set")))
|
||||
ret)
|
||||
|
||||
#
|
||||
# Importing a file
|
||||
#
|
||||
|
||||
(def- _env (fiber/getenv (fiber/current)))
|
||||
|
||||
(defn- proto-flatten
|
||||
[into x]
|
||||
(when x
|
||||
(proto-flatten into (table/getproto x))
|
||||
(loop [k :keys x]
|
||||
(put into k (x k))))
|
||||
into)
|
||||
|
||||
(defn import-rules
|
||||
"Import another file that defines more cook rules. This ruleset
|
||||
is merged into the current ruleset."
|
||||
[path]
|
||||
(def env (make-env))
|
||||
(unless (os/stat path :mode)
|
||||
(error (string "cannot open " path)))
|
||||
(loop [k :keys _env :when (symbol? k)]
|
||||
(unless ((_env k) :private) (put env k (_env k))))
|
||||
(def currenv (proto-flatten @{} (fiber/getenv (fiber/current))))
|
||||
(loop [k :keys currenv :when (keyword? k)]
|
||||
(put env k (currenv k)))
|
||||
(dofile path :env env)
|
||||
(when-let [rules (env :rules)] (merge-into (getrules) rules)))
|
||||
|
||||
#
|
||||
# OS and shell helpers
|
||||
#
|
||||
|
||||
(def- filepath-replacer
|
||||
"Convert url with potential bad characters into a file path element."
|
||||
(peg/compile ~(% (any (+ (/ '(set "<>:\"/\\|?*") "_") '1)))))
|
||||
|
||||
(defn filepath-replace
|
||||
"Remove special characters from a string or path
|
||||
to make it into a path segment."
|
||||
[repo]
|
||||
(get (peg/match filepath-replacer repo) 0))
|
||||
|
||||
(defn shell
|
||||
"Do a shell command"
|
||||
[& args]
|
||||
(if (dyn :verbose)
|
||||
(print ;(interpose " " args)))
|
||||
(def res (os/execute args :p))
|
||||
(unless (zero? res)
|
||||
(error (string "command exited with status " res))))
|
||||
@@ -190,42 +225,20 @@
|
||||
(string/replace-all sep "___")
|
||||
(string/replace-all ".janet" "")))
|
||||
|
||||
(defn- embed-c-name
|
||||
"Rename a janet file for embedding."
|
||||
[path]
|
||||
(defn- out-path
|
||||
"Take a source file path and convert it to an output path."
|
||||
[path from-ext to-ext]
|
||||
(->> path
|
||||
(string/replace-all sep "___")
|
||||
(string/replace-all ".janet" ".janet.c")
|
||||
(string/replace-all from-ext to-ext)
|
||||
(string "build" sep)))
|
||||
|
||||
(defn- embed-o-name
|
||||
"Get object file for c file."
|
||||
[path]
|
||||
(->> path
|
||||
(string/replace-all sep "___")
|
||||
(string/replace-all ".janet" (string ".janet" objext))
|
||||
(string "build" sep)))
|
||||
|
||||
(defn- object-name
|
||||
"Rename a source file so it can be built in a flat source tree."
|
||||
[path]
|
||||
(->> path
|
||||
(string/replace-all sep "___")
|
||||
(string/replace-all ".c" (if is-win ".obj" ".o"))
|
||||
(string "build" sep)))
|
||||
|
||||
(defn- lib-name
|
||||
"Generate name for dynamic library."
|
||||
[name]
|
||||
(string "build" sep name modext))
|
||||
|
||||
(defn- make-define
|
||||
"Generate strings for adding custom defines to the compiler."
|
||||
[define value]
|
||||
(def pre (if is-win "/D" "-D"))
|
||||
(if value
|
||||
(string pre define "=" value)
|
||||
(string pre define)))
|
||||
(string (if is-win "/D" "-D") define "=" value)
|
||||
(string (if is-win "/D" "-D") define)))
|
||||
|
||||
(defn- make-defines
|
||||
"Generate many defines. Takes a dictionary of defines. If a value is
|
||||
@@ -236,16 +249,19 @@
|
||||
(defn- getcflags
|
||||
"Generate the c flags from the input options."
|
||||
[opts]
|
||||
@[;(opt opts :cflags CFLAGS)
|
||||
(string (if is-win "/I" "-I") (opt opts :headerpath JANET_HEADERPATH))
|
||||
(string (if is-win "/O" "-O") (opt opts :optimize OPTIMIZE))])
|
||||
@[;(opt opts :cflags default-cflags)
|
||||
(string (if is-win "/I" "-I") (dyn :headerpath JANET_HEADERPATH))
|
||||
(string (if is-win "/O" "-O") (opt opts :optimize 2))])
|
||||
|
||||
(defn- compile-c
|
||||
"Compile a C file into an object file."
|
||||
[opts src dest]
|
||||
(def cc (opt opts :compiler COMPILER))
|
||||
(def cflags (getcflags opts))
|
||||
(def defines (interpose " " (make-defines (opt opts :defines {}))))
|
||||
[opts src dest &opt static?]
|
||||
(def cc (opt opts :compiler default-compiler))
|
||||
(def cflags [;(getcflags opts) ;(if static? [] dynamic-cflags)])
|
||||
(def entry-defines (if-let [n (opts :entry-name)]
|
||||
[(make-define "JANET_ENTRY_NAME" (string "janet_module_entry_" (filepath-replace n)))]
|
||||
[]))
|
||||
(def defines [;(make-defines (opt opts :defines {})) ;entry-defines])
|
||||
(def headers (or (opts :headers) []))
|
||||
(rule dest [src ;headers]
|
||||
(print "compiling " dest "...")
|
||||
@@ -253,36 +269,151 @@
|
||||
(shell cc ;defines "/c" ;cflags (string "/Fo" dest) src)
|
||||
(shell cc "-c" src ;defines ;cflags "-o" dest))))
|
||||
|
||||
(defn- libjanet
|
||||
"Find libjanet.a (or libjanet.lib on windows) at compile time"
|
||||
[]
|
||||
(def libpath (dyn :libpath JANET_LIBPATH))
|
||||
(unless libpath
|
||||
(error "cannot find libpath: provide --libpath or JANET_LIBPATH"))
|
||||
(string (dyn :libpath JANET_LIBPATH)
|
||||
sep
|
||||
(if is-win "libjanet.lib" "libjanet.a")))
|
||||
|
||||
(defn- win-import-library
|
||||
"On windows, an import library is needed to link to a dll statically."
|
||||
[]
|
||||
(def hpath (dyn :headerpath JANET_HEADERPATH))
|
||||
(unless hpath
|
||||
(error "cannot find headerpath: provide --headerpath or JANET_HEADERPATH"))
|
||||
(string hpath `\\janet.lib`))
|
||||
|
||||
(defn- link-c
|
||||
"Link a number of object files together."
|
||||
"Link object files together to make a native module."
|
||||
[opts target & objects]
|
||||
(def ld (opt opts :linker LINKER))
|
||||
(def ld (opt opts :linker default-linker))
|
||||
(def cflags (getcflags opts))
|
||||
(def lflags (opt opts :lflags LFLAGS))
|
||||
(def standalone (opts :standalone))
|
||||
(def lflags [;(opt opts :lflags default-lflags)
|
||||
;(if (opts :static) [] dynamic-lflags)
|
||||
;(if standalone (case (os/which)
|
||||
:macos ["-ldl" "-lm"]
|
||||
:windows []
|
||||
:linux ["-lm" "-ldl" "-lrt"]
|
||||
#default
|
||||
["-lm"]) [])])
|
||||
(rule target objects
|
||||
(print "linking " target "...")
|
||||
(if is-win
|
||||
(shell ld ;lflags (string "/OUT:" target) ;objects (string (opt opts :headerpath JANET_HEADERPATH) `\\janet.lib`))
|
||||
(shell ld ;cflags `-o` target ;objects ;lflags))))
|
||||
(shell ld ;lflags (string "/OUT:" target) (if standalone (libjanet) (win-import-library)) ;objects)
|
||||
(shell ld ;cflags `-o` target ;objects ;(if standalone [(libjanet)] []) ;lflags))))
|
||||
|
||||
(defn- archive-c
|
||||
"Link object files together to make a static library."
|
||||
[opts target & objects]
|
||||
(def ar (opt opts :archiver default-archiver))
|
||||
(rule target objects
|
||||
(print "creating static library " target "...")
|
||||
(if is-win
|
||||
(do (print "Not Yet Implemented!") (os/exit 1))
|
||||
(shell ar "rcs" target ;objects))))
|
||||
|
||||
(defn- create-buffer-c-impl
|
||||
[bytes dest name]
|
||||
(def out (file/open dest :w))
|
||||
(def chunks (seq [b :in bytes] (string b)))
|
||||
(file/write out
|
||||
"#include <janet.h>\n"
|
||||
"static const unsigned char bytes[] = {"
|
||||
;(interpose ", " chunks)
|
||||
"};\n\n"
|
||||
"const unsigned char *" name "_embed = bytes;\n"
|
||||
"size_t " name "_embed_size = sizeof(bytes);\n")
|
||||
(file/close out))
|
||||
|
||||
(defn- create-buffer-c
|
||||
"Inline raw byte file as a c file."
|
||||
[source dest name]
|
||||
(rule dest [source]
|
||||
(print "generating " dest "...")
|
||||
(def f (file/open source :r))
|
||||
(if (not f) (error (string "file " f " not found")))
|
||||
(def out (file/open dest :w))
|
||||
(def chunks (seq [b :in (file/read f :all)] (string b)))
|
||||
(file/write out
|
||||
"#include <janet.h>\n"
|
||||
"static const unsigned char bytes[] = {"
|
||||
;(interpose ", " chunks)
|
||||
"};\n\n"
|
||||
"const unsigned char *" name "_embed = bytes;\n"
|
||||
"size_t " name "_embed_size = sizeof(bytes);\n")
|
||||
(file/close out)
|
||||
(file/close f)))
|
||||
(with [f (file/open source :r)]
|
||||
(create-buffer-c-impl (:read f :all) dest name))))
|
||||
|
||||
(def- root-env (table/getproto (fiber/getenv (fiber/current))))
|
||||
|
||||
(defn- create-executable
|
||||
"Links an image with libjanet.a (or .lib) to produce an
|
||||
executable. Also will try to link native modules into the
|
||||
final executable as well."
|
||||
[opts source dest]
|
||||
|
||||
# Create executable's janet image
|
||||
(def cimage_dest (string dest ".c"))
|
||||
(rule cimage_dest [source]
|
||||
(print "generating executable c source...")
|
||||
# Load entry environment and get main function.
|
||||
(def entry-env (dofile source))
|
||||
(def main ((entry-env 'main) :value))
|
||||
# Create marshalling dictionary
|
||||
(def mdict (invert (env-lookup root-env)))
|
||||
# Build image
|
||||
(def image (marshal main mdict))
|
||||
# Make image byte buffer
|
||||
(create-buffer-c-impl image cimage_dest "janet_payload_image")
|
||||
# Append main function
|
||||
(spit cimage_dest ```
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
janet_init();
|
||||
|
||||
/* Unmarshal bytecode */
|
||||
JanetTable *env = janet_core_env(NULL);
|
||||
JanetTable *lookup = janet_env_lookup(env);
|
||||
Janet marsh_out = janet_unmarshal(
|
||||
janet_payload_image_embed,
|
||||
janet_payload_image_embed_size,
|
||||
0,
|
||||
lookup,
|
||||
NULL);
|
||||
|
||||
/* Verify the marshalled object is a function */
|
||||
if (!janet_checktype(marsh_out, JANET_FUNCTION)) {
|
||||
fprintf(stderr, "invalid bytecode image - expected function.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Collect command line arguments */
|
||||
JanetArray *args = janet_array(argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
janet_array_push(args, janet_cstringv(argv[i]));
|
||||
}
|
||||
|
||||
/* Create enviornment */
|
||||
JanetTable *runtimeEnv = janet_table(0);
|
||||
runtimeEnv->proto = env;
|
||||
janet_table_put(runtimeEnv, janet_ckeywordv("args"), janet_wrap_array(args));
|
||||
janet_gcroot(janet_wrap_table(runtimeEnv));
|
||||
|
||||
/* Run everything */
|
||||
JanetFiber *fiber = janet_fiber(janet_unwrap_function(marsh_out), 64, argc, args->data);
|
||||
fiber->env = runtimeEnv;
|
||||
Janet out;
|
||||
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||
if (result) {
|
||||
janet_stacktrace(fiber, out);
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
``` :ab))
|
||||
|
||||
# Compile c source
|
||||
(def entryo (string dest objext))
|
||||
(compile-c opts cimage_dest entryo true)
|
||||
|
||||
# Link
|
||||
(link-c (merge @{:static true :standalone true} opts)
|
||||
dest
|
||||
entryo))
|
||||
|
||||
(defn- abspath
|
||||
"Create an absolute path. Does not resolve . and .. (useful for
|
||||
@@ -296,32 +427,27 @@
|
||||
# Public utilities
|
||||
#
|
||||
|
||||
(defn repo-id
|
||||
"Convert a repo url into a path component that serves as its id."
|
||||
[repo]
|
||||
(string/replace-all "\\" "_" (string/replace-all "/" "_" repo)))
|
||||
|
||||
(defn find-manifest-dir
|
||||
"Get the path to the directory containing manifests for installed
|
||||
packages."
|
||||
[&opt opts]
|
||||
(string (opt (or opts @{}) :modpath JANET_MODPATH) sep ".manifests"))
|
||||
[]
|
||||
(string (dyn :modpath JANET_MODPATH) sep ".manifests"))
|
||||
|
||||
(defn find-manifest
|
||||
"Get the full path of a manifest file given a package name."
|
||||
[name &opt opts]
|
||||
(string (find-manifest-dir opts) sep name ".txt"))
|
||||
[name]
|
||||
(string (find-manifest-dir) sep name ".txt"))
|
||||
|
||||
(defn find-cache
|
||||
"Return the path to the global cache."
|
||||
[&opt opts]
|
||||
(def path (opt (or opts @{}) :modpath JANET_MODPATH))
|
||||
[]
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(string path sep ".cache"))
|
||||
|
||||
(defn uninstall
|
||||
"Uninstall bundle named name"
|
||||
[name &opt opts]
|
||||
(def manifest (find-manifest name opts))
|
||||
[name]
|
||||
(def manifest (find-manifest name))
|
||||
(def f (file/open manifest :r))
|
||||
(unless f (print manifest " does not exist") (break))
|
||||
(loop [line :iterate (:read f :line)]
|
||||
@@ -337,16 +463,16 @@
|
||||
|
||||
(defn clear-cache
|
||||
"Clear the global git cache."
|
||||
[&opt opts]
|
||||
(rm (find-cache opts)))
|
||||
[]
|
||||
(rm (find-cache)))
|
||||
|
||||
(defn install-git
|
||||
"Install a bundle from git. If the bundle is already installed, the bundle
|
||||
is reinistalled (but not rebuilt if artifacts are cached)."
|
||||
[repo &opt opts]
|
||||
(def cache (find-cache opts))
|
||||
[repo]
|
||||
(def cache (find-cache))
|
||||
(os/mkdir cache)
|
||||
(def id (repo-id repo))
|
||||
(def id (filepath-replace repo))
|
||||
(def module-dir (string cache sep id))
|
||||
(when (os/mkdir module-dir)
|
||||
(os/execute ["git" "clone" repo module-dir] :p))
|
||||
@@ -378,49 +504,84 @@
|
||||
#
|
||||
|
||||
(defn declare-native
|
||||
"Declare a native binary. This is a shared library that can be loaded
|
||||
dynamically by a janet runtime."
|
||||
"Declare a native module. This is a shared library that can be loaded
|
||||
dynamically by a janet runtime. This also builds a static libary that
|
||||
can be used to bundle janet code and native into a single executable."
|
||||
[&keys opts]
|
||||
(def sources (opts :source))
|
||||
(def name (opts :name))
|
||||
(def lname (lib-name name))
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
|
||||
# Make dynamic module
|
||||
(def lname (string "build" sep name modext))
|
||||
(loop [src :in sources]
|
||||
(compile-c opts src (object-name src)))
|
||||
(def objects (map object-name sources))
|
||||
(compile-c opts src (out-path src ".c" objext)))
|
||||
(def objects (map (fn [path] (out-path path ".c" objext)) sources))
|
||||
(when-let [embedded (opts :embedded)]
|
||||
(loop [src :in embedded]
|
||||
(def c-src (embed-c-name src))
|
||||
(def o-src (embed-o-name src))
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" (if is-win ".janet.obj" ".janet.o")))
|
||||
(array/push objects o-src)
|
||||
(create-buffer-c src c-src (embed-name src))
|
||||
(compile-c opts c-src o-src)))
|
||||
(link-c opts lname ;objects)
|
||||
(add-dep "build" lname)
|
||||
(def path (opt opts :modpath JANET_MODPATH))
|
||||
(install-rule lname path))
|
||||
(install-rule lname path)
|
||||
|
||||
# Make static module
|
||||
(unless (or is-win (dyn :nostatic))
|
||||
(def opts (merge @{:entry-name name} opts))
|
||||
(def sname (string "build" sep name statext))
|
||||
(def sobjext (string ".static" objext))
|
||||
(def sjobjext (string ".janet" sobjext))
|
||||
(loop [src :in sources]
|
||||
(compile-c opts src (out-path src ".c" sobjext) true))
|
||||
(def sobjects (map (fn [path] (out-path path ".c" sobjext)) sources))
|
||||
(when-let [embedded (opts :embedded)]
|
||||
(loop [src :in embedded]
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" sjobjext))
|
||||
(array/push sobjects o-src)
|
||||
# Buffer c-src is already declared by dynamic module
|
||||
(compile-c opts c-src o-src true)))
|
||||
(archive-c opts sname ;sobjects)
|
||||
(add-dep "build" sname)
|
||||
(install-rule sname path)))
|
||||
|
||||
(defn declare-source
|
||||
"Create a Janet modules. This does not actually build the module(s),
|
||||
but registers it for packaging and installation."
|
||||
[&keys opts]
|
||||
(def sources (opts :source))
|
||||
(def path (opt opts :modpath JANET_MODPATH))
|
||||
(each s sources
|
||||
(install-rule s path)))
|
||||
[&keys {:source sources}]
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(if (bytes? sources)
|
||||
(install-rule sources path)
|
||||
(each s sources
|
||||
(install-rule s path))))
|
||||
|
||||
(defn declare-bin
|
||||
"Declare a generic file to be installed as an executable."
|
||||
[&keys opts]
|
||||
(def main (opts :main))
|
||||
(def binpath (opt opts :binpath JANET_BINPATH))
|
||||
(install-rule main binpath))
|
||||
[&keys {:main main}]
|
||||
(install-rule main (dyn :binpath JANET_BINPATH)))
|
||||
|
||||
(defn declare-executable
|
||||
"Declare a janet file to be the entry of a standalone executable program. The entry
|
||||
file is evaluated and a main function is looked for in the entry file. This function
|
||||
is marshalled into bytecode which is then embedded in a final executable for distribution.\n\n
|
||||
This executable can be installed as well to the --binpath given."
|
||||
[&keys {:install install :name name :entry entry}]
|
||||
(def name (if is-win (string name ".exe") name))
|
||||
(def dest (string "build" sep name))
|
||||
(create-executable @{} entry dest)
|
||||
(add-dep "build" dest)
|
||||
(when install
|
||||
(install-rule dest (dyn :binpath JANET_BINPATH))))
|
||||
|
||||
(defn declare-binscript
|
||||
"Declare a janet file to be installed as an executable script. Creates
|
||||
a shim on windows."
|
||||
[&keys opts]
|
||||
(def main (opts :main))
|
||||
(def binpath (opt opts :binpath JANET_BINPATH))
|
||||
(def binpath (dyn :binpath JANET_BINPATH))
|
||||
(install-rule main binpath)
|
||||
# Create a dud batch file when on windows.
|
||||
(when is-win
|
||||
@@ -442,7 +603,8 @@
|
||||
(def iname (string "build" sep name ".jimage"))
|
||||
(rule iname (or (opts :deps) [])
|
||||
(spit iname (make-image (require entry))))
|
||||
(def path (opt opts :modpath JANET_MODPATH))
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(add-dep "build" iname)
|
||||
(install-rule iname path))
|
||||
|
||||
(defn declare-project
|
||||
@@ -479,8 +641,9 @@
|
||||
(uninstall (meta :name)))
|
||||
|
||||
(phony "clean" []
|
||||
(rm "build")
|
||||
(print "Deleted build directory."))
|
||||
(when (os/stat "./build" :mode)
|
||||
(rm "build")
|
||||
(print "Deleted build directory.")))
|
||||
|
||||
(phony "test" ["build"]
|
||||
(defn dodir
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Version
|
||||
!define VERSION "1.1.0"
|
||||
!define VERSION "1.2.0"
|
||||
!define PRODUCT_VERSION "${VERSION}.0"
|
||||
VIProductVersion "${PRODUCT_VERSION}"
|
||||
VIFileVersion "${PRODUCT_VERSION}"
|
||||
@@ -114,6 +114,7 @@ section "Janet" BfWSection
|
||||
# Set up Environment variables
|
||||
!insertmacro WriteEnv JANET_PATH "$INSTDIR\Library"
|
||||
!insertmacro WriteEnv JANET_HEADERPATH "$INSTDIR\C"
|
||||
!insertmacro WriteEnv JANET_LIBPATH "$INSTDIR\C"
|
||||
!insertmacro WriteEnv JANET_BINPATH "$INSTDIR\bin"
|
||||
|
||||
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
|
||||
@@ -163,6 +164,7 @@ section "uninstall"
|
||||
# Remove env vars
|
||||
!insertmacro DelEnv JANET_PATH
|
||||
!insertmacro DelEnv JANET_HEADERPATH
|
||||
!insertmacro DelEnv JANET_LIBPATH
|
||||
!insertmacro DelEnv JANET_BINPATH
|
||||
|
||||
# Unset PATH
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
project('janet', 'c',
|
||||
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
version : '1.1.0')
|
||||
version : '1.2.0')
|
||||
|
||||
# Global settings
|
||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||
@@ -206,7 +206,8 @@ test_files = [
|
||||
'test/suite3.janet',
|
||||
'test/suite4.janet',
|
||||
'test/suite5.janet',
|
||||
'test/suite6.janet'
|
||||
'test/suite6.janet',
|
||||
'test/suite7.janet'
|
||||
]
|
||||
foreach t : test_files
|
||||
test(t, janet_nativeclient, args : files([t]), workdir : meson.current_source_dir())
|
||||
|
||||
@@ -50,7 +50,7 @@ int main(int argc, const char **argv) {
|
||||
JanetArray *args = janet_array(argc);
|
||||
for (int i = 0; i < argc; i++)
|
||||
janet_array_push(args, janet_cstringv(argv[i]));
|
||||
janet_def(env, "process/args", janet_wrap_array(args), "Command line arguments.");
|
||||
janet_def(env, "boot/args", janet_wrap_array(args), "Command line arguments.");
|
||||
|
||||
/* Add in options from janetconf.h so boot.janet can configure the image as needed. */
|
||||
JanetTable *opts = janet_table(0);
|
||||
@@ -60,7 +60,7 @@ int main(int argc, const char **argv) {
|
||||
#ifdef JANET_NO_SOURCEMAPS
|
||||
janet_table_put(opts, janet_ckeywordv("no-sourcemaps"), janet_wrap_true());
|
||||
#endif
|
||||
janet_def(env, "process/config", janet_wrap_table(opts), "Boot options");
|
||||
janet_def(env, "boot/config", janet_wrap_table(opts), "Boot options");
|
||||
|
||||
/* Run bootstrap script to generate core image */
|
||||
const char *boot_file;
|
||||
|
||||
@@ -1080,7 +1080,7 @@
|
||||
"Read all data from a file with name path
|
||||
and then close the file."
|
||||
[path]
|
||||
(def f (file/open path :r))
|
||||
(def f (file/open path :rb))
|
||||
(if-not f (error (string "could not open file " path)))
|
||||
(def contents (file/read f :all))
|
||||
(file/close f)
|
||||
@@ -1090,7 +1090,7 @@
|
||||
"Write contents to a file at path.
|
||||
Can optionally append to the file."
|
||||
[path contents &opt mode]
|
||||
(default mode :w)
|
||||
(default mode :wb)
|
||||
(def f (file/open path mode))
|
||||
(if-not f (error (string "could not open file " path " with mode " mode)))
|
||||
(file/write f contents)
|
||||
@@ -1433,10 +1433,10 @@
|
||||
###
|
||||
###
|
||||
|
||||
# Get process options
|
||||
(def- process/opts @{})
|
||||
(each [k v] (partition 2 (tuple/slice process/args 2))
|
||||
(put process/opts k v))
|
||||
# Get boot options
|
||||
(def- boot/opts @{})
|
||||
(each [k v] (partition 2 (tuple/slice boot/args 2))
|
||||
(put boot/opts k v))
|
||||
|
||||
(defn make-env
|
||||
"Create a new environment table. The new environment
|
||||
@@ -1624,8 +1624,8 @@
|
||||
[":sys:/:all:/init.janet" :source not-check-.]
|
||||
[(string ":sys:/:all:" nati) :native not-check-.]])
|
||||
|
||||
(setdyn :syspath (process/opts "JANET_PATH"))
|
||||
(setdyn :headerpath (process/opts "JANET_HEADERPATH"))
|
||||
(setdyn :syspath (boot/opts "JANET_PATH"))
|
||||
(setdyn :headerpath (boot/opts "JANET_HEADERPATH"))
|
||||
|
||||
# Version of fexists that works even with a reduced OS
|
||||
(if-let [has-stat (_env 'os/stat)]
|
||||
@@ -1633,7 +1633,7 @@
|
||||
(defglobal "fexists" (fn fexists [path] (= :file (stat path :mode)))))
|
||||
(defglobal "fexists"
|
||||
(fn fexists [path]
|
||||
(def f (file/open path))
|
||||
(def f (file/open path :rb))
|
||||
(when f
|
||||
(def res
|
||||
(try (do (file/read f 1) true)
|
||||
@@ -1699,7 +1699,7 @@
|
||||
:compile-only compile-only} (table ;args))
|
||||
(def f (if (= (type path) :core/file)
|
||||
path
|
||||
(file/open path)))
|
||||
(file/open path :rb)))
|
||||
(default env (make-env))
|
||||
(put env :current-file (string path))
|
||||
(defn chunks [buf _] (file/read f 2048 buf))
|
||||
@@ -1732,6 +1732,7 @@
|
||||
:source (fn [path args]
|
||||
(put module/loading path true)
|
||||
(def newenv (dofile path ;args))
|
||||
(put newenv :source path)
|
||||
(put module/loading path nil)
|
||||
newenv)
|
||||
:image (fn [path &] (load-image (slurp path)))})
|
||||
@@ -1782,6 +1783,12 @@
|
||||
args))
|
||||
(tuple import* (string path) ;argm))
|
||||
|
||||
(defmacro use
|
||||
"Similar to import, but imported bindings are not prefixed with a namespace
|
||||
identifier. Can also import multiple modules in one shot."
|
||||
[& modules]
|
||||
~(do ,;(map (fn [x] ~(,import* ,(string x) :prefix "")) modules)))
|
||||
|
||||
(defn repl
|
||||
"Run a repl. The first parameter is an optional function to call to
|
||||
get a chunk of source code that should return nil for end of file.
|
||||
@@ -1847,7 +1854,7 @@ _fiber is bound to the suspended fiber
|
||||
(env-walk keyword? env))
|
||||
|
||||
# Clean up some extra defs
|
||||
(put _env 'process/opts nil)
|
||||
(put _env 'boot/opts nil)
|
||||
(put _env 'env-walk nil)
|
||||
(put _env '_env nil)
|
||||
|
||||
@@ -1874,13 +1881,14 @@ _fiber is bound to the suspended fiber
|
||||
(loop [[k v] :pairs env
|
||||
:when (symbol? k)]
|
||||
(def flat (proto-flatten @{} v))
|
||||
(when (process/config :no-docstrings)
|
||||
(when (boot/config :no-docstrings)
|
||||
(put flat :doc nil))
|
||||
(when (process/config :no-sourcemaps)
|
||||
(when (boot/config :no-sourcemaps)
|
||||
(put flat :source-map nil))
|
||||
(put env k flat))
|
||||
|
||||
(put env 'process/config nil)
|
||||
(put env 'boot/config nil)
|
||||
(put env 'boot/args nil)
|
||||
(def image (let [env-pairs (pairs (env-lookup env))
|
||||
essential-pairs (filter (fn [[k v]] (or (cfunction? v) (abstract? v))) env-pairs)
|
||||
lookup (table ;(mapcat identity essential-pairs))
|
||||
@@ -1891,7 +1899,7 @@ _fiber is bound to the suspended fiber
|
||||
# can be compiled and linked statically into the main janet library
|
||||
# and example client.
|
||||
(def chunks (string/bytes image))
|
||||
(def image-file (file/open (process/args 1) :w))
|
||||
(def image-file (file/open (boot/args 1) :wb))
|
||||
(file/write image-file
|
||||
"#ifndef JANET_AMALG\n"
|
||||
"#include <janet.h>\n"
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
#define JANETCONF_H
|
||||
|
||||
#define JANET_VERSION_MAJOR 1
|
||||
#define JANET_VERSION_MINOR 1
|
||||
#define JANET_VERSION_MINOR 2
|
||||
#define JANET_VERSION_PATCH 0
|
||||
#define JANET_VERSION_EXTRA "-dev"
|
||||
#define JANET_VERSION "1.1.0-dev"
|
||||
#define JANET_VERSION "1.2.0-dev"
|
||||
|
||||
/* #define JANET_BUILD "local" */
|
||||
|
||||
|
||||
@@ -218,6 +218,10 @@ static Janet janet_core_expand_path(int32_t argc, Janet *argv) {
|
||||
}
|
||||
dot_count = 0;
|
||||
} else {
|
||||
while (dot_count > 0) {
|
||||
--dot_count;
|
||||
*print++ = '.';
|
||||
}
|
||||
dot_count = -1;
|
||||
*print++ = *scan;
|
||||
}
|
||||
@@ -266,6 +270,7 @@ static Janet janet_core_native(int32_t argc, Janet *argv) {
|
||||
janet_panicf("could not load native %S: %S", path, error);
|
||||
}
|
||||
init(env);
|
||||
janet_table_put(env, janet_ckeywordv("native"), argv[0]);
|
||||
return janet_wrap_table(env);
|
||||
}
|
||||
|
||||
|
||||
@@ -1070,7 +1070,7 @@ static const uint8_t *unmarshal_one(
|
||||
#else
|
||||
memcpy(&u.bytes, data + 1, sizeof(double));
|
||||
#endif
|
||||
*out = janet_wrap_number(u.d);
|
||||
*out = janet_wrap_number_safe(u.d);
|
||||
janet_v_push(st->lookup, *out);
|
||||
return data + 9;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,14 @@ static Janet os_which(int32_t argc, Janet *argv) {
|
||||
return janet_ckeywordv("macos");
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
return janet_ckeywordv("web");
|
||||
#elif defined(__linux__)
|
||||
return janet_ckeywordv("linux");
|
||||
#elif defined(__FreeBSD__)
|
||||
return janet_ckeywordv("freebsd");
|
||||
#elif defined(__NetBSD__)
|
||||
return janet_ckeywordv("netbsd");
|
||||
#elif defined(__OpenBSD__)
|
||||
return janet_ckeywordv("openbsd");
|
||||
#else
|
||||
return janet_ckeywordv("posix");
|
||||
#endif
|
||||
@@ -761,8 +769,13 @@ static const JanetReg os_cfuns[] = {
|
||||
"os/which", os_which,
|
||||
JDOC("(os/which)\n\n"
|
||||
"Check the current operating system. Returns one of:\n\n"
|
||||
"\t:windows - Microsoft Windows\n"
|
||||
"\t:macos - Apple macos\n"
|
||||
"\t:windows\n"
|
||||
"\t:macos\n"
|
||||
"\t:web - Web assembly (emscripten)\n"
|
||||
"\t:linux\n"
|
||||
"\t:freebsd\n"
|
||||
"\t:openbsd\n"
|
||||
"\t:netbsd\n"
|
||||
"\t:posix - A POSIX compatible system (default)")
|
||||
},
|
||||
{
|
||||
|
||||
@@ -294,7 +294,7 @@ static int stringchar(JanetParser *p, JanetParseState *state, uint8_t c) {
|
||||
return stringend(p, state);
|
||||
}
|
||||
/* normal char */
|
||||
if (c != '\n')
|
||||
if (c != '\n' && c != '\r')
|
||||
push_buf(p, c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -197,10 +197,10 @@ static Janet ta_getter(void *p, Janet key) {
|
||||
break;
|
||||
#endif
|
||||
case JANET_TARRAY_TYPE_F32:
|
||||
value = janet_wrap_number(array->as.f32[i]);
|
||||
value = janet_wrap_number_safe(array->as.f32[i]);
|
||||
break;
|
||||
case JANET_TARRAY_TYPE_F64:
|
||||
value = janet_wrap_number(array->as.f64[i]);
|
||||
value = janet_wrap_number_safe(array->as.f64[i]);
|
||||
break;
|
||||
default:
|
||||
janet_panicf("cannot get from typed array of type %s",
|
||||
|
||||
@@ -57,7 +57,11 @@ JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
/* How we dispatch instructions. By default, we use
|
||||
* a switch inside an infinite loop. For GCC/clang, we use
|
||||
* computed gotos. */
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) && !defined(__EMSCRIPTEN__)
|
||||
#define JANET_USE_COMPUTED_GOTOS
|
||||
#endif
|
||||
|
||||
#ifdef JANET_USE_COMPUTED_GOTOS
|
||||
#define VM_START() { goto *op_lookup[first_opcode];
|
||||
#define VM_END() }
|
||||
#define VM_OP(op) label_##op :
|
||||
@@ -192,7 +196,7 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
||||
static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status) {
|
||||
|
||||
/* opcode -> label lookup if using clang/GCC */
|
||||
#ifdef __GNUC__
|
||||
#ifdef JANET_USE_COMPUTED_GOTOS
|
||||
static void *op_lookup[255] = {
|
||||
&&label_JOP_NOOP,
|
||||
&&label_JOP_ERROR,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include <math.h>
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
@@ -182,6 +183,12 @@ void janet_memempty(JanetKV *mem, int32_t count) {
|
||||
|
||||
#ifdef JANET_NANBOX_64
|
||||
|
||||
Janet janet_wrap_number_safe(double d) {
|
||||
Janet ret;
|
||||
ret.number = isnan(d) ? NAN : d;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *janet_nanbox_to_pointer(Janet x) {
|
||||
x.i64 &= JANET_NANBOX_PAYLOADBITS;
|
||||
return x.pointer;
|
||||
@@ -222,6 +229,11 @@ Janet janet_wrap_number(double x) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
Janet janet_wrap_number_safe(double d) {
|
||||
double x = isnan(d) ? NAN : d;
|
||||
return janet_wrap_number(x);
|
||||
}
|
||||
|
||||
Janet janet_nanbox32_from_tagi(uint32_t tag, int32_t integer) {
|
||||
Janet ret;
|
||||
ret.tagged.type = tag;
|
||||
@@ -243,6 +255,10 @@ double janet_unwrap_number(Janet x) {
|
||||
|
||||
#else
|
||||
|
||||
Janet janet_wrap_number_safe(double d) {
|
||||
return janet_wrap_number(d);
|
||||
}
|
||||
|
||||
Janet janet_wrap_nil(void) {
|
||||
Janet y;
|
||||
y.type = JANET_NIL;
|
||||
@@ -298,3 +314,4 @@ JANET_WRAP_DEFINE(pointer, void *, JANET_POINTER, pointer)
|
||||
#undef JANET_WRAP_DEFINE
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -238,9 +238,9 @@ typedef struct {
|
||||
#include <stdio.h>
|
||||
|
||||
/* Names of all of the types */
|
||||
JANET_API const char *const janet_type_names[16];
|
||||
JANET_API const char *const janet_signal_names[14];
|
||||
JANET_API const char *const janet_status_names[16];
|
||||
JANET_API extern const char *const janet_type_names[16];
|
||||
JANET_API extern const char *const janet_signal_names[14];
|
||||
JANET_API extern const char *const janet_status_names[16];
|
||||
|
||||
/* Fiber signals */
|
||||
typedef enum {
|
||||
@@ -1276,6 +1276,7 @@ JANET_API void janet_put(Janet ds, Janet key, Janet value);
|
||||
JANET_API void janet_putindex(Janet ds, int32_t index, Janet value);
|
||||
JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags);
|
||||
#define janet_flag_at(F, I) ((F) & ((1ULL) << (I)))
|
||||
JANET_API Janet janet_wrap_number_safe(double x);
|
||||
|
||||
/* VM functions */
|
||||
JANET_API int janet_init(void);
|
||||
@@ -1305,11 +1306,16 @@ JANET_API void janet_register(const char *name, JanetCFunction cfun);
|
||||
|
||||
/* New C API */
|
||||
|
||||
/* 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_init
|
||||
JANET_API void JANET_ENTRY_NAME
|
||||
|
||||
JANET_NO_RETURN JANET_API void janet_panicv(Janet message);
|
||||
JANET_NO_RETURN JANET_API void janet_panic(const char *message);
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
|
||||
(if-let [jp (os/getenv "JANET_PATH")] (setdyn :syspath jp))
|
||||
(if-let [jp (os/getenv "JANET_HEADERPATH")] (setdyn :headerpath jp))
|
||||
(def args (dyn :args))
|
||||
|
||||
# Flag handlers
|
||||
(def handlers :private
|
||||
{"h" (fn [&]
|
||||
(print "usage: " (get process/args 0) " [options] script args...")
|
||||
(print "usage: " (get args 0) " [options] script args...")
|
||||
(print
|
||||
`Options are:
|
||||
-h : Show this help
|
||||
@@ -42,20 +43,20 @@
|
||||
"q" (fn [&] (set *quiet* true) 1)
|
||||
"k" (fn [&] (set *compile-only* true) (set *exit-on-error* false) 1)
|
||||
"n" (fn [&] (set *colorize* false) 1)
|
||||
"m" (fn [i &] (setdyn :syspath (get process/args (+ i 1))) 2)
|
||||
"m" (fn [i &] (setdyn :syspath (get args (+ i 1))) 2)
|
||||
"c" (fn [i &]
|
||||
(def e (dofile (get process/args (+ i 1))))
|
||||
(spit (get process/args (+ i 2)) (make-image e))
|
||||
(def e (dofile (get args (+ i 1))))
|
||||
(spit (get args (+ i 2)) (make-image e))
|
||||
(set *no-file* false)
|
||||
3)
|
||||
"-" (fn [&] (set *handleopts* false) 1)
|
||||
"l" (fn [i &]
|
||||
(import* (get process/args (+ i 1))
|
||||
(import* (get args (+ i 1))
|
||||
:prefix "" :exit *exit-on-error*)
|
||||
2)
|
||||
"e" (fn [i &]
|
||||
(set *no-file* false)
|
||||
(eval-string (get process/args (+ i 1)))
|
||||
(eval-string (get args (+ i 1)))
|
||||
2)})
|
||||
|
||||
(defn- dohandler [n i &]
|
||||
@@ -63,10 +64,10 @@
|
||||
(if h (h i) (do (print "unknown flag -" n) ((get handlers "h")))))
|
||||
|
||||
# Process arguments
|
||||
(var i 1)
|
||||
(def lenargs (length process/args))
|
||||
(var i 0)
|
||||
(def lenargs (length args))
|
||||
(while (< i lenargs)
|
||||
(def arg (get process/args i))
|
||||
(def arg (get args i))
|
||||
(if (and *handleopts* (= "-" (string/slice arg 0 1)))
|
||||
(+= i (dohandler (string/slice arg 1 2) i))
|
||||
(do
|
||||
|
||||
@@ -61,9 +61,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
/* Create args tuple */
|
||||
args = janet_array(argc);
|
||||
for (i = 0; i < argc; i++)
|
||||
for (i = 1; i < argc; i++)
|
||||
janet_array_push(args, janet_cstringv(argv[i]));
|
||||
janet_def(env, "process/args", janet_wrap_array(args), "Command line arguments.");
|
||||
janet_table_put(env, janet_ckeywordv("args"), janet_wrap_array(args));
|
||||
|
||||
/* Save current executable path to (dyn :executable) */
|
||||
janet_table_put(env, janet_ckeywordv("executable"), janet_cstringv(argv[0]));
|
||||
|
||||
/* Run startup script */
|
||||
status = janet_dobytes(env, janet_gen_init, janet_gen_init_size, "init.janet", NULL);
|
||||
|
||||
3
test/install/.gitignore
vendored
3
test/install/.gitignore
vendored
@@ -1 +1,4 @@
|
||||
/build
|
||||
.cache
|
||||
.manifest
|
||||
json.*
|
||||
|
||||
@@ -5,3 +5,6 @@
|
||||
:name "testmod"
|
||||
:source @["testmod.c"])
|
||||
|
||||
(declare-executable
|
||||
:name "testexec"
|
||||
:entry "testexec.janet")
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
(import build/testmod :as testmod)
|
||||
|
||||
(if (not= 5 (testmod/get5)) (error "testmod/get5 failed"))
|
||||
|
||||
(import cook)
|
||||
|
||||
(with-dyns [:modpath (os/cwd)]
|
||||
(cook/install-git "https://github.com/janet-lang/json.git"))
|
||||
|
||||
2
test/install/testexec.janet
Normal file
2
test/install/testexec.janet
Normal file
@@ -0,0 +1,2 @@
|
||||
(defn main [&]
|
||||
(print "Hello from executable!"))
|
||||
@@ -113,4 +113,26 @@
|
||||
(check-table-clone @{:a 123 :b 34 :c :hello : 945 0 1 2 3 4 5} "table/clone 1")
|
||||
(check-table-clone @{} "table/clone 1")
|
||||
|
||||
# Issue #142
|
||||
|
||||
(def buffer (tarray/buffer 8))
|
||||
(def buffer-float64-view (tarray/new :float64 1 1 0 buffer))
|
||||
(def buffer-uint32-view (tarray/new :uint32 2 1 0 buffer))
|
||||
|
||||
(set (buffer-uint32-view 1) 0xfffe9234)
|
||||
(set (buffer-uint32-view 0) 0x56789abc)
|
||||
|
||||
(assert (buffer-float64-view 0) "issue #142 nanbox hijack 1")
|
||||
(assert (= (type (buffer-float64-view 0)) :number) "issue #142 nanbox hijack 2")
|
||||
(assert (= (type (unmarshal @"\xC8\xbc\x9axV4\x92\xfe\xff")) :number) "issue #142 nanbox hijack 3")
|
||||
|
||||
# Make sure Carriage Returns don't end up in doc strings.
|
||||
|
||||
(assert (not (string/find "\r" (get ((fiber/getenv (fiber/current)) 'cond) :doc))) "no \\r in doc strings")
|
||||
|
||||
# module/expand-path regression
|
||||
(with-dyns [:syspath ".janet/.janet"]
|
||||
(assert (= (string (module/expand-path "hello" ":sys:/:all:.janet"))
|
||||
".janet/.janet/hello.janet") "module/expand-path 1"))
|
||||
|
||||
(end-suite)
|
||||
|
||||
192
tools/FileAssociation.nsh
Normal file
192
tools/FileAssociation.nsh
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
_____________________________________________________________________________
|
||||
|
||||
File Association
|
||||
_____________________________________________________________________________
|
||||
|
||||
Based on code taken from http://nsis.sourceforge.net/File_Association
|
||||
|
||||
Usage in script:
|
||||
1. !include "FileAssociation.nsh"
|
||||
2. [Section|Function]
|
||||
${FileAssociationFunction} "Param1" "Param2" "..." $var
|
||||
[SectionEnd|FunctionEnd]
|
||||
|
||||
FileAssociationFunction=[RegisterExtension|UnRegisterExtension]
|
||||
|
||||
_____________________________________________________________________________
|
||||
|
||||
${RegisterExtension} "[executable]" "[extension]" "[description]"
|
||||
|
||||
"[executable]" ; executable which opens the file format
|
||||
;
|
||||
"[extension]" ; extension, which represents the file format to open
|
||||
;
|
||||
"[description]" ; description for the extension. This will be display in Windows Explorer.
|
||||
;
|
||||
|
||||
|
||||
${UnRegisterExtension} "[extension]" "[description]"
|
||||
|
||||
"[extension]" ; extension, which represents the file format to open
|
||||
;
|
||||
"[description]" ; description for the extension. This will be display in Windows Explorer.
|
||||
;
|
||||
|
||||
_____________________________________________________________________________
|
||||
|
||||
Macros
|
||||
_____________________________________________________________________________
|
||||
|
||||
Change log window verbosity (default: 3=no script)
|
||||
|
||||
Example:
|
||||
!include "FileAssociation.nsh"
|
||||
!insertmacro RegisterExtension
|
||||
${FileAssociation_VERBOSE} 4 # all verbosity
|
||||
!insertmacro UnRegisterExtension
|
||||
${FileAssociation_VERBOSE} 3 # no script
|
||||
*/
|
||||
|
||||
|
||||
!ifndef FileAssociation_INCLUDED
|
||||
!define FileAssociation_INCLUDED
|
||||
|
||||
!include Util.nsh
|
||||
|
||||
!verbose push
|
||||
!verbose 3
|
||||
!ifndef _FileAssociation_VERBOSE
|
||||
!define _FileAssociation_VERBOSE 3
|
||||
!endif
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
!define FileAssociation_VERBOSE `!insertmacro FileAssociation_VERBOSE`
|
||||
!verbose pop
|
||||
|
||||
!macro FileAssociation_VERBOSE _VERBOSE
|
||||
!verbose push
|
||||
!verbose 3
|
||||
!undef _FileAssociation_VERBOSE
|
||||
!define _FileAssociation_VERBOSE ${_VERBOSE}
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!macro RegisterExtensionCall _EXECUTABLE _EXTENSION _DESCRIPTION
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
Push `${_DESCRIPTION}`
|
||||
Push `${_EXTENSION}`
|
||||
Push `${_EXECUTABLE}`
|
||||
${CallArtificialFunction} RegisterExtension_
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
!macro UnRegisterExtensionCall _EXTENSION _DESCRIPTION
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
Push `${_EXTENSION}`
|
||||
Push `${_DESCRIPTION}`
|
||||
${CallArtificialFunction} UnRegisterExtension_
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!define RegisterExtension `!insertmacro RegisterExtensionCall`
|
||||
!define un.RegisterExtension `!insertmacro RegisterExtensionCall`
|
||||
|
||||
!macro RegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro un.RegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro RegisterExtension_
|
||||
!verbose push
|
||||
!verbose ${_FileAssociation_VERBOSE}
|
||||
|
||||
Exch $R2 ;exe
|
||||
Exch
|
||||
Exch $R1 ;ext
|
||||
Exch
|
||||
Exch 2
|
||||
Exch $R0 ;desc
|
||||
Exch 2
|
||||
Push $0
|
||||
Push $1
|
||||
|
||||
ReadRegStr $1 HKCR $R1 "" ; read current file association
|
||||
StrCmp "$1" "" NoBackup ; is it empty
|
||||
StrCmp "$1" "$R0" NoBackup ; is it our own
|
||||
WriteRegStr HKCR $R1 "backup_val" "$1" ; backup current value
|
||||
NoBackup:
|
||||
WriteRegStr HKCR $R1 "" "$R0" ; set our file association
|
||||
|
||||
ReadRegStr $0 HKCR $R0 ""
|
||||
StrCmp $0 "" 0 Skip
|
||||
WriteRegStr HKCR "$R0" "" "$R0"
|
||||
WriteRegStr HKCR "$R0\shell" "" "open"
|
||||
WriteRegStr HKCR "$R0\DefaultIcon" "" "$R2,0"
|
||||
Skip:
|
||||
WriteRegStr HKCR "$R0\shell\open\command" "" '"$R2" "%1"'
|
||||
WriteRegStr HKCR "$R0\shell\edit" "" "Edit $R0"
|
||||
WriteRegStr HKCR "$R0\shell\edit\command" "" '"$R2" "%1"'
|
||||
|
||||
Pop $1
|
||||
Pop $0
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!define UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
|
||||
!define un.UnRegisterExtension `!insertmacro UnRegisterExtensionCall`
|
||||
|
||||
!macro UnRegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro un.UnRegisterExtension
|
||||
!macroend
|
||||
|
||||
!macro UnRegisterExtension_
|
||||
!verbose push
|
||||
!verbose ${_
|
||||
|
||||
FileAssociation_VERBOSE}
|
||||
|
||||
Exch $R1 ;desc
|
||||
Exch
|
||||
Exch $R0 ;ext
|
||||
Exch
|
||||
Push $0
|
||||
Push $1
|
||||
|
||||
ReadRegStr $1 HKCR $R0 ""
|
||||
StrCmp $1 $R1 0 NoOwn ; only do this if we own it
|
||||
ReadRegStr $1 HKCR $R0 "backup_val"
|
||||
StrCmp $1 "" 0 Restore ; if backup="" then delete the whole key
|
||||
DeleteRegKey HKCR $R0
|
||||
Goto NoOwn
|
||||
|
||||
Restore:
|
||||
WriteRegStr HKCR $R0 "" $1
|
||||
DeleteRegValue HKCR $R0 "backup_val"
|
||||
DeleteRegKey HKCR $R1 ;Delete key with association name settings
|
||||
|
||||
NoOwn:
|
||||
|
||||
Pop $1
|
||||
Pop $0
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
|
||||
!verbose pop
|
||||
!macroend
|
||||
|
||||
!endif # !FileAssociation_INCLUDED
|
||||
@@ -1,14 +1,12 @@
|
||||
# Creates an amalgamated janet.c
|
||||
|
||||
# Head
|
||||
(def {:year YY :month MM :month-day DD} (os/date))
|
||||
(print "/* Amalgamated build - DO NOT EDIT */")
|
||||
(print "/* Generated " YY "-" (inc MM) "-" (inc DD)
|
||||
" with janet version " janet/version "-" janet/build " */")
|
||||
(print "/* Generated from janet version " janet/version "-" janet/build " */")
|
||||
(print "#define JANET_BUILD \"" janet/build "\"")
|
||||
(print ```#define JANET_AMALG```)
|
||||
(print ```#include "janet.h"```)
|
||||
|
||||
# Body
|
||||
(each path (tuple/slice process/args 2)
|
||||
(each path (tuple/slice (dyn :args) 1)
|
||||
(print (slurp path)))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@echo off
|
||||
@rem Wrapper around jpm
|
||||
|
||||
janet %~dp0\jpm.janet %*
|
||||
janet "%~dp0\jpm.janet" %*
|
||||
|
||||
Reference in New Issue
Block a user