Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,8 @@ Comments can be added with `//`. When a comment character is reached, the interp
- `neq arg1 arg2 ...` - Opposite of eq.
- `not arg` - Reverses a boolean value.
- `or arg1 arg2 ...` - Returns true if any of the args are true, false otherwise.
- `and arg1 arg2 ...` - Returns true if all of the args are true, false otherwise.
- `and arg1 arg2 ...` - Returns true if all of the args are true, false otherwise.
- `< arg1 arg2` - returns whether the first value is less than the second.
- `<= arg1 arg2` - returns whether the first value is less than or equal to the second.
- `> arg1 arg2` - returns whether the first value is greater than the second.
- `>= arg1 arg2` - returns whether the first value is greater than or equal to the second.
10 changes: 4 additions & 6 deletions examples/fibonacci.zisp
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// not doable yet with current std
(var "cache" (createTable))
(def fibonacci (n) (
(if (or (eq n 0) (eq n 1)) (
(return n)
(if (<= n 1) (
return n
))

(if (has cache n) (
(return (kget cache n))
return (kget cache n)
))

(var "v" (- (fibonacci (- n 1)) (fibonacci (- n 2))))

(var "v" (+ (fibonacci (- n 1)) (fibonacci (- n 2))))
(put cache n v)

(return v)
Expand Down
5 changes: 5 additions & 0 deletions examples/return.zisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(def test () (
return "hi"
))

(println (test))
71 changes: 68 additions & 3 deletions src/eval.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@ const String = @import("string").String;
const internal_std = @import("std/root.zig");

pub fn evaluate(allocator: std.mem.Allocator, ast: std.ArrayList(model.TokenTree), runtime: *Runtime) !?model.Atom {
if(runtime.env.has_returned()) {
return runtime.env.get_current_return();
}

if (ast.items.len == 1) {
return switch (ast.items[0]) {
.constant => |constant| constant,
.context => |context| evaluate(allocator, context, runtime),
.ident => |ident| runtime.run_function(allocator, ident.str(), &[_]*model.Atom{}),
.ident => |ident| {
if(std.mem.eql(u8, ident.str(), "return")) {
// no-value return
runtime.env.return_current(null);
return null;
}

return runtime.run_function(allocator, ident.str(), &[_]*model.Atom{});
},
.list_init => |items| {
var contents = std.ArrayList(model.Atom).init(allocator);

Expand All @@ -35,6 +47,37 @@ pub fn evaluate(allocator: std.mem.Allocator, ast: std.ArrayList(model.TokenTree

return switch (ast.items[0]) {
.ident => |ident| {
if(std.mem.eql(u8, ident.str(), "return")) {
if(ast.items.len == 2) {
return switch(ast.items[1]) {
.constant => |constant| {
runtime.env.return_current(constant);
return constant;
},
.context => |context| {
const atom = try evaluate(allocator, context, runtime);
runtime.env.return_current(atom);
return atom;
},
.ident => |ident2| {
const atom = (try runtime.env.fetch_variable(ident2.str())).?.*;
runtime.env.return_current(atom);
return atom;
},
.list_init => {
var list = std.ArrayList(model.TokenTree).init(allocator);
defer list.deinit();
try list.append(ast.items[1]);

const list2 = try evaluate(allocator, list, runtime);
runtime.env.return_current(list2);

return list2;
},
};
}
}

if (std.mem.eql(u8, ident.str(), "if")) {
// if cond (true) (false)
const cond = switch (ast.items[1]) {
Expand Down Expand Up @@ -115,6 +158,7 @@ pub fn evaluate(allocator: std.mem.Allocator, ast: std.ArrayList(model.TokenTree

// TODO evaluation could be null, need an actual error handling
.context => |context| {
// runtime.env.print_stacktrace();
var result = (try evaluate(allocator, context, runtime)).?;

try args.append(&result);
Expand Down Expand Up @@ -144,6 +188,10 @@ pub fn evaluate(allocator: std.mem.Allocator, ast: std.ArrayList(model.TokenTree
_ = try evaluate(allocator, context, runtime);

for (ast.items[1..]) |tree| {
if(runtime.env.has_returned()) {
return runtime.env.get_current_return();
}

switch (tree) {
.context => |context2| _ = try evaluate(allocator, context2, runtime),
.constant => return error.CannotCallValue,
Expand All @@ -156,7 +204,7 @@ pub fn evaluate(allocator: std.mem.Allocator, ast: std.ArrayList(model.TokenTree
}
}

return null;
return runtime.env.get_current_return();
},
.list_init => return error.CannotCallValue,
};
Expand Down Expand Up @@ -208,6 +256,7 @@ pub const Runtime = struct {
const val = try self.env.fetch_variable(ident);

if (val == null) {
std.debug.print("Identifier: {s}\n", .{ident});
return error.IdentDoesNotExist;
}

Expand Down Expand Up @@ -259,7 +308,7 @@ pub const Environment = struct {
}

pub fn enter_new_frame(self: *Self, functionName: []const u8, allocator: std.mem.Allocator) !void {
try self.stack.append(StackFrame{ .name = functionName, .locals = std.StringHashMap(model.Atom).init(allocator) });
try self.stack.append(StackFrame{ .name = functionName, .locals = std.StringHashMap(model.Atom).init(allocator), .return_value = null, .has_returned = false });
}

pub fn exit_frame(self: *Self) void {
Expand Down Expand Up @@ -314,13 +363,29 @@ pub const Environment = struct {
},
});
}

pub fn return_current(self: *Self, val: ?model.Atom) void {
var frame = self.current_stack_frame();
frame.return_value = val;
frame.has_returned = true;
}

pub fn get_current_return(self: *Self) ?model.Atom {
return self.current_stack_frame().return_value;
}

pub fn has_returned(self: *Self) bool {
return self.current_stack_frame().has_returned;
}
};

pub const StackFrame = struct {
const Self = @This();

locals: std.StringHashMap(model.Atom),
name: []const u8,
return_value: ?model.Atom,
has_returned: bool,

pub fn deinit(self: *Self) void {
//self.name.deinit();
Expand Down
60 changes: 60 additions & 0 deletions src/std/conditional.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub fn setup(env: *eval.Environment) !void {
try env.register_internal_function("not", internal_not);
try env.register_internal_function("or", internal_or);
try env.register_internal_function("and", internal_and);
try env.register_internal_function("<", internal_lessthan);
try env.register_internal_function("<=", internal_lessthaneq);
try env.register_internal_function(">", internal_greaterthan);
try env.register_internal_function(">=", internal_greaterthaneq);
}

pub fn internal_eq(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom {
Expand Down Expand Up @@ -77,3 +81,59 @@ pub fn internal_and(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom

return model.Atom{ .bool = true };
}

pub fn internal_lessthan(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom {
if(args.len != 2) {
return error.InvalidArgCount;
}

return switch(args[0].*) {
.int => |a| switch(args[1].*) {
.int => |b| model.Atom { .bool = a < b },
else => error.TypeMismatch,
},
else => error.TypeMismatch,
};
}

pub fn internal_lessthaneq(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom {
if(args.len != 2) {
return error.InvalidArgCount;
}

return switch(args[0].*) {
.int => |a| switch(args[1].*) {
.int => |b| model.Atom { .bool = a <= b },
else => error.TypeMismatch,
},
else => error.TypeMismatch,
};
}

pub fn internal_greaterthan(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom {
if(args.len != 2) {
return error.InvalidArgCount;
}

return switch (args[0].*) {
.int => |a| switch (args[1].*) {
.int => |b| model.Atom { .bool = a > b },
else => error.TypeMismatch,
},
else => error.TypeMismatch,
};
}

pub fn internal_greaterthaneq(_: Allocator, args: []*model.Atom, _: *Runtime) !?model.Atom {
if(args.len != 2) {
return error.InvalidArgCount;
}

return switch (args[0].*) {
.int => |a| switch(args[1].*) {
.int => |b| model.Atom { .bool = a >= b },
else => error.TypeMismatch,
},
else => error.TypeMismatch,
};
}