1
0
mirror of https://github.com/janet-lang/janet synced 2026-04-02 04:51:26 +00:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Calvin Rose
10bb17199c Prepare for 1.41.0 release 2026-02-15 08:45:56 -06:00
Calvin Rose
0aa7dfeb9a Work on windows for WSAConnect not working.
For remote connections, if you did not manually wait for the connection
to settle, the programmer would see unspecified network errors. This is
is because the underlying TCP Connection had not been established yet.
The correct way to deal with this is to use ConnectEx if available
instead of WSAConnect.
2026-02-14 21:11:28 -06:00
Calvin Rose
8f7c32e5cb Update for msvc build. 2026-02-14 18:31:57 -06:00
sogaiu
abd7bb1110 Use snprintf instead of sprintf (#1711)
Co-authored-by: sogaiu <983021772@users.noreply.github.com>
2026-02-14 09:04:33 -06:00
Calvin Rose
d81512723b When pretty printing, don't sort keys for huge tables.
This was exposed when printing `(invert (range 200000))`, which
isn't so large that we shouldn't be able to sort it, but was taking
far too long to compute.
2026-02-14 08:57:27 -06:00
Calvin Rose
2a54154976 Don't use preload on absolute paths.
When importing full paths, the old preload code was preventing
(import <fullpath> :fresh true) from working as expected.
2026-02-13 19:36:09 -06:00
Calvin Rose
306ce892ea Merge branch 'make-modules-easier' 2026-02-06 00:31:08 -06:00
Calvin Rose
c7c3821aa6 Remove extra output from peg test. 2026-02-06 00:23:45 -06:00
Calvin Rose
d2685594f9 VERBOSE=1 caused tests to fail as we did more asserts inside the assert.
Thenc checked stderr for messages. Since the helper makes assert write
to stderr, this caused extra cruft in our test output.
2026-02-06 00:17:11 -06:00
Calvin Rose
ca5c617fba More tweaks to peg suite for arm32 failures. 2026-02-06 00:04:18 -06:00
Calvin Rose
16b449a137 Print "actual" output on verbose mode for suite-peg 2026-02-05 23:52:28 -06:00
Calvin Rose
2e8dd90a51 Line endings in tests. 2026-02-05 23:38:55 -06:00
14 changed files with 119 additions and 76 deletions

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@ janet
/src/include/generated/*.h
janet-*.tar.gz
dist
/tmp
# jpm lockfile
lockfile.janet

View File

@@ -1,7 +1,8 @@
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased - ???
## 1.41.0 - 2026-02-15
- Revert to blocking behaior of `net/connect` on windows to fix spurious errors.
- Allow overriding the loader when doing imports with the `:loader` argument.
- Allow importing modules with a path extension to do what one would expect.
- Add `find-all` argument to `module/find`

View File

@@ -2874,7 +2874,8 @@
(defn- check-dyn-relative [x] (if (string/has-prefix? "@" x) x))
(defn- check-relative [x] (if (string/has-prefix? "." x) x))
(defn- check-not-relative [x] (if-not (string/has-prefix? "." x) x))
# Don't try to preload absolute or relative paths
(defn- check-preloadable [x] (if-not (or (string/has-prefix? "/" x) (string/find "." x) (string/find "@" x)) x))
(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "@" x) (string/has-prefix? "." x)) x))
(defn- check-project-relative [x] (if (string/has-prefix? "/" x) x))
@@ -2949,7 +2950,10 @@
(module/add-paths "/init.janet" :source)
(module/add-paths ".janet" :source)
(module/add-paths ".jimage" :image)
(array/insert module/paths 0 [(fn is-cached [path] (if (in (dyn *module-cache* module/cache) path) path)) :preload check-not-relative])
(array/insert module/paths 0
[(fn is-cached [path] (if (in (dyn *module-cache* module/cache) path) path))
:preload
check-preloadable])
# Version of fexists that works even with a reduced OS
(defn- fexists
@@ -3219,7 +3223,7 @@
(def prefix (or
(and as (string as "/"))
prefix
(string (last (string/split "/" path)) "/")))
(string (first (string/split "." (last (string/split "/" path)))) "/")))
(merge-module env newenv prefix ep only))
(defmacro import

View File

@@ -37,7 +37,7 @@ int system_test() {
/* Check the version defines are self consistent */
char version_combined[256];
sprintf(version_combined, "%d.%d.%d%s", JANET_VERSION_MAJOR, JANET_VERSION_MINOR, JANET_VERSION_PATCH, JANET_VERSION_EXTRA);
snprintf(version_combined, sizeof(version_combined), "%d.%d.%d%s", JANET_VERSION_MAJOR, JANET_VERSION_MINOR, JANET_VERSION_PATCH, JANET_VERSION_EXTRA);
assert(!strcmp(JANET_VERSION, version_combined));
/* Reflexive testing and nanbox testing */

View File

@@ -2416,7 +2416,7 @@ Janet janet_ev_lasterr(void) {
msgbuf,
sizeof(msgbuf),
NULL);
if (!*msgbuf) sprintf(msgbuf, "%d", code);
if (!*msgbuf) snprintf(msgbuf, sizeof(msgbuf), "%d", code);
char *c = msgbuf;
while (*c) {
if (*c == '\n' || *c == '\r') {

View File

@@ -570,15 +570,16 @@ JANET_CORE_FN(cfun_net_connect,
if (socktype == SOCK_DGRAM) udp_flag = JANET_STREAM_UDPSERVER;
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE | udp_flag);
/* Set up the socket for non-blocking IO before connecting */
janet_net_socknoblock(sock);
/* Connect to socket */
#ifdef JANET_WINDOWS
int status = WSAConnect(sock, addr, addrlen, NULL, NULL, NULL, NULL);
int err = WSAGetLastError();
freeaddrinfo(ai);
/* Set up the socket for non-blocking IO after connecting on windows by default */
janet_net_socknoblock(sock);
#else
/* Set up the socket for non-blocking IO before connecting */
janet_net_socknoblock(sock);
int status;
do {
status = connect(sock, addr, addrlen);
@@ -599,10 +600,11 @@ JANET_CORE_FN(cfun_net_connect,
return janet_wrap_abstract(stream);
}
if (status == -1) {
#ifdef JANET_WINDOWS
if (status == SOCKET_ERROR) {
if (err != WSAEWOULDBLOCK) {
#else
if (status == -1) {
if (err != EINPROGRESS) {
#endif
JSOCKCLOSE(sock);

View File

@@ -1331,7 +1331,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
msgbuf,
sizeof(msgbuf),
NULL);
if (!*msgbuf) sprintf(msgbuf, "%d", cp_error_code);
if (!*msgbuf) snprintf(msgbuf, sizeof(msgbuf), "%d", cp_error_code);
char *c = msgbuf;
while (*c) {
if (*c == '\n' || *c == '\r') {

View File

@@ -220,9 +220,9 @@ tail:
janet_eprintf("tag stack [%d]:\n", s->tagged_captures->count);
for (int32_t i = 0; i < s->tagged_captures->count; i++) {
if (has_color) {
janet_eprintf(" [%d] tag=%d: %M\n", i, s->tags->data[i], s->tagged_captures->data[i]);
janet_eprintf(" [%d] tag=%d: %M\n", i, (int32_t) s->tags->data[i], s->tagged_captures->data[i]);
} else {
janet_eprintf(" [%d] tag=%d: %m\n", i, s->tags->data[i], s->tagged_captures->data[i]);
janet_eprintf(" [%d] tag=%d: %m\n", i, (int32_t) s->tags->data[i], s->tagged_captures->data[i]);
}
}
}

View File

@@ -487,6 +487,7 @@ static const char *janet_pretty_colors[] = {
#define JANET_PRETTY_DICT_ONELINE 4
#define JANET_PRETTY_IND_ONELINE 10
#define JANET_PRETTY_DICT_LIMIT 30
#define JANET_PRETTY_DICT_KEYSORT_LIMIT 2000
#define JANET_PRETTY_ARRAY_LIMIT 160
/* Helper for pretty printing */
@@ -625,55 +626,78 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
if (S->depth == 0) {
janet_buffer_push_cstring(S->buffer, "...");
} else {
int32_t i = 0, len = 0, cap = 0;
int32_t len = 0, cap = 0;
const JanetKV *kvs = NULL;
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);
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 = (int32_t)(mincap * 2);
/* Shortcut for huge dictionaries, don't bother sorting keys */
if (len > JANET_PRETTY_DICT_KEYSORT_LIMIT) {
if (!(S->flags & JANET_PRETTY_NOTRUNC) && (len > JANET_PRETTY_DICT_LIMIT)) {
len = JANET_PRETTY_DICT_LIMIT;
truncated = 1;
}
S->keysort_buffer = janet_srealloc(S->keysort_buffer, sizeof(int32_t) * S->keysort_capacity);
if (NULL == S->keysort_buffer) {
JANET_OUT_OF_MEMORY;
int32_t j = 0;
for (int32_t i = 0; i < len; i++) {
while (janet_checktype(kvs[j].key, JANET_NIL)) j++;
if (i) print_newline(S, len < JANET_PRETTY_DICT_ONELINE);
janet_pretty_one(S, kvs[j].key, 0);
janet_buffer_push_u8(S->buffer, ' ');
janet_pretty_one(S, kvs[j].value, 1);
j++;
}
}
if (truncated) {
print_newline(S, 0);
janet_buffer_push_cstring(S->buffer, "...");
}
} else {
/* Sorted keys dictionaries */
janet_sorted_keys(kvs, cap, S->keysort_buffer == NULL ? NULL : 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;
}
/* Ensure buffer is large enough to sort keys. */
int64_t mincap = (int64_t) len + (int64_t) ks_start;
if (mincap > INT32_MAX) {
truncated = 1;
len = 0;
mincap = ks_start;
}
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 (S->keysort_capacity < mincap) {
if (mincap >= INT32_MAX / 2) {
S->keysort_capacity = INT32_MAX;
} else {
S->keysort_capacity = (int32_t)(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;
}
}
if (truncated) {
print_newline(S, 0);
janet_buffer_push_cstring(S->buffer, "...");
}
janet_sorted_keys(kvs, cap, S->keysort_buffer == NULL ? NULL : 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 (int32_t 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;
@@ -897,7 +921,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
case 's':
case 'S': {
const char *str = va_arg(args, const char *);
int32_t len = c[-1] == 's'
int32_t len = (c[-1] == 's')
? (int32_t) strlen(str)
: janet_string_length((JanetString) str);
if (form[2] == '\0')

View File

@@ -157,7 +157,7 @@ Janet janet_table_get(JanetTable *t, Janet key) {
/* Used internally for compiler stuff */
Janet janet_table_get_keyword(JanetTable *t, const char *keyword) {
int32_t keyword_len = strlen(keyword);
int32_t keyword_len = (int32_t) strlen(keyword);
for (int i = JANET_MAX_PROTO_DEPTH; t && i; t = t->proto, --i) {
JanetKV *bucket = (JanetKV *) janet_dict_find_keyword(t->data, t->capacity, (const uint8_t *) keyword, keyword_len);
if (NULL != bucket && !janet_checktype(bucket->key, JANET_NIL))

View File

@@ -335,10 +335,9 @@ int32_t janet_hash(Janet x) {
} as;
as.d = janet_unwrap_number(x);
as.d += 0.0; /* normalize negative 0 */
uint32_t lo = (uint32_t)(as.u & 0xFFFFFFFF);
as.u = murmur64(as.u);
uint32_t hi = (uint32_t)(as.u >> 32);
uint32_t hilo = (hi ^ lo) * 2654435769u;
hash = (int32_t)((hilo << 16) | (hilo >> 16));
hash = (int32_t)hi;
break;
}
case JANET_ABSTRACT: {

View File

@@ -853,40 +853,48 @@
# Debug and ?? tests.
(defn test-stderr [name peg input expected-matches expected-stderr]
(with-dyns [:err @""]
(test name peg input expected-matches))
(def actual @"")
(with-dyns [:err actual *err-color* true]
(test name peg input expected-matches))
(peg/match peg input))
(assert (deep= (string actual) expected-stderr)))
(defn test-stderr-no-color [name peg input expected-matches expected-stderr]
(with-dyns [:err @""]
(test name peg input expected-matches))
(def actual @"")
(with-dyns [:err actual *err-color* false]
(test name peg input expected-matches))
(peg/match peg input))
(assert (deep= (string actual) expected-stderr)))
(test-stderr "?? long form"
'(* (debug) "abc")
"abc"
@[]
"?? at [abc] (index 0)\n")
(test-stderr
"?? long form"
'(* (debug) "abc")
"abc"
@[]
"?? at [abc] (index 0)\n")
(test-stderr "?? short form"
'(* (??) "abc")
"abc"
@[]
"?? at [abc] (index 0)\n")
(test-stderr
"?? short form"
'(* (??) "abc")
"abc"
@[]
"?? at [abc] (index 0)\n")
(test-stderr "?? end of text"
'(* "abc" (??))
"abc"
@[]
"?? at [] (index 3)\n")
(test-stderr
"?? end of text"
'(* "abc" (??))
"abc"
@[]
"?? at [] (index 3)\n")
(test-stderr "?? between rules"
'(* "a" (??) "bc")
"abc"
@[]
"?? at [bc] (index 1)\n")
(test-stderr
"?? between rules"
'(* "a" (??) "bc")
"abc"
@[]
"?? at [bc] (index 1)\n")
(test-stderr
"?? stack display, string"

Binary file not shown.

View File

@@ -87,7 +87,9 @@
<Directory Id="BinDir" Name="bin"/>
<Directory Id="CDir" Name="C"/>
<Directory Id="DocsDir" Name="docs"/>
<Directory Id="LibraryDir" Name="Library"/>
<Directory Id="LibraryDir" Name="Library">
<Directory Id="LibBinDir" Name="bin"/>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
@@ -169,6 +171,7 @@
<Component Id="SetEnvVarsPerMachine" Directory="ApplicationProgramsFolder" Guid="57b1e1ef-89c8-4ce4-9f0f-37618677c5a4" KeyPath="yes">
<Condition>ALLUSERS=1</Condition>
<Environment Id="PATH_PERMACHINE" Name="PATH" Value="[BinDir]" Action="set" Permanent="no" System="yes" Part="last"/>
<Environment Id="PATH2_PERMACHINE" Name="PATH" Value="[LibBinDir]" Action="set" Permanent="no" System="yes" Part="last"/>
<Environment Id="JANET_BINPATH_PERMACHINE" Name="JANET_BINPATH" Value="[BinDir]" Action="set" Permanent="no" System="yes"/>
<Environment Id="JANET_MANPATH_PERMACHINE" Name="JANET_MANPATH" Value="[DocsDir]" Action="set" Permanent="no" System="yes"/>
<Environment Id="JANET_PATH_PERMACHINE" Name="JANET_PATH" Value="[LibraryDir]" Action="set" Permanent="no" System="yes" />
@@ -178,6 +181,7 @@
<Component Id="SetEnvVarsPerUser" Directory="ApplicationProgramsFolder" Guid="128be307-488b-49aa-971a-d2ae00a1a584" KeyPath="yes">
<Condition>NOT ALLUSERS=1</Condition>
<Environment Id="PATH_PERUSER" Name="PATH" Value="[BinDir]" Action="set" Permanent="no" System="no" Part="last"/>
<Environment Id="PATH2_PERUSER" Name="PATH" Value="[LibBinDir]" Action="set" Permanent="no" System="no" Part="last"/>
<Environment Id="JANET_BINPATH_PERUSER" Name="JANET_BINPATH" Value="[BinDir]" Action="set" Permanent="no" System="no"/>
<Environment Id="JANET_MANPATH_PERUSER" Name="JANET_MANPATH" Value="[DocsDir]" Action="set" Permanent="no" System="no"/>
<Environment Id="JANET_PATH_PERUSER" Name="JANET_PATH" Value="[LibraryDir]" Action="set" Permanent="no" System="no" />