1
0
mirror of https://github.com/janet-lang/janet synced 2025-11-08 19:43:41 +00:00

Compare commits

..

29 Commits

Author SHA1 Message Date
Calvin Rose
f2815d7068 Actually run the installer in build_win.bat. 2020-04-01 09:26:20 -05:00
Calvin Rose
f48d9465f5 Fix appveyor.yml 2020-04-01 09:23:19 -05:00
Calvin Rose
6b1d5c6d7b Work on improving deployment for windows. 2020-04-01 09:22:27 -05:00
Calvin Rose
789ef3608b Make format. 2020-04-01 08:54:01 -05:00
Calvin Rose
5b6b9f1597 Prepare for 1.8.1 release. 2020-03-31 09:49:09 -05:00
Calvin Rose
47f246ba66 Merge pull request #329 from pepe/master
Fix typo flie
2020-03-31 09:17:39 -05:00
Josef Pospíšil
b6b70d54ef Fix typo flie 2020-03-31 15:31:27 +02:00
Calvin Rose
417d9a14cc s/yaml/yml/g in README.md 2020-03-31 08:03:38 -05:00
Calvin Rose
244566ccd4 Remove manual feature definitions in boot.
Instead, reuse features as defined in features.h
2020-03-31 07:52:20 -05:00
Calvin Rose
ca4a35c90a Update CHANGELOG.md 2020-03-30 16:59:51 -05:00
Calvin Rose
e4ea8bc867 Fix features for bsd.
Don't define XOPEN_SOURCE unless we actually need it.
2020-03-30 15:38:03 -05:00
q66
5d840b944b Fix wrong check on big endian systems
We can't randomly type pun random-sized types on big endian
systems.
2020-03-30 13:38:49 -05:00
q66
1e28876494 Fix typo in big endian unmarshalling code
This was subtly breaking everything.
2020-03-30 13:38:49 -05:00
q66
a40b2767c5 Fix endian check for little endian PowerPC and maybe others
This fixes various subtle breakage on ppc64le at very least.
2020-03-30 13:38:49 -05:00
Calvin Rose
279b536646 Prepare for 1.8.0 release. 2020-03-29 14:18:28 -05:00
Calvin Rose
ff163a5ae4 Use modulo instead of remainder for even?/odd?.
Works better for negative and fractional numbers.
2020-03-28 10:23:28 -05:00
Calvin Rose
65379741f7 Address edge case of reduce2 when ind is empty.
Same for accumulate 2.
2020-03-27 12:45:40 -05:00
Calvin Rose
3eb0927a2b Add accumulate(2) and reduce2
These functions are variations on reduce and can be quite useful.
Improve error message for jpm as well.
2020-03-26 21:35:11 -05:00
Calvin Rose
a3a45511e5 Remove lockfile.janet 2020-03-26 00:40:03 -05:00
Calvin Rose
a20ea702e2 Add infinite loop detection and complex deps.
We needed to handle dependencies that had both a url
and a tag component.
2020-03-26 00:34:34 -05:00
Calvin Rose
d2d0300c7e Remove use of cd in make-lockfile. 2020-03-26 00:12:18 -05:00
Calvin Rose
6e8aac984f Update CHANGELOG.md 2020-03-25 21:06:45 -05:00
Calvin Rose
6721c70b9e Fix typo in jpm. 2020-03-25 21:01:54 -05:00
Calvin Rose
b8c1c1c144 Get lockfile info from manifest, not cache.
Make manifest files track more information.
Use jdn to store manifest files, as well as repo url and
sha.
2020-03-25 20:58:53 -05:00
Calvin Rose
e380c01dd1 Add lockfiles to jpm.
Add make-lockfile and load-lockfile commands.
2020-03-25 19:44:30 -05:00
Calvin Rose
655633ef34 Tweak docstring. 2020-03-25 18:00:15 -05:00
Calvin Rose
3d1de237f6 Several changes to the os module.
- Add os/symlink
- Add os/realpath
2020-03-24 19:47:21 -05:00
Calvin Rose
6a63b13d69 Fix os/link docstring - Address #323 2020-03-21 16:18:58 -05:00
Calvin Rose
3aca5502dc Allow :dst to be nil to set tm_isdst to be -1. 2020-03-18 22:23:27 -05:00
16 changed files with 272 additions and 55 deletions

