All blocks have result types.

This commit is contained in:
James Harton 2019-04-03 19:56:05 +13:00
parent c465cdf9a4
commit 396a6d020b
13 changed files with 71 additions and 34 deletions

View file

@ -33,8 +33,8 @@ impl Clause {
} }
impl ResultType for Clause { impl ResultType for Clause {
fn result_type(&self) -> Option<&TyIdx> { fn result_type(&self) -> &TyIdx {
Some(&self.result_type) &self.result_type
} }
} }

View file

@ -159,7 +159,11 @@ fn fmt_types(buffer: &mut String, context: &Context) {
} else if ty.is_unresolved() { } else if ty.is_unresolved() {
buffer.push_str("unknown type"); buffer.push_str("unknown type");
} }
buffer.push_str("\n") if let Some(location) = ty.get_location() {
buffer.push_str(&format!(" defined at {}\n", location));
} else {
buffer.push_str("\n");
}
} }
} }
@ -195,7 +199,7 @@ fn fmt_functions(mut buffer: &mut String, context: &Context) {
} }
buffer.push_str(&format!( buffer.push_str(&format!(
" -> {}\n", " -> {}\n",
fmt_ty_name(clause.result_type().unwrap(), &context) fmt_ty_name(clause.result_type(), &context)
)); ));
let mut jumps = Vec::new(); let mut jumps = Vec::new();
@ -530,7 +534,7 @@ fn fmt_methods(mut buffer: &mut String, context: &Context) {
} }
buffer.push_str(&format!( buffer.push_str(&format!(
" -> {}\n", " -> {}\n",
fmt_ty_name(clause.result_type().unwrap(), &context) fmt_ty_name(clause.result_type(), &context)
)); ));
let mut jumps = vec![clause.body().clone()]; let mut jumps = vec![clause.body().clone()];

View file

@ -88,20 +88,20 @@ impl Locatable for &mut Function {
} }
impl ResultType for Function { impl ResultType for Function {
fn result_type(&self) -> Option<&TyIdx> { fn result_type(&self) -> &TyIdx {
Some(&self.return_type) &self.return_type
} }
} }
impl ResultType for &Function { impl ResultType for &Function {
fn result_type(&self) -> Option<&TyIdx> { fn result_type(&self) -> &TyIdx {
Some(&self.return_type) &self.return_type
} }
} }
impl ResultType for &mut Function { impl ResultType for &mut Function {
fn result_type(&self) -> Option<&TyIdx> { fn result_type(&self) -> &TyIdx {
Some(&self.return_type) &self.return_type
} }
} }

View file

