Skip to content

Commit 8a12d58

Browse files
add record, option, tagged enum lowering and lifting
1 parent c2abb4a commit 8a12d58

4 files changed

Lines changed: 397 additions & 5 deletions

File tree

gabagool/src/component/binary_grammar.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,23 @@ impl ComponentValueKind {
390390
ComponentTypeDef::Defined(ComponentDefinedKind::Tuple(tys)) => {
391391
tys.iter().map(|ty| ty.flat_count(types)).sum()
392392
}
393+
ComponentTypeDef::Defined(ComponentDefinedKind::Variant(cases)) => {
394+
let max_payload = cases
395+
.iter()
396+
.map(|c| c.ty.as_ref().map_or(0, |ty| ty.flat_count(types)))
397+
.max()
398+
.unwrap_or(0);
399+
1 + max_payload
400+
}
401+
ComponentTypeDef::Defined(ComponentDefinedKind::Enum(_)) => 1,
402+
ComponentTypeDef::Defined(ComponentDefinedKind::Option(ty)) => {
403+
1 + ty.flat_count(types)
404+
}
405+
ComponentTypeDef::Defined(ComponentDefinedKind::Result { ok, err }) => {
406+
let ok_count = ok.as_ref().map_or(0, |ty| ty.flat_count(types));
407+
let err_count = err.as_ref().map_or(0, |ty| ty.flat_count(types));
408+
1 + ok_count.max(err_count)
409+
}
393410
_ => todo!("flat_count for type {i}"),
394411
},
395412
}

gabagool/src/component/execution_grammar.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,30 @@ where
161161
}
162162
}
163163

164+
impl<V> From<Option<V>> for ComponentValue
165+
where
166+
V: Into<Self>,
167+
{
168+
fn from(value: Option<V>) -> Self {
169+
Self::Option(value.map(|v| Box::new(v.into())))
170+
}
171+
}
172+
173+
impl<T, E> From<StdResult<T, E>> for ComponentValue
174+
where
175+
T: Into<Self>,
176+
E: Into<Self>,
177+
{
178+
fn from(res: StdResult<T, E>) -> Self {
179+
let out = match res {
180+
Ok(v) => Ok(Some(Box::new(v.into()))),
181+
Err(e) => Err(Some(Box::new(e.into()))),
182+
};
183+
184+
Self::Result(out)
185+
}
186+
}
187+
164188
#[derive(Debug, Copy, Clone)]
165189
pub struct ComponentInstance(pub(crate) usize);
166190

gabagool/src/store.rs

Lines changed: 197 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ use std::sync::Arc;
66

77
use crate::compiler::ModuleCode;
88
use crate::component::binary_grammar::{
9-
ComponentDefinedKind, ComponentFuncResult, ComponentTypeDef, ComponentValueKind,
10-
PrimitiveValueKind,
9+
ComponentDefinedKind, ComponentTypeDef, ComponentValueKind, PrimitiveValueKind,
1110
};
1211
use crate::component::flatten::Initializer;
1312
use crate::error::{Error, Result};
1413
#[cfg(feature = "jit")]
1514
use crate::jit::assembler::JitFunction;
1615
use crate::{
17-
compiler, ensure, instantiation_err, trap, AddrType, Component, ComponentFuncKind,
18-
ComponentInstance, ComponentValue, DataMode, ElementMode, ImportDescription,
19-
InstantiatedComponent, Instruction, LiftedFunc, Module, Mutability, Trap,
16+
compiler, ensure, instantiation_err, trap, AddrType, Component, ComponentInstance,
17+
ComponentValue, DataMode, ElementMode, ImportDescription, InstantiatedComponent, Instruction,
18+
LiftedFunc, Module, Mutability, Trap,
2019
};
2120

