mirror of
https://github.com/janet-lang/janet
synced 2026-04-11 01:11:26 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd3f48d26a |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,18 +1,6 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## Unreleased - ???
|
|
||||||
- Increase default nesting depth of pretty printing to `JANET_RECURSION_GUARD`
|
|
||||||
- Update meson.build
|
|
||||||
- Add option to automatically add shebang line in installed scripts with `jpm`.
|
|
||||||
- Add `partition-by` and `group-by` to the core.
|
|
||||||
- Sort keys in pretty printing output.
|
|
||||||
|
|
||||||
## 1.15.3 - 2021-02-28
|
|
||||||
- Fix a fiber bug that occured in deeply nested fibers
|
|
||||||
- Add `unref` combinator to pegs.
|
|
||||||
- Small docstring changes.
|
|
||||||
|
|
||||||
## 1.15.2 - 2021-02-15
|
## 1.15.2 - 2021-02-15
|
||||||
- Fix bug in windows version of `os/spawn` and `os/execute` with setting environment variables.
|
- Fix bug in windows version of `os/spawn` and `os/execute` with setting environment variables.
|
||||||
- Fix documentation typos.
|
- Fix documentation typos.
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -27,7 +27,7 @@ PREFIX?=/usr/local
|
|||||||
INCLUDEDIR?=$(PREFIX)/include
|
INCLUDEDIR?=$(PREFIX)/include
|
||||||
BINDIR?=$(PREFIX)/bin
|
BINDIR?=$(PREFIX)/bin
|
||||||
LIBDIR?=$(PREFIX)/lib
|
LIBDIR?=$(PREFIX)/lib
|
||||||
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 1 2> /dev/null || echo local)\""
|
JANET_BUILD?="\"$(shell git log --pretty=format:'%h' -n 2> /dev/null || echo local)\""
|
||||||
CLIBS=-lm -lpthread
|
CLIBS=-lm -lpthread
|
||||||
JANET_TARGET=build/janet
|
JANET_TARGET=build/janet
|
||||||
JANET_LIBRARY=build/libjanet.so
|
JANET_LIBRARY=build/libjanet.so
|
||||||
|
|||||||
17
jpm
17
jpm
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
(defn- try-real [path]
|
(defn- try-real [path]
|
||||||
"If os/realpath fails just use normal path."
|
"If os/realpath fails just use normal path."
|
||||||
(try (os/realpath path) ([_] path)))
|
(try (os/realpath) ([_] path)))
|
||||||
|
|
||||||
(defn- install-paths []
|
(defn- install-paths []
|
||||||
{:headerpath (try-real (string exe-dir "/../include/janet"))
|
{:headerpath (try-real (string exe-dir "/../include/janet"))
|
||||||
@@ -1080,15 +1080,12 @@ int main(int argc, const char **argv) {
|
|||||||
(install-rule dest (dyn :binpath JANET_BINPATH))))))
|
(install-rule dest (dyn :binpath JANET_BINPATH))))))
|
||||||
|
|
||||||
(defn declare-binscript
|
(defn declare-binscript
|
||||||
``Declare a janet file to be installed as an executable script. Creates
|
"Declare a janet file to be installed as an executable script. Creates
|
||||||
a shim on windows. If hardcode is true, will insert code into the script
|
a shim on windows. If hardcode is true, will insert code into the script
|
||||||
such that it will run correctly even when JANET_PATH is changed. if auto-shebang
|
such that it will run correctly even when JANET_PATH is changed."
|
||||||
is truthy, will also automatically insert a correct shebang line.
|
[&keys {:main main :hardcode-syspath hardcode}]
|
||||||
``
|
|
||||||
[&keys {:main main :hardcode-syspath hardcode :is-janet is-janet}]
|
|
||||||
(def binpath (dyn :binpath JANET_BINPATH))
|
(def binpath (dyn :binpath JANET_BINPATH))
|
||||||
(def auto-shebang (and is-janet (dyn :auto-shebang)))
|
(if hardcode
|
||||||
(if (or auto-shebang hardcode)
|
|
||||||
(let [syspath (dyn :modpath JANET_MODPATH)]
|
(let [syspath (dyn :modpath JANET_MODPATH)]
|
||||||
(def parts (peg/match path-splitter main))
|
(def parts (peg/match path-splitter main))
|
||||||
(def name (last parts))
|
(def name (last parts))
|
||||||
@@ -1100,9 +1097,7 @@ int main(int argc, const char **argv) {
|
|||||||
(def first-line (:read f :line))
|
(def first-line (:read f :line))
|
||||||
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
|
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
|
||||||
(def rest (:read f :all))
|
(def rest (:read f :all))
|
||||||
(string (if auto-shebang
|
(string first-line second-line rest)))
|
||||||
(string "#!" (dyn :binpath JANET_BINPATH) "/janet\n"))
|
|
||||||
first-line (if hardcode second-line) rest)))
|
|
||||||
(create-dirs path)
|
(create-dirs path)
|
||||||
(spit path contents)
|
(spit path contents)
|
||||||
(unless is-win (shell "chmod" "+x" path))))
|
(unless is-win (shell "chmod" "+x" path))))
|
||||||
|
|||||||
4
jpm.1
4
jpm.1
@@ -42,10 +42,6 @@ Prevents jpm from going to network to get dependencies - all dependencies should
|
|||||||
Use this flag with the deps and update-pkgs subcommands. This is not a surefire way to prevent a build script from accessing
|
Use this flag with the deps and update-pkgs subcommands. This is not a surefire way to prevent a build script from accessing
|
||||||
the network, for example, a build script that invokes curl will still have network access.
|
the network, for example, a build script that invokes curl will still have network access.
|
||||||
|
|
||||||
.TP
|
|
||||||
.BR \-\-auto\-shebang
|
|
||||||
Prepends installed scripts with a generated shebang line, such that they will use a janet binary located in JANET_BINPATH.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
# IN THE SOFTWARE.
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
project('janet', 'c',
|
project('janet', 'c',
|
||||||
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
|
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||||
version : '1.15.3')
|
version : '1.15.2')
|
||||||
|
|
||||||
# Global settings
|
# Global settings
|
||||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||||
@@ -33,7 +33,7 @@ dl_dep = cc.find_library('dl', required : false)
|
|||||||
thread_dep = dependency('threads')
|
thread_dep = dependency('threads')
|
||||||
|
|
||||||
# Link options
|
# Link options
|
||||||
if get_option('default_library') != 'static' and build_machine.system() != 'windows'
|
if build_machine.system() != 'windows'
|
||||||
add_project_link_arguments('-rdynamic', language : 'c')
|
add_project_link_arguments('-rdynamic', language : 'c')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -244,7 +244,6 @@ janet_dep = declare_dependency(include_directories : incdir,
|
|||||||
# pkgconfig
|
# pkgconfig
|
||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
pkg.generate(libjanet,
|
pkg.generate(libjanet,
|
||||||
subdirs: 'janet',
|
|
||||||
description: 'Library for the Janet programming language.')
|
description: 'Library for the Janet programming language.')
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|||||||
@@ -778,28 +778,24 @@
|
|||||||
a)
|
a)
|
||||||
|
|
||||||
(defn sort
|
(defn sort
|
||||||
``Sort `ind` in-place, and return it. Uses quick-sort and is not a stable sort.
|
"Sort an array in-place. Uses quick-sort and is not a stable sort."
|
||||||
If a `before?` comparator function is provided, sorts elements using that,
|
[a &opt before?]
|
||||||
otherwise uses `<`.``
|
(sort-help a 0 (- (length a) 1) (or before? <)))
|
||||||
[ind &opt before?]
|
|
||||||
(sort-help ind 0 (- (length ind) 1) (or before? <)))
|
|
||||||
|
|
||||||
(defn sort-by
|
(defn sort-by
|
||||||
``Returns `ind` sorted by calling
|
``Returns `ind` sorted by calling
|
||||||
a function `f` on each element and comparing the result with `<`.``
|
a function `f` on each element and comparing the result with <.``
|
||||||
[f ind]
|
[f ind]
|
||||||
(sort ind (fn [x y] (< (f x) (f y)))))
|
(sort ind (fn [x y] (< (f x) (f y)))))
|
||||||
|
|
||||||
(defn sorted
|
(defn sorted
|
||||||
``Returns a new sorted array without modifying the old one.
|
"Returns a new sorted array without modifying the old one."
|
||||||
If a `before?` comparator function is provided, sorts elements using that,
|
|
||||||
otherwise uses `<`.``
|
|
||||||
[ind &opt before?]
|
[ind &opt before?]
|
||||||
(sort (array/slice ind) before?))
|
(sort (array/slice ind) before?))
|
||||||
|
|
||||||
(defn sorted-by
|
(defn sorted-by
|
||||||
``Returns a new sorted array that compares elements by invoking
|
``Returns a new sorted array that compares elements by invoking
|
||||||
a function `f` on each element and comparing the result with `<`.``
|
a function `f` on each element and comparing the result with <.``
|
||||||
[f ind]
|
[f ind]
|
||||||
(sorted ind (fn [x y] (< (f x) (f y)))))
|
(sorted ind (fn [x y] (< (f x) (f y)))))
|
||||||
|
|
||||||
@@ -1451,36 +1447,6 @@
|
|||||||
(set (freqs x) (if n (+ 1 n) 1)))
|
(set (freqs x) (if n (+ 1 n) 1)))
|
||||||
freqs)
|
freqs)
|
||||||
|
|
||||||
(defn group-by
|
|
||||||
``Group elements of `ind` by a function `f` and put the results into a table. The keys of
|
|
||||||
the table are the distinct return values of `f`, and the values are arrays of all elements of `ind`
|
|
||||||
that are equal to that value.``
|
|
||||||
[f ind]
|
|
||||||
(def ret @{})
|
|
||||||
(each x ind
|
|
||||||
(def y (f x))
|
|
||||||
(if-let [arr (get ret y)]
|
|
||||||
(array/push arr x)
|
|
||||||
(put ret y @[x])))
|
|
||||||
ret)
|
|
||||||
|
|
||||||
(defn partition-by
|
|
||||||
``Partition elements of a sequential data structure by a representative function `f`. Partitions
|
|
||||||
split when `(f x)` changes values when iterating to the next element `x` of `ind`. Returns a new array
|
|
||||||
of arrays.``
|
|
||||||
[f ind]
|
|
||||||
(def ret @[])
|
|
||||||
(var span nil)
|
|
||||||
(var category nil)
|
|
||||||
(var is-new true)
|
|
||||||
(each x ind
|
|
||||||
(def y (f x))
|
|
||||||
(cond
|
|
||||||
is-new (do (set is-new false) (set category y) (set span @[x]) (array/push ret span))
|
|
||||||
(= y category) (array/push span x)
|
|
||||||
(do (set category y) (set span @[x]) (array/push ret span))))
|
|
||||||
ret)
|
|
||||||
|
|
||||||
(defn interleave
|
(defn interleave
|
||||||
"Returns an array of the first elements of each col, then the second, etc."
|
"Returns an array of the first elements of each col, then the second, etc."
|
||||||
[& cols]
|
[& cols]
|
||||||
@@ -2132,7 +2098,7 @@
|
|||||||
:on-parse-error on-parse-error
|
:on-parse-error on-parse-error
|
||||||
:fiber-flags guard
|
:fiber-flags guard
|
||||||
:evaluator evaluator
|
:evaluator evaluator
|
||||||
:source default-where
|
:source where
|
||||||
:parser parser
|
:parser parser
|
||||||
:read read
|
:read read
|
||||||
:expander expand} opts)
|
:expander expand} opts)
|
||||||
@@ -2142,11 +2108,9 @@
|
|||||||
(default on-compile-error bad-compile)
|
(default on-compile-error bad-compile)
|
||||||
(default on-parse-error bad-parse)
|
(default on-parse-error bad-parse)
|
||||||
(default evaluator (fn evaluate [x &] (x)))
|
(default evaluator (fn evaluate [x &] (x)))
|
||||||
(default default-where "<anonymous>")
|
(default where "<anonymous>")
|
||||||
(default guard :ydt)
|
(default guard :ydt)
|
||||||
|
|
||||||
(var where default-where)
|
|
||||||
|
|
||||||
# Evaluate 1 source form in a protected manner
|
# Evaluate 1 source form in a protected manner
|
||||||
(defn eval1 [source &opt l c]
|
(defn eval1 [source &opt l c]
|
||||||
(def source (if expand (expand source) source))
|
(def source (if expand (expand source) source))
|
||||||
@@ -2199,18 +2163,11 @@
|
|||||||
(while parser-not-done
|
(while parser-not-done
|
||||||
(if (env :exit) (break))
|
(if (env :exit) (break))
|
||||||
(buffer/clear buf)
|
(buffer/clear buf)
|
||||||
(match (chunks buf p)
|
(if (= (chunks buf p) :cancel)
|
||||||
:cancel
|
|
||||||
(do
|
(do
|
||||||
# A :cancel chunk represents a cancelled form in the REPL, so reset.
|
# A :cancel chunk represents a cancelled form in the REPL, so reset.
|
||||||
(:flush p)
|
(:flush p)
|
||||||
(buffer/clear buf))
|
(buffer/clear buf))
|
||||||
|
|
||||||
[:source new-where]
|
|
||||||
(if (string? new-where)
|
|
||||||
(set where new-where)
|
|
||||||
(set where default-where))
|
|
||||||
|
|
||||||
(do
|
(do
|
||||||
(var pindex 0)
|
(var pindex 0)
|
||||||
(var pstatus nil)
|
(var pstatus nil)
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#define JANET_VERSION_MAJOR 1
|
#define JANET_VERSION_MAJOR 1
|
||||||
#define JANET_VERSION_MINOR 15
|
#define JANET_VERSION_MINOR 15
|
||||||
#define JANET_VERSION_PATCH 3
|
#define JANET_VERSION_PATCH 2
|
||||||
#define JANET_VERSION_EXTRA ""
|
#define JANET_VERSION_EXTRA ""
|
||||||
#define JANET_VERSION "1.15.3"
|
#define JANET_VERSION "1.15.2"
|
||||||
|
|
||||||
/* #define JANET_BUILD "local" */
|
/* #define JANET_BUILD "local" */
|
||||||
|
|
||||||
|
|||||||
@@ -2085,7 +2085,7 @@ static const JanetReg os_cfuns[] = {
|
|||||||
#ifndef JANET_NO_PROCESSES
|
#ifndef JANET_NO_PROCESSES
|
||||||
{
|
{
|
||||||
"os/execute", os_execute,
|
"os/execute", os_execute,
|
||||||
JDOC("(os/execute args &opt flags env)\n\n"
|
JDOC("(os/execute args &opts flags env)\n\n"
|
||||||
"Execute a program on the system and pass it string arguments. `flags` "
|
"Execute a program on the system and pass it string arguments. `flags` "
|
||||||
"is a keyword that modifies how the program will execute.\n\n"
|
"is a keyword that modifies how the program will execute.\n\n"
|
||||||
"* :e - enables passing an environment to the program. Without :e, the "
|
"* :e - enables passing an environment to the program. Without :e, the "
|
||||||
@@ -2105,7 +2105,7 @@ static const JanetReg os_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"os/spawn", os_spawn,
|
"os/spawn", os_spawn,
|
||||||
JDOC("(os/spawn args &opt flags env)\n\n"
|
JDOC("(os/spawn args &opts flags env)\n\n"
|
||||||
"Execute a program on the system and return a handle to the process. Otherwise, the "
|
"Execute a program on the system and return a handle to the process. Otherwise, the "
|
||||||
"same arguments as os/execute. Does not wait for the process.")
|
"same arguments as os/execute. Does not wait for the process.")
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -596,28 +596,65 @@ tail:
|
|||||||
return text + width;
|
return text + width;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RULE_UNREF: {
|
case RULE_MATCHCAP: {
|
||||||
int32_t tcap = s->tags->count;
|
const uint32_t *rule_a = s->bytecode + rule[1];
|
||||||
|
const uint32_t *rule_b = s->bytecode + rule[2];
|
||||||
|
|
||||||
|
int oldmode = s->mode;
|
||||||
|
CapState cs = cap_save(s);
|
||||||
|
s->mode = PEG_MODE_NORMAL;
|
||||||
|
int32_t old_cap = s->captures->count;
|
||||||
down1(s);
|
down1(s);
|
||||||
const uint8_t *result = peg_rule(s, s->bytecode + rule[1], text);
|
const uint8_t *b_result = peg_rule(s, rule_b, text);
|
||||||
up1(s);
|
up1(s);
|
||||||
if (!result) return NULL;
|
s->mode = oldmode;
|
||||||
int32_t final_tcap = s->tags->count;
|
if (!b_result) return NULL;
|
||||||
/* Truncate tagged captures to not include items of the given tag */
|
int32_t new_cap = s->captures->count;
|
||||||
int32_t w = tcap;
|
|
||||||
/* If no tag is given, drop ALL tagged captures */
|
/* Check for bad captures */
|
||||||
if (rule[2]) {
|
for (int32_t i = old_cap; i < new_cap; i++) {
|
||||||
for (int32_t i = tcap; i < final_tcap; i++) {
|
Janet capture = s->captures->data[i];
|
||||||
if (s->tags->data[i] != (0xFF & rule[2])) {
|
if (!janet_checktype(capture, JANET_STRING)) {
|
||||||
s->tags->data[w] = s->tags->data[i];
|
return NULL;
|
||||||
s->tagged_captures->data[w] = s->tagged_captures->data[i];
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->tags->count = w;
|
|
||||||
s->tagged_captures->count = w;
|
/* Save captures to temporary buffer */
|
||||||
return result;
|
Janet *temp_mem = janet_smalloc(sizeof(Janet) * (new_cap - old_cap));
|
||||||
|
for (int32_t i = old_cap; i < new_cap; i++) {
|
||||||
|
temp_mem[i - old_cap] = s->captures->data[i];
|
||||||
|
}
|
||||||
|
cap_load(s, cs);
|
||||||
|
|
||||||
|
for (int32_t i = old_cap; i < new_cap; i++) {
|
||||||
|
Janet capture = temp_mem[i - old_cap];
|
||||||
|
const uint8_t *str = janet_unwrap_string(capture);
|
||||||
|
PegState subs;
|
||||||
|
subs.mode = PEG_MODE_NORMAL;
|
||||||
|
subs.text_start = str;
|
||||||
|
subs.text_end = str + janet_string_length(str);
|
||||||
|
subs.depth = s->depth - 1;
|
||||||
|
subs.captures = s->captures;
|
||||||
|
subs.tagged_captures = s->tagged_captures;
|
||||||
|
subs.scratch = janet_buffer(10);
|
||||||
|
subs.tags = s->tags;
|
||||||
|
subs.constants = s->constants;
|
||||||
|
subs.bytecode = s->bytecode;
|
||||||
|
subs.linemap = NULL;
|
||||||
|
subs.linemaplen = -1;
|
||||||
|
subs.has_backref = s->has_backref;
|
||||||
|
subs.extrac = s->extrac;
|
||||||
|
subs.extrav = s->extrav;
|
||||||
|
|
||||||
|
const uint8_t *a_result = peg_rule(&subs, rule_a, str);
|
||||||
|
if (NULL == a_result) {
|
||||||
|
janet_sfree(temp_mem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
janet_sfree(temp_mem);
|
||||||
|
return b_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -868,6 +905,9 @@ static void spec_ifnot(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
static void spec_lenprefix(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_lenprefix(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_branch(b, argc, argv, RULE_LENPREFIX);
|
spec_branch(b, argc, argv, RULE_LENPREFIX);
|
||||||
}
|
}
|
||||||
|
static void spec_matchcap(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
|
spec_branch(b, argc, argv, RULE_MATCHCAP);
|
||||||
|
}
|
||||||
|
|
||||||
static void spec_between(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_between(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
peg_fixarity(b, argc, 3);
|
peg_fixarity(b, argc, 3);
|
||||||
@@ -943,15 +983,15 @@ static void spec_error(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
spec_onerule(b, argc, argv, RULE_ERROR);
|
spec_onerule(b, argc, argv, RULE_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void spec_drop(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
|
spec_onerule(b, argc, argv, RULE_DROP);
|
||||||
|
}
|
||||||
static void spec_to(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_to(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_onerule(b, argc, argv, RULE_TO);
|
spec_onerule(b, argc, argv, RULE_TO);
|
||||||
}
|
}
|
||||||
static void spec_thru(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_thru(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_onerule(b, argc, argv, RULE_THRU);
|
spec_onerule(b, argc, argv, RULE_THRU);
|
||||||
}
|
}
|
||||||
static void spec_drop(Builder *b, int32_t argc, const Janet *argv) {
|
|
||||||
spec_onerule(b, argc, argv, RULE_DROP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rule of the form [rule, tag] */
|
/* Rule of the form [rule, tag] */
|
||||||
static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
|
static void spec_cap1(Builder *b, int32_t argc, const Janet *argv, uint32_t op) {
|
||||||
@@ -971,9 +1011,6 @@ static void spec_accumulate(Builder *b, int32_t argc, const Janet *argv) {
|
|||||||
static void spec_group(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_group(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
spec_cap1(b, argc, argv, RULE_GROUP);
|
spec_cap1(b, argc, argv, RULE_GROUP);
|
||||||
}
|
}
|
||||||
static void spec_unref(Builder *b, int32_t argc, const Janet *argv) {
|
|
||||||
spec_cap1(b, argc, argv, RULE_UNREF);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
static void spec_reference(Builder *b, int32_t argc, const Janet *argv) {
|
||||||
peg_arity(b, argc, 1, 2);
|
peg_arity(b, argc, 1, 2);
|
||||||
@@ -1117,6 +1154,7 @@ static const SpecialPair peg_specials[] = {
|
|||||||
{"lenprefix", spec_lenprefix},
|
{"lenprefix", spec_lenprefix},
|
||||||
{"line", spec_line},
|
{"line", spec_line},
|
||||||
{"look", spec_look},
|
{"look", spec_look},
|
||||||
|
{"matchcap", spec_matchcap},
|
||||||
{"not", spec_not},
|
{"not", spec_not},
|
||||||
{"opt", spec_opt},
|
{"opt", spec_opt},
|
||||||
{"position", spec_position},
|
{"position", spec_position},
|
||||||
@@ -1131,7 +1169,6 @@ static const SpecialPair peg_specials[] = {
|
|||||||
{"to", spec_to},
|
{"to", spec_to},
|
||||||
{"uint", spec_uint_le},
|
{"uint", spec_uint_le},
|
||||||
{"uint-be", spec_uint_be},
|
{"uint-be", spec_uint_be},
|
||||||
{"unref", spec_unref},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Compile a janet value into a rule and return the rule index. */
|
/* Compile a janet value into a rule and return the rule index. */
|
||||||
@@ -1390,6 +1427,7 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
|||||||
case RULE_IF:
|
case RULE_IF:
|
||||||
case RULE_IFNOT:
|
case RULE_IFNOT:
|
||||||
case RULE_LENPREFIX:
|
case RULE_LENPREFIX:
|
||||||
|
case RULE_MATCHCAP:
|
||||||
/* [rule_a, rule_b (b if not a)] */
|
/* [rule_a, rule_b (b if not a)] */
|
||||||
if (rule[1] >= blen) goto bad;
|
if (rule[1] >= blen) goto bad;
|
||||||
if (rule[2] >= blen) goto bad;
|
if (rule[2] >= blen) goto bad;
|
||||||
@@ -1420,7 +1458,6 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
|||||||
case RULE_ACCUMULATE:
|
case RULE_ACCUMULATE:
|
||||||
case RULE_GROUP:
|
case RULE_GROUP:
|
||||||
case RULE_CAPTURE:
|
case RULE_CAPTURE:
|
||||||
case RULE_UNREF:
|
|
||||||
/* [rule, tag] */
|
/* [rule, tag] */
|
||||||
if (rule[1] >= blen) goto bad;
|
if (rule[1] >= blen) goto bad;
|
||||||
op_flags[rule[1]] |= 0x01;
|
op_flags[rule[1]] |= 0x01;
|
||||||
|
|||||||
@@ -351,9 +351,6 @@ struct pretty {
|
|||||||
int indent;
|
int indent;
|
||||||
int flags;
|
int flags;
|
||||||
int32_t bufstartlen;
|
int32_t bufstartlen;
|
||||||
int32_t *keysort_buffer;
|
|
||||||
int32_t keysort_capacity;
|
|
||||||
int32_t keysort_start;
|
|
||||||
JanetTable seen;
|
JanetTable seen;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -597,55 +594,31 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
|||||||
janet_buffer_push_cstring(S->buffer, "...");
|
janet_buffer_push_cstring(S->buffer, "...");
|
||||||
} else {
|
} else {
|
||||||
int32_t i = 0, len = 0, cap = 0;
|
int32_t i = 0, len = 0, cap = 0;
|
||||||
|
int first_kv_pair = 1;
|
||||||
const JanetKV *kvs = NULL;
|
const JanetKV *kvs = NULL;
|
||||||
|
int counter = 0;
|
||||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||||
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
||||||
janet_buffer_push_u8(S->buffer, ' ');
|
janet_buffer_push_u8(S->buffer, ' ');
|
||||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||||
int32_t ks_start = S->keysort_start;
|
for (i = 0; i < cap; i++) {
|
||||||
|
if (!janet_checktype(kvs[i].key, JANET_NIL)) {
|
||||||
/* Ensure buffer is large enough to sort keys. */
|
if (counter == JANET_PRETTY_DICT_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
||||||
int truncated = 0;
|
print_newline(S, 0);
|
||||||
int64_t mincap = (int64_t) len + (int64_t) ks_start;
|
janet_buffer_push_cstring(S->buffer, "...");
|
||||||
if (mincap > INT32_MAX) {
|
break;
|
||||||
truncated = 1;
|
}
|
||||||
len = 0;
|
if (first_kv_pair) {
|
||||||
mincap = ks_start;
|
first_kv_pair = 0;
|
||||||
}
|
} else {
|
||||||
|
print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
||||||
if (S->keysort_capacity < mincap) {
|
}
|
||||||
if (mincap >= INT32_MAX / 2) {
|
janet_pretty_one(S, kvs[i].key, 0);
|
||||||
S->keysort_capacity = INT32_MAX;
|
janet_buffer_push_u8(S->buffer, ' ');
|
||||||
} else {
|
janet_pretty_one(S, kvs[i].value, 1);
|
||||||
S->keysort_capacity = mincap * 2;
|
counter++;
|
||||||
}
|
|
||||||
S->keysort_buffer = janet_srealloc(S->keysort_buffer, sizeof(int32_t) * S->keysort_capacity);
|
|
||||||
if (NULL == S->keysort_buffer) {
|
|
||||||
JANET_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
janet_sorted_keys(kvs, cap, S->keysort_buffer + ks_start);
|
|
||||||
S->keysort_start += len;
|
|
||||||
if (!(S->flags & JANET_PRETTY_NOTRUNC) && (len > JANET_PRETTY_DICT_LIMIT)) {
|
|
||||||
len = JANET_PRETTY_DICT_LIMIT;
|
|
||||||
truncated = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
if (i) print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
|
||||||
int32_t j = S->keysort_buffer[i + ks_start];
|
|
||||||
janet_pretty_one(S, kvs[j].key, 0);
|
|
||||||
janet_buffer_push_u8(S->buffer, ' ');
|
|
||||||
janet_pretty_one(S, kvs[j].value, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (truncated) {
|
|
||||||
print_newline(S, 0);
|
|
||||||
janet_buffer_push_cstring(S->buffer, "...");
|
|
||||||
}
|
|
||||||
|
|
||||||
S->keysort_start = ks_start;
|
|
||||||
}
|
}
|
||||||
S->indent -= 2;
|
S->indent -= 2;
|
||||||
S->depth++;
|
S->depth++;
|
||||||
@@ -668,9 +641,6 @@ static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Jan
|
|||||||
S.indent = 0;
|
S.indent = 0;
|
||||||
S.flags = flags;
|
S.flags = flags;
|
||||||
S.bufstartlen = startlen;
|
S.bufstartlen = startlen;
|
||||||
S.keysort_capacity = 0;
|
|
||||||
S.keysort_buffer = NULL;
|
|
||||||
S.keysort_start = 0;
|
|
||||||
janet_table_init(&S.seen, 10);
|
janet_table_init(&S.seen, 10);
|
||||||
janet_pretty_one(&S, x, 0);
|
janet_pretty_one(&S, x, 0);
|
||||||
janet_table_deinit(&S.seen);
|
janet_table_deinit(&S.seen);
|
||||||
@@ -693,9 +663,6 @@ static JanetBuffer *janet_jdn_(JanetBuffer *buffer, int depth, Janet x, int32_t
|
|||||||
S.indent = 0;
|
S.indent = 0;
|
||||||
S.flags = 0;
|
S.flags = 0;
|
||||||
S.bufstartlen = startlen;
|
S.bufstartlen = startlen;
|
||||||
S.keysort_capacity = 0;
|
|
||||||
S.keysort_buffer = NULL;
|
|
||||||
S.keysort_start = 0;
|
|
||||||
janet_table_init(&S.seen, 10);
|
janet_table_init(&S.seen, 10);
|
||||||
int res = print_jdn_one(&S, x, depth);
|
int res = print_jdn_one(&S, x, depth);
|
||||||
janet_table_deinit(&S.seen);
|
janet_table_deinit(&S.seen);
|
||||||
@@ -855,7 +822,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
|||||||
case 'P':
|
case 'P':
|
||||||
case 'p': { /* janet pretty , precision = depth */
|
case 'p': { /* janet pretty , precision = depth */
|
||||||
int depth = atoi(precision);
|
int depth = atoi(precision);
|
||||||
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
if (depth < 1) depth = 4;
|
||||||
char d = c[-1];
|
char d = c[-1];
|
||||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||||
@@ -1007,7 +974,7 @@ void janet_buffer_format(
|
|||||||
case 'P':
|
case 'P':
|
||||||
case 'p': { /* janet pretty , precision = depth */
|
case 'p': { /* janet pretty , precision = depth */
|
||||||
int depth = atoi(precision);
|
int depth = atoi(precision);
|
||||||
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
if (depth < 1) depth = 4;
|
||||||
char d = strfrmt[-1];
|
char d = strfrmt[-1];
|
||||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||||
|
|||||||
@@ -602,38 +602,6 @@ JanetTable *janet_get_core_table(const char *name) {
|
|||||||
return janet_unwrap_table(out);
|
return janet_unwrap_table(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sort keys of a dictionary type */
|
|
||||||
int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer) {
|
|
||||||
|
|
||||||
/* First, put populated indices into index_buffer */
|
|
||||||
int32_t next_index = 0;
|
|
||||||
for (int32_t i = 0; i < cap; i++) {
|
|
||||||
if (!janet_checktype(dict[i].key, JANET_NIL)) {
|
|
||||||
index_buffer[next_index++] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next, sort those (simple insertion sort here for now) */
|
|
||||||
for (int32_t i = 1; i < next_index; i++) {
|
|
||||||
int32_t index_to_insert = index_buffer[i];
|
|
||||||
Janet lhs = dict[index_to_insert].key;
|
|
||||||
for (int32_t j = i - 1; j >= 0; j--) {
|
|
||||||
index_buffer[j + 1] = index_buffer[j];
|
|
||||||
Janet rhs = dict[index_buffer[j]].key;
|
|
||||||
if (janet_compare(lhs, rhs) >= 0) {
|
|
||||||
index_buffer[j + 1] = index_to_insert;
|
|
||||||
break;
|
|
||||||
} else if (j == 0) {
|
|
||||||
index_buffer[0] = index_to_insert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return number of indices found */
|
|
||||||
return next_index;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clock shims for various platforms */
|
/* Clock shims for various platforms */
|
||||||
#ifdef JANET_GETTIME
|
#ifdef JANET_GETTIME
|
||||||
/* For macos */
|
/* For macos */
|
||||||
|
|||||||
@@ -1630,7 +1630,6 @@ JANET_API Janet janet_wrap_number_safe(double x);
|
|||||||
JANET_API int janet_keyeq(Janet x, const char *cstring);
|
JANET_API int janet_keyeq(Janet x, const char *cstring);
|
||||||
JANET_API int janet_streq(Janet x, const char *cstring);
|
JANET_API int janet_streq(Janet x, const char *cstring);
|
||||||
JANET_API int janet_symeq(Janet x, const char *cstring);
|
JANET_API int janet_symeq(Janet x, const char *cstring);
|
||||||
JANET_API int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer);
|
|
||||||
|
|
||||||
/* VM functions */
|
/* VM functions */
|
||||||
JANET_API int janet_init(void);
|
JANET_API int janet_init(void);
|
||||||
@@ -1843,7 +1842,7 @@ typedef enum {
|
|||||||
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
|
RULE_READINT, /* [(signedness << 4) | (endianess << 5) | bytewidth, tag] */
|
||||||
RULE_LINE, /* [tag] */
|
RULE_LINE, /* [tag] */
|
||||||
RULE_COLUMN, /* [tag] */
|
RULE_COLUMN, /* [tag] */
|
||||||
RULE_UNREF /* [rule, tag] */
|
RULE_MATCHCAP /* [rule_a, rule_b] */
|
||||||
} JanetPegOpcod;
|
} JanetPegOpcod;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -481,16 +481,13 @@
|
|||||||
(check-deep '(to "b") "aaaa" nil)
|
(check-deep '(to "b") "aaaa" nil)
|
||||||
(check-deep '(thru "b") "aaaa" nil)
|
(check-deep '(thru "b") "aaaa" nil)
|
||||||
|
|
||||||
# unref
|
# matchcap
|
||||||
(def grammar
|
(def matchcap-test
|
||||||
(peg/compile
|
~{:span (* "{" '(to "}") "}")
|
||||||
~{:main (* :tagged -1)
|
:parse-span (* '3 3)
|
||||||
:tagged (unref (replace (* :open-tag :value :close-tag) ,struct))
|
:main (matchcap :parse-span (any :span ))})
|
||||||
:open-tag (* (constant :tag) "<" (capture :w+ :tag-name) ">")
|
|
||||||
:value (* (constant :value) (group (any (+ :tagged :untagged))))
|
(check-deep matchcap-test "{bigrig}{fatman}{catdog}" @["big" "fat" "cat"])
|
||||||
:close-tag (* "</" (backmatch :tag-name) ">")
|
(check-deep matchcap-test "{bigrig}{fatman}{catdoggy}" @["big" "fat" "cat"])
|
||||||
:untagged (capture (any (if-not "<" 1)))}))
|
|
||||||
(check-deep grammar "<p><em>foobar</em></p>" @[{:tag "p" :value @[{:tag "em" :value @["foobar"]}]}])
|
|
||||||
(check-deep grammar "<p>foobar</p>" @[{:tag "p" :value @["foobar"]}])
|
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
Reference in New Issue
Block a user