From 2697b0e425f0dc4f2ab9624c548ec6d1802c10ea Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 8 Sep 2024 20:55:10 -0500 Subject: [PATCH 1/6] More CI testing. Add multiple windows versions, and differentiate between arm and intel macs. --- .github/workflows/release.yml | 31 ++++++++++++++++++++++++++++++- .github/workflows/test.yml | 7 +++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c19750b..689dd540 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-latest, macos-13 ] steps: - name: Checkout the repository uses: actions/checkout@master @@ -39,6 +39,35 @@ jobs: build/c/janet.c build/c/shell.c + release-arm: + permissions: + contents: write # for softprops/action-gh-release to create GitHub release + name: Build release binaries + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ macos-latest ] + steps: + - name: Checkout the repository + uses: actions/checkout@master + - name: Set the version + run: echo "version=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV + - name: Set the platform + run: echo "platform=$(tr '[A-Z]' '[a-z]' <<< $RUNNER_OS)" >> $GITHUB_ENV + - name: Compile the project + run: make clean && make + - name: Build the artifact + run: JANET_DIST_DIR=janet-${{ env.version }}-${{ env.platform }} make build/janet-${{ env.version }}-${{ env.platform }}-aarch64.tar.gz + - name: Draft the release + uses: softprops/action-gh-release@v1 + with: + draft: true + files: | + build/*.gz + build/janet.h + build/c/janet.c + build/c/shell.c + release-windows: permissions: contents: write # for softprops/action-gh-release to create GitHub release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68afc1ce..dfb93321 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-latest, macos-latest, macos-13 ] steps: - name: Checkout the repository uses: actions/checkout@master @@ -23,7 +23,10 @@ jobs: test-windows: name: Build and test on Windows - runs-on: windows-latest + strategy: + matrix: + os: [ windows-latest, windows-2019 ] + runs-on: ${{ matrix.os }} steps: - name: Checkout the repository uses: actions/checkout@master From 9694aee819af65f0089e351c450343d5d11b41ad Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 12 Sep 2024 17:03:03 -0500 Subject: [PATCH 2/6] Add rules for nth and only-tags. Address #1503 These rules allow selecting from a number of sub-captures while dropping the rest. `nth` is more succinct in many cases, but `only-tags` is more general and corresponds to an internal mechanism already present. --- src/core/filewatch.c | 1 + src/core/peg.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ src/include/janet.h | 4 +++- test/suite-peg.janet | 16 +++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/core/filewatch.c b/src/core/filewatch.c index 4e8e85b7..ef666af6 100644 --- a/src/core/filewatch.c +++ b/src/core/filewatch.c @@ -588,6 +588,7 @@ JANET_CORE_FN(cfun_filewatch_make, "* `:wd-path` -- the string path for watched directory of file. For files, will be the same as `:file-name`, and for directories, will be the same as `:dir-name`.\n\n" "* `:cookie` -- a randomized integer used to associate related events, such as :moved-from and :moved-to events.\n\n" "") { + janet_sandbox_assert(JANET_SANDBOX_FS_READ); janet_arity(argc, 1, -1); JanetChannel *channel = janet_getchannel(argv, 0); JanetWatcher *watcher = janet_abstract(&janet_filewatch_at, sizeof(JanetWatcher)); diff --git a/src/core/peg.c b/src/core/peg.c index 48ba88d1..0a2b7d4f 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -465,6 +465,16 @@ tail: return result; } + case RULE_ONLY_TAGS: { + CapState cs = cap_save(s); + down1(s); + const uint8_t *result = peg_rule(s, s->bytecode + rule[1], text); + up1(s); + if (!result) return NULL; + cap_load_keept(s, cs); + return result; + } + case RULE_GROUP: { uint32_t tag = rule[2]; int oldmode = s->mode; @@ -486,6 +496,29 @@ tail: return result; } + case RULE_NTH: { + uint32_t nth = rule[1]; + uint32_t tag = rule[3]; + int oldmode = s->mode; + CapState cs = cap_save(s); + s->mode = PEG_MODE_NORMAL; + down1(s); + const uint8_t *result = peg_rule(s, s->bytecode + rule[2], text); + up1(s); + s->mode = oldmode; + if (!result) return NULL; + int32_t num_sub_captures = s->captures->count - cs.cap; + Janet cap; + if (num_sub_captures > (int32_t) nth) { + cap = s->captures->data[cs.cap + nth]; + } else { + return NULL; + } + cap_load_keept(s, cs); + pushcap(s, cap, tag); + return result; + } + case RULE_SUB: { const uint8_t *text_start = text; const uint32_t *rule_window = s->bytecode + rule[1]; @@ -1061,6 +1094,9 @@ static void spec_thru(Builder *b, int32_t argc, const Janet *argv) { static void spec_drop(Builder *b, int32_t argc, const Janet *argv) { spec_onerule(b, argc, argv, RULE_DROP); } +static void spec_only_tags(Builder *b, int32_t argc, const Janet *argv) { + spec_onerule(b, argc, argv, RULE_ONLY_TAGS); +} /* Rule of the form [rule, tag] */ static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) { @@ -1084,6 +1120,15 @@ static void spec_unref(Builder *b, int32_t argc, const Janet *argv) { spec_cap1(b, argc, argv, RULE_UNREF); } +static void spec_nth(Builder *b, int32_t argc, const Janet *argv) { + peg_arity(b, argc, 2, 3); + Reserve r = reserve(b, 4); + uint32_t nth = peg_getnat(b, argv[0]); + uint32_t rule = peg_compile1(b, argv[1]); + uint32_t tag = (argc == 3) ? emit_tag(b, argv[2]) : 0; + emit_3(r, RULE_NTH, nth, rule, tag); +} + static void spec_capture_number(Builder *b, int32_t argc, const Janet *argv) { peg_arity(b, argc, 1, 3); Reserve r = reserve(b, 4); @@ -1262,7 +1307,9 @@ static const SpecialPair peg_specials[] = { {"line", spec_line}, {"look", spec_look}, {"not", spec_not}, + {"nth", spec_nth}, {"number", spec_capture_number}, + {"only-tags", spec_only_tags}, {"opt", spec_opt}, {"position", spec_position}, {"quote", spec_capture}, @@ -1619,6 +1666,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) { break; case RULE_ERROR: case RULE_DROP: + case RULE_ONLY_TAGS: case RULE_NOT: case RULE_TO: case RULE_THRU: @@ -1632,6 +1680,12 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) { if (rule[1] > JANET_MAX_READINT_WIDTH) goto bad; i += 3; break; + case RULE_NTH: + /* [nth, rule, tag] */ + if (rule[2] >= blen) goto bad; + op_flags[rule[2]] |= 0x01; + i += 4; + break; default: goto bad; } diff --git a/src/include/janet.h b/src/include/janet.h index ce37b84a..eb0b462f 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -2180,7 +2180,9 @@ typedef enum { RULE_UNREF, /* [rule, tag] */ RULE_CAPTURE_NUM, /* [rule, tag] */ RULE_SUB, /* [rule, rule] */ - RULE_SPLIT /* [rule, rule] */ + RULE_SPLIT, /* [rule, rule] */ + RULE_NTH, /* [nth, rule, tag] */ + RULE_ONLY_TAGS, /* [rule] */ } JanetPegOpcod; typedef struct { diff --git a/test/suite-peg.janet b/test/suite-peg.janet index b4547db2..ac426cfc 100644 --- a/test/suite-peg.janet +++ b/test/suite-peg.janet @@ -664,6 +664,8 @@ @[]) "peg if not") (defn test [name peg input expected] + (assert-no-error "compile peg" (peg/compile peg)) + (assert-no-error "marshal/unmarshal peg" (-> peg marshal unmarshal)) (assert (deep= (peg/match peg input) expected) name)) (test "sub: matches the same input twice" @@ -756,5 +758,19 @@ "a,b,c" @["a" "b" "c"]) +(test "nth 1" + ~{:prefix (number :d+ nil :n) + :word '(lenprefix (-> :n) :w) + :main (some (nth 1 (* :prefix ":" :word)))} + "5:apple6:banana6:cherry" + @["apple" "banana" "cherry"]) + +(test "only-tags 1" + ~{:prefix (number :d+ nil :n) + :word (capture (lenprefix (-> :n) :w) :W) + :main (some (* (only-tags (* :prefix ":" :word)) (-> :W)))} + "5:apple6:banana6:cherry" + @["apple" "banana" "cherry"]) + (end-suite) From 88e60c309c0e05970cfed012f5b1eae98ad92bbb Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 12 Sep 2024 17:28:53 -0500 Subject: [PATCH 3/6] Add overflow check. --- src/core/peg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/peg.c b/src/core/peg.c index 0a2b7d4f..f2e70213 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -498,6 +498,7 @@ tail: case RULE_NTH: { uint32_t nth = rule[1]; + if (nth > INT32_MAX) nth = INT32_MAX; uint32_t tag = rule[3]; int oldmode = s->mode; CapState cs = cap_save(s); From 906a982aceef8ad9dfbd4f5011a161c85bbdb3c9 Mon Sep 17 00:00:00 2001 From: sogaiu <983021772@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:04:16 +0900 Subject: [PATCH 4/6] Add some detail to signal docstring --- src/core/corelib.c | 10 +++++++++- src/core/util.c | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/corelib.c b/src/core/corelib.c index 7ac7f564..ee4723b6 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -700,7 +700,15 @@ JANET_CORE_FN(janet_core_is_lengthable, JANET_CORE_FN(janet_core_signal, "(signal what x)", - "Raise a signal with payload x. ") { + "Raise a signal with payload x. `what` can be an integer\n" + "from 0 through 7 indicating user(0-7), or one of:\n\n" + "* :ok\n" + "* :error\n" + "* :debug\n" + "* :yield\n" + "* :user(0-7)\n" + "* :interrupt\n" + "* :await") { janet_arity(argc, 1, 2); Janet payload = argc == 2 ? argv[1] : janet_wrap_nil(); if (janet_checkint(argv[0])) { diff --git a/src/core/util.c b/src/core/util.c index 6cb5676e..a95f43af 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -79,6 +79,7 @@ const char *const janet_type_names[16] = { "pointer" }; +/* Docstring for signal lists these */ const char *const janet_signal_names[14] = { "ok", "error", @@ -96,6 +97,7 @@ const char *const janet_signal_names[14] = { "await" }; +/* Docstring for fiber/status lists these */ const char *const janet_status_names[16] = { "dead", "error", From 8084e4c7284154144c2f9b6c02fa20d159069124 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 20 Sep 2024 22:21:46 -0500 Subject: [PATCH 5/6] Add support for multiple directories in JANET_PATH. Use a colon ":" as the separator on posix, and semicolon ";" on windows (and mingw). --- CHANGELOG.md | 4 ++++ Makefile | 13 ++++++++++--- janet.1 | 3 ++- meson.build | 2 +- src/boot/boot.janet | 25 ++++++++++++++++++++++++- src/conf/janetconf.h | 6 +++--- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94901287..c5528007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog All notable changes to this project will be documented in this file. +## ??? - Unreleased +- Add multiple path support in the `JANET_PATH` environment variables. This lets + user more easily import modules from many directories. + ## 1.36.0 - 2024-09-07 - Improve error messages in `bundle/add*` functions. - Add CI testing and verify tests pass on the s390x architecture. diff --git a/Makefile b/Makefile index 6bca2559..f43c9dbc 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Calvin Rose +# Copyright (c) 2024 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 @@ -43,6 +43,7 @@ JANET_DIST_DIR?=janet-dist JANET_BOOT_FLAGS:=. JANET_PATH '$(JANET_PATH)' JANET_TARGET_OBJECTS=build/janet.o build/shell.o JPM_TAG?=master +SPORK_TAG?=master HAS_SHARED?=1 DEBUGGER=gdb SONAME_SETTER=-Wl,-soname, @@ -205,9 +206,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile ######################## ifeq ($(UNAME), Darwin) -SONAME=libjanet.1.36.dylib +SONAME=libjanet.1.37.dylib else -SONAME=libjanet.so.1.36 +SONAME=libjanet.so.1.37 endif build/c/shell.c: src/mainclient/shell.c @@ -359,6 +360,12 @@ install-jpm-git: $(JANET_TARGET) JANET_LIBPATH='$(LIBDIR)' \ $(RUN) ../../$(JANET_TARGET) ./bootstrap.janet +install-spork-git: $(JANET_TARGET) + mkdir -p build + rm -rf build/spork + git clone --depth=1 --branch='$(SPORK_TAG)' https://github.com/janet-lang/spork.git build/spork + $(JANET_TARGET) -e '(bundle/install "build/spork")' + uninstall: -rm '$(DESTDIR)$(BINDIR)/janet' -rm -rf '$(DESTDIR)$(INCLUDEDIR)/janet' diff --git a/janet.1 b/janet.1 index 0c946b2b..9e7c0ae2 100644 --- a/janet.1 +++ b/janet.1 @@ -255,7 +255,8 @@ and then arguments to the script. .RS The location to look for Janet libraries. This is the only environment variable Janet needs to find native and source code modules. If no JANET_PATH is set, Janet will look in -the default location set at compile time. +the default location set at compile time. This should be a list of as well as a colon +separate list of such directories. .RE .B JANET_PROFILE diff --git a/meson.build b/meson.build index 6fffb5df..f17e8a59 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,7 @@ project('janet', 'c', default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'], - version : '1.36.0') + version : '1.37.0') # Global settings janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet') diff --git a/src/boot/boot.janet b/src/boot/boot.janet index d1aab5d8..b3dc0db9 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -2827,6 +2827,24 @@ (array/insert mp curall-index [(string ":cur:/:all:" ext) loader check-relative]) mp) +# Don't expose this externally yet - could break if custom module/paths is setup. +(defn- module/add-syspath + ``` + Add a custom syspath to `module/paths` by duplicating all entries that being with `:sys:` and + adding duplicates with a specific path prefix instead. + ``` + [path] + (def copies @[]) + (var last-index 0) + (def mp (dyn *module-paths* module/paths)) + (eachp [index entry] mp + (def pattern (first entry)) + (when (and (string? pattern) (string/has-prefix? ":sys:/" pattern)) + (set last-index index) + (array/push copies [(string/replace ":sys:" path pattern) ;(drop 1 entry)]))) + (array/insert mp (+ 1 last-index) ;copies) + mp) + (module/add-paths ":native:" :native) (module/add-paths "/init.janet" :source) (module/add-paths ".janet" :source) @@ -4488,7 +4506,12 @@ (var error-level nil) (var expect-image false) - (if-let [jp (getenv-alias "JANET_PATH")] (setdyn *syspath* jp)) + (when-let [jp (getenv-alias "JANET_PATH")] + (def path-sep (if (index-of (os/which) [:windows :mingw]) ";" ":")) + (def paths (reverse! (string/split path-sep jp))) + (for i 1 (length paths) + (module/add-syspath (get paths i))) + (setdyn *syspath* (first paths))) (if-let [jprofile (getenv-alias "JANET_PROFILE")] (setdyn *profilepath* jprofile)) (set colorize (and (not (getenv-alias "NO_COLOR")) diff --git a/src/conf/janetconf.h b/src/conf/janetconf.h index c7c48b1e..0211ee22 100644 --- a/src/conf/janetconf.h +++ b/src/conf/janetconf.h @@ -4,10 +4,10 @@ #define JANETCONF_H #define JANET_VERSION_MAJOR 1 -#define JANET_VERSION_MINOR 36 +#define JANET_VERSION_MINOR 37 #define JANET_VERSION_PATCH 0 -#define JANET_VERSION_EXTRA "" -#define JANET_VERSION "1.36.0" +#define JANET_VERSION_EXTRA "-dev" +#define JANET_VERSION "1.37.0-dev" /* #define JANET_BUILD "local" */ From 2570e0f7a0fa9aed82ae443427c4a57e0ef7d61a Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 21 Sep 2024 08:58:04 -0500 Subject: [PATCH 6/6] Add *repl-prompt*. --- CHANGELOG.md | 2 ++ src/boot/boot.janet | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5528007..c9fdb6ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. ## ??? - Unreleased +- Change how JANET_PROFILE is loaded to allow more easily customizing the environment. +- Add `*repl-prompt*` dynamic binding to allow customizing the built in repl. - Add multiple path support in the `JANET_PATH` environment variables. This lets user more easily import modules from many directories. diff --git a/src/boot/boot.janet b/src/boot/boot.janet index b3dc0db9..56a1a1a5 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1853,6 +1853,9 @@ (defdyn *pretty-format* "Format specifier for the `pp` function") +(defdyn *repl-prompt* + "Allow setting a custom prompt at the default REPL. Not all REPLs will respect this binding.") + (defn pp ``Pretty-print to stdout or `(dyn *out*)`. The format string used is `(dyn *pretty-format* "%q")`.`` [x] @@ -4643,17 +4646,15 @@ (if-not quiet (print "Janet " janet/version "-" janet/build " " (os/which) "/" (os/arch) "/" (os/compiler) " - '(doc)' for help")) (flush) + (def env (make-env)) (defn getprompt [p] + (when-let [custom-prompt (get env *repl-prompt*)] (break (custom-prompt p))) (def [line] (parser/where p)) (string "repl:" line ":" (parser/state p :delimiters) "> ")) (defn getstdin [prompt buf _] (file/write stdout prompt) (file/flush stdout) (file/read stdin :line buf)) - (def env (make-env)) - (when-let [profile.janet (dyn *profilepath*)] - (def new-env (dofile profile.janet :exit true)) - (merge-module env new-env "" false)) (when debug-flag (put env *debug* true) (put env *redef* true)) @@ -4665,6 +4666,8 @@ (setdyn *doc-color* (if colorize true)) (setdyn *lint-error* error-level) (setdyn *lint-warn* error-level) + (when-let [profile.janet (dyn *profilepath*)] + (dofile profile.janet :exit true :env env)) (repl getchunk nil env))))) ###