@ -1,6 +1,7 @@
use crate::block::BlockIdx; use crate::block::BlockIdx;
use crate::clause::Clauseable; use crate::clause::Clauseable;
use crate::context::Context; use crate::context::Context;
use crate::ty::ResultType;
pub fn pass<T: Clauseable>(fun: &mut T, mut context: &mut Context) { pub fn pass<T: Clauseable>(fun: &mut T, mut context: &mut Context) {
for clause in fun.clauses() { for clause in fun.clauses() {

View file

@ -6,7 +6,7 @@ use crate::ty::ResultType;
pub fn pass<T: Clauseable + Locatable + ResultType>(fun: &mut T, context: &mut Context) { pub fn pass<T: Clauseable + Locatable + ResultType>(fun: &mut T, context: &mut Context) {
for clause in fun.clauses() { for clause in fun.clauses() {
let block_idx = clause.body(); let block_idx = clause.body();
let ty_idx = clause.result_type().unwrap(); let ty_idx = clause.result_type();
let result_type = context.get_block(block_idx).unwrap().result_type().clone(); let result_type = context.get_block(block_idx).unwrap().result_type().clone();
let ty = context.get_type_mut(ty_idx).unwrap(); let ty = context.get_type_mut(ty_idx).unwrap();
ty.resolve(&result_type); ty.resolve(&result_type);

View file

@ -43,6 +43,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
mod test { mod test {
use super::*; use super::*;
use crate::ir::builder::Builder; use crate::ir::builder::Builder;
use crate::location::Location;
use huia_parser::ast::Term; use huia_parser::ast::Term;
#[test] #[test]
@ -50,6 +51,7 @@ mod test {
let terms = Term::input("3 * 2").unwrap(); let terms = Term::input("3 * 2").unwrap();
let mut context = Context::test(); let mut context = Context::test();
let mut builder = Builder::default(); let mut builder = Builder::default();
builder.push_block(context.unknown_type(Location::test()));
for term in terms { for term in terms {
builder.build(term, &mut context); builder.build(term, &mut context);

View file

@ -27,6 +27,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
mod test { mod test {
use super::*; use super::*;
use crate::ir::builder::Builder; use crate::ir::builder::Builder;
use crate::location::Location;
use huia_parser::ast::Term; use huia_parser::ast::Term;
#[test] #[test]
@ -34,6 +35,7 @@ mod test {
let terms = Term::input("!3").unwrap(); let terms = Term::input("!3").unwrap();
let mut context = Context::test(); let mut context = Context::test();
let mut builder = Builder::default(); let mut builder = Builder::default();
builder.push_block(context.unknown_type(Location::test()));
for term in terms { for term in terms {
builder.build(term, &mut context); builder.build(term, &mut context);

View file

@ -71,6 +71,7 @@ fn perform_f64_infix_fold(op: &BinOp, lhs: f64, rhs: f64) -> Option<f64> {
mod test { mod test {
use super::*; use super::*;
use crate::ir::builder::Builder; use crate::ir::builder::Builder;
use crate::location::Location;
use huia_parser::ast::Term; use huia_parser::ast::Term;
#[test] #[test]
@ -78,6 +79,7 @@ mod test {
let term = Term::input("3 * 2 + 13 / 2").unwrap()[0].clone(); let term = Term::input("3 * 2 + 13 / 2").unwrap()[0].clone();
let mut context = Context::test(); let mut context = Context::test();
let mut builder = Builder::default(); let mut builder = Builder::default();
builder.push_block(context.unknown_type(Location::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let mut ir = builder.pop_ir().unwrap(); let mut ir = builder.pop_ir().unwrap();
@ -92,6 +94,7 @@ mod test {
let term = Term::input("1.5 * 2.0 / 3.0").unwrap()[0].clone(); let term = Term::input("1.5 * 2.0 / 3.0").unwrap()[0].clone();
let mut context = Context::test(); let mut context = Context::test();
let mut builder = Builder::default(); let mut builder = Builder::default();
builder.push_block(context.unknown_type(Location::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let mut ir = builder.pop_ir().unwrap(); let mut ir = builder.pop_ir().unwrap();

View file

@ -54,6 +54,8 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
mod test { mod test {
use super::*; use super::*;
use crate::ir::builder::Builder; use crate::ir::builder::Builder;
use crate::location::Location;
use crate::ty::ResultType;
use huia_parser::ast::Term; use huia_parser::ast::Term;
#[test] #[test]
@ -61,6 +63,7 @@ mod test {
let term = Term::input("!3").unwrap()[0].clone(); let term = Term::input("!3").unwrap()[0].clone();
let mut context = Context::test(); let mut context = Context::test();
let mut builder = Builder::default(); let mut builder = Builder::default();
builder.push_block(context.unknown_type(Location::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let mut ir = builder.pop_ir().unwrap(); let mut ir = builder.pop_ir().unwrap();

View file

@ -9,7 +9,7 @@ use crate::location::Locatable;
use crate::location::Location as Loc; use crate::location::Location as Loc;
use crate::method::{Method, MethodIdx, Modifier}; use crate::method::{Method, MethodIdx, Modifier};
use crate::stable::StringIdx; use crate::stable::StringIdx;
use crate::ty::TyIdx; use crate::ty::{ResultType, TyIdx};
use huia_parser::ast::{Identifier, Location, NodeType, Term, TypeSpec, Value}; use huia_parser::ast::{Identifier, Location, NodeType, Term, TypeSpec, Value};
/// The Builder is a simple stack machine for converting AST into IR. /// The Builder is a simple stack machine for converting AST into IR.
@ -69,7 +69,7 @@ impl Builder {
context.reference_type(&name, location.clone()) context.reference_type(&name, location.clone())
} }
else if op.is_arithmetic() { else if op.is_arithmetic() {
lhs.result_type() lhs.result_type().clone()
} }
else { else {
panic!("Operator {:?} is neither arithmetic nor logical", op); panic!("Operator {:?} is neither arithmetic nor logical", op);
@ -123,7 +123,7 @@ impl Builder {
self.build(rhs.clone(), &mut context); self.build(rhs.clone(), &mut context);
let rhs = self.pop_ir().unwrap(); let rhs = self.pop_ir().unwrap();
self.env_set(&name, &rhs.result_type()); self.env_set(&name, &rhs.result_type());
self.push_ir(IR::new_set_local(rhs.result_type(), location, name, rhs)); self.push_ir(IR::new_set_local(rhs.result_type().clone(), location, name, rhs));
} }
NodeType::Float => { NodeType::Float => {
let ty_idx = context.constant_string("Huia.Native.Float"); let ty_idx = context.constant_string("Huia.Native.Float");
@ -171,8 +171,8 @@ impl Builder {
if let Some(last_ir) = self.pop_ir() { if let Some(last_ir) = self.pop_ir() {
let rt = context.get_type_mut(&result_type).unwrap(); let rt = context.get_type_mut(&result_type).unwrap();
rt.resolve(&last_ir.result_type()); rt.resolve(&last_ir.result_type());
self.push_ir(IR::new_set_local(last_ir.result_type(), location.clone(), value_var_name.clone(), last_ir.clone())); self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name.clone(), last_ir.clone()));
self.push_ir(IR::new_jump(last_ir.result_type(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into()));
} else { } else {
self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into()));
} }
@ -198,12 +198,12 @@ impl Builder {
if let Some(last_ir) = self.pop_ir() { if let Some(last_ir) = self.pop_ir() {
let rt = context.get_type(&result_type).unwrap(); let rt = context.get_type(&result_type).unwrap();
if rt.target().unwrap() != &last_ir.result_type() { if rt.target().unwrap() != last_ir.result_type() {
context.compile_error("Both branches of an if statement must result in the same type.", location.clone(), ErrorKind::InconsistentBranchTypes); context.compile_error("Both branches of an if statement must result in the same type.", location.clone(), ErrorKind::InconsistentBranchTypes);
} }
self.push_ir(IR::new_set_local(last_ir.result_type(), location.clone(), value_var_name.clone(), last_ir.clone())); self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name.clone(), last_ir.clone()));
self.push_ir(IR::new_jump(last_ir.result_type(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into()));
} else { } else {
self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into()));
} }
@ -454,7 +454,7 @@ impl Builder {
let (op, rhs) = node.unary().unwrap(); let (op, rhs) = node.unary().unwrap();
self.build(rhs.clone(), &mut context); self.build(rhs.clone(), &mut context);
let rhs = self.pop_ir().unwrap(); let rhs = self.pop_ir().unwrap();
let result_type = rhs.result_type(); let result_type = rhs.result_type().clone();
self.push_ir(IR::new_unary( self.push_ir(IR::new_unary(
result_type, result_type,
location, location,
@ -524,7 +524,7 @@ impl Builder {
self.push_ir(last_ir); self.push_ir(last_ir);
} else { } else {
self.push_ir(IR::new_return( self.push_ir(IR::new_return(
last_ir.result_type(), last_ir.result_type().clone(),
last_ir.get_location().clone(), last_ir.get_location().clone(),
last_ir, last_ir,
)); ));
@ -668,7 +668,7 @@ impl Builder {
None None
} }
fn push_block(&mut self, result_type: TyIdx) { pub fn push_block(&mut self, result_type: TyIdx) {
match self.peek_block() { match self.peek_block() {
Some(ref block) => { Some(ref block) => {
let env = block.env().clone(); let env = block.env().clone();
@ -707,6 +707,7 @@ mod test {
let term = Term::input(":marty").unwrap()[0].clone(); let term = Term::input(":marty").unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -718,6 +719,7 @@ mod test {
let term = Term::input("true").unwrap()[0].clone(); let term = Term::input("true").unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -729,6 +731,7 @@ mod test {
let term = Term::input("1.23").unwrap()[0].clone(); let term = Term::input("1.23").unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -740,6 +743,7 @@ mod test {
let term = Term::input(r#" "Marty McFly" "#).unwrap()[0].clone(); let term = Term::input(r#" "Marty McFly" "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -751,6 +755,7 @@ mod test {
let term = Term::input(r#" MartyMcFly "#).unwrap()[0].clone(); let term = Term::input(r#" MartyMcFly "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_type_reference()); assert!(ir.is_type_reference());
@ -762,6 +767,7 @@ mod test {
let term = Term::input(r#" [1, 2, 3] "#).unwrap()[0].clone(); let term = Term::input(r#" [1, 2, 3] "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -774,6 +780,7 @@ mod test {
let term = Term::input(r#" { a: 2, :b => 3 } "#).unwrap()[0].clone(); let term = Term::input(r#" { a: 2, :b => 3 } "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constant()); assert!(ir.is_constant());
@ -787,6 +794,7 @@ mod test {
let term = Term::input(r#" if true do 123 end "#).unwrap()[0].clone(); let term = Term::input(r#" if true do 123 end "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
// Pop the follower block off the block stack. // Pop the follower block off the block stack.
@ -803,6 +811,7 @@ mod test {
let term = Term::input(r#" if true do 123 else 456 end "#).unwrap()[0].clone(); let term = Term::input(r#" if true do 123 else 456 end "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
// Pop the follower block off the block stack. // Pop the follower block off the block stack.
@ -820,6 +829,7 @@ mod test {
let term = Term::input(r#" 1 + 2 "#).unwrap()[0].clone(); let term = Term::input(r#" 1 + 2 "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_infix()); assert!(ir.is_infix());
@ -831,6 +841,7 @@ mod test {
let term = Term::input(r#" Delorean { speed: 88 } "#).unwrap()[0].clone(); let term = Term::input(r#" Delorean { speed: 88 } "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_constructor()); assert!(ir.is_constructor());
@ -843,6 +854,7 @@ mod test {
let term = Term::input(r#" +88 "#).unwrap()[0].clone(); let term = Term::input(r#" +88 "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_unary()); assert!(ir.is_unary());
@ -854,6 +866,7 @@ mod test {
let terms = Term::input(" let x = 1\n x(123) ").unwrap(); let terms = Term::input(" let x = 1\n x(123) ").unwrap();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
for term in terms { for term in terms {
builder.build(term, &mut context); builder.build(term, &mut context);
} }
@ -867,6 +880,7 @@ mod test {
let term = Term::input(r#" let x = 123 "#).unwrap()[0].clone(); let term = Term::input(r#" let x = 123 "#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_set_local()); assert!(ir.is_set_local());
@ -878,6 +892,7 @@ mod test {
let term = Term::file("type Delorean(speed: Integer)").unwrap()[0].clone(); let term = Term::file("type Delorean(speed: Integer)").unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
assert!(context.find_type("Delorean").is_some()); assert!(context.find_type("Delorean").is_some());
assert!(context.find_type("Integer").is_some()); assert!(context.find_type("Integer").is_some());
@ -888,6 +903,7 @@ mod test {
let term = Term::file("trait TimeMachine").unwrap()[0].clone(); let term = Term::file("trait TimeMachine").unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
assert!(context.find_type("TimeMachine").is_some()); assert!(context.find_type("TimeMachine").is_some());
} }
@ -905,6 +921,7 @@ mod test {
.clone(); .clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
assert!(context.find_type("Delorean").is_some()); assert!(context.find_type("Delorean").is_some());
assert!(context.find_type("TimeMachine").is_some()); assert!(context.find_type("TimeMachine").is_some());
@ -915,6 +932,7 @@ mod test {
let term = Term::input(r#"fn (speed: Integer) do "WAT" end"#).unwrap()[0].clone(); let term = Term::input(r#"fn (speed: Integer) do "WAT" end"#).unwrap()[0].clone();
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
let ir = builder.pop_ir().unwrap(); let ir = builder.pop_ir().unwrap();
assert!(ir.is_function()); assert!(ir.is_function());
@ -964,9 +982,7 @@ mod test {
let mut builder = Builder::default(); let mut builder = Builder::default();
let mut context = Context::test(); let mut context = Context::test();
builder.push_block(context.unknown_type(Loc::test()));
builder.build(term, &mut context); builder.build(term, &mut context);
// println!("context: {:#?}", context);
// assert!(false);
} }
} }

View file

@ -5,7 +5,7 @@ use crate::context::Context;
use crate::function::FunctionIdx; use crate::function::FunctionIdx;
use crate::location::Location; use crate::location::Location;
use crate::stable::StringIdx; use crate::stable::StringIdx;
use crate::ty::TyIdx; use crate::ty::{ResultType, TyIdx};
use huia_parser::ast::binary::Operator as BinOp; use huia_parser::ast::binary::Operator as BinOp;
use huia_parser::ast::unary::Operator as UnOp; use huia_parser::ast::unary::Operator as UnOp;
@ -526,10 +526,6 @@ impl IR {
} }
} }
pub fn result_type(&self) -> TyIdx {
self.result_type.clone()
}
pub fn set_kind(&mut self, kind: IRKind) { pub fn set_kind(&mut self, kind: IRKind) {
self.kind = kind; self.kind = kind;
} }
@ -539,6 +535,12 @@ impl IR {
} }
} }
impl ResultType for IR {
fn result_type(&self) -> &TyIdx {
&self.result_type
}
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum IRKind { pub enum IRKind {
/// Call the provided callee with arguments. /// Call the provided callee with arguments.

View file

@ -159,8 +159,8 @@ impl Locatable for &mut Method {
} }
impl ResultType for &mut Method { impl ResultType for &mut Method {
fn result_type(&self) -> Option<&TyIdx> { fn result_type(&self) -> &TyIdx {
Some(&self.return_type) &self.return_type
} }
} }

View file

@ -23,6 +23,10 @@ impl Ty {
} }
} }
pub fn get_location(&self) -> Option<&Location> {
self.location.as_ref()
}
pub fn get_prop_type(&self, name: &StringIdx) -> Option<&TyIdx> { pub fn get_prop_type(&self, name: &StringIdx) -> Option<&TyIdx> {
match self.inner { match self.inner {
TyInner::Type { ref properties } => properties.get(name), TyInner::Type { ref properties } => properties.get(name),
@ -369,5 +373,5 @@ enum TyInner {
} }
pub trait ResultType { pub trait ResultType {
fn result_type(&self) -> Option<&TyIdx>; fn result_type(&self) -> &TyIdx;
} }