greenfork/jzignet
Zig library to connect Janet and Zig together
Zig is a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
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.
Jzignet - Zig library to connect Janet and Zig together.
You can:
Why use these bindings, besides obvious reasons such as connecting together two wonderful languages:
Currently supported versions:
Repository is available at sourcehut and at GitHub.
If you want to just start using it, jump to the examples. Copy them or look at the source code, it is heavily commented.
zig build run-embed_janet
.WARNING: examples are currently not working:
Write bindings in Zig for a C library to be used as a Janet module - this is very close to "Write Janet module in Zig" example, you just need to know how to wrap a C library in Zig, this repository is a perfect example for this.
build.zig.zon
with the following content. Put the
correct version for tar archive, and change the .hash
value when you get
and error..{
.name = "janet-zig-test",
.version = "0.0.1",
.dependencies = .{
.jzignet = .{
.url = "https://git.sr.ht/~greenfork/jzignet/archive/0.7.2.tar.gz",
.hash = "122087fa45b016bd8ce5fbadd17ef2bd84cd1389119edd3c345486870032ea2b7217",
},
},
}
build.zig
. const jzignet = b.dependency("jzignet", .{ .target=target, .optimize=optimize });
// your executable defined here
// const exe = ...;
exe.addModule("jzignet", jzignet.module("jzignet"));
exe.linkLibrary(jzignet.artifact("jzignet"));
const jzignet = @import("jzignet");
Currently you can include jzignet as a git submodule. Janet is bundled as a single C source amalgamation file and is compiled directly into this library.
libpath
is
the directory where this library is installedgit submodule add https://github.com/greenfork/jzignet libpath
build.zig
const jzignet = b.anonymousDependency("lib/jzignet", @import("lib/jzignet/build.zig"), .{});
// your executable defined here
// const exe = ...;
exe.addModule("jzignet", jzignet.module("jzignet"));
exe.linkLibrary(jzignet.artifact("jzignet"));
const jzignet = @import("jzignet");
janet_
prefix is mostly not present.janet_table_get(table, key)
becomes table.get(key)
.arity
and fixarity
are arity
and fixArity
in Zig.janet_table
are available as Table.init
, please consult
the source code for that.Function return types return error sets as well as optional values where it
makes sense to do so, for example, table.get
returns ?Janet
and pcall
returns Signal.Error!void
.
All types are wrapped into structs. Most of the types support this natively
since they are structs in C too, others (Tuple, Struct, String, Keyword,
Symbol) cannot be represented as structs directly and they are wrappers
with a ptr
or slice
field containing the original value.
All functions that have a type at the end, for example, janet_get_number
,
instead use this signature: get(comptime T: type, ...)
. Currently these
functions exist: get
, opt
, wrap
, Janet.unwrap
.
When you need to supply a pointer to the array and a length in the C version, in Zig version you need to supply just a slice since it has both the pointer and the length, so it's one parameter instead of two. For example,
int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);
becomes
pub fn doBytes(env: *Environment, bytes: []const u8, source_path: [:0]const u8) !Janet
Abstracts are fully typed, no *void pointers to @ptrCast. Take a look at tests for examples with abstracts, they are generally reworked to make them easier to use.
All functions returning Signal
instead return void
on OK
and return
error otherwise with the specified signal, signature is Signal.Error!void
.
doString
and doBytes
are aliases and return !Janet
directly instead of
accepting a reference for the return value.
string
, keyword
, symbol
, nil
top-level functions are the only ones to
create these types and they do what you want.
Environment
type introduced which is internally a Table
but allows
conceptually different operations such as defining values and executing code.
Bindings are not complete 100% but all the generally useful things are there. If you need any specific part of the API, feel free to contribute or just ask (and you shall receive).
Q: What's with the name?
A: "janet".replace("a", "zig")
Q: I hate that name.
A: Yes, I know.
MIT, see LICENSE file.