Skip to content

Commit 7ecb690

Browse files
authored
implement enum (#15)
1 parent 440a863 commit 7ecb690

6 files changed

Lines changed: 108 additions & 3 deletions

File tree

src/api.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ fn library() -> lu::Library<Config> {
125125
.with_function_norm("array", array)
126126
.with_function_norm("set", set)
127127
.with_function_norm("map", map)
128+
.with_function_norm("enum", enumn)
128129
.with_function_norm("struct", strukt)
129130
}
130131

@@ -175,6 +176,7 @@ pub enum Type {
175176
Array(ArrayType),
176177
Set(SetType),
177178
Map(MapType),
179+
Enum(EnumType),
178180
Struct(StructType),
179181
}
180182

@@ -673,6 +675,28 @@ extern "C-unwind" fn map(ctx: Context) -> lu::FnReturn {
673675
ctx.ret_with(1)
674676
}
675677

678+
#[derive(Clone)]
679+
pub struct EnumType {
680+
pub variants: Vec<String>,
681+
}
682+
683+
extern "C-unwind" fn enumn(ctx: Context) -> lu::FnReturn {
684+
ctx.arg_table(1);
685+
let mut variants = Vec::new();
686+
687+
ctx.iter(1, || {
688+
let Some(str) = ctx.to_string_str(-1) else {
689+
ctx.error_msg("enum variant must be a string");
690+
};
691+
692+
variants.push(str.to_string());
693+
ControlFlow::<()>::Continue(())
694+
});
695+
696+
ctx.push_userdata(Type::Enum(EnumType { variants }));
697+
ctx.ret_with(1)
698+
}
699+
676700
#[derive(Clone)]
677701
pub struct StructType {
678702
pub fields: Vec<(String, Type)>,

src/hir/build.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::{
22
api,
33
hir::{
4-
ArrayType, BinaryStringType, Event, Item, Length, MapType, NumberType, SetType, StructType,
5-
Type, Utf8StringType, VectorType,
4+
ArrayType, BinaryStringType, EnumType, Event, Item, Length, MapType, NumberType, SetType,
5+
StructType, Type, Utf8StringType, VectorType,
66
},
77
shared::Range,
88
};
@@ -42,6 +42,7 @@ impl From<api::Type> for Type {
4242
api::Type::Array(ty) => Type::Array(ty.into()),
4343
api::Type::Set(ty) => Type::Set(ty.into()),
4444
api::Type::Map(ty) => Type::Map(ty.into()),
45+
api::Type::Enum(ty) => Type::Enum(ty.into()),
4546
api::Type::Struct(ty) => Type::Struct(ty.into()),
4647
}
4748
}
@@ -110,6 +111,22 @@ impl From<api::MapType> for MapType {
110111
}
111112
}
112113

