Skip to content

Commit

Permalink
Update version (v0.2.3)
Browse files Browse the repository at this point in the history
Many type inference bugs have been fixed in this version.

Other changes:
Fix: REPL server starts for file input
Improve: Error messages now show operators as human-readable
  • Loading branch information
mtshiba committed Aug 16, 2022
1 parent 5a16310 commit 8028ed8
Show file tree
Hide file tree
Showing 18 changed files with 1,014 additions and 441 deletions.
2 changes: 1 addition & 1 deletion compiler/erg_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "erg_common"
version = "0.2.2"
version = "0.2.3"
description = "A common components library of Erg"
authors = ["Shunsuke Shibayama <[email protected]>"]
license = "MIT OR Apache-2.0"
Expand Down
6 changes: 6 additions & 0 deletions compiler/erg_common/codeobj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,15 @@ impl HasType for CodeObj {
fn ref_t(&self) -> &Type {
&Type::Code
}
fn ref_mut_t(&mut self) -> &mut Type {
todo!()
}
fn signature_t(&self) -> Option<&Type> {
None
}
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}

impl fmt::Debug for CodeObj {
Expand Down
2 changes: 1 addition & 1 deletion compiler/erg_common/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ impl ErrorCore {
}

pub fn unreachable(fn_name: &str, line: u32) -> Self {
Self::bug(0, Location::Unknown, fn_name, line)
Self::bug(line as usize, Location::Unknown, fn_name, line)
}

pub fn bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
Expand Down
6 changes: 3 additions & 3 deletions compiler/erg_common/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,8 @@ pub trait ImmutableStream<T>: Sized {
// for Runnable::run
fn expect_block(src: &str) -> bool {
src.ends_with(&['=', ':'])
|| src.ends_with(":=")
|| src.ends_with("->")
|| src.ends_with("=>")
|| src.ends_with("do")
|| src.ends_with("do!")
}

/// this trait implements REPL (Read-Eval-Print-Loop) automatically
Expand Down Expand Up @@ -497,6 +494,9 @@ pub trait HasType {
fn ref_t(&self) -> &Type;
// 関数呼び出しの場合、.ref_t()は戻り値を返し、signature_t()は関数全体の型を返す
fn signature_t(&self) -> Option<&Type>;
// 最後にHIR全体の型変数を消すために使う
fn ref_mut_t(&mut self) -> &mut Type;
fn signature_mut_t(&mut self) -> Option<&mut Type>;
#[inline]
fn t(&self) -> Type {
self.ref_t().clone()
Expand Down
20 changes: 13 additions & 7 deletions compiler/erg_common/tsort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,35 @@ fn reorder_by_key<T: Eq, U>(mut g: Graph<T, U>, idx: Vec<T>) -> Graph<T, U> {
g
}

fn dfs<T: Eq + Hash + Clone, U>(g: &Graph<T, U>, v: T, used: &mut Set<T>, idx: &mut Vec<T>) {
fn dfs<T: Eq + Hash + Clone, U>(g: &Graph<T, U>, v: T, used: &mut Set<T>, idx: &mut Vec<T>) -> Result<(), ()> {
used.insert(v.clone());
for node_id in g.iter().find(|n| &n.id == &v).unwrap().depends_on.iter() {
// detecting cycles
if used.contains(node_id) && !idx.contains(node_id) {
return Err(());
}
if !used.contains(node_id) {
dfs(g, node_id.clone(), used, idx);
dfs(g, node_id.clone(), used, idx)?;
}
}
idx.push(v);
Ok(())
}

/// perform topological sort on a graph
pub fn tsort<T: Eq + Hash + Clone, U>(g: Graph<T, U>) -> Graph<T, U> {
pub fn tsort<T: Eq + Hash + Clone, U>(g: Graph<T, U>) -> Result<Graph<T, U>, ()> {
let n = g.len();
let mut idx = Vec::with_capacity(n);
let mut used = Set::new();
for v in g.iter() {
if !used.contains(&v.id) {
dfs(&g, v.id.clone(), &mut used, &mut idx);
dfs(&g, v.id.clone(), &mut used, &mut idx)?;
}
}
reorder_by_key(g, idx)
Ok(reorder_by_key(g, idx))
}

fn _test() {
fn _test() -> Result<(), ()> {
let v = vec!["e", "d", "b", "a", "c"];
let idx = vec![3, 2, 4, 1, 0];
assert_eq!(vec!["a", "b", "c", "d", "e"], _reorder_by_idx(v, idx));
Expand All @@ -83,5 +88,6 @@ fn _test() {
on_2.clone(),
];
let dag = vec![en_0, o0_1, on_2, e0_3, ond_4];
assert_eq!(sorted, tsort(dag));
assert_eq!(sorted, tsort(dag)?);
Ok(())
}
124 changes: 119 additions & 5 deletions compiler/erg_common/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,15 @@ pub trait HasLevel {
// REVIEW: TyBoundと微妙に役割が被っている
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Constraint {
/// :> T
SupertypeOf(Type),
/// <: T
SubtypeOf(Type),
/// :> Sub, <: Sup
Sandwiched { sub: Type, sup: Type },
/// : T
TypeOf(Type),
Uninited,
}

impl fmt::Display for Constraint {
Expand All @@ -102,18 +107,34 @@ impl fmt::Display for Constraint {
Self::SubtypeOf(sup) => write!(f, "<: {sup}"),
Self::Sandwiched { sub, sup } => write!(f, ":> {sub}, <: {sup}"),
Self::TypeOf(ty) => write!(f, ": {}", ty),
Self::Uninited => write!(f, "<uninited>"),
}
}
}

impl Constraint {
pub const fn sandwiched(sub: Type, sup: Type) -> Self {
Self::Sandwiched { sub, sup }
}

pub const fn is_uninited(&self) -> bool {
matches!(self, Self::Uninited)
}

pub fn typ(&self) -> Option<&Type> {
match self {
Self::TypeOf(ty) => Some(ty),
_ => None,
}
}

pub fn sub_type(&self) -> Option<&Type> {
match self {
Self::SupertypeOf(ty) => Some(ty),
_ => None,
}
}

pub fn super_type(&self) -> Option<&Type> {
match self {
Self::SubtypeOf(ty) => Some(ty),
Expand Down Expand Up @@ -269,7 +290,23 @@ impl<T: Clone + HasLevel> Free<T> {
}
}

pub fn unwrap(self) -> T {
pub fn get_name(&self) -> Option<Str> {
match self.0.clone_inner() {
FreeKind::Linked(_) => panic!("the value is linked"),
FreeKind::Unbound { .. } => None,
FreeKind::NamedUnbound { name, .. } => Some(name),
}
}

pub fn unwrap_unbound(self) -> (Option<Str>, usize, Constraint) {
match self.0.clone_inner() {
FreeKind::Linked(_) => panic!("the value is linked"),
FreeKind::Unbound { constraint, lev, .. } => (None, lev, constraint),
| FreeKind::NamedUnbound { name, lev, constraint } => (Some(name), lev, constraint),
}
}

pub fn unwrap_linked(self) -> T {
match self.0.clone_inner() {
FreeKind::Linked(t) => t,
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {
Expand All @@ -289,6 +326,14 @@ impl<T: Clone + HasLevel> Free<T> {
})
}

pub fn crack_constraint(&self) -> Ref<'_, Constraint> {
Ref::map(self.0.borrow(), |f| match f {
FreeKind::Linked(_) => panic!("the value is linked"),
FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } => constraint,
})
}

pub fn type_of(&self) -> Option<Type> {
self.0.borrow().constraint().and_then(|c| c.typ().cloned())
}
Expand All @@ -307,6 +352,30 @@ impl<T: Clone + HasLevel> Free<T> {
)
}

pub fn constraint_is_typeof(&self) -> bool {
matches!(
&*self.0.borrow(),
FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } if constraint.typ().is_some()
)
}

pub fn constraint_is_supertypeof(&self) -> bool {
matches!(
&*self.0.borrow(),
FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } if constraint.sub_type().is_some()
)
}

pub fn constraint_is_subtypeof(&self) -> bool {
matches!(
&*self.0.borrow(),
FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } if constraint.super_type().is_some()
)
}

pub fn is_linked(&self) -> bool {
matches!(&*self.0.borrow(), FreeKind::Linked(_))
}
Expand Down Expand Up @@ -812,6 +881,13 @@ impl TyParam {
_ => true,
}
}

pub fn update_constraint(&self, new_constraint: Constraint) {
match self {
Self::Type(t) => { t.update_constraint(new_constraint) },
_ => {}
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand All @@ -824,6 +900,7 @@ pub enum TyParamOrdering {
NotEqual, // Less or Greater
GreaterEqual, // Greater or Equal
Any,
NoRelation,
}

use TyParamOrdering::*;
Expand Down Expand Up @@ -877,7 +954,7 @@ impl TyParamOrdering {
GreaterEqual => LessEqual,
Equal => NotEqual,
NotEqual => Equal,
Any => Any,
Any | NoRelation => Any,
}
}
}
Expand Down Expand Up @@ -1692,6 +1769,8 @@ pub enum Type {
}, // e.g. T.U
ASTOmitted, // call中のcalleeの型など、不要な部分に付ける
Failure, // when failed to infer
/// used to represent `TyParam` is not initialized (see `erg_compiler::context::instantiate_tp`)
Uninited,
}

impl fmt::Display for Type {
Expand Down Expand Up @@ -1802,6 +1881,10 @@ impl HasType for Type {
fn ref_t(&self) -> &Type {
self
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
self
}
fn inner_ts(&self) -> Vec<Type> {
match self {
Self::Ref(t) | Self::RefMut(t) | Self::VarArgs(t) => {
Expand All @@ -1817,6 +1900,9 @@ impl HasType for Type {
fn signature_t(&self) -> Option<&Type> {
None
}
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}

impl HasLevel for Type {
Expand Down Expand Up @@ -2044,7 +2130,7 @@ impl Type {
Self::poly("Iter", vec![TyParam::t(t)])
}

pub fn refer(t: Type) -> Self {
pub fn ref_(t: Type) -> Self {
Self::Ref(Box::new(t))
}

Expand Down Expand Up @@ -2315,6 +2401,14 @@ impl Type {
Self::Quantified(QuantifiedType::new(unbound_t, bounds))
}

pub fn is_mono_q(&self) -> bool {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_mono_q(),
Self::MonoQVar(_) => true,
_ => false,
}
}

pub fn mutate(self) -> Self {
match self {
Self::Int => Self::IntMut,
Expand Down Expand Up @@ -2403,10 +2497,14 @@ impl Type {

pub fn rec_eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::FreeVar(v), other) | (other, Self::FreeVar(v)) => match &*v.borrow() {
(Self::FreeVar(v), other) => match &*v.borrow() {
FreeKind::Linked(t) => t.rec_eq(other),
_ => self == other,
},
(self_, Self::FreeVar(v)) => match &*v.borrow() {
FreeKind::Linked(t) => t.rec_eq(self_),
_ => self_ == other,
},
(Self::Ref(l), Self::Ref(r)) | (Self::RefMut(l), Self::RefMut(r)) => l.rec_eq(r),
(Self::Subr(l), Self::Subr(r)) => {
match (&l.kind, &r.kind) {
Expand Down Expand Up @@ -2578,6 +2676,7 @@ impl Type {
Self::MonoProj { .. } => "MonoProj",
Self::ASTOmitted => "ASTOmitted",
Self::Failure => "<Failure>",
Self::Uninited => "<Uninited>",
}
}

Expand Down Expand Up @@ -2662,7 +2761,7 @@ impl Type {
pub fn typarams(&self) -> Vec<TyParam> {
match self {
Self::FreeVar(f) if f.is_linked() => f.crack().typarams(),
Self::FreeVar(_unbound) => todo!(),
Self::FreeVar(_unbound) => vec![],
Self::Ref(t) | Self::RefMut(t) => vec![TyParam::t(*t.clone())],
Self::And(param_ts) | Self::Or(param_ts) | Self::Not(param_ts) => {
param_ts.iter().map(|t| TyParam::t(t.clone())).collect()
Expand Down Expand Up @@ -2745,6 +2844,13 @@ impl Type {
_ => None,
}
}

pub fn update_constraint(&self, new_constraint: Constraint) {
match self {
Self::FreeVar(fv) => { fv.update_constraint(new_constraint); },
_ => {},
}
}
}

pub mod type_constrs {
Expand All @@ -2770,6 +2876,11 @@ pub mod type_constrs {
Type::mono_q(name)
}

#[inline]
pub fn mono_proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type {
Type::mono_proj(lhs, rhs)
}

#[inline]
pub fn poly<S: Into<Str>>(name: S, params: Vec<TyParam>) -> Type {
Type::poly(name, params)
Expand Down Expand Up @@ -2890,6 +3001,7 @@ impl From<&Type> for TypeCode {
"Proc" => Self::Proc,
_ => Self::Other,
},
Type::Refinement(refine) => Self::from(&*refine.t),
_ => Self::Other,
}
}
Expand Down Expand Up @@ -3148,6 +3260,8 @@ impl TypePair {
{
Self::ProcProc
}
(Type::Refinement(refine), r) => Self::new(&*refine.t, r),
(l, Type::Refinement(refine)) => Self::new(l, &*refine.t),
(_, _) => Self::Others,
}
}
Expand Down
Loading

0 comments on commit 8028ed8

Please sign in to comment.