Skip to content

Commit

Permalink
another stopping point
Browse files Browse the repository at this point in the history
  • Loading branch information
jtenner committed Sep 19, 2024
1 parent ec40697 commit 4ac82d9
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 87 deletions.
2 changes: 1 addition & 1 deletion src/internal/binary/types.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ pub fn decode_sub_type(bits: BitArray) {
/// and a single composite type.
/// 3. A single composite type that is *FINAL*
pub fn encode_sub_type(builder: BytesBuilder, sub_type: SubType) {
case sub_type.final, sub_type.type_idxs {
case sub_type.final, sub_type.match_idxs {
True, [] -> builder |> encode_composite_type(sub_type.composite_type)
True, match_idxs -> {
use builder <- result.try(
Expand Down
50 changes: 25 additions & 25 deletions src/internal/structure/types.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,75 +7,75 @@ import internal/structure/numbers.{
}

/// Get the lane_16 indx nvalue as an integer
pub fn unwrap_lane_16(val: LaneIDX16) {
val.val
pub fn unwrap_lane_16(lane_idx: LaneIDX16) {
lane_idx.lane
}

/// Create a lane index that indexes 16 lanes
pub fn lane_16(val: Int) {
case val |> between(#(0, 15)) {
True -> Ok(LaneIDX16(val))
pub fn lane_16(lane: Int) {
case lane |> between(#(0, 15)) {
True -> Ok(LaneIDX16(lane))
_ -> Error("Lane index out of range")
}
}

/// This type is used to describe lane indexes with a range of [0, 15]
pub opaque type LaneIDX16 {
LaneIDX16(val: Int)
LaneIDX16(lane: Int)
}

/// Get the lane_2 index value as an integer
pub fn unwrap_lane_2(val: LaneIDX2) {
val.val
pub fn unwrap_lane_2(lane_idx: LaneIDX2) {
lane_idx.lane
}

/// Create a lane index that indexes 2 lanes
pub fn lane_2(val: Int) {
case val |> between(#(0, 1)) {
True -> Ok(LaneIDX2(val))
pub fn lane_2(lane: Int) {
case lane |> between(#(0, 1)) {
True -> Ok(LaneIDX2(lane))
_ -> Error("Lane index out of range")
}
}

/// This type is used to describe lane indexes with a range of [0, 1]
pub opaque type LaneIDX2 {
LaneIDX2(val: Int)
LaneIDX2(lane: Int)
}

/// Get the lane_4 index value as an integer
pub fn unwrap_lane_4(val: LaneIDX4) {
val.val
pub fn unwrap_lane_4(lane_idx: LaneIDX4) {
lane_idx.lane
}

/// Create a lane index that indexes 4 lanes
pub fn lane_4(val: Int) {
case val |> between(#(0, 3)) {
True -> Ok(LaneIDX4(val))
pub fn lane_4(lane: Int) {
case lane |> between(#(0, 3)) {
True -> Ok(LaneIDX4(lane))
_ -> Error("Lane index out of range")
}
}

/// This type is used to describe lane indexes with a range of [0, 3]
pub opaque type LaneIDX4 {
LaneIDX4(val: Int)
LaneIDX4(lane: Int)
}

/// Get the lane_8 index value as an integer
pub fn unwrap_lane_8(val: LaneIDX8) {
val.val
pub fn unwrap_lane_8(lane_idx: LaneIDX8) {
lane_idx.lane
}

/// Create a lane index that indexes 8 lanes
pub fn lane_8(val: Int) {
case val |> between(#(0, 7)) {
True -> Ok(LaneIDX8(val))
pub fn lane_8(lane: Int) {
case lane |> between(#(0, 7)) {
True -> Ok(LaneIDX8(lane))
_ -> Error("Lane index out of range")
}
}

/// This type is used to describe lane indexes with a range of [0, 7]
pub opaque type LaneIDX8 {
LaneIDX8(val: Int)
LaneIDX8(lane: Int)
}

/// Please see: https://webassembly.github.io/gc/core/syntax/types.html#heap-types
Expand Down Expand Up @@ -291,7 +291,7 @@ pub type MemIDX {
/// also an array of matching subtype indexes that the type matches.
/// Please see: https://webassembly.github.io/gc/core/syntax/types.html#recursive-types
pub type SubType {
SubType(final: Bool, type_idxs: List(TypeIDX), composite_type: CompositeType)
SubType(final: Bool, match_idxs: List(TypeIDX), composite_type: CompositeType)
}

/// A definition of a limit range, which has a minimum, and an optional maximum which defaults
Expand Down
93 changes: 79 additions & 14 deletions src/internal/validation/common.gleam
Original file line number Diff line number Diff line change
@@ -1,25 +1,90 @@
import gleam/dict.{type Dict}
import gleam/list
import internal/structure/numbers.{type U32}
import gleam/int
import gleamy/red_black_tree_map.{type Map}
import internal/structure/numbers
import internal/structure/types.{
type Data, type DefType, type Elem, type FuncIDX, type GlobalType, type Locals,
type MemType, type RecType, type TableType, type ValType,
type DefType, type RecType, type SubType, type TypeIDX, DefType, TypeIDX,
}
import shine_tree.{type ShineTree}

pub type TypeEntry {
TypeEntry(
type_idx: Int,
def_type: DefType,
rec_type: RecType,
sub_type: SubType,
rec_type_idx: Int,
)
}

pub type Context {
Context(types: List(DefType))
Context(types_length: Int, types: Map(TypeIDX, TypeEntry))
}

pub const empty_context = Context(types: [])
fn compare_type_idx(type_idx_a: TypeIDX, type_idx_b: TypeIDX) {
let TypeIDX(type_idx_a) = type_idx_a
let TypeIDX(type_idx_b) = type_idx_b
let type_idx_a = numbers.unwrap_u32(type_idx_a)
let type_idx_b = numbers.unwrap_u32(type_idx_b)
int.compare(type_idx_a, type_idx_b)
}

pub fn get_def_type(ctx: Context, idx: U32) {
let idx = numbers.unwrap_u32(idx)
case list.drop(ctx.types, idx) {
[def_type, ..] -> Ok(def_type)
_ -> Error("Invalid TypeIDX")
pub fn new_context(rec_types: List(RecType)) {
do_new_context(
rec_types,
0,
Context(0, red_black_tree_map.new(compare_type_idx)),
)
}

fn do_new_context(rec_types: List(RecType), type_idx: Int, acc: Context) {
case rec_types {
[] -> acc
[rec_type, ..rec_types] ->
do_new_sub_types(
rec_type.sub_types,
rec_type,
rec_types,
type_idx,
0,
acc,
)
}
}

pub fn roll_rec_type(ctx: Context, rec_type: RecType) {
todo
fn do_new_sub_types(
sub_types: List(SubType),
rec_type: RecType,
rec_types: List(RecType),
type_idx: Int,
rec_type_idx: Int,
acc: Context,
) {
case sub_types {
[] -> do_new_context(rec_types, type_idx, acc)
[sub_type, ..sub_types] -> {
let assert Ok(type_idx_key) = numbers.u32(type_idx)

do_new_sub_types(
sub_types,
rec_type,
rec_types,
type_idx + 1,
rec_type_idx + 1,
Context(
types_length: acc.types_length + 1,
types: red_black_tree_map.insert(
acc.types,
TypeIDX(type_idx_key),
TypeEntry(
type_idx,
DefType(rec_type, rec_type_idx),
rec_type,
sub_type,
rec_type_idx,
),
),
),
)
}
}
}
120 changes: 74 additions & 46 deletions src/internal/validation/match.gleam
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import gleam/list.{Continue, Stop}
import gleamy/red_black_tree_map as map
import internal/structure/numbers
import internal/structure/types.{
type ArrayType, type CompositeType, type DefType, type FieldType,
type FuncType, type HeapType, type RefType, type StorageType, type StructType,
type ValType, AnyHeapType, AnyRefType, ArrayCompositeType, ArrayHeapType,
ArrayRefType, ArrayType, BotHeapType, BotValType, ConcreteHeapType, Const,
EqHeapType, EqRefType, ExternHeapType, ExternRefType, FieldType,
FuncCompositeType, FuncHeapType, FuncRefType, FuncType, HeapTypeRefType,
I31HeapType, I31RefType, NoExternHeapType, NoExternRefType, NoFuncHeapType,
NoFuncRefType, NoneHeapType, NoneRefType, RefTypeValType, StructCompositeType,
StructHeapType, StructRefType, StructType, SubType, TypeIDX,
ValTypeStorageType, Var,
type TypeIDX, type ValType, AnyHeapType, AnyRefType, ArrayCompositeType,
ArrayHeapType, ArrayRefType, ArrayType, BotHeapType, BotValType,
ConcreteHeapType, Const, EqHeapType, EqRefType, ExternHeapType, ExternRefType,
FieldType, FuncCompositeType, FuncHeapType, FuncRefType, FuncType,
HeapTypeRefType, I31HeapType, I31RefType, NoExternHeapType, NoExternRefType,
NoFuncHeapType, NoFuncRefType, NoneHeapType, NoneRefType, RefTypeValType,
StructCompositeType, StructHeapType, StructRefType, StructType, SubType,
TypeIDX, ValTypeStorageType, Var,
}

import internal/validation/common.{type Context}
import internal/validation/common.{type Context, TypeEntry}

pub fn matches_val_type(ctx: Context, val_type_1: ValType, val_type_2: ValType) {
case val_type_1, val_type_2 {
Expand Down Expand Up @@ -55,51 +57,34 @@ pub fn matches_heap_type(
heap_type_2: HeapType,
) {
case heap_type_1, heap_type_2 {
// Either both heaptype1 and heaptype2 are the same.
heap_type_1, heap_type_2 if heap_type_1 == heap_type_2 -> True
ConcreteHeapType(type_idx_1), ConcreteHeapType(type_idx_2) ->
match_heap_type_idxs(ctx, type_idx_1, type_idx_2)
ConcreteHeapType(type_idx), heap_type_2 ->
match_type_idx_to_heap_type(ctx, type_idx, heap_type_2)
heap_type_1, ConcreteHeapType(type_idx) ->
match_heap_type_to_type_idx(ctx, heap_type_1, type_idx)

// Or heaptype1 is bot.
BotHeapType, _
| EqHeapType, AnyHeapType
| I31HeapType, EqHeapType
| // Or heaptype1 is eq and heaptype2 is any
EqHeapType,
AnyHeapType
| // Or heaptype1 is one of i31, struct, or array and heaptype2 is eq.
I31HeapType,
EqHeapType
| StructHeapType, EqHeapType
| ArrayHeapType, EqHeapType
-> True

// TODO: Fix how type indices are matched
// ConcreteHeapType(DefTypeReference(def_type_1)),
// ConcreteHeapType(DefTypeReference(def_type_2))
// -> matches_def_type(ctx, def_type_1, def_type_2)
// ConcreteHeapType(DefTypeReference(def_type)), heap_type_2 -> {
// case types.def_type_expand(def_type), heap_type_2 {
// Ok(FuncCompositeType(_)), FuncHeapType
// | Ok(StructCompositeType(_)), StructHeapType
// | Ok(ArrayCompositeType(_)), ArrayHeapType
// -> True
// _, _ -> False
// }
// }
// ConcreteHeapType(TypeIDX(idx)), heap_type_2 ->
// case common.get_def_type(ctx, idx) {
// Ok(def_type) ->
// matches_heap_type(
// ctx,
// ConcreteHeapType(DefTypeReference(def_type)),
// heap_type_2,
// )
// _ -> False
// }
// heap_type_1, ConcreteHeapType(TypeIDX(idx)) ->
// case common.get_def_type(ctx, idx) {
// Ok(def_type) ->
// matches_heap_type(
// ctx,
// heap_type_1,
// ConcreteHeapType(DefTypeReference(def_type)),
// )
// _ -> False
// }
NoneHeapType, heap_type_2 ->
matches_heap_type(ctx, heap_type_2, AnyHeapType)

// Or heaptype1 is nofunc and heaptype2 matches func.
NoFuncHeapType, heap_type_2 ->
matches_heap_type(ctx, heap_type_2, FuncHeapType)

// Or heaptype1 is noextern and heaptype2 matches extern.
NoExternHeapType, heap_type_2 ->
matches_heap_type(ctx, heap_type_2, ExternHeapType)

Expand All @@ -109,6 +94,49 @@ pub fn matches_heap_type(
}
}

fn match_type_idx_to_heap_type(
ctx: Context,
type_idx: TypeIDX,
heap_type: HeapType,
) {
case ctx.types |> map.find(type_idx) {
Ok(TypeEntry(_, _, _, SubType(_, _, composite_type), _)) ->
case composite_type, heap_type {
FuncCompositeType(_), FuncHeapType
| ArrayCompositeType(_), ArrayHeapType
| StructCompositeType(_), StructHeapType
-> True
_, _ -> False
}
_ -> False
}
}

// TODO: How to compare heap types to def_types
fn match_heap_type_to_type_idx(
ctx: Context,
heap_type: HeapType,
type_idx: TypeIDX,
) {
case map.find(ctx.types, type_idx) {
Ok(TypeEntry(_, _, _, SubType(_, _, _composite_type), _)) -> False
_ -> False
}
}

fn match_heap_type_idxs(ctx: Context, type_idx_1: TypeIDX, type_idx_2: TypeIDX) {
// Or there exists a valid heap type heaptype', such that heaptype1 matches heaptype' and heaptype' matches
// heaptype2.
case map.find(ctx.types, type_idx_1) {
Ok(TypeEntry(_, _, _, SubType(_, match_idxs, _), _)) -> {
use type_idx_1 <- list.any(match_idxs)
match_heap_type_idxs(ctx, type_idx_1, type_idx_2)
}

_ -> False
}
}

pub fn matches_result_type(
ctx: Context,
result_type_1: List(ValType),
Expand Down
2 changes: 1 addition & 1 deletion test/decode_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ fn do_func_idxs_equal(

fn sub_type_equals(a: structure_types.SubType, b: structure_types.SubType) {
a.final |> should.equal(b.final)
do_type_idxs_equal(a.type_idxs, b.type_idxs)
do_type_idxs_equal(a.match_idxs, b.match_idxs)
composite_type_equals(a.composite_type, b.composite_type)
}

Expand Down

0 comments on commit 4ac82d9

Please sign in to comment.