Skip to content

Commit

Permalink
Add clNewChoice.
Browse files Browse the repository at this point in the history
  • Loading branch information
fubark committed Sep 2, 2024
1 parent d5f4e68 commit a90159d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/capi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ pub const ZVM = struct {
return c.clNewInstance(@ptrCast(self), type_id, fields.ptr, fields.len);
}

pub fn newChoice(self: *ZVM, choice_t: Type, name: []const u8, val: Value) Value {
return c.clNewChoice(@ptrCast(self), choice_t, toStr(name), val);
}

pub fn findType(self: *ZVM, path: []const u8) Type {
return c.clFindType(@ptrCast(self), toStr(path));
}
Expand Down
3 changes: 3 additions & 0 deletions src/include/cyber.h
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,9 @@ void* clNewHostObjectPtr(CLVM* vm, CLType typeId, size_t n);
// Returns a new instance of `type` with a list of field initializers.
CLValue clNewInstance(CLVM* vm, CLType type, const CLFieldInit* fields, size_t nfields);

// Returns a new choice of a given case name and value.
CLValue clNewChoice(CLVM* vm, CLType choice_t, CLStr name, CLValue val);

// Returns the type of boxed value.
CLType clGetType(CLValue val);

Expand Down
36 changes: 36 additions & 0 deletions src/lib.zig
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,42 @@ test "clNewInstance()" {
try t.eqStr(c.asString(vm.getField(val, "b")), "abc");
}

export fn clNewChoice(vm: *cy.VM, choice_t: cy.TypeId, name: c.Str, val: cy.Value) cy.Value {
const type_e = vm.c.types[choice_t];
if (type_e.kind != .choice) {
return cy.panicFmt("Expected choice type. Found `{}`.", .{type_e.kind});
}

const zname = c.fromStr(name);
const sym = type_e.sym.getMod().?.getSym(zname) orelse {
return cy.panicFmt("Can not find case `{s}`.", .{zname});
};
if (sym.type != .enumMember) {
return cy.panicFmt("`{s}` is not choice case.", .{zname});
}
const case = sym.cast(.enumMember);
return cy.heap.allocObjectSmall(vm, choice_t, &.{
@bitCast(c.int(@intCast(case.val))),
val,
}) catch cy.fatal();
}

test "clNewChoice()" {
const vm = c.create();
defer vm.destroy();

var res: c.Value = undefined;
vm.evalMust(
\\type Foo enum:
\\ case a int
\\ case b String
, &res);
const foo_t = vm.findType("Foo");
const val = vm.newChoice(foo_t, "a", c.int(123));
try t.eq(c.getType(val), foo_t);
try t.eq(vm.unwrapChoice(val, "a"), 123);
}

export fn clSymbol(vm: *cy.VM, str: c.Str) Value {
const id = vm.ensureSymbolExt(c.fromStr(str), true) catch fatal();
return Value.initSymbol(@intCast(id));
Expand Down

0 comments on commit a90159d

Please sign in to comment.