diff --git a/huia-compiler/src/context.rs b/huia-compiler/src/context.rs index 0164a51..258c72e 100644 --- a/huia-compiler/src/context.rs +++ b/huia-compiler/src/context.rs @@ -66,6 +66,13 @@ impl Context { idx.into() } + pub fn declare_impl(&mut self, tr: TyIdx, ty: TyIdx, location: Location) -> TyIdx { + let idx = self.types.len(); + let ty = Ty::new_impl(ty, tr, location); + self.types.push(ty); + idx.into() + } + pub fn reference_type(&mut self, name: &StringIdx, location: Location) -> TyIdx { // Try and eagerly deference types if we can. // This can theoretically return another type reference, so we still @@ -87,6 +94,12 @@ impl Context { self.types.get(usize::from(idx)) } + #[cfg(test)] + pub fn find_type(&mut self, name: &str) -> Option<&Ty> { + let name = self.constant_string(name); + self.types.iter().find(|ty| ty.name() == Some(name.clone())) + } + pub fn location(&self, location: &InputLocation) -> Location { let path = self.strings.get(self.current_file.clone()).unwrap(); Location::new(location.clone(), path) diff --git a/huia-compiler/src/ir/builder.rs b/huia-compiler/src/ir/builder.rs index fb229ec..5c94c28 100644 --- a/huia-compiler/src/ir/builder.rs +++ b/huia-compiler/src/ir/builder.rs @@ -182,7 +182,6 @@ impl Builder { } self.pop_ty(); - self.push_ir(IR::TypeDefinition(ty)); } NodeType::TraitDef => { let (ty, typespec, body) = node.traitdef().unwrap(); @@ -212,49 +211,48 @@ impl Builder { } self.pop_ty(); - self.push_ir(IR::TraitDefinition(ty)); } NodeType::ImplDef => { let (ty, body) = node.impldef().unwrap(); let ty_idx = context.constant_string(ty.value_ref().as_str()); let location = context.location(&node.location()); - let ty = context.reference_type(&ty_idx, location); + let tr = context.reference_type(&ty_idx, location.clone()); // the parser state should stop us from being in an // implementation whilst not inside a type definition. - let current_type = self.peek_ty().unwrap().clone(); + let ty = self.peek_ty().unwrap().clone(); + + let im = context.declare_impl(tr, ty, location); + + self.push_ty(im.clone()); for node in body { self.build(node.clone(), &mut context); } - self.push_ir(IR::ImplementTrait(current_type, ty)); + self.pop_ty(); } _ => (), } } - pub fn pop(&mut self) -> Option { - self.pop_ir() - } - - fn push_ir(&mut self, ir: IR) { + pub fn push_ir(&mut self, ir: IR) { self.ir_stack.push(ir); } - fn pop_ir(&mut self) -> Option { + pub fn pop_ir(&mut self) -> Option { self.ir_stack.pop() } - fn push_ty(&mut self, ty: TyIdx) { + pub fn push_ty(&mut self, ty: TyIdx) { self.ty_stack.push(ty); } - fn pop_ty(&mut self) -> Option { + pub fn pop_ty(&mut self) -> Option { self.ty_stack.pop() } - fn peek_ty(&self) -> Option<&TyIdx> { + pub fn peek_ty(&self) -> Option<&TyIdx> { let len = self.ty_stack.len(); self.ty_stack.get(len - 1) } @@ -270,8 +268,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.Atom").is_some()); } #[test] @@ -280,8 +279,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.Boolean").is_some()); } #[test] @@ -290,8 +290,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.Float").is_some()); } #[test] @@ -300,8 +301,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.String").is_some()); } #[test] @@ -310,8 +312,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_type_reference()); + assert!(context.find_type("MartyMcFly").is_some()); } #[test] @@ -320,8 +323,10 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.Array").is_some()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -330,8 +335,11 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constant()); + assert!(context.find_type("Huia.Native.Map").is_some()); + assert!(context.find_type("Huia.Native.Atom").is_some()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -340,8 +348,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_infix()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -350,8 +359,10 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_constuctor()); + assert!(context.find_type("Delorean").is_some()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -360,8 +371,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_unary()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -370,8 +382,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_call()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -380,8 +393,9 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); + let ir = builder.pop_ir().unwrap(); assert!(ir.is_declaration()); + assert!(context.find_type("Huia.Native.Integer").is_some()); } #[test] @@ -390,8 +404,8 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); - assert!(ir.is_type_definition()); + assert!(context.find_type("Delorean").is_some()); + assert!(context.find_type("Integer").is_some()); } #[test] @@ -400,8 +414,7 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - let ir = builder.pop().unwrap(); - assert!(ir.is_trait_definition()); + assert!(context.find_type("TimeMachine").is_some()); } #[test] @@ -418,13 +431,8 @@ mod test { let mut builder = Builder::default(); let mut context = Context::test(); builder.build(term, &mut context); - - // The type definition is pushed onto the stack last. - let ir = builder.pop().unwrap(); - assert!(ir.is_type_definition()); - - let ir = builder.pop().unwrap(); - assert!(ir.is_trait_implementation()); + assert!(context.find_type("Delorean").is_some()); + assert!(context.find_type("TimeMachine").is_some()); } } diff --git a/huia-compiler/src/ir/mod.rs b/huia-compiler/src/ir/mod.rs index a8702c6..befb568 100644 --- a/huia-compiler/src/ir/mod.rs +++ b/huia-compiler/src/ir/mod.rs @@ -18,9 +18,6 @@ pub enum IR { Unary(UnOp, Box), Call(StringIdx, Vec), Declaration(StringIdx, Box), - TypeDefinition(TyIdx), - TraitDefinition(TyIdx), - ImplementTrait(TyIdx, TyIdx), } impl IR { @@ -72,27 +69,6 @@ impl IR { _ => false, } } - - pub fn is_type_definition(&self) -> bool { - match self { - IR::TypeDefinition(..) => true, - _ => false, - } - } - - pub fn is_trait_definition(&self) -> bool { - match self { - IR::TraitDefinition(..) => true, - _ => false, - } - } - - pub fn is_trait_implementation(&self) -> bool { - match self { - IR::ImplementTrait(..) => true, - _ => false, - } - } } /// A constant value. diff --git a/huia-compiler/src/ty.rs b/huia-compiler/src/ty.rs index bd18485..063d54c 100644 --- a/huia-compiler/src/ty.rs +++ b/huia-compiler/src/ty.rs @@ -47,6 +47,15 @@ impl Ty { } } + pub fn new_impl(ty: TyIdx, tr: TyIdx, location: Location) -> Ty { + Ty { + name: None, + location, + kind: TyKind::Impl, + inner: TyInner::Impl { ty, tr }, + } + } + pub fn name(&self) -> Option { self.name.clone() } @@ -72,6 +81,13 @@ impl Ty { _ => false, } } + + pub fn is_impl(&self) -> bool { + match self.kind { + TyKind::Impl => true, + _ => false, + } + } } #[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] @@ -100,6 +116,7 @@ pub enum TyKind { Native, Type, Trait, + Impl, Unresolved, } @@ -109,6 +126,7 @@ impl fmt::Display for TyKind { TyKind::Native => write!(f, "native type"), TyKind::Type => write!(f, "type"), TyKind::Trait => write!(f, "trait"), + TyKind::Impl => write!(f, "trait implementation"), TyKind::Unresolved => write!(f, "unresolved type"), } } @@ -118,6 +136,7 @@ impl fmt::Display for TyKind { enum TyInner { Type { properties: Vec<(StringIdx, TyIdx)> }, Trait { dependencies: Vec }, + Impl { tr: TyIdx, ty: TyIdx }, NativeInteger, NativeFloat, NativeString,