diff --git a/src/api.rs b/src/api.rs index 421f855..5f40a62 100644 --- a/src/api.rs +++ b/src/api.rs @@ -110,6 +110,7 @@ fn library() -> lu::Library { lu::Library::default() .with_function_norm("event", event) + .with_function_norm("boolean", boolean) .with_function_norm("u8", u8) .with_function_norm("u16", u16) .with_function_norm("u32", u32) @@ -169,6 +170,7 @@ extern "C-unwind" fn event(ctx: Context) -> lu::FnReturn { #[derive(lu::Userdata, Clone)] pub enum Type { + Boolean(BooleanType), Number(NumberType), Vector(VectorType), BinaryString(BinaryStringType), @@ -180,6 +182,14 @@ pub enum Type { Struct(StructType), } +#[derive(Clone)] +pub struct BooleanType; + +extern "C-unwind" fn boolean(ctx: Context) -> lu::FnReturn { + ctx.push_userdata(Type::Boolean(BooleanType)); + ctx.ret_with(1) +} + #[derive(Clone)] pub struct NumberType { pub kind: NumberKind, diff --git a/src/header.luau b/src/header.luau index b07cfe1..3da0abb 100644 --- a/src/header.luau +++ b/src/header.luau @@ -2,6 +2,7 @@ --!nolint -- This file was generated by zap local buf, pos, len = buffer.create(1024), 0, 1024 +local bit = { [true] = 1, [false] = 0 } local function resize(bytes) local newlen = pos * 2 if newlen < pos + bytes then diff --git a/src/hir/build.rs b/src/hir/build.rs index 22c1a48..3894484 100644 --- a/src/hir/build.rs +++ b/src/hir/build.rs @@ -1,8 +1,8 @@ use crate::{ api, hir::{ - ArrayType, BinaryStringType, EnumType, Event, Item, Length, MapType, NumberType, SetType, - StructType, Type, Utf8StringType, VectorType, + ArrayType, BinaryStringType, BooleanType, EnumType, Event, Item, Length, MapType, + NumberType, SetType, StructType, Type, Utf8StringType, VectorType, }, shared::Range, }; @@ -35,6 +35,7 @@ impl From for Event { impl From for Type { fn from(value: api::Type) -> Self { match value { + api::Type::Boolean(ty) => Type::Boolean(ty.into()), api::Type::Number(ty) => Type::Number(ty.into()), api::Type::Vector(ty) => Type::Vector(ty.into()), api::Type::BinaryString(ty) => Type::BinaryString(ty.into()), @@ -48,6 +49,12 @@ impl From for Type { } } +impl From for BooleanType { + fn from(_: api::BooleanType) -> Self { + BooleanType + } +} + impl From for NumberType { fn from(value: api::NumberType) -> Self { let kind = value.kind; @@ -141,7 +148,7 @@ impl From for StructType { impl From for Length { fn from(value: Range) -> Self { - let min = value.min.map(|n| n as u32); + let min = value.min.map(|n| n as u32).unwrap_or(0); let max = value.max.map(|n| n as u32); Length { min, max } diff --git a/src/hir/mod.rs b/src/hir/mod.rs index bccbaf8..1b7b614 100644 --- a/src/hir/mod.rs +++ b/src/hir/mod.rs @@ -20,6 +20,7 @@ pub struct Event { #[derive(Clone)] pub enum Type { + Boolean(BooleanType), Number(NumberType), Vector(VectorType), BinaryString(BinaryStringType), @@ -31,6 +32,9 @@ pub enum Type { Struct(StructType), } +#[derive(Clone)] +pub struct BooleanType; + #[derive(Clone)] pub struct NumberType { pub kind: NumberKind, @@ -86,13 +90,19 @@ pub struct StructType { #[derive(Clone, Copy)] pub struct Length { - pub min: Option, + pub min: u32, pub max: Option, } impl Length { pub fn exact(&self) -> Option { - if self.min == self.max { self.min } else { None } + if let Some(max) = self.max + && self.min == max + { + Some(max) + } else { + None + } } pub fn kind(&self) -> NumberKind { @@ -111,7 +121,7 @@ impl Length { NumberType { kind: self.kind(), range: Range { - min: self.min.map(|min| min as f64), + min: Some(self.min as f64), max: self.max.map(|max| max as f64), }, } @@ -121,7 +131,7 @@ impl Length { impl From for Range { fn from(value: Length) -> Self { Range { - min: value.min.map(|min| min as f64), + min: Some(value.min as f64), max: value.max.map(|max| max as f64), } } diff --git a/src/hir/size.rs b/src/hir/size.rs index 25b902a..593ebff 100644 --- a/src/hir/size.rs +++ b/src/hir/size.rs @@ -48,7 +48,7 @@ impl Mul for Size { type Output = Self; fn mul(self, rhs: hir::Length) -> Self::Output { - let min = rhs.min.unwrap_or(0); + let min = rhs.min; let max = rhs.max; Self { @@ -83,6 +83,7 @@ impl Size { impl hir::Type { pub fn size(&self) -> Size { match self { + hir::Type::Boolean(ty) => ty.size(), hir::Type::Number(ty) => ty.size(), hir::Type::Vector(ty) => ty.size(), hir::Type::BinaryString(ty) => ty.size(), @@ -96,6 +97,12 @@ impl hir::Type { } } +impl hir::BooleanType { + pub fn size(&self) -> Size { + Size::from(1) + } +} + impl hir::NumberType { pub fn size(&self) -> Size { Size { diff --git a/src/mir/mod.rs b/src/mir/mod.rs index c10efee..51b81e9 100644 --- a/src/mir/mod.rs +++ b/src/mir/mod.rs @@ -313,6 +313,7 @@ pub enum Expr { Vector(Box, Box, Box), Type(Box), Utf8(Box), + Bit(Box), } impl From for Expr { @@ -368,6 +369,10 @@ impl Expr { Expr::Binary(Box::new(self), BinaryOp::Mul, Box::new(rhs.into())) } + pub fn mud(self, rhs: impl Into) -> Self { + Expr::Binary(Box::new(self), BinaryOp::Mod, Box::new(rhs.into())) + } + pub fn eq(self, rhs: impl Into) -> Self { Expr::Binary(Box::new(self), BinaryOp::Eq, Box::new(rhs.into())) } @@ -391,6 +396,10 @@ impl Expr { pub fn len(self) -> Self { Expr::Unary(UnaryOp::Len, Box::new(self)) } + + pub fn bit(self) -> Self { + Expr::Bit(Box::new(self)) + } } impl Display for Expr { @@ -423,6 +432,7 @@ impl Display for Expr { Expr::Vector(x, y, z) => write!(f, "vector.create({x}, {y}, {z})"), Expr::Type(expr) => write!(f, "type({expr})"), Expr::Utf8(expr) => write!(f, "utf8.len({expr})"), + Expr::Bit(expr) => write!(f, "bit[{expr}]"), } } } @@ -433,6 +443,7 @@ pub enum BinaryOp { Add, Mul, + Mod, Eq, Lt, @@ -447,6 +458,7 @@ impl Display for BinaryOp { BinaryOp::And => write!(f, "and"), BinaryOp::Add => write!(f, "+"), BinaryOp::Mul => write!(f, "*"), + BinaryOp::Mod => write!(f, "%"), BinaryOp::Eq => write!(f, "=="), BinaryOp::Lt => write!(f, "<"), BinaryOp::Gt => write!(f, ">"), diff --git a/src/mir/serdes.rs b/src/mir/serdes.rs index bae6c3d..4d5c0ec 100644 --- a/src/mir/serdes.rs +++ b/src/mir/serdes.rs @@ -1,7 +1,7 @@ use crate::{ hir, mir::{ - Expr, FuncD, + Expr, FuncD, FuncK, builder::{Builder, InitVar}, }, shared::{ApiCheck, NumberKind, Range}, @@ -118,6 +118,7 @@ impl Serdes for hir::Type { ) -> impl Fn(&mut Builder, Expr) + use<'ty, 'ser> + 'ty { #[allow(clippy::type_complexity)] let cb: Box = match self { + hir::Type::Boolean(ty) => Box::new(ty.ser(b, ser)), hir::Type::Number(ty) => Box::new(ty.ser(b, ser)), hir::Type::Vector(ty) => Box::new(ty.ser(b, ser)), hir::Type::BinaryString(ty) => Box::new(ty.ser(b, ser)), @@ -140,6 +141,7 @@ impl Serdes for hir::Type { des: &'des Des, ) -> impl Fn(&mut Builder) -> InitVar + use<'ty, 'des> + 'ty { let cb: Box InitVar> = match self { + hir::Type::Boolean(ty) => Box::new(ty.des(b, des)), hir::Type::Number(ty) => Box::new(ty.des(b, des)), hir::Type::Vector(ty) => Box::new(ty.des(b, des)), hir::Type::BinaryString(ty) => Box::new(ty.des(b, des)), @@ -155,6 +157,32 @@ impl Serdes for hir::Type { } } +impl Serdes for hir::BooleanType { + fn ser<'ty, 'b, 'ser: 'ty>( + &'ty self, + _: &'b mut Builder, + ser: &'ser Ser, + ) -> impl Fn(&mut Builder, Expr) + use<'ty, 'ser> + 'ty { + move |b: &mut Builder, from: Expr| { + apicheck_full!(ser, check_type(b, from.clone(), "boolean")); + + b.alloc_k(1); + b.write_k(FuncK::U8, from.bit()); + } + } + + fn des<'ty, 'b, 'des: 'ty>( + &'ty self, + _: &'b mut Builder, + _: &'des Des, + ) -> impl Fn(&mut Builder) -> InitVar + use<'ty, 'des> + 'ty { + move |b: &mut Builder| { + let value = b.read_k(FuncK::U8); + b.expr(value.expr().eq(1)) + } + } +} + impl Serdes for hir::NumberType { fn ser<'ty, 'b, 'ser: 'ty>( &'ty self, diff --git a/src/zap.d.luau b/src/zap.d.luau index bab7e23..a68d098 100644 --- a/src/zap.d.luau +++ b/src/zap.d.luau @@ -8,6 +8,8 @@ declare class ZapEvent end declare zap: { + boolean: () -> ZapType, + u8: (min: number?, max: number?) -> ZapNumberType, u16: (min: number?, max: number?) -> ZapNumberType, u32: (min: number?, max: number?) -> ZapNumberType,