nifty_codegen/compile/
types.rs1use std::collections::HashMap;
6use std::mem::size_of;
7
8use cranelift_module::{DataId, Module};
9use nifty_check::hir::{Program, Type};
10use nifty_rt::{TypeDesc, TypeKind};
11
12use super::runtime::Runtime;
13use crate::CodegenError;
14use crate::emit::{Blob, Emitter, Target};
15
16#[derive(Debug, Default)]
17pub(super) struct Types {
18 declared: HashMap<Type, DataId>,
19 pending: Vec<(Type, DataId)>,
21}
22
23impl Types {
24 pub fn desc<M: Module>(
26 &mut self,
27 module: &mut M,
28 runtime: &Runtime,
29 ty: &Type,
30 ) -> Result<DataId, CodegenError> {
31 match ty {
32 Type::Int => return Ok(runtime.int),
33 Type::Float => return Ok(runtime.float),
34 Type::Bool => return Ok(runtime.bool),
35 Type::String => return Ok(runtime.string),
36 Type::List(_) | Type::Struct(_) => {}
37 Type::Void | Type::Error => {
38 return Err(CodegenError::new(format!("no value has the type {ty:?}")));
39 }
40 }
41 if let Some(id) = self.declared.get(ty) {
42 return Ok(*id);
43 }
44 let id = module.declare_anonymous_data(false, false)?;
45 self.declared.insert(ty.clone(), id);
46 self.pending.push((ty.clone(), id));
47 Ok(id)
48 }
49
50 pub fn emit<M: Module>(
52 &mut self,
53 emitter: &mut Emitter<M>,
54 runtime: &Runtime,
55 program: &Program,
56 ) -> Result<(), CodegenError> {
57 while let Some((ty, id)) = self.pending.pop() {
58 let (kind, children) = match &ty {
59 Type::List(element) => (TypeKind::List, vec![Type::clone(element)]),
60 Type::Struct(id) => {
61 let fields = &program.structs[id.0].fields;
62 let fields = fields.iter().map(|field| field.ty.clone()).collect();
63 (TypeKind::Struct, fields)
64 }
65 other => {
66 return Err(CodegenError::new(format!(
67 "{other:?} has no descriptor of its own"
68 )));
69 }
70 };
71 let mut list = Blob::zeroed(children.len() * size_of::<&TypeDesc>());
72 for (index, child) in children.iter().enumerate() {
73 let child = self.desc(emitter.module_mut(), runtime, child)?;
74 list.put_pointer(index * size_of::<&TypeDesc>(), Target::Data(child));
75 }
76 let list = emitter.data(list)?;
77 let mut desc = Blob::zeroed(size_of::<TypeDesc>());
78 desc.put_u8(TypeDesc::KIND_OFFSET, kind.code());
79 desc.put_slice(
80 TypeDesc::CHILDREN_OFFSET,
81 Some(Target::Data(list)),
82 children.len(),
83 );
84 emitter.define_data(id, desc)?;
85 }
86 Ok(())
87 }
88}
89
90pub(super) fn is_object(ty: &Type) -> bool {
92 matches!(ty, Type::String | Type::List(_) | Type::Struct(_))
93}