wip: anyone know how to write a type checker?
This commit is contained in:
parent
9675e7fff5
commit
de99800349
4 changed files with 59 additions and 7 deletions
|
@ -4,7 +4,6 @@ use crate::source::Source;
|
||||||
use crate::span::Span;
|
use crate::span::Span;
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::num::{ParseFloatError, ParseIntError};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,39 @@ impl Type {
|
||||||
matches!(self, Type::External { .. })
|
matches!(self, Type::External { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_bound(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Type::Struct { .. } => true,
|
||||||
|
Type::Protocol { .. } => true,
|
||||||
|
Type::Impl { .. } => true,
|
||||||
|
Type::Union { types, .. } => types.iter().all(|t| t.is_bound()),
|
||||||
|
Type::Atom => true,
|
||||||
|
Type::Boolean => true,
|
||||||
|
Type::Integer => true,
|
||||||
|
Type::Float => true,
|
||||||
|
Type::String => true,
|
||||||
|
Type::Array => true,
|
||||||
|
Type::Map => true,
|
||||||
|
Type::Function {
|
||||||
|
associated_type,
|
||||||
|
arguments,
|
||||||
|
result,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
associated_type.is_bound()
|
||||||
|
&& result.is_bound()
|
||||||
|
&& arguments.iter().all(|t| t.is_bound())
|
||||||
|
}
|
||||||
|
Type::Variable { r#type, .. } => r#type.borrow().is_bound(),
|
||||||
|
Type::External { .. } => true,
|
||||||
|
Type::Alias { target, .. } => target.is_bound(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_unbound(&self) -> bool {
|
||||||
|
!self.is_bound()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span(&self) -> Option<Span> {
|
pub fn span(&self) -> Option<Span> {
|
||||||
match self {
|
match self {
|
||||||
Type::Struct { span, .. } => Some(span.clone()),
|
Type::Struct { span, .. } => Some(span.clone()),
|
||||||
|
@ -190,6 +223,14 @@ impl TypeVariable {
|
||||||
pub fn is_reference(&self) -> bool {
|
pub fn is_reference(&self) -> bool {
|
||||||
matches!(self, TypeVariable::Reference { .. })
|
matches!(self, TypeVariable::Reference { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_bound(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
TypeVariable::Unbound { .. } => false,
|
||||||
|
TypeVariable::Reference { .. } => false,
|
||||||
|
TypeVariable::Link { target } => target.is_bound(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for TypeVariable {
|
impl ToString for TypeVariable {
|
||||||
|
|
|
@ -22,6 +22,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use ir::Context;
|
pub use ir::Context;
|
||||||
|
pub use ir::Type;
|
||||||
pub use source::Source;
|
pub use source::Source;
|
||||||
|
|
||||||
pub fn compile(source: Arc<Source>) -> Result<Context, Error> {
|
pub fn compile(source: Arc<Source>) -> Result<Context, Error> {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate miette;
|
extern crate miette;
|
||||||
|
|
||||||
extern crate outrun_compiler;
|
extern crate outrun_compiler;
|
||||||
|
|
||||||
use outrun_compiler::{Context, Error, Source};
|
use outrun_compiler::{Context, Error, Source};
|
||||||
|
@ -17,7 +15,7 @@ pub fn init() -> Result<Vec<Context>, Error> {
|
||||||
|
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
|
|
||||||
for path in files.iter() {
|
for path in files.iter().take(1) {
|
||||||
let source = Source::from_file(path)?;
|
let source = Source::from_file(path)?;
|
||||||
let source = Arc::new(source);
|
let source = Arc::new(source);
|
||||||
let context = outrun_compiler::compile(source)?;
|
let context = outrun_compiler::compile(source)?;
|
||||||
|
@ -50,13 +48,26 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use miette::Result;
|
use miette::Result;
|
||||||
|
use outrun_compiler::Type;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_init() -> Result<()> {
|
fn test_init() -> Result<()> {
|
||||||
let result = init()?;
|
let results = init()?;
|
||||||
|
|
||||||
|
println!("results: {:#?}", results);
|
||||||
|
|
||||||
|
for context in results {
|
||||||
|
let unbound_types: Vec<Arc<Type>> = context
|
||||||
|
.types
|
||||||
|
.iter()
|
||||||
|
.filter(|t| t.is_unbound())
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
println!("unbound_types: {:#?}", unbound_types);
|
||||||
|
|
||||||
|
assert_eq!(unbound_types.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
println!("result: {:?}", result);
|
|
||||||
assert!(false);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue