Coder Social home page Coder Social logo

jzignet's Introduction

Jzignet

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:

  • Embed Janet programs into Zig
  • Write Janet modules in Zig
  • Write bindings in Zig for a C library to be used as a Janet module

Why use these bindings, besides obvious reasons such as connecting together two wonderful languages:

  • You don't need to care about conversion between Zig and C. But you have full access to C internals if you need to.
  • Plenty of tests which are great examples and guarantee minimal regressions when updating.
  • Idiomatic Zig code - everything is typed, names are properly cased, operations on types use methods instead of prefixed global functions.

Currently supported versions:

  • Zig 0.11.0
  • Janet 1.31.0

Repository is available at sourcehut and at GitHub.

How to use

If you want to just start using it, jump to the examples. Copy them or look at the source code, it is heavily commented.

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.

How to include as a dependency (with zon)

  1. Create a file named build.zig.zon with the following content.
.{
    .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",
        },
    },
}
  1. Add this to 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"));
  1. Use in your Zig code
const jzignet = @import("jzignet");

How to include as a dependency (with git submodule)

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.

  1. Include git submodule into your library, assuming further that libpath is the directory where this library is installed
git submodule add https://github.com/greenfork/jzignet libpath
  1. Include the library in 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"));
  1. Use in your Zig code
const jzignet = @import("jzignet");

Differences with C API

Naming

  • janet_ prefix is mostly not present.
  • Every type is a Zig struct and corresponding functions are called as methods, for example, janet_table_get(table, key) becomes table.get(key).
  • All bindings have idiomatic Zig naming even when Janet uses different ones, for example arity and fixarity are arity and fixArity in Zig.
  • Functions like janet_table are available as Table.init, please consult the source code for that.

Semantics

  • 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.

Completeness

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'n'A

Q: What's with the name?

A: "janet".replace("a", "zig")

Q: I hate that name.

A: Yes, I know.

License

MIT, see LICENSE file.

jzignet's People

Contributors

greenfork avatar iacore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

jzignet's Issues

(sh/exec-slurp) returns nil

I don't understand why this is happening.

here's the program. res is Janet nil.

const std = @import("std");
const janet = @import("janet");

pub fn main() !void {
    try janet.init();
    const env = janet.Environment.coreEnv(null);
    // var env_ = janet.Table.initDynamic(0);
    // env_.proto = core_env.toTable();
    // const env = env_.toEnvironment();
    // janet.gcRoot(env_.wrap()); // this doesn't fix the problem either

    _ = try env.doString("(import spork/sh)", "embed");
    _ = try env.doString(
        \\(pp (sh/exec-slurp "uname"))
    , "embed");
    const res = try env.doString(
        \\(sh/exec-slurp "uname")
    , "embed");
    _ = res;
    @breakpoint();
}

To reproduce this problem:

First clone the repo

git clone https://github.com/iacore/janet-graphical-repl  -b f3ceb4e

here's what I see

user@x17 ~/c/g/janet-graphical-repl (debug)
❯ zig build
user@x17 ~/c/g/janet-graphical-repl (debug)
❯ lldb zig-out/bin/janet-dvui
(lldb) target create "zig-out/bin/janet-dvui"
Current executable set to '/home/user/computing/gui/janet-graphical-repl/zig-out/bin/janet-dvui' (x86_64).
(lldb) r
Process 26114 launched: '/home/user/computing/gui/janet-graphical-repl/zig-out/bin/janet-dvui' (x86_64)
Process 26114 stopped and restarted: thread 1 received signal: SIGCHLD
"Linux"
Process 26114 stopped and restarted: thread 1 received signal: SIGCHLD
Process 26114 stopped
* thread #1, name = 'janet-dvui', stop reason = signal SIGTRAP
    frame #0: 0x000000000027d70e janet-dvui`main.main at main.zig:20:5
   17  	       \\(sh/exec-slurp "uname")
   18  	   , "embed");
   19  	   _ = res;
-> 20  	   @breakpoint();
   21  	}
(lldb) p res
(janet.Janet__union_5967) $0 = (u64 = 18444633011384221697, i64 = -2111062325329919, number = NaN, pointer = 0xfff8800000000001)
(lldb) 

0xfff8800000000001 is nil

If you don't believe me you can replace the line \\(sh/exec-slurp "uname") with \\nil.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.