mirror of
https://github.com/janet-lang/janet
synced 2025-11-26 12:14:49 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa163093d2 | ||
|
|
e70f64e23d | ||
|
|
6f605f8141 | ||
|
|
d9419ef994 | ||
|
|
7e8639a682 | ||
|
|
452b303b4c | ||
|
|
b0f1a4967d | ||
|
|
9eb4c59c04 | ||
|
|
0d42506cde | ||
|
|
c8a13ce475 | ||
|
|
05e3467d09 | ||
|
|
90639e5068 | ||
|
|
73c7711c78 | ||
|
|
78f6b6a507 | ||
|
|
84f0ab5356 | ||
|
|
546437d799 | ||
|
|
0f05aec563 | ||
|
|
c9097623d6 |
@@ -1,6 +1,13 @@
|
||||
# Changelog
|
||||
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.
|
||||
|
||||
17
jpm
17
jpm
@@ -44,7 +44,7 @@
|
||||
|
||||
(defn- try-real [path]
|
||||
"If os/realpath fails just use normal path."
|
||||
(try (os/realpath) ([_] path)))
|
||||
(try (os/realpath path) ([_] path)))
|
||||
|
||||
(defn- install-paths []
|
||||
{:headerpath (try-real (string exe-dir "/../include/janet"))
|
||||
@@ -1080,12 +1080,15 @@ int main(int argc, const char **argv) {
|
||||
(install-rule dest (dyn :binpath JANET_BINPATH))))))
|
||||
|
||||
(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
|
||||
such that it will run correctly even when JANET_PATH is changed."
|
||||
[&keys {:main main :hardcode-syspath hardcode}]
|
||||
such that it will run correctly even when JANET_PATH is changed. if auto-shebang
|
||||
is truthy, will also automatically insert a correct shebang line.
|
||||
``
|
||||
[&keys {:main main :hardcode-syspath hardcode :is-janet is-janet}]
|
||||
(def binpath (dyn :binpath JANET_BINPATH))
|
||||
(if hardcode
|
||||
(def auto-shebang (and is-janet (dyn :auto-shebang)))
|
||||
(if (or auto-shebang hardcode)
|
||||
(let [syspath (dyn :modpath JANET_MODPATH)]
|
||||
(def parts (peg/match path-splitter main))
|
||||
(def name (last parts))
|
||||
@@ -1097,7 +1100,9 @@ int main(int argc, const char **argv) {
|
||||
(def first-line (:read f :line))
|
||||
(def second-line (string/format "(put root-env :syspath %v)\n" syspath))
|
||||
(def rest (:read f :all))
|
||||
(string first-line second-line rest)))
|
||||
(string (if auto-shebang
|
||||
(string "#!" (dyn :binpath JANET_BINPATH) "/janet\n"))
|
||||
first-line (if hardcode second-line) rest)))
|
||||
(create-dirs path)
|
||||
(spit path contents)
|
||||
(unless is-win (shell "chmod" "+x" path))))
|
||||
|
||||
4
jpm.1
4
jpm.1
@@ -42,6 +42,10 @@ 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
|
||||
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
|
||||
|
||||
.TP
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
project('janet', 'c',
|
||||
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
version : '1.15.3')
|
||||
|
||||
# Global settings
|
||||
@@ -33,7 +33,7 @@ dl_dep = cc.find_library('dl', required : false)
|
||||
thread_dep = dependency('threads')
|
||||
|
||||
# Link options
|
||||
if build_machine.system() != 'windows'
|
||||
if get_option('default_library') != 'static' and build_machine.system() != 'windows'
|
||||
add_project_link_arguments('-rdynamic', language : 'c')
|
||||
endif
|
||||
|
||||
@@ -244,6 +244,7 @@ janet_dep = declare_dependency(include_directories : incdir,
|
||||
# pkgconfig
|
||||
pkg = import('pkgconfig')
|
||||
pkg.generate(libjanet,
|
||||
subdirs: 'janet',
|
||||
description: 'Library for the Janet programming language.')
|
||||
|
||||
# Installation
|
||||
|
||||
@@ -1451,6 +1451,36 @@
|
||||
(set (freqs x) (if n (+ 1 n) 1)))
|
||||
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
|
||||
"Returns an array of the first elements of each col, then the second, etc."
|
||||
[& cols]
|
||||
|
||||
@@ -2085,7 +2085,7 @@ static const JanetReg os_cfuns[] = {
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
{
|
||||
"os/execute", os_execute,
|
||||
JDOC("(os/execute args &opts flags env)\n\n"
|
||||
JDOC("(os/execute args &opt flags env)\n\n"
|
||||
"Execute a program on the system and pass it string arguments. `flags` "
|
||||
"is a keyword that modifies how the program will execute.\n\n"
|
||||
"* :e - enables passing an environment to the program. Without :e, the "
|
||||
@@ -2105,7 +2105,7 @@ static const JanetReg os_cfuns[] = {
|
||||
},
|
||||
{
|
||||
"os/spawn", os_spawn,
|
||||
JDOC("(os/spawn args &opts flags env)\n\n"
|
||||
JDOC("(os/spawn args &opt flags env)\n\n"
|
||||
"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.")
|
||||
},
|
||||
|
||||
@@ -351,6 +351,9 @@ struct pretty {
|
||||
int indent;
|
||||
int flags;
|
||||
int32_t bufstartlen;
|
||||
int32_t *keysort_buffer;
|
||||
int32_t keysort_capacity;
|
||||
int32_t keysort_start;
|
||||
JanetTable seen;
|
||||
};
|
||||
|
||||
@@ -594,31 +597,55 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
} else {
|
||||
int32_t i = 0, len = 0, cap = 0;
|
||||
int first_kv_pair = 1;
|
||||
const JanetKV *kvs = NULL;
|
||||
int counter = 0;
|
||||
janet_dictionary_view(x, &kvs, &len, &cap);
|
||||
if (!istable && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_DICT_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||
for (i = 0; i < cap; i++) {
|
||||
if (!janet_checktype(kvs[i].key, JANET_NIL)) {
|
||||
if (counter == JANET_PRETTY_DICT_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
break;
|
||||
}
|
||||
if (first_kv_pair) {
|
||||
first_kv_pair = 0;
|
||||
} else {
|
||||
print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
|
||||
}
|
||||
janet_pretty_one(S, kvs[i].key, 0);
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
janet_pretty_one(S, kvs[i].value, 1);
|
||||
counter++;
|
||||
int32_t ks_start = S->keysort_start;
|
||||
|
||||
/* Ensure buffer is large enough to sort keys. */
|
||||
int truncated = 0;
|
||||
int64_t mincap = (int64_t) len + (int64_t) ks_start;
|
||||
if (mincap > INT32_MAX) {
|
||||
truncated = 1;
|
||||
len = 0;
|
||||
mincap = ks_start;
|
||||
}
|
||||
|
||||
if (S->keysort_capacity < mincap) {
|
||||
if (mincap >= INT32_MAX / 2) {
|
||||
S->keysort_capacity = INT32_MAX;
|
||||
} else {
|
||||
S->keysort_capacity = mincap * 2;
|
||||
}
|
||||
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->depth++;
|
||||
@@ -641,6 +668,9 @@ static JanetBuffer *janet_pretty_(JanetBuffer *buffer, int depth, int flags, Jan
|
||||
S.indent = 0;
|
||||
S.flags = flags;
|
||||
S.bufstartlen = startlen;
|
||||
S.keysort_capacity = 0;
|
||||
S.keysort_buffer = NULL;
|
||||
S.keysort_start = 0;
|
||||
janet_table_init(&S.seen, 10);
|
||||
janet_pretty_one(&S, x, 0);
|
||||
janet_table_deinit(&S.seen);
|
||||
@@ -663,6 +693,9 @@ static JanetBuffer *janet_jdn_(JanetBuffer *buffer, int depth, Janet x, int32_t
|
||||
S.indent = 0;
|
||||
S.flags = 0;
|
||||
S.bufstartlen = startlen;
|
||||
S.keysort_capacity = 0;
|
||||
S.keysort_buffer = NULL;
|
||||
S.keysort_start = 0;
|
||||
janet_table_init(&S.seen, 10);
|
||||
int res = print_jdn_one(&S, x, depth);
|
||||
janet_table_deinit(&S.seen);
|
||||
@@ -822,7 +855,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
case 'P':
|
||||
case 'p': { /* janet pretty , precision = depth */
|
||||
int depth = atoi(precision);
|
||||
if (depth < 1) depth = 4;
|
||||
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
||||
char d = c[-1];
|
||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||
@@ -974,7 +1007,7 @@ void janet_buffer_format(
|
||||
case 'P':
|
||||
case 'p': { /* janet pretty , precision = depth */
|
||||
int depth = atoi(precision);
|
||||
if (depth < 1) depth = 4;
|
||||
if (depth < 1) depth = JANET_RECURSION_GUARD;
|
||||
char d = strfrmt[-1];
|
||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||
|
||||
@@ -602,6 +602,38 @@ JanetTable *janet_get_core_table(const char *name) {
|
||||
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 */
|
||||
#ifdef JANET_GETTIME
|
||||
/* For macos */
|
||||
|
||||
@@ -1630,6 +1630,7 @@ JANET_API Janet janet_wrap_number_safe(double x);
|
||||
JANET_API int janet_keyeq(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 int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer);
|
||||
|
||||
/* VM functions */
|
||||
JANET_API int janet_init(void);
|
||||
|
||||
Reference in New Issue
Block a user