3
.gitignore vendored
View File

@@ -13,6 +13,9 @@ janet
janet-*.tar.gz janet-*.tar.gz
dist dist
# jpm lockfile
lockfile.janet
# Kakoune (fzf via fd) # Kakoune (fzf via fd)
.fdignore .fdignore

View File

@@ -1,7 +1,14 @@
# 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 ## 1.8.1 - 2020-03-31
- Fix bugs for big endian systems
- Fix 1.8.0 regression on BSDs
## 1.8.0 - 2020-03-29
- Add `reduce2`, `accumulate`, and `accumulate2`.
- Add lockfiles to `jpm` via `jpm make-lockfile` and `jpm load-lockfile`.
- Add `os/realpath` (Not supported on windows).
- Add `os/chmod`. - Add `os/chmod`.
- Add `chr` macro. - Add `chr` macro.
- Allow `_` in the `match` macro to match anything without creating a binding - Allow `_` in the `match` macro to match anything without creating a binding

View File

@@ -2,8 +2,8 @@
   
[![Appveyor Status](https://ci.appveyor.com/api/projects/status/bjraxrxexmt3sxyv/branch/master?svg=true)](https://ci.appveyor.com/project/bakpakin/janet/branch/master) [![Appveyor Status](https://ci.appveyor.com/api/projects/status/bjraxrxexmt3sxyv/branch/master?svg=true)](https://ci.appveyor.com/project/bakpakin/janet/branch/master)
[![Build Status](https://travis-ci.org/janet-lang/janet.svg?branch=master)](https://travis-ci.org/janet-lang/janet) [![Build Status](https://travis-ci.org/janet-lang/janet.svg?branch=master)](https://travis-ci.org/janet-lang/janet)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/.freebsd.yaml.svg)](https://builds.sr.ht/~bakpakin/janet/.freebsd.yaml?) [![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/freebsd.yml.svg)](https://builds.sr.ht/~bakpakin/janet/freebsd.yml?)
[![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/.openbsd.yaml.svg)](https://builds.sr.ht/~bakpakin/janet/.openbsd.yaml?) [![builds.sr.ht status](https://builds.sr.ht/~bakpakin/janet/openbsd.yml.svg)](https://builds.sr.ht/~bakpakin/janet/openbsd.yml?)
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left"> <img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">

View File

@@ -30,7 +30,7 @@ install:
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %platform% - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %platform%
- build_win test-install - build_win test-install
- set janet_outname=%appveyor_repo_tag_name% - set janet_outname=%appveyor_repo_tag_name%
- if "%janet_outname%"=="" set janet_outname=v1.7.1 - if "%janet_outname%"=="" set /P janet_outname=<build\version.txt
build: off build: off
artifacts: artifacts:
@@ -49,8 +49,7 @@ artifacts:
- name: "janet-$(janet_outname)-windows-%platform%" - name: "janet-$(janet_outname)-windows-%platform%"
path: dist path: dist
type: Zip type: Zip
- path: "janet-$(janet_outname)-windows-installer.exe" - path: "janet-$(janet_outname)-windows-%platform%-installer.exe"
name: "janet-$(janet_outname)-windows-%platform%-installer.exe"
type: File type: File
deploy: deploy:

View File

@@ -194,7 +194,8 @@
(loop [k :keys currenv :when (keyword? k)] (loop [k :keys currenv :when (keyword? k)]
(put env k (currenv k))) (put env k (currenv k)))
(dofile path :env env :exit true) (dofile path :env env :exit true)
(when-let [rules (env :rules)] (merge-into (getrules) rules))) (when-let [rules (env :rules)] (merge-into (getrules) rules))
env)
# #
# OS and shell helpers # OS and shell helpers
@@ -251,11 +252,7 @@
If we can't create it, give a friendly error. Return true if created, false if If we can't create it, give a friendly error. Return true if created, false if
existing. Throw an error if we can't create it." existing. Throw an error if we can't create it."
[dir] [dir]
(if (os/mkdir dir) (os/mkdir dir))
true
(if (os/stat dir :mode)
false
(error (string "Could not create " dir " - this could be a permission issue.")))))
# #
# C Compilation # C Compilation
@@ -554,6 +551,15 @@ int main(int argc, const char **argv) {
# Public utilities # Public utilities
# #
(defn parse
"Read a string of Janet source and parse out the first expression."
[src]
(let [p (parser/new)]
(:consume p src)
(if (= :error (:status p))
(error (string "Could not parse: " (parser/error p))))
(:produce p)))
(defn find-manifest-dir (defn find-manifest-dir
"Get the path to the directory containing manifests for installed "Get the path to the directory containing manifests for installed
packages." packages."
@@ -563,7 +569,7 @@ int main(int argc, const char **argv) {
(defn find-manifest (defn find-manifest
"Get the full path of a manifest file given a package name." "Get the full path of a manifest file given a package name."
[name] [name]
(string (find-manifest-dir) sep name ".txt")) (string (find-manifest-dir) sep name ".jdn"))
(defn find-cache (defn find-cache
"Return the path to the global cache." "Return the path to the global cache."
@@ -575,17 +581,14 @@ int main(int argc, const char **argv) {
"Uninstall bundle named name" "Uninstall bundle named name"
[name] [name]
(def manifest (find-manifest name)) (def manifest (find-manifest name))
(def f (file/open manifest :r)) (when-with [f (file/open manifest)]
(unless f (print manifest " does not exist") (break)) (def man (parse (:read f :all)))
(loop [line :iterate (:read f :line)] (each path (get man :paths [])
(def path ((string/split "\n" line) 0)) (print "removing " path)
(def path ((string/split "\r" path) 0)) (rm path))
(print "removing " path) (print "removing " manifest)
(rm path)) (rm manifest)
(:close f) (print "Uninstalled.")))
(print "removing " manifest)
(rm manifest)
(print "Uninstalled."))
(defn- rimraf (defn- rimraf
"Hard delete directory tree" "Hard delete directory tree"
@@ -607,7 +610,7 @@ int main(int argc, const char **argv) {
(defn install-git (defn install-git
"Install a bundle from git. If the bundle is already installed, the bundle "Install a bundle from git. If the bundle is already installed, the bundle
is reinistalled (but not rebuilt if artifacts are cached)." is reinistalled (but not rebuilt if artifacts are cached)."
[repotab &opt recurse] [repotab &opt recurse no-deps]
(def repo (if (string? repotab) repotab (repotab :repo))) (def repo (if (string? repotab) repotab (repotab :repo)))
(def tag (unless (string? repotab) (repotab :tag))) (def tag (unless (string? repotab) (repotab :tag)))
# prevent infinite recursion (very unlikely, but consider # prevent infinite recursion (very unlikely, but consider
@@ -652,7 +655,7 @@ int main(int argc, const char **argv) {
(os/execute ["git" "reset" "--hard" tag] :p)) (os/execute ["git" "reset" "--hard" tag] :p))
(os/execute ["git" "submodule" "update" "--init" "--recursive"] :p) (os/execute ["git" "submodule" "update" "--init" "--recursive"] :p)
(import-rules "./project.janet") (import-rules "./project.janet")
(do-rule "install-deps") (unless no-deps (do-rule "install-deps"))
(do-rule "build") (do-rule "build")
(do-rule "install")) (do-rule "install"))
([err] (print "Error building git repository dependency: " err))) ([err] (print "Error building git repository dependency: " err)))
@@ -669,6 +672,49 @@ int main(int argc, const char **argv) {
(mkdir destdir) (mkdir destdir)
(copy src destdir))) (copy src destdir)))
(defn- pslurp
"Like slurp, but with file/popen instead file/open. Also trims output"
[cmd]
(string/trim (with [f (file/popen cmd)] (:read f :all))))
(defn- make-lockfile
[&opt filename]
(default filename "lockfile.janet")
(def cwd (os/cwd))
(def packages @[])
# Read installed modules from manifests
(def mdir (find-manifest-dir))
(each man (os/dir mdir)
(def package (parse (slurp (string mdir sep man))))
(if (and (dictionary? package) (package :repo) (package :sha))
(array/push packages package)
(print "Cannot add local or malformed package " mdir sep man " to lockfile, skipping...")))
# Put in correct order, such that a package is preceded by all of its dependencies
(def ordered-packages @[])
(def resolved @{})
(while (< (length ordered-packages) (length packages))
(var made-progress false)
(each p packages
(def {:repo r :sha s :dependencies d} p)
(def dep-urls (map |(if (string? $) $ ($ :repo)) d))
(unless (resolved r)
(when (all resolved dep-urls)
(array/push ordered-packages p)
(set made-progress true)
(put resolved r true))))
(unless made-progress
(error (string/format "could not resolve package order for: %j"
(filter (complement resolved) (map |($ :repo) packages))))))
# Write to file
(with [f (file/open filename :w)] (with-dyns [:out f] (printf "%j" ordered-packages))))
(defn- load-lockfile
[&opt filename]
(default filename "lockfile.janet")
(def lockarray (parse (slurp filename)))
(each {:repo url :sha sha} lockarray
(install-git {:repo url :tag sha} nil true)))
# #
# Declaring Artifacts - used in project.janet, targets specifically # Declaring Artifacts - used in project.janet, targets specifically
# tailored for janet. # tailored for janet.
@@ -814,7 +860,15 @@ int main(int argc, const char **argv) {
(phony "manifest" [] (phony "manifest" []
(print "generating " manifest "...") (print "generating " manifest "...")
(mkdir manifests) (mkdir manifests)
(spit manifest (string (string/join installed-files "\n") "\n"))) (def sha (pslurp "git rev-parse HEAD"))
(def url (pslurp "git remote get-url origin"))
(def man
{:sha (if-not (empty? sha) sha)
:repo (if-not (empty? url) url)
:dependencies (array/slice (get meta :dependencies []))
:paths installed-files})
(spit manifest (string/format "%j\n" man)))
(phony "install" ["uninstall" "build" "manifest"] (phony "install" ["uninstall" "build" "manifest"]
(when (dyn :test) (when (dyn :test)
(do-rule "test")) (do-rule "test"))
@@ -888,6 +942,12 @@ Subcommands are:
rules : list rules available with run. rules : list rules available with run.
update-pkgs : Update the current package listing from the remote git repository selected. update-pkgs : Update the current package listing from the remote git repository selected.
quickbin entry executable : Create an executable from a janet script with a main function. quickbin entry executable : Create an executable from a janet script with a main function.
make-lockfile (lockfile) : Create a lockfile based on repositories in the cache. The
lockfile will record the exact versions of dependencies used to ensure a reproducible
build. Lockfiles are best used with applications, not libraries. The default lockfile
name is lockfile.janet.
load-lockfile (lockfile) : Install modules from a lockfile in a reproducible way. The
default lockfile name is lockfile.janet.
Keys are: Keys are:
--modpath : The directory to install modules to. Defaults to $JANET_MODPATH, $JANET_PATH, or (dyn :syspath) --modpath : The directory to install modules to. Defaults to $JANET_MODPATH, $JANET_PATH, or (dyn :syspath)
@@ -974,6 +1034,8 @@ Flags are:
"rules" list-rules "rules" list-rules
"update-pkgs" update-pkgs "update-pkgs" update-pkgs
"uninstall" uninstall-cmd "uninstall" uninstall-cmd
"make-lockfile" make-lockfile
"load-lockfile" load-lockfile
"quickbin" quickbin}) "quickbin" quickbin})
(def- args (tuple/slice (dyn :args) 1)) (def- args (tuple/slice (dyn :args) 1))

View File

@@ -131,7 +131,7 @@ exit /b 0
@rem Run the installer. (Installs to the local user with default settings) @rem Run the installer. (Installs to the local user with default settings)
:INSTALL :INSTALL
@echo Running Installer... @echo Running Installer...
FOR %%a in (janet-*-windows-installer.exe) DO ( FOR %%a in (janet-*-windows-*-installer.exe) DO (
%%a /S /CurrentUser %%a /S /CurrentUser
) )
exit /b 0 exit /b 0

View File

@@ -1,3 +1,6 @@
# This file is invoked by build_win.bat
# Relevant configuration variables are set there.
Unicode True Unicode True
!echo "Program Files: ${PROGRAMFILES}" !echo "Program Files: ${PROGRAMFILES}"
@@ -20,6 +23,9 @@ VIFileVersion "${PRODUCT_VERSION}"
!if ${SIXTYFOUR} == "true" !if ${SIXTYFOUR} == "true"
!define MULTIUSER_USE_PROGRAMFILES64 !define MULTIUSER_USE_PROGRAMFILES64
!define PLATNAME "x64"
!else
!define PLATNAME "x86"
!endif !endif
# Includes # Includes
@@ -36,12 +42,12 @@ Name "Janet"
!define DOLLAR "$" !define DOLLAR "$"
!ifdef CHECK_${DOLLAR}%APPVEYOR_REPO_TAG_NAME% !ifdef CHECK_${DOLLAR}%APPVEYOR_REPO_TAG_NAME%
# We are not in the appveyor environment, use version name # We are not in the appveyor environment, use version name
!define OUTNAME_PART v${VERSION} !define OUTNAME_PART ${VERSION}
!else !else
# We are in appveyor, use git tag name for installer # We are in appveyor, use git tag name for installer
!define OUTNAME_PART ${OUTNAME} !define OUTNAME_PART ${OUTNAME}
!endif !endif
OutFile "janet-${OUTNAME_PART}-windows-installer.exe" OutFile "janet-${OUTNAME_PART}-windows-${PLATNAME}-installer.exe"
# Some Configuration # Some Configuration
!define APPNAME "Janet" !define APPNAME "Janet"

View File

@@ -20,7 +20,7 @@
project('janet', 'c', project('janet', 'c',
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'], default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.7.1-dev') version : '1.8.1')
# 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')

View File

@@ -79,8 +79,8 @@
# Basic predicates # Basic predicates
(defn nan? "Check if x is NaN" [x] (not= x x)) (defn nan? "Check if x is NaN" [x] (not= x x))
(defn even? "Check if x is even." [x] (= 0 (% x 2))) (defn even? "Check if x is even." [x] (= 0 (mod x 2)))
(defn odd? "Check if x is odd." [x] (not= 0 (% x 2))) (defn odd? "Check if x is odd." [x] (= 1 (mod x 2)))
(defn zero? "Check if x is zero." [x] (= x 0)) (defn zero? "Check if x is zero." [x] (= x 0))
(defn pos? "Check if x is greater than 0." [x] (> x 0)) (defn pos? "Check if x is greater than 0." [x] (> x 0))
(defn neg? "Check if x is less than 0." [x] (< x 0)) (defn neg? "Check if x is less than 0." [x] (< x 0))
@@ -699,6 +699,45 @@
(each x ind (set res (f res x))) (each x ind (set res (f res x)))
res) res)
(defn reduce2
"The 2 argument version of reduce that does not take an initialization value.
Instead the first element of the array is used for initialization."
[f ind]
(var k (next ind))
(if (= nil k) (break nil))
(var res (in ind k))
(set k (next ind k))
(while (not= nil k)
(set res (f res (in ind k)))
(set k (next ind k)))
res)
(defn accumulate
"Similar to reduce, but accumulates intermediate values into an array.
The last element in the array is what would be the return value from reduce.
The init value is not added to the array.
Returns a new array."
[f init ind]
(var res init)
(def ret (array/new (length ind)))
(each x ind (array/push ret (set res (f res x))))
ret)
(defn accumulate2
"The 2 argument version of accumulate that does not take an initialization value."
[f ind]
(var k (next ind))
(def ret (array/new (length ind)))
(if (= nil k) (break ret))
(var res (in ind k))
(array/push ret res)
(set k (next ind k))
(while (not= nil k)
(set res (f res (in ind k)))
(array/push ret res)
(set k (next ind k)))
ret)
(defn map (defn map
"Map a function over every element in an indexed data structure and "Map a function over every element in an indexed data structure and
return an array of the results." return an array of the results."
@@ -2489,9 +2528,10 @@
# Create amalgamation # Create amalgamation
(def feature-header "src/core/features.h")
(def local-headers (def local-headers
["src/core/features.h" ["src/core/util.h"
"src/core/util.h"
"src/core/state.h" "src/core/state.h"
"src/core/gc.h" "src/core/gc.h"
"src/core/vector.h" "src/core/vector.h"
@@ -2545,21 +2585,23 @@
(print "/* Generated from janet version " janet/version "-" janet/build " */") (print "/* Generated from janet version " janet/version "-" janet/build " */")
(print "#define JANET_BUILD \"" janet/build "\"") (print "#define JANET_BUILD \"" janet/build "\"")
(print ```#define JANET_AMALG```) (print ```#define JANET_AMALG```)
(print ```#define _POSIX_C_SOURCE 200112L```)
(print ```#include "janet.h"```)
(defn do-one-flie (defn do-one-file
[fname] [fname]
(print "\n/* " fname " */") (print "\n/* " fname " */")
(print "#line 0 \"" fname "\"\n") (print "#line 0 \"" fname "\"\n")
(def source (slurp fname)) (def source (slurp fname))
(print (string/replace-all "\r" "" source))) (print (string/replace-all "\r" "" source)))
(do-one-file feature-header)
(print ```#include "janet.h"```)
(each h local-headers (each h local-headers
(do-one-flie h)) (do-one-file h))
(each s core-sources (each s core-sources
(do-one-flie s)) (do-one-file s))
# Create C source file that contains images a uint8_t buffer. This # Create C source file that contains images a uint8_t buffer. This
# can be compiled and linked statically into the main janet library # can be compiled and linked statically into the main janet library

View File

@@ -27,10 +27,10 @@
#define JANETCONF_H #define JANETCONF_H
#define JANET_VERSION_MAJOR 1 #define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 7 #define JANET_VERSION_MINOR 8
#define JANET_VERSION_PATCH 1 #define JANET_VERSION_PATCH 1
#define JANET_VERSION_EXTRA "-dev" #define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.7.1-dev" #define JANET_VERSION "1.8.1"
/* #define JANET_BUILD "local" */ /* #define JANET_BUILD "local" */

View File

@@ -29,4 +29,9 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#endif #endif
/* Needed for realpath on linux */
#if !defined(_XOPEN_SOURCE) && defined(__linux__)
#define _XOPEN_SOURCE 500
#endif
#endif #endif

View File

@@ -1141,7 +1141,7 @@ static const uint8_t *unmarshal_one(
u.bytes[0] = data[8]; u.bytes[0] = data[8];
u.bytes[1] = data[7]; u.bytes[1] = data[7];
u.bytes[2] = data[6]; u.bytes[2] = data[6];
u.bytes[5] = data[5]; u.bytes[3] = data[5];
u.bytes[4] = data[4]; u.bytes[4] = data[4];
u.bytes[5] = data[3]; u.bytes[5] = data[3];
u.bytes[6] = data[2]; u.bytes[6] = data[2];

View File

@@ -674,14 +674,20 @@ static Janet os_date(int32_t argc, Janet *argv) {
} }
static int entry_getdst(Janet env_entry) { static int entry_getdst(Janet env_entry) {
Janet v;
if (janet_checktype(env_entry, JANET_TABLE)) { if (janet_checktype(env_entry, JANET_TABLE)) {
JanetTable *entry = janet_unwrap_table(env_entry); JanetTable *entry = janet_unwrap_table(env_entry);
return janet_truthy(janet_table_get(entry, janet_ckeywordv("dst"))); v = janet_table_get(entry, janet_ckeywordv("dst"));
} else if (janet_checktype(env_entry, JANET_STRUCT)) { } else if (janet_checktype(env_entry, JANET_STRUCT)) {
const JanetKV *entry = janet_unwrap_struct(env_entry); const JanetKV *entry = janet_unwrap_struct(env_entry);
return janet_truthy(janet_struct_get(entry, janet_ckeywordv("dst"))); v = janet_struct_get(entry, janet_ckeywordv("dst"));
} else { } else {
return 0; v = janet_wrap_nil();
}
if (janet_checktype(v, JANET_NIL)) {
return -1;
} else {
return janet_truthy(v);
} }
} }
@@ -769,9 +775,25 @@ static Janet os_link(int32_t argc, Janet *argv) {
#else #else
const char *oldpath = janet_getcstring(argv, 0); const char *oldpath = janet_getcstring(argv, 0);
const char *newpath = janet_getcstring(argv, 1); const char *newpath = janet_getcstring(argv, 1);
int res = ((argc == 3 && janet_getboolean(argv, 2)) ? symlink : link)(oldpath, newpath); int res = ((argc == 3 && janet_truthy(argv[2])) ? symlink : link)(oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath); if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
return janet_wrap_integer(res); return janet_wrap_nil();
#endif
}
static Janet os_symlink(int32_t argc, Janet *argv) {
janet_fixarity(argc, 2);
#ifdef JANET_WINDOWS
(void) argc;
(void) argv;
janet_panic("os/symlink not supported on Windows");
return janet_wrap_nil();
#else
const char *oldpath = janet_getcstring(argv, 0);
const char *newpath = janet_getcstring(argv, 1);
int res = symlink(oldpath, newpath);
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
return janet_wrap_nil();
#endif #endif
} }
@@ -783,7 +805,9 @@ static Janet os_mkdir(int32_t argc, Janet *argv) {
#else #else
int res = mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH); int res = mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH);
#endif #endif
return janet_wrap_boolean(res != -1); if (res == 0) return janet_wrap_true();
if (errno == EEXIST) return janet_wrap_false();
janet_panicf("%s: %s", strerror(errno), path);
} }
static Janet os_rmdir(int32_t argc, Janet *argv) { static Janet os_rmdir(int32_t argc, Janet *argv) {
@@ -1152,6 +1176,21 @@ static Janet os_rename(int32_t argc, Janet *argv) {
return janet_wrap_nil(); return janet_wrap_nil();
} }
static Janet os_realpath(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
#ifdef JANET_WINDOWS
(void) argv;
janet_panic("os/realpath not supported on Windows");
#else
const char *src = janet_getcstring(argv, 0);
char *dest = realpath(src, NULL);
if (NULL == dest) janet_panicf("%s: %s", strerror(errno), src);
Janet ret = janet_cstringv(dest);
free(dest);
return ret;
#endif
}
#endif /* JANET_REDUCED_OS */ #endif /* JANET_REDUCED_OS */
static const JanetReg os_cfuns[] = { static const JanetReg os_cfuns[] = {
@@ -1250,7 +1289,8 @@ static const JanetReg os_cfuns[] = {
"os/mkdir", os_mkdir, "os/mkdir", os_mkdir,
JDOC("(os/mkdir path)\n\n" JDOC("(os/mkdir path)\n\n"
"Create a new directory. The path will be relative to the current directory if relative, otherwise " "Create a new directory. The path will be relative to the current directory if relative, otherwise "
"it will be an absolute path.") "it will be an absolute path. Returns true if the directory was create, false if the directoyr already exists, and "
"errors otherwise.")
}, },
{ {
"os/rmdir", os_rmdir, "os/rmdir", os_rmdir,
@@ -1265,8 +1305,13 @@ static const JanetReg os_cfuns[] = {
{ {
"os/link", os_link, "os/link", os_link,
JDOC("(os/link oldpath newpath &opt symlink)\n\n" JDOC("(os/link oldpath newpath &opt symlink)\n\n"
"Create a symlink from oldpath to newpath. The 3 optional paramater " "Create a symlink from oldpath to newpath, returning nil. The 3rd optional paramater "
"enables a hard link over a soft link. Does not work on Windows.") "enables a symlink iff truthy, hard link otherwise or if not provided. Does not work on Windows.")
},
{
"os/symlink", os_symlink,
JDOC("(os/symlink oldpath newpath)\n\n"
"Create a symlink from oldpath to newpath, returning nil. Same as (os/link oldpath newpath true).")
}, },
{ {
"os/readlink", os_readlink, "os/readlink", os_readlink,
@@ -1355,6 +1400,12 @@ static const JanetReg os_cfuns[] = {
JDOC("(os/rename oldname newname)\n\n" JDOC("(os/rename oldname newname)\n\n"
"Rename a file on disk to a new path. Returns nil.") "Rename a file on disk to a new path. Returns nil.")
}, },
{
"os/realpath", os_realpath,
JDOC("(os/realpath path)\n\n"
"Get the absolute path for a given path, following ../, ./, and symlinks. "
"Returns an absolute path as a string. Will raise an error on Windows.")
},
#endif #endif
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

View File

@@ -97,7 +97,14 @@ extern "C" {
#endif #endif
/* Check big endian */ /* Check big endian */
#if defined(__MIPSEB__) /* MIPS 32-bit */ \ #if defined(__LITTLE_ENDIAN__) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
/* If we know the target is LE, always use that - e.g. ppc64 little endian
* defines the __LITTLE_ENDIAN__ macro in the ABI spec, so we can rely
* on that and if that's not defined, fall back to big endian assumption
*/
#define JANET_LITTLE_ENDIAN 1
#elif defined(__MIPSEB__) /* MIPS 32-bit */ \
|| defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \ || defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \
|| defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \ || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \
|| defined(_M_PPC) || defined(__PPC) \ || defined(_M_PPC) || defined(__PPC) \
@@ -656,7 +663,7 @@ struct Janet {
#define janet_type(x) ((x).type) #define janet_type(x) ((x).type)
#define janet_checktype(x, t) ((x).type == (t)) #define janet_checktype(x, t) ((x).type == (t))
#define janet_truthy(x) \ #define janet_truthy(x) \
((x).type != JANET_NIL && ((x).type != JANET_BOOLEAN || ((x).as.integer & 0x1))) ((x).type != JANET_NIL && ((x).type != JANET_BOOLEAN || ((x).as.u64 & 0x1)))
#define janet_unwrap_struct(x) ((const JanetKV *)(x).as.pointer) #define janet_unwrap_struct(x) ((const JanetKV *)(x).as.pointer)
#define janet_unwrap_tuple(x) ((const Janet *)(x).as.pointer) #define janet_unwrap_tuple(x) ((const Janet *)(x).as.pointer)

View File

@@ -259,4 +259,26 @@
(assert (array= (array/slice @[1 2 3] 0 2) @[1 2]) "array/slice 1") (assert (array= (array/slice @[1 2 3] 0 2) @[1 2]) "array/slice 1")
(assert (array= (array/slice @[0 7 3 9 1 4] 2 -2) @[3 9 1]) "array/slice 2") (assert (array= (array/slice @[0 7 3 9 1 4] 2 -2) @[3 9 1]) "array/slice 2")
# Even and odd
(assert (odd? 9) "odd? 1")
(assert (odd? -9) "odd? 2")
(assert (not (odd? 10)) "odd? 3")
(assert (not (odd? 0)) "odd? 4")
(assert (not (odd? -10)) "odd? 5")
(assert (not (odd? 1.1)) "odd? 6")
(assert (not (odd? -0.1)) "odd? 7")
(assert (not (odd? -1.1)) "odd? 8")
(assert (not (odd? -1.6)) "odd? 9")
(assert (even? 10) "even? 1")
(assert (even? -10) "even? 2")
(assert (even? 0) "even? 3")
(assert (not (even? 9)) "even? 4")
(assert (not (even? -9)) "even? 5")
(assert (not (even? 0.1)) "even? 6")
(assert (not (even? -0.1)) "even? 7")
(assert (not (even? -10.1)) "even? 8")
(assert (not (even? -10.6)) "even? 9")
(end-suite) (end-suite)

View File

@@ -181,4 +181,17 @@
(def c (unmarshal (marshal b))) (def c (unmarshal (marshal b)))
(assert (= 2 (c 1)) "marshal-on-stack-closure 1")) (assert (= 2 (c 1)) "marshal-on-stack-closure 1"))
# Reduce2
(assert (= (reduce + 0 (range 1 10)) (reduce2 + (range 10))) "reduce2 1")
(assert (= (reduce * 1 (range 2 10)) (reduce2 * (range 1 10))) "reduce2 2")
(assert (= nil (reduce2 * [])) "reduce2 3")
# Accumulate
(assert (deep= (accumulate + 0 (range 5)) @[0 1 3 6 10]) "accumulate 1")
(assert (deep= (accumulate2 + (range 5)) @[0 1 3 6 10]) "accumulate2 1")
(assert (deep= @[] (accumulate2 + [])) "accumulate2 2")
(assert (deep= @[] (accumulate 0 + [])) "accumulate 2")
(end-suite) (end-suite)