Move init.janet into cli-main in boot.janet

This makes it easier to get the CLI functionality when
embedding Janet, although the main reason is the init script
is now pre-compiled to bytecode when generating the boot image.
This commit is contained in:
Calvin Rose 2019-10-29 18:16:32 -05:00
parent b2263ed5b5
commit 0d16b9e1a1
6 changed files with 129 additions and 127 deletions

View File

@ -147,7 +147,7 @@ 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)) build/init.gen.o
JANET_MAINCLIENT_OBJECTS=$(patsubst src/%.c,build/%.o,$(JANET_MAINCLIENT_SOURCES))
# Compile the core image generated by the bootstrap build
build/core_image.o: build/core_image.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
@ -204,8 +204,6 @@ emscripten: $(JANET_EMTARGET)
build/xxd: tools/xxd.c
$(CC) $< -o $@
build/init.gen.c: src/mainclient/init.janet build/xxd
build/xxd $< $@ janet_gen_init
build/webinit.gen.c: src/webclient/webinit.janet build/xxd
build/xxd $< $@ janet_gen_webinit
build/boot.gen.c: src/boot/boot.janet build/xxd

View File

@ -40,14 +40,10 @@ link /nologo /out:build\xxd.exe build\xxd.obj
@if errorlevel 1 goto :BUILDFAIL
@rem Generate the embedded sources
build\xxd.exe src\mainclient\init.janet build\init.gen.c janet_gen_init
@if errorlevel 1 goto :BUILDFAIL
build\xxd.exe src\boot\boot.janet build\boot.gen.c janet_gen_boot
@if errorlevel 1 goto :BUILDFAIL
@rem Build the generated sources
%JANET_COMPILE% /Fobuild\mainclient\init.gen.obj build\init.gen.c
@if errorlevel 1 goto :BUILDFAIL
%JANET_COMPILE% /Fobuild\boot\boot.gen.obj build\boot.gen.c
@if errorlevel 1 goto :BUILDFAIL

View File

