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()
}
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)

View file

@ -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<IR> {
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<IR> {
pub fn pop_ir(&mut self) -> Option<IR> {
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<TyIdx> {
pub fn pop_ty(&mut self) -> Option<TyIdx> {
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());
}
}

View file

@ -18,9 +18,6 @@ pub enum IR {
Unary(UnOp, Box<IR>),
Call(StringIdx, Vec<IR>),
Declaration(StringIdx, Box<IR>),
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.

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> {
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<TyIdx> },
Impl { tr: TyIdx, ty: TyIdx },
NativeInteger,
NativeFloat,
NativeString,