There's no need to store the type declarations in the IR.

This commit is contained in:
James Harton 2019-03-14 16:51:15 +13:00
parent 292fdb1305
commit 781832eb7d
4 changed files with 77 additions and 61 deletions

View file

@ -66,6 +66,13 @@ impl Context {
idx.into() 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 { pub fn reference_type(&mut self, name: &StringIdx, location: Location) -> TyIdx {
// Try and eagerly deference types if we can. // Try and eagerly deference types if we can.
// This can theoretically return another type reference, so we still // This can theoretically return another type reference, so we still
@ -87,6 +94,12 @@ impl Context {
self.types.get(usize::from(idx)) 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 { pub fn location(&self, location: &InputLocation) -> Location {
let path = self.strings.get(self.current_file.clone()).unwrap(); let path = self.strings.get(self.current_file.clone()).unwrap();
Location::new(location.clone(), path) Location::new(location.clone(), path)

View file

@ -182,7 +182,6 @@ impl Builder {
} }
self.pop_ty(); self.pop_ty();
self.push_ir(IR::TypeDefinition(ty));
} }
NodeType::TraitDef => { NodeType::TraitDef => {
let (ty, typespec, body) = node.traitdef().unwrap(); let (ty, typespec, body) = node.traitdef().unwrap();
@ -212,49 +211,48 @@ impl Builder {
} }
self.pop_ty(); self.pop_ty();
self.push_ir(IR::TraitDefinition(ty));
} }
NodeType::ImplDef => { NodeType::ImplDef => {
let (ty, body) = node.impldef().unwrap(); let (ty, body) = node.impldef().unwrap();
let ty_idx = context.constant_string(ty.value_ref().as_str()); let ty_idx = context.constant_string(ty.value_ref().as_str());
let location = context.location(&node.location()); 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 // the parser state should stop us from being in an
// implementation whilst not inside a type definition. // 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 { for node in body {
self.build(node.clone(), &mut context); self.build(node.clone(), &mut context);
} }
self.push_ir(IR::ImplementTrait(current_type, ty)); self.pop_ty();
} }
_ => (), _ => (),
} }
} }
pub fn pop(&mut self) -> Option<IR> { pub fn push_ir(&mut self, ir: IR) {
self.pop_ir()
}
fn push_ir(&mut self, ir: IR) {
self.ir_stack.push(ir); self.ir_stack.push(ir);
} }
fn pop_ir(&mut self) -> Option<IR> { pub fn pop_ir(&mut self) -> Option<IR> {
self.ir_stack.pop() self.ir_stack.pop()
} }
fn push_ty(&mut self, ty: TyIdx) { pub fn push_ty(&mut self, ty: TyIdx) {
self.ty_stack.push(ty); self.ty_stack.push(ty);
} }
fn pop_ty(&mut self) -> Option<TyIdx> { pub fn pop_ty(&mut self) -> Option<TyIdx> {
self.ty_stack.pop() self.ty_stack.pop()
} }
fn peek_ty(&self) -> Option<&TyIdx> { pub fn peek_ty(&self) -> Option<&TyIdx> {
let len = self.ty_stack.len(); let len = self.ty_stack.len();
self.ty_stack.get(len - 1) self.ty_stack.get(len - 1)
} }
@ -270,8 +268,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
assert!(context.find_type("Huia.Native.Atom").is_some());
} }
#[test] #[test]
@ -280,8 +279,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
assert!(context.find_type("Huia.Native.Boolean").is_some());
} }
#[test] #[test]
@ -290,8 +290,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
assert!(context.find_type("Huia.Native.Float").is_some());
} }
#[test] #[test]
@ -300,8 +301,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
assert!(context.find_type("Huia.Native.String").is_some());
} }
#[test] #[test]
@ -310,8 +312,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_type_reference()); assert!(ir.is_type_reference());
assert!(context.find_type("MartyMcFly").is_some());
} }
#[test] #[test]
@ -320,8 +323,10 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
assert!(context.find_type("Huia.Native.Array").is_some());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -330,8 +335,11 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); 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] #[test]
@ -340,8 +348,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_infix()); assert!(ir.is_infix());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -350,8 +359,10 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constuctor()); assert!(ir.is_constuctor());
assert!(context.find_type("Delorean").is_some());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -360,8 +371,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_unary()); assert!(ir.is_unary());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -370,8 +382,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_call()); assert!(ir.is_call());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -380,8 +393,9 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_declaration()); assert!(ir.is_declaration());
assert!(context.find_type("Huia.Native.Integer").is_some());
} }
#[test] #[test]
@ -390,8 +404,8 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); assert!(context.find_type("Delorean").is_some());
assert!(ir.is_type_definition()); assert!(context.find_type("Integer").is_some());
} }
#[test] #[test]
@ -400,8 +414,7 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop().unwrap(); assert!(context.find_type("TimeMachine").is_some());
assert!(ir.is_trait_definition());
} }
#[test] #[test]
@ -418,13 +431,8 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.build(term, &mut context); builder.build(term, &mut context);
assert!(context.find_type("Delorean").is_some());
// The type definition is pushed onto the stack last. assert!(context.find_type("TimeMachine").is_some());
let ir = builder.pop().unwrap();
assert!(ir.is_type_definition());
let ir = builder.pop().unwrap();
assert!(ir.is_trait_implementation());
} }
} }

View file

@ -18,9 +18,6 @@ pub enum IR {
Unary(UnOp, Box<IR>), Unary(UnOp, Box<IR>),
Call(StringIdx, Vec<IR>), Call(StringIdx, Vec<IR>),
Declaration(StringIdx, Box<IR>), Declaration(StringIdx, Box<IR>),
TypeDefinition(TyIdx),
TraitDefinition(TyIdx),
ImplementTrait(TyIdx, TyIdx),
} }
impl IR { impl IR {
@ -72,27 +69,6 @@ impl IR {
_ => false, _ => 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. /// A constant value.

View file

@ -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<StringIdx> { pub fn name(&self) -> Option<StringIdx> {
self.name.clone() self.name.clone()
} }
@ -72,6 +81,13 @@ impl Ty {
_ => false, _ => false,
} }
} }
pub fn is_impl(&self) -> bool {
match self.kind {
TyKind::Impl => true,
_ => false,
}
}
} }
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] #[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
@ -100,6 +116,7 @@ pub enum TyKind {
Native, Native,
Type, Type,
Trait, Trait,
Impl,
Unresolved, Unresolved,
} }
@ -109,6 +126,7 @@ impl fmt::Display for TyKind {
TyKind::Native => write!(f, "native type"), TyKind::Native => write!(f, "native type"),
TyKind::Type => write!(f, "type"), TyKind::Type => write!(f, "type"),
TyKind::Trait => write!(f, "trait"), TyKind::Trait => write!(f, "trait"),
TyKind::Impl => write!(f, "trait implementation"),
TyKind::Unresolved => write!(f, "unresolved type"), TyKind::Unresolved => write!(f, "unresolved type"),
} }
} }
@ -118,6 +136,7 @@ impl fmt::Display for TyKind {
enum TyInner { enum TyInner {
Type { properties: Vec<(StringIdx, TyIdx)> }, Type { properties: Vec<(StringIdx, TyIdx)> },
Trait { dependencies: Vec<TyIdx> }, Trait { dependencies: Vec<TyIdx> },
Impl { tr: TyIdx, ty: TyIdx },
NativeInteger, NativeInteger,
NativeFloat, NativeFloat,
NativeString, NativeString,