@ -83,7 +83,6 @@ gen = generator(xxd,
output : '@BASENAME@.gen.c',
arguments : ['@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@'])
boot_gen = gen.process('src/boot/boot.janet', extra_args: 'janet_gen_boot')
init_gen = gen.process('src/mainclient/init.janet', extra_args: 'janet_gen_init')
# Order is important here, as some headers
# depend on other headers for the amalg target
@ -185,14 +184,14 @@ else
extra_cross_cflags = []
endif
janet_mainclient = executable('janet', core_src, core_image, init_gen, mainclient_src,
janet_mainclient = executable('janet', core_src, core_image, mainclient_src,
include_directories : incdir,
dependencies : [m_dep, dl_dep],
c_args : extra_native_cflags,
install : true)
if meson.is_cross_build()
janet_nativeclient = executable('janet-native', core_src, core_image, init_gen, mainclient_src,
janet_nativeclient = executable('janet-native', core_src, core_image, mainclient_src,
include_directories : incdir,
dependencies : [m_dep, dl_dep],
c_args : extra_cross_cflags,
@ -216,7 +215,7 @@ amalg = custom_target('amalg',
command : [janet_nativeclient, '@INPUT@'])
# Amalgamated client
janet_amalgclient = executable('janet-amalg', amalg, init_gen, mainclient_src,
janet_amalgclient = executable('janet-amalg', amalg, mainclient_src,
include_directories : incdir,
dependencies : [m_dep, dl_dep],
build_by_default : false)

View File

@ -1906,6 +1906,8 @@
(def ret (bad-compile x y z))
(if exit-on-error (os/exit 1))
ret)
(unless f
(error (string "could not find file " path)))
(run-context {:env env
:chunks chunks
:on-parse-error bp
@ -2054,6 +2056,125 @@ _fiber is bound to the suspended fiber
(put _env 'env-walk nil)
(put _env '_env nil)
###
###
### CLI Tool Main
###
###
(defn cli-main
"Entrance for the Janet CLI tool. Call this functions with the command line
arguments as an array or tuple of strings to invoke the CLI interface."
[args]
(setdyn :args args)
(var *should-repl* false)
(var *no-file* true)
(var *quiet* false)
(var *raw-stdin* false)
(var *handleopts* true)
(var *exit-on-error* true)
(var *colorize* true)
(var *compile-only* false)
(if-let [jp (os/getenv "JANET_PATH")] (setdyn :syspath jp))
(if-let [jp (os/getenv "JANET_HEADERPATH")] (setdyn :headerpath jp))
# Flag handlers
(def handlers :private
{"h" (fn [&]
(print "usage: " (dyn :executable "janet") " [options] script args...")
(print
`Options are:
-h : Show this help
-v : Print the version string
-s : Use raw stdin instead of getline like functionality
-e code : Execute a string of janet
-r : Enter the repl after running all scripts
-p : Keep on executing if there is a top level error (persistent)
-q : Hide prompt, logo, and repl output (quiet)
-k : Compile scripts but do not execute
-m syspath : Set system path for loading global modules
-c source output : Compile janet source code into an image
-n : Disable ANSI color output in the repl
-l path : Execute code in a file before running the main script
-- : Stop handling options`)
(os/exit 0)
1)
"v" (fn [&] (print janet/version "-" janet/build) (os/exit 0) 1)
"s" (fn [&] (set *raw-stdin* true) (set *should-repl* true) 1)
"r" (fn [&] (set *should-repl* true) 1)
"p" (fn [&] (set *exit-on-error* false) 1)
"q" (fn [&] (set *quiet* true) 1)
"k" (fn [&] (set *compile-only* true) (set *exit-on-error* false) 1)
"n" (fn [&] (set *colorize* false) 1)
"m" (fn [i &] (setdyn :syspath (get args (+ i 1))) 2)
"c" (fn [i &]
(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 args (+ i 1))
:prefix "" :exit *exit-on-error*)
2)
"e" (fn [i &]
(set *no-file* false)
(eval-string (get args (+ i 1)))
2)})
(defn- dohandler [n i &]
(def h (get handlers n))
(if h (h i) (do (print "unknown flag -" n) ((get handlers "h")))))
(def- safe-forms {'defn true 'defn- true 'defmacro true 'defmacro- true})
(def- importers {'import true 'import* true 'use true 'dofile true 'require true})
(defn- evaluator
[thunk source env where]
(if *compile-only*
(when (tuple? source)
(cond
(safe-forms (source 0)) (thunk)
(importers (source 0))
(do
(let [[l c] (tuple/sourcemap source)
newtup (tuple/setmap (tuple ;source :evaluator evaluator) l c)]
((compile newtup env where))))))
(thunk)))
# Process arguments
(var i 0)
(def lenargs (length args))
(while (< i lenargs)
(def arg (get args i))
(if (and *handleopts* (= "-" (string/slice arg 0 1)))
(+= i (dohandler (string/slice arg 1 2) i))
(do
(set *no-file* false)
(dofile arg :prefix "" :exit *exit-on-error* :evaluator evaluator)
(set i lenargs))))
(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"))
(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]
(file/write stdout prompt)
(file/flush stdout)
(file/read stdin :line buf))
(def getter (if *raw-stdin* getstdin getline))
(defn getchunk [buf p]
(getter (prompter p) buf))
(def onsig (if *quiet* (fn [x &] x) nil))
(setdyn :pretty-format (if *colorize* "%.20Q" "%.20q"))
(setdyn :err-color (if *colorize* true))
(repl getchunk onsig)))
###
###
### Bootstrap

View File

@ -1,111 +0,0 @@
# Copyright 2017-2019 (C) Calvin Rose
(do
(var *should-repl* false)
(var *no-file* true)
(var *quiet* false)
(var *raw-stdin* false)
(var *handleopts* true)
(var *exit-on-error* true)
(var *colorize* true)
(var *compile-only* false)
(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 args 0) " [options] script args...")
(print
`Options are:
-h : Show this help
-v : Print the version string
-s : Use raw stdin instead of getline like functionality
-e code : Execute a string of janet
-r : Enter the repl after running all scripts
-p : Keep on executing if there is a top level error (persistent)
-q : Hide prompt, logo, and repl output (quiet)
-k : Compile scripts but do not execute
-m syspath : Set system path for loading global modules
-c source output : Compile janet source code into an image
-n : Disable ANSI color output in the repl
-l path : Execute code in a file before running the main script
-- : Stop handling options`)
(os/exit 0)
1)
"v" (fn [&] (print janet/version "-" janet/build) (os/exit 0) 1)
"s" (fn [&] (set *raw-stdin* true) (set *should-repl* true) 1)
"r" (fn [&] (set *should-repl* true) 1)
"p" (fn [&] (set *exit-on-error* false) 1)
"q" (fn [&] (set *quiet* true) 1)
"k" (fn [&] (set *compile-only* true) (set *exit-on-error* false) 1)
"n" (fn [&] (set *colorize* false) 1)
"m" (fn [i &] (setdyn :syspath (get args (+ i 1))) 2)
"c" (fn [i &]
(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 args (+ i 1))
:prefix "" :exit *exit-on-error*)
2)
"e" (fn [i &]
(set *no-file* false)
(eval-string (get args (+ i 1)))
2)})
(defn- dohandler [n i &]
(def h (get handlers n))
(if h (h i) (do (print "unknown flag -" n) ((get handlers "h")))))
(def- safe-forms {'defn true 'defn- true 'defmacro true 'defmacro- true})
(def- importers {'import true 'import* true 'use true 'dofile true 'require true})
(defn- evaluator
[thunk source env where]
(if *compile-only*
(when (tuple? source)
(cond
(safe-forms (source 0)) (thunk)
(importers (source 0))
(do
(let [[l c] (tuple/sourcemap source)
newtup (tuple/setmap (tuple ;source :evaluator evaluator) l c)]
((compile newtup env where))))))
(thunk)))
# Process arguments
(var i 0)
(def lenargs (length args))
(while (< i lenargs)
(def arg (get args i))
(if (and *handleopts* (= "-" (string/slice arg 0 1)))
(+= i (dohandler (string/slice arg 1 2) i))
(do
(set *no-file* false)
(dofile arg :prefix "" :exit *exit-on-error* :evaluator evaluator)
(set i lenargs))))
(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"))
(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]
(file/write stdout prompt)
(file/flush stdout)
(file/read stdin :line buf))
(def getter (if *raw-stdin* getstdin getline))
(defn getchunk [buf p]
(getter (prompter p) buf))
(def onsig (if *quiet* (fn [x &] x) nil))
(setdyn :pretty-format (if *colorize* "%.20Q" "%.20q"))
(setdyn :err-color (if *colorize* true))
(repl getchunk onsig)))

View File

@ -31,9 +31,6 @@
#endif
#endif
extern const unsigned char *janet_gen_init;
extern int32_t janet_gen_init_size;
int main(int argc, char **argv) {
int i, status;
JanetArray *args;
@ -83,13 +80,15 @@ int main(int argc, char **argv) {
args = janet_array(argc);
for (i = 1; i < argc; i++)
janet_array_push(args, janet_cstringv(argv[i]));
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);
Janet mainfun, out;
janet_resolve(env, janet_csymbol("cli-main"), &mainfun);
Janet mainargs[1] = { janet_wrap_array(args) };
status = janet_pcall(janet_unwrap_function(mainfun), 1, mainargs, &out, NULL);
/* Deinitialize vm */
janet_deinit();