Skip to content

Commit

Permalink
Made errors independent of error sets (#332)
Browse files Browse the repository at this point in the history
  • Loading branch information
chung-leong committed Apr 8, 2024
1 parent 45f75d4 commit 78b34c7
Show file tree
Hide file tree
Showing 22 changed files with 352 additions and 487 deletions.
9 changes: 4 additions & 5 deletions zigar-compiler/test/code-generator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ describe('Code generation', function() {
instance: {
members: [
{
type: MemberType.EnumerationItem,
type: MemberType.Uint,
bitOffset: 0,
bitSize: 16,
byteSize: 2,
Expand All @@ -327,8 +327,7 @@ describe('Code generation', function() {
};
const def = { structures: [ enumSetStructure, structure ], options, keys: { MEMORY, SLOTS, CONST }};
const { code } = generateCode(def, params);
expect(code).to.contain('useEnumerationItem()');
expect(code).to.contain('enumItem');
expect(code).to.contain('useEnumeration()');
expect(code).to.contain('enum {}');
})
it('should generate code for defining a non-standard enum type', function() {
Expand Down Expand Up @@ -367,7 +366,7 @@ describe('Code generation', function() {
instance: {
members: [
{
type: MemberType.EnumerationItem,
type: MemberType.Uint,
bitOffset: 3,
bitSize: 16,
structure: enumSetStructure,
Expand All @@ -384,7 +383,7 @@ describe('Code generation', function() {
};
const def = { structures: [ enumSetStructure, structure ], options, keys: { MEMORY, SLOTS, CONST }};
const { code } = generateCode(def, params);
expect(code).to.contain('useEnumerationItem()');
expect(code).to.contain('useUint()');
expect(code).to.contain('enumItem');
expect(code).to.contain('enum {}');
})
Expand Down
50 changes: 6 additions & 44 deletions zigar-compiler/zig/exporter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ pub const MemberType = enum(u32) {
int,
uint,
float,
enumeration_item,
@"error",
object,
type,
@"comptime",
Expand Down Expand Up @@ -349,8 +347,8 @@ fn getMemberType(comptime T: type) MemberType {
.Bool => .bool,
.Int => |int| if (int.signedness == .signed) .int else .uint,
.Float => .float,
.Enum => .enumeration_item,
.ErrorSet => .@"error",
.Enum => |en| getMemberType(en.tag_type),
.ErrorSet => .uint,
.Struct,
.Union,
.Array,
Expand Down Expand Up @@ -946,7 +944,10 @@ test "getUnionSelector" {

fn addMembers(host: anytype, structure: Value, comptime T: type) !void {
return switch (comptime getStructureType(T)) {
.primitive => addPrimitiveMember(host, structure, T),
.primitive,
.error_set,
.enumeration,
=> addPrimitiveMember(host, structure, T),
.array => addArrayMember(host, structure, T),
.@"struct",
.extern_struct,
Expand All @@ -958,8 +959,6 @@ fn addMembers(host: anytype, structure: Value, comptime T: type) !void {
.tagged_union,
=> addUnionMembers(host, structure, T),
.error_union => addErrorUnionMembers(host, structure, T),
.error_set => addErrorSetMember(host, structure, T),
.enumeration => addEnumerationMember(host, structure, T),
.optional => addOptionalMembers(host, structure, T),
.pointer => addPointerMember(host, structure, T),
.vector => addVectorMember(host, structure, T),
Expand Down Expand Up @@ -1412,17 +1411,6 @@ test "StandardInt" {
assert(StandardInt(i127) == i128);
}

fn addEnumerationMember(host: anytype, structure: Value, comptime T: type) !void {
const IT = StandardInt(@typeInfo(T).Enum.tag_type);
try host.attachMember(structure, .{
.member_type = getMemberType(IT),
.bit_size = getStructureBitSize(IT),
.bit_offset = 0,
.byte_size = getStructureSize(IT),
.structure = null,
}, false);
}

fn addOptionalMembers(host: anytype, structure: Value, comptime T: type) !void {
const op = @typeInfo(T).Optional;
// value always comes first
Expand Down Expand Up @@ -1476,32 +1464,6 @@ fn addErrorUnionMembers(host: anytype, structure: Value, comptime T: type) !void
}, false);
}

fn ErrorIntType() type {
return @Type(.{
.Int = .{
.signedness = .unsigned,
.bits = @bitSizeOf(anyerror),
},
});
}

test "ErrorIntType" {
const T = ErrorIntType();
assert(T == u16);
}

fn addErrorSetMember(host: anytype, structure: Value, comptime T: type) !void {
_ = T;
const IT = ErrorIntType();
try host.attachMember(structure, .{
.member_type = getMemberType(IT),
.bit_size = getStructureBitSize(IT),
.bit_offset = 0,
.byte_size = getStructureSize(IT),
.structure = null,
}, false);
}

fn addStaticMembers(host: anytype, structure: Value, comptime T: type) !void {
// a stand-in type representing the "static side" of the structure
const Static = opaque {};
Expand Down
35 changes: 18 additions & 17 deletions zigar-runtime/src/enumeration.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getDataView, getTypedArrayClass } from './data-view.js';
import { throwInvalidInitializer } from './error.js';
import { MemberType, getDescriptor } from './member.js';
import { getDescriptor } from './member.js';
import { getDestructor, getMemoryCopier } from './memory.js';
import { convertToJSON, getBase64Descriptor, getDataViewDescriptor, getTypedArrayDescriptor, getValueOf } from './special.js';
import { attachDescriptors, createConstructor, createPropertyApplier, defineProperties } from './structure.js';
import { ALIGN, COPIER, ITEMS, MORE, NAME, NORMALIZER, SIZE, TAG } from './symbol.js';
import { ALIGN, COPIER, MORE, NAME, NORMALIZER, SIZE, TAG } from './symbol.js';

export function defineEnumerationShape(structure, env) {
const {
Expand All @@ -14,9 +14,7 @@ export function defineEnumerationShape(structure, env) {
members: [ member ],
},
} = structure;
const { get: getIndex, set: setIndex } = getDescriptor(member, env);
// get the enum descriptor instead of the int/uint descriptor
const { get, set } = getDescriptor({ ...member, type: MemberType.EnumerationItem, structure }, env);
const { get, set } = getDescriptor(member, env);
const expected = [ 'string', 'number', 'tagged union' ];
const propApplier = createPropertyApplier(structure);
const initializer = function(arg) {
Expand All @@ -30,17 +28,19 @@ export function defineEnumerationShape(structure, env) {
};
const alternateCaster = function(arg) {
if (typeof(arg) === 'string' || typeof(arg) === 'number' || typeof(arg) === 'bigint') {
const items = constructor[ITEMS];
let item = items[arg];
let item = constructor[arg];
if (!item) {
if (constructor[MORE] && typeof(arg) !== 'string') {
// create the item on-the-fly when enum is non-exhaustive
item = items[arg] = new constructor(undefined);
setIndex.call(item, arg);
defineProperties(item, { [NAME]: { value: `${arg}` } });
item = new constructor(undefined);
debugger;
set.call(item, arg, 'number');
appendEnumeration(constructor, `${arg}`, item);
}
}
return item;
} else if (arg instanceof constructor) {
return arg;
} else if (arg?.[TAG] instanceof constructor) {
// a tagged union, return the active tag
return arg[TAG];
Expand All @@ -53,7 +53,7 @@ export function defineEnumerationShape(structure, env) {
const constructor = structure.constructor = createConstructor(structure, { initializer, alternateCaster }, env);
const typedArray = structure.typedArray = getTypedArrayClass(member);
const toPrimitive = function(hint) {
return (hint === 'string') ? this.$[NAME] : getIndex.call(this);
return (hint === 'string') ? this.$[NAME] : get.call(this, 'number');
};
const instanceDescriptors = {
$: { get, set },
Expand All @@ -70,7 +70,6 @@ export function defineEnumerationShape(structure, env) {
const staticDescriptors = {
[ALIGN]: { value: align },
[SIZE]: { value: byteSize },
[ITEMS]: { value: {} },
};
return attachDescriptors(constructor, instanceDescriptors, staticDescriptors);
};
Expand All @@ -80,16 +79,18 @@ export function normalizeEnumerationItem(cb) {
}

export function appendEnumeration(enumeration, name, item) {
const enums = enumeration[ITEMS];
if (name !== undefined) {
// place item in hash to facilitate lookup,
if (item instanceof constructor) {
// enum can have static variables
if (item instanceof enumeration) {
// attach name to item so tagged union code can quickly find it
defineProperties(item, { [NAME]: { value: name } });
// call toPrimitive directly since enum can be bigint or number
const index = item[Symbol.toPrimitive]();
enums[index] = enums[name] = item;
}
defineProperties(enumeration, {
[index]: { value: item },
[name]: { value: item },
});
}
} else {
// non-exhaustive enum
defineProperties(enumeration, { [MORE]: { value: true } });
Expand Down
Loading

0 comments on commit 78b34c7

Please sign in to comment.