114+
impl From<api::EnumType> for EnumType {
115+
fn from(value: api::EnumType) -> Self {
116+
let variants = value.variants;
117+
let range = Range {
118+
min: Some(0f64),
119+
max: Some(variants.len() as f64 - 1f64),
120+
};
121+
let number = NumberType {
122+
kind: range.kind(),
123+
range,
124+
};
125+
126+
EnumType { variants, number }
127+
}
128+
}
129+
113130
impl From<api::StructType> for StructType {
114131
fn from(value: api::StructType) -> Self {
115132
let fields = value

src/hir/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum Type {
2727
Array(ArrayType),
2828
Set(SetType),
2929
Map(MapType),
30+
Enum(EnumType),
3031
Struct(StructType),
3132
}
3233

@@ -72,6 +73,12 @@ pub struct MapType {
7273
pub value: Box<Type>,
7374
}
7475

76+
#[derive(Clone)]
77+
pub struct EnumType {
78+
pub variants: Vec<String>,
79+
pub number: NumberType,
80+
}
81+
7582
#[derive(Clone)]
7683
pub struct StructType {
7784
pub fields: Vec<(String, Type)>,

src/hir/size.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ impl hir::Type {
9090
hir::Type::Array(ty) => ty.size(),
9191
hir::Type::Set(ty) => ty.size(),
9292
hir::Type::Map(ty) => ty.size(),
93+
hir::Type::Enum(ty) => ty.size(),
9394
hir::Type::Struct(ty) => ty.size(),
9495
}
9596
}
@@ -140,6 +141,12 @@ impl hir::MapType {
140141
}
141142
}
142143

144+
impl hir::EnumType {
145+
pub fn size(&self) -> Size {
146+
self.number.size()
147+
}
148+
}
149+
143150
impl hir::StructType {
144151
pub fn size(&self) -> Size {
145152
self.fields

src/mir/serdes.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ impl Serdes for hir::Type {
125125
hir::Type::Array(ty) => Box::new(ty.ser(b, ser)),
126126
hir::Type::Set(ty) => Box::new(ty.ser(b, ser)),
127127
hir::Type::Map(ty) => Box::new(ty.ser(b, ser)),
128+
hir::Type::Enum(ty) => Box::new(ty.ser(b, ser)),
128129
hir::Type::Struct(ty) => Box::new(ty.ser(b, ser)),
129130
};
130131

@@ -146,6 +147,7 @@ impl Serdes for hir::Type {
146147
hir::Type::Array(ty) => Box::new(ty.des(b, des)),
147148
hir::Type::Set(ty) => Box::new(ty.des(b, des)),
148149
hir::Type::Map(ty) => Box::new(ty.des(b, des)),
150+
hir::Type::Enum(ty) => Box::new(ty.des(b, des)),
149151
hir::Type::Struct(ty) => Box::new(ty.des(b, des)),
150152
};
151153

@@ -439,6 +441,54 @@ impl Serdes for hir::MapType {
439441
}
440442
}
441443

444+
impl Serdes for hir::EnumType {
445+
fn ser<'ty, 'b, 'ser: 'ty>(
446+
&'ty self,
447+
b: &'b mut Builder,
448+
ser: &'ser Ser,
449+
) -> impl Fn(&mut Builder, Expr) + use<'ty, 'ser> + 'ty {
450+
let variants = b.expr(Expr::Table(
451+
self.variants
452+
.iter()
453+
.enumerate()
454+
.map(|(i, v)| (Expr::from(v.as_str()), Expr::from(i as f64)))
455+
.collect(),
456+
));
457+
458+
let number = self.number.ser(b, ser);
459+
460+
move |b: &mut Builder, from: Expr| {
461+
apicheck_full!(ser, check_type(b, from.clone(), "string"));
462+
463+
let value = b.expr(variants.expr().index(from));
464+
apicheck_some!(ser, b.assert(value.expr(), "not a valid enum variant"));
465+
466+
number(b, value.expr());
467+
}
468+
}
469+
470+
fn des<'ty, 'b, 'des: 'ty>(
471+
&'ty self,
472+
b: &'b mut Builder,
473+
des: &'des Des,
474+
) -> impl Fn(&mut Builder) -> InitVar + use<'ty, 'des> + 'ty {
475+
let variants = b.expr(Expr::Table(
476+
self.variants
477+
.iter()
478+
.enumerate()
479+
.map(|(i, v)| (Expr::from(i as f64), Expr::from(v.as_str())))
480+
.collect(),
481+
));
482+
483+
let number = self.number.des(b, des);
484+
485+
move |b: &mut Builder| {
486+
let value = number(b);
487+
b.expr(variants.expr().index(&value))
488+
}
489+
}
490+
}
491+
442492
impl Serdes for hir::StructType {
443493
fn ser<'ty, 'b, 'ser: 'ty>(
444494
&'ty self,

src/shared.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Range {
7171
if self.min == self.max { self.min } else { None }
7272
}
7373

74-
pub fn len_kind(&self) -> NumberKind {
74+
pub fn kind(&self) -> NumberKind {
7575
let max = self.max.unwrap_or(f64::MAX);
7676

7777
if max <= u8::MAX as f64 {

0 commit comments

Comments
 (0)