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()
|
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)
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Reference in a new issue