+struct Struct<'a> {
+ name: &'a str,
+ fields: Vec<(&'a str, usize)>,
+}
+
+fn size_str_to_usize(size_str: &str) -> usize {
+ match size_str {
+ "u8" => 1,
+ "i8" => 1,
+ "u16" => 2,
+ "i16" => 2,
+ "u32" => 4,
+ "i32" => 4,
+ "u64" => 8,
+ "i64" => 8,
+ "ptr" => size_of::<usize>(),
+ _ => 0, // TODO should this error out instead?
+ }
+}
+
+impl<'a> Struct<'a> {
+ fn to_words(&'a self, module: &mut Module) {
+ let mut total_size = 0;
+
+ for (name, size) in self.fields.clone() {
+ let remainder = total_size % size;
+ let offset = if remainder == 0 {
+ total_size
+ } else {
+ total_size + (size - remainder)
+ };
+ module.words.push(WordDefinition {
+ name: format!("{}.{}", self.name, name),
+ instructions: vec![Token::NumU64(offset as u64), Token::Word("+")],
+ });
+ total_size = offset + size;
+ }
+
+ module.words.push(WordDefinition {
+ name: format!("sizeof.{}", self.name),
+ instructions: vec![Token::NumU64(total_size as u64)]
+ });
+ }
+
+ fn add_field(&mut self, token: Token<'a>) -> Result<()> {
+ if let Token::Word(token) = token {
+ let splat: Vec<_> = token.split(":").collect();
+ let name = splat[0];
+ let size_str = splat[1];
+ self.fields.push((name, size_str_to_usize(size_str)));
+ Ok(())
+ } else {
+ bail!("Improper struct definition!");
+ }
+ }
+}
+