There's no need to store the type declarations in the IR.
This commit is contained in:
parent
292fdb1305
commit
781832eb7d
4 changed files with 77 additions and 61 deletions
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
Reference in a new issue