~bakpakin/janet

80e7fdb99340a9044e566522bdc52145f79d653c — Calvin Rose 1 year, 3 months ago c0f5f97 + 658941d zevv-tests
Merge branch 'master' into zevv-tests
3 files changed, 125 insertions(+), 32 deletions(-)

M README.md
M meson.build
M src/boot/boot.janet
M README.md => README.md +94 -17
@@ 6,10 6,8 @@

<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">

**Janet** is a functional and imperative programming language and bytecode interpreter. It is a
Lisp-like language, but lists are replaced
by other data structures (arrays, tables (hash table), struct (immutable hash table), tuples).
The language also supports bridging to native code written in C, meta-programming with macros, and bytecode assembly.
**Janet** is a dynamic language and bytecode interpreter for system scripting, expressive automation, and
extending programs written in C or C++ with user scripting capabilities.

There is a REPL for trying out the language, as well as the ability
to run script files. This client program is separate from the core runtime, so


@@ 21,14 19,104 @@ If you'd like to financially support the ongoing development of Janet, consider

<br>

## Examples

See the examples directory for all provided example programs.

### Game of Life

```janet
# John Conway's Game of Life

(def- window
  (seq [x :range [-1 2]
         y :range [-1 2]
         :when (not (and (zero? x) (zero? y)))]
       [x y]))

(defn- neighbors
  [[x y]]
  (map (fn [[x1 y1]] [(+ x x1) (+ y y1)]) window))

(defn tick
  "Get the next state in the Game Of Life."
  [state]
  (def cell-set (frequencies state))
  (def neighbor-set (frequencies (mapcat neighbors state)))
  (seq [coord :keys neighbor-set
         :let [count (get neighbor-set coord)]
         :when (or (= count 3) (and (get cell-set coord) (= count 2)))]
      coord))

(defn draw
  "Draw cells in the game of life from (x1, y1) to (x2, y2)"
  [state x1 y1 x2 y2]
  (def cellset @{})
  (each cell state (put cellset cell true))
  (loop [x :range [x1 (+ 1 x2)]
         :after (print)
         y :range [y1 (+ 1 y2)]]
    (file/write stdout (if (get cellset [x y]) "X " ". ")))
  (print))

# Print the first 20 generations of a glider
(var *state* '[(0 0) (-1 0) (1 0) (1 1) (0 2)])
(for i 0 20
  (print "generation " i)
  (draw *state* -7 -7 7 7)
  (set *state* (tick *state*)))
```

### TCP Echo Server

```janet
# A simple TCP echo server using the built-in socket networking and event loop.

(defn handler
  "Simple handler for connections."
  [stream]
  (defer (:close stream)
    (def id (gensym))
    (def b @"")
    (print "Connection " id "!")
    (while (:read stream 1024 b)
      (printf " %v -> %v" id b)
      (:write stream b)
      (buffer/clear b))
    (printf "Done %v!" id)
    (ev/sleep 0.5)))

(net/server "127.0.0.1" "8000" handler)
```

### Windows FFI Hello, World!

```janet
# Use the FFI to popup a Windows message box - no C required

(ffi/context "user32.dll")

(ffi/defbind MessageBoxA :int
  [w :ptr text :string cap :string typ :int])

(MessageBoxA nil "Hello, World!" "Test" 0)
```

## Use Cases

Janet makes a good system scripting language, or a language to embed in other programs.
It's like Lua and Guile in that regard. It has more built-in functionality and a richer core language than
Lua, but smaller than GNU Guile or Python.
Lua, but smaller than GNU Guile or Python. However, it is much easier to embed and port than these languages.

## Features

* 600+ functions and macros in the core library
* Build in socket networking, threading, subprocesses, and more.
* Parsing Expression Grammars (PEG) engine as a more robust Regex alternative
* Macros
* Per-thread event loop for efficient IO (epoll/IOCP/kqueue)
* Built-in C FFI lets you load existing binaries and run them.
* Erlang-style supervision trees that integrate with the event loop
* Configurable at build time - turn features on or off for a smaller or more featureful build
* Minimal setup - one binary and you are good to go!
* First-class closures


@@ 38,19 126,12 @@ Lua, but smaller than GNU Guile or Python.
* Mutable and immutable arrays (array/tuple)
* Mutable and immutable hashtables (table/struct)
* Mutable and immutable strings (buffer/string)
* Macros
* Multithreading
* Per-thread event loop for efficient evented IO
* Bytecode interpreter with an assembly interface, as well as bytecode verification
* Tail-call optimization
* Direct interop with C via abstract types and C functions
* Interface with C via abstract types and C functions
* Dynamically load C libraries
* Functional and imperative standard library
* Lexical scoping
* Imperative programming as well as functional
* REPL
* Parsing Expression Grammars built into the core library
* 400+ functions and macros in the core library
* Embedding Janet in other programs
* Interactive environment with detailed stack traces



@@ 240,10 321,6 @@ there is no need for dynamic modules, add the define

See the [Embedding Section](https://janet-lang.org/capi/embedding.html) on the website for more information.

## Examples

See the examples directory for some example Janet code.

## Discussion

Feel free to ask questions and join the discussion on the [Janet Gitter channel](https://gitter.im/janet-language/community).

M meson.build => meson.build +28 -15
@@ 227,21 227,34 @@ docs = custom_target('docs',

# Tests
test_files = [
  'test/suite0000.janet',
  'test/suite0001.janet',
  'test/suite0002.janet',
  'test/suite0003.janet',
  'test/suite0004.janet',
  'test/suite0005.janet',
  'test/suite0006.janet',
  'test/suite0007.janet',
  'test/suite0008.janet',
  'test/suite0009.janet',
  'test/suite0010.janet',
  'test/suite0011.janet',
  'test/suite0012.janet',
  'test/suite0013.janet',
  'test/suite0014.janet'
  'test/suite-array.janet',
  'test/suite-asm.janet',
  'test/suite-boot.janet',
  'test/suite-buffer.janet',
  'test/suite-capi.janet',
  'test/suite-cfuns.janet',
  'test/suite-compile.janet',
  'test/suite-corelib.janet',
  'test/suite-debug.janet',
  'test/suite-ev.janet',
  'test/suite-ffi.janet',
  'test/suite-inttypes.janet',
  'test/suite-io.janet',
  'test/suite-marsh.janet',
  'test/suite-math.janet',
  'test/suite-os.janet',
  'test/suite-parse.janet',
  'test/suite-peg.janet',
  'test/suite-pp.janet',
  'test/suite-specials.janet',
  'test/suite-string.janet',
  'test/suite-strtod.janet',
  'test/suite-struct.janet',
  'test/suite-symcache.janet',
  'test/suite-table.janet',
  'test/suite-unknown.janet',
  'test/suite-value.janet',
  'test/suite-vm.janet'
]
foreach t : test_files
  test(t, janet_nativeclient, args : files([t]), workdir : meson.current_source_dir())

M src/boot/boot.janet => src/boot/boot.janet +3 -0
@@ 3881,6 3881,9 @@
(defdyn *profilepath*
  "Path to profile file loaded when starting up the repl.")

(compwhen (not (dyn 'os/isatty))
  (defmacro os/isatty [&] true))

(defn cli-main
  `Entrance for the Janet CLI tool. Call this function with the command line
  arguments as an array or tuple of strings to invoke the CLI interface.`