2221
use crate::binary_grammar::{
@@ -1246,6 +1245,103 @@ impl Store {
12461245
self.lower_value(value, None, types, lifted, flat)?;
12471246
}
12481247
}
1248+
ComponentValue::Variant(case_name, payload) => {
1249+
let defined = resolve_defined_type(param_ty, types);
1250+
let cases = match defined {
1251+
Some(ComponentDefinedKind::Variant(cases)) => cases,
1252+
_ => instantiation_err!("variant lower requires variant type"),
1253+
};
1254+
1255+
let Some(case_i) = cases.iter().position(|c| c.name == case_name) else {
1256+
instantiation_err!("enum case not found: {case_name}")
1257+
};
1258+
1259+
let max_payload = cases
1260+
.iter()
1261+
.map(|c| c.ty.as_ref().map_or(0, |ty| ty.flat_count(types)))
1262+
.max()
1263+
.unwrap_or(0);
1264+
1265+
flat.push(RawValue::from(case_i as i32));
1266+
1267+
let before = flat.len();
1268+
if let Some(value) = payload {
1269+
self.lower_value(*value, None, types, lifted, flat)?;
1270+
}
1271+
1272+
let written = flat.len() - before - 1;
1273+
let padding = max_payload - written;
1274+
flat.extend(std::iter::repeat_n(RawValue::from(i32::MAX), padding));
1275+
}
1276+
ComponentValue::Enum(case_name) => {
1277+
let defined = resolve_defined_type(param_ty, types);
1278+
1279+
let cases = match defined {
1280+
Some(ComponentDefinedKind::Enum(cases)) => cases,
1281+
_ => instantiation_err!("enum lower requires enum type"),
1282+
};
1283+
1284+
let Some(case_i) = cases.iter().position(|c| *c == case_name) else {
1285+
instantiation_err!("enum case not found: {case_name}")
1286+
};
1287+
1288+
flat.push(RawValue::from(case_i as i32));
1289+
}
1290+
ComponentValue::Option(opt) => {
1291+
let defined = resolve_defined_type(param_ty, types);
1292+
1293+
let inner_ty = match defined {
1294+
Some(ComponentDefinedKind::Option(ty)) => ty,
1295+
_ => instantiation_err!("option lower requires option type"),
1296+
};
1297+
1298+
let payload_count = inner_ty.flat_count(types);
1299+
1300+
match opt {
1301+
None => flat.extend(std::iter::repeat_n(
1302+
RawValue::from(i32::MAX),
1303+
payload_count + 1,
1304+
)),
1305+
Some(value) => {
1306+
flat.push(RawValue::from(1i32));
1307+
self.lower_value(*value, None, types, lifted, flat)?;
1308+
}
1309+
}
1310+
}
1311+
ComponentValue::Result(result) => {
1312+
let defined = resolve_defined_type(param_ty, types);
1313+
let (ok_ty, err_ty) = match defined {
1314+
Some(ComponentDefinedKind::Result { ok, err }) => (ok, err),
1315+
_ => instantiation_err!("result lower requires result type"),
1316+
};
1317+
1318+
let ok_count = ok_ty.as_ref().map_or(0, |ty| ty.flat_count(types));
1319+
let err_count = err_ty.as_ref().map_or(0, |ty| ty.flat_count(types));
1320+
let max_payload = ok_count.max(err_count);
1321+
1322+
let before = flat.len();
1323+
1324+
match result {
1325+
Ok(value) => {
1326+
flat.push(RawValue::from(0i32));
1327+
1328+
if let Some(value) = value {
1329+
self.lower_value(*value, None, types, lifted, flat)?;
1330+
}
1331+
}
1332+
Err(value) => {
1333+
flat.push(RawValue::from(1i32));
1334+
1335+
if let Some(value) = value {
1336+
self.lower_value(*value, None, types, lifted, flat)?;
1337+
}
1338+
}
1339+
}
1340+
1341+
let written = flat.len() - before - 1;
1342+
let padding = max_payload - written;
1343+
flat.extend(std::iter::repeat_n(RawValue::from(i32::MAX), padding));
1344+
}
12491345
_ => todo!("lower {:?}", value),
12501346
}
12511347
Ok(())
@@ -1279,6 +1375,7 @@ impl Store {
12791375
ComponentValueKind::Primitive(p) => {
12801376
let val = flat[*cursor];
12811377
*cursor += 1;
1378+
12821379
Ok(match p {
12831380
PrimitiveValueKind::Bool => ComponentValue::Bool(val.as_i32() != 0),
12841381
PrimitiveValueKind::S8 => ComponentValue::S8(val.as_i32() as i8),
@@ -1387,6 +1484,88 @@ impl Store {
13871484

13881485
Ok(ComponentValue::Tuple(values))
13891486
}
1487+
ComponentTypeDef::Defined(ComponentDefinedKind::Variant(cases)) => {
1488+
let discriminant = flat[*cursor].as_i32() as usize;
1489+
*cursor += 1;
1490+
1491+
let max_payload = cases
1492+
.iter()
1493+
.map(|c| c.ty.as_ref().map_or(0, |ty| ty.flat_count(types)))
1494+
.max()
1495+
.unwrap_or(0);
1496+
1497+
let case = &cases[discriminant];
1498+
let payload = if let Some(ty) = &case.ty {
1499+
let val = self.lift_value(ty, flat, cursor, lifted, types)?;
1500+
let this_count = ty.flat_count(types);
1501+
1502+
*cursor += max_payload - this_count;
1503+
1504+
Some(Box::new(val))
1505+
} else {
1506+
*cursor += max_payload;
1507+
1508+
None
1509+
};
1510+
1511+
Ok(ComponentValue::Variant(case.name.clone(), payload))
1512+
}
1513+
ComponentTypeDef::Defined(ComponentDefinedKind::Enum(cases)) => {
1514+
let discriminant = flat[*cursor].as_i32() as usize;
1515+
*cursor += 1;
1516+
1517+
Ok(ComponentValue::Enum(cases[discriminant].clone()))
1518+
}
1519+
ComponentTypeDef::Defined(ComponentDefinedKind::Option(inner_ty)) => {
1520+
let discriminant = flat[*cursor].as_i32();
1521+
*cursor += 1;
1522+
1523+
let payload_count = inner_ty.flat_count(types);
1524+
if discriminant == 0 {
1525+
*cursor += payload_count;
1526+
1527+
return Ok(ComponentValue::Option(None));
1528+
}
1529+
1530+
let val = self.lift_value(inner_ty, flat, cursor, lifted, types)?;
1531+
1532+
Ok(ComponentValue::Option(Some(Box::new(val))))
1533+
}
1534+
ComponentTypeDef::Defined(ComponentDefinedKind::Result { ok, err }) => {
1535+
let discriminant = flat[*cursor].as_i32();
1536+
*cursor += 1;
1537+
1538+
let ok_count = ok.as_ref().map_or(0, |ty| ty.flat_count(types));
1539+
let err_count = err.as_ref().map_or(0, |ty| ty.flat_count(types));
1540+
let max_payload = ok_count.max(err_count);
1541+
1542+
if discriminant == 0 {
1543+
let val = if let Some(ty) = ok {
1544+
let v = self.lift_value(ty, flat, cursor, lifted, types)?;
1545+
*cursor += max_payload - ok_count;
1546+
1547+
Some(Box::new(v))
1548+
} else {
1549+
*cursor += max_payload;
1550+
1551+
None
1552+
};
1553+
return Ok(ComponentValue::Result(Ok(val)));
1554+
}
1555+
1556+
let val = if let Some(ty) = err {
1557+
let v = self.lift_value(ty, flat, cursor, lifted, types)?;
1558+
*cursor += max_payload - err_count;
1559+
1560+
Some(Box::new(v))
1561+
} else {
1562+
*cursor += max_payload;
1563+
1564+
None
1565+
};
1566+
1567+
Ok(ComponentValue::Result(Err(val)))
1568+
}
13901569
other => todo!("lift type {:?}", other),
13911570
},
13921571
}
@@ -3185,6 +3364,19 @@ const fn limits_match(actual: &Limit, expected: &Limit) -> bool {
31853364
actual.min >= expected.min && (expected.max == u64::MAX || actual.max <= expected.max)
31863365
}
31873366

3367+
fn resolve_defined_type<'a>(
3368+
param_ty: Option<&ComponentValueKind>,
3369+
types: &'a [ComponentTypeDef],
3370+
) -> Option<&'a ComponentDefinedKind> {
3371+
match param_ty? {
3372+
ComponentValueKind::Type(i) => match &types[*i as usize] {
3373+
ComponentTypeDef::Defined(d) => Some(d),
3374+
_ => None,
3375+
},
3376+
_ => None,
3377+
}
3378+
}
3379+
31883380
fn component_value_byte_size(v: &ComponentValue) -> usize {
31893381
match v {
31903382
ComponentValue::Bool(_) | ComponentValue::S8(_) | ComponentValue::U8(_) => 1,

0 commit comments

Comments
 (0)