>>1
So why would I want to use it? Tell me more-
>>2
Writing games for fantasy consoles like WASM-4
https://wasm4.org/blog/jam-2-results/#programming-language
I hate the wasm binary format. It's a bitch and a half to parse.
Is there a comptime lisp interperter in zig? I noticed that S-Expressions can
be embbeded in zig quite easly, for instance:
Scheme:
(define (power b e)
(define (recursive_step b e accum)
(cond
((= e 0) accum)
((even? e) (recursive_step (* b b) (/ e 2) accum ))
(else (recursive_step b (- e 1) (* accum b)))))
(recursive_step b e 1))
Zig:
.{ .define, .{ .power, .b, .e },
.{ .define, .{ .recursive_step, .b, .e, .accum },
.{ .cond,
.{ .{ .equals, .e, 0 }, .accum },
.{ .{ .isEven, .e }, .{ .recursive_step, .{ .mul, .b, .b }, .{ .div, .e, 2 }, .accum } },
.{ .Else, .{ .recursive_step, .b, .{ .sub, .e, 1 }, .{ .mul, .accum, .b } } },
},
},
.{ .recursive_step, .b, .e, 1 } };
With some minor alterations due to not beeing able to have .else and .= .+ and etc
>>5
But does this actually work? I don't know Zig well enough to judge whether this would type check (or... whatever) in the macro facility.
If you demonstrated a simple proof of concept that can evaluate arbitrary subexpressions in place of a word/atom, that would be a good starting point.
Zig has annonymous structs and "typeless" enum literals
Like .{ 1, 2, "hello world" } is a tuple,
it could have the type Tuple(.{ i32, i32, []const u8 }) for example
(the compiler will automatically infer it)
An expression like .word is an enum literal, it can be casted into an enum,
provided that enum has the field "word" defined.
Zig's comptime is dynamically typed and lazy (even tough the runtime
is static and strict) so you can manipulate arbitrarily complicated expressions like that.
>>6
Here I just cooked this up:
const std = @import("std");
pub fn Eval(comptime sexpr: anytype) type {
return switch (sexpr[0]) {
.add => u32,
.print => void,
else => @compileError("invalid opcode"),
};
}
pub fn eval(comptime sexpr: anytype) Eval(sexpr) {
switch (sexpr[0]) {
.add => {
var ret: u32 = 0;
inline for (1..sexpr.len) |i| {
ret += sexpr[i];
}
return ret;
},
.print => {
inline for (1..sexpr.len) |i| {
std.debug.print("-> {any}\n", .{sexpr[i]});
}
},
else => @compileError("invalid opcode"),
}
}
test {
std.debug.print("{d}\n", .{eval(.{ .add, 1, 2, 3 })});
eval(.{ .print, .lol, 777, "hello world" });
}
>>7,8
That raises further questions. How can the evaluator handle words (like variable names) it hasn't seen before?
Also it sounds like evaluating arguments and passing them to a function just won't work.
>>9
You only need to handle a small set of keywords to introduce the fundamental
primitives of the language, this is a finite set that you cal manually
implement on eval()
If you want to introduce new symbols you do the same thing you do in a normal
interperter, by introducing a mutable symbol table and adding symbols as
they are defined.
the else => branch above would search this table for the symbol and it would
evaluate it.
Also it sounds like evaluating arguments and passing them to a function just won't work.
If you can guarantee the result has a fixed type, you can pass the evaluation
result to a normal function, I did that in first print statement where it
expected an integer
Also it sounds like evaluating arguments and passing them to a function just won't work.
nevermind I didnt get what you were saying.
Once you have the aforementioned tables, you can implement functions calls
as youl would on a normal interperter, by simply binding the argument symbols
to the arguments and evaling the body of the function
I want to try and make one, but im busy right now :///
Actually now that I think of it, it would be quite hard to make a mutable
table data structure that can hold objects of different types,
(it is required, since the SExpressions all have different types in
this representation)
Actually#2 now that I think about it, one could define a function that
preprocesses the tuple into something that has the type:
const SExpr : type = struct {
symbol : Symbol,
pair : struct {
left : *SExpr,
right : *SExpr,
},
nil : void,
// etc etc
};
(Where symbol could be an integer hash of the tag names)
Once you have this, It should not be hard to make an interperter
Additionally, if we really wanted a the previous representation,
we could make a function that converts a comptime known SExpr back
into nested tuples like before
>>3,4
I boycott WebAssembly.
In Mozilla Firefox:
* Go to about:config
.
* Set javascript.options.wasm
to false
.
* Enjoy a beautiful world free from WebAssembly.
>>15
You are the Gandhi of the internet, a silent hero leading a revolution. The People will not lie down like dogs and give up their Java Scripts. Not on your watch. The Illuminati have to be peeing and pooping their pants right now.
Why code in Python+C if you can code in Lisp+Zig?
https://icfp23.sigplan.org/details/declmed-2023-papers/5/Why-code-in-Python-C-if-you-can-code-in-Lisp-Zig
>>17
Very nice.
GCC/Clang is deprecated
https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html
llvm
eh thanks but no
>>20
What's so bad about LLVM?
>>21
Well, first of all, it's huge and slow, even when performing minimal optimization. For anything but release builds, you could make a much better tradeoff between compile times and execution speed.
Furthermore, it's deeply wedded to the C/C++ memory model, because it was literally designed for that from the ground up. Yes, I said C/C++. This is the one topic where it's both correct and appropriate. That means almost every form of undefined behavior present in C or C++ also infects LLVM IR, and by extension, any language you compile via LLVM. Some of these are hard to catch in the front end.
There is plenty of room in the world for a simpler, smaller, faster backend, and some languages really need it. QBE tried and I don't think it's succeeded. Maybe Cranelift will get there. I'm not hedging my bets though.
>>22
Good point. LLVM is a behemoth.
Looks like Java
>>24
good morning sirs!
No.
All these languages look the same, c, go, java, just a different dialect of the programming equivalent of ebonics
Java is kinda nice these days.
I haven't touched languages without automatic memory management since university. Zig and its built in GeneralPurposeAllocator + ArenaAllocator cured my fear of memory management. Stuff like cache line optimization still fly over my head but at least I got a start.