mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-24 18:39:50 -04:00
feat: Tuple shape narrowing
This commit is contained in:
parent
5835adbf7a
commit
bdfa424545
@ -306,8 +306,7 @@ impl Shape {
|
|||||||
self.narrow_list_shapes(left_slist, right_slist, right)
|
self.narrow_list_shapes(left_slist, right_slist, right)
|
||||||
}
|
}
|
||||||
(Shape::Tuple(left_slist), Shape::Tuple(right_slist)) => {
|
(Shape::Tuple(left_slist), Shape::Tuple(right_slist)) => {
|
||||||
// TODO
|
self.narrow_tuple_shapes(left_slist, right_slist, right)
|
||||||
unimplemented!("Can't merge these yet.");
|
|
||||||
}
|
}
|
||||||
(Shape::Func(left_opshape), Shape::Func(right_opshape)) => {
|
(Shape::Func(left_opshape), Shape::Func(right_opshape)) => {
|
||||||
// TODO
|
// TODO
|
||||||
@ -328,6 +327,18 @@ impl Shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn narrow_tuple_shapes(&self, left_slist: &PositionedItem<Vec<(Token, Shape)>>, right_slist: &PositionedItem<Vec<(Token, Shape)>>, right: &Shape) -> Shape {
|
||||||
|
let left_iter = left_slist.val.iter();
|
||||||
|
let right_iter = right_slist.val.iter();
|
||||||
|
if is_tuple_subset(left_iter, right_slist) {
|
||||||
|
self.clone()
|
||||||
|
} else if is_tuple_subset(right_iter, left_slist) {
|
||||||
|
right.clone()
|
||||||
|
} else {
|
||||||
|
Shape::TypeErr(right.pos().clone(), "Incompatible Tuple Shapes".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn narrow_list_shapes(
|
fn narrow_list_shapes(
|
||||||
&self,
|
&self,
|
||||||
left_slist: &NarrowedShape,
|
left_slist: &NarrowedShape,
|
||||||
@ -336,9 +347,9 @@ impl Shape {
|
|||||||
) -> Shape {
|
) -> Shape {
|
||||||
let left_iter = left_slist.types.iter();
|
let left_iter = left_slist.types.iter();
|
||||||
let right_iter = right_slist.types.iter();
|
let right_iter = right_slist.types.iter();
|
||||||
if is_shape_subset(left_iter, right_slist) {
|
if is_list_subset(left_iter, right_slist) {
|
||||||
self.clone()
|
self.clone()
|
||||||
} else if is_shape_subset(right_iter, left_slist) {
|
} else if is_list_subset(right_iter, left_slist) {
|
||||||
right.clone()
|
right.clone()
|
||||||
} else {
|
} else {
|
||||||
Shape::TypeErr(right.pos().clone(), "Incompatible List Shapes".to_owned())
|
Shape::TypeErr(right.pos().clone(), "Incompatible List Shapes".to_owned())
|
||||||
@ -406,7 +417,34 @@ impl Shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_shape_subset(mut right_iter: std::slice::Iter<Shape>, left_slist: &NarrowedShape) -> bool {
|
fn is_tuple_subset(
|
||||||
|
mut left_iter: std::slice::Iter<(Token, Shape)>,
|
||||||
|
right_slist: &PositionedItem<Vec<(Token, Shape)>>,
|
||||||
|
) -> bool {
|
||||||
|
return loop {
|
||||||
|
if let Some((lt, ls)) = left_iter.next() {
|
||||||
|
let mut matched = false;
|
||||||
|
for (rt, rs) in right_slist.val.iter() {
|
||||||
|
if rt.fragment == lt.fragment {
|
||||||
|
if let Shape::TypeErr(_, _) = ls.narrow(rs) {
|
||||||
|
// noop
|
||||||
|
} else {
|
||||||
|
matched = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
break false;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_list_subset(mut right_iter: std::slice::Iter<Shape>, left_slist: &NarrowedShape) -> bool {
|
||||||
let right_subset = loop {
|
let right_subset = loop {
|
||||||
let mut matches = false;
|
let mut matches = false;
|
||||||
let ls = if let Some(ls) = right_iter.next() {
|
let ls = if let Some(ls) = right_iter.next() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
|
use crate::ast::{Token, TokenType};
|
||||||
use crate::ast::walk::Walker;
|
use crate::ast::walk::Walker;
|
||||||
use crate::ast::{Position, PositionedItem};
|
use crate::ast::{Position, PositionedItem};
|
||||||
use crate::parse;
|
use crate::parse;
|
||||||
@ -54,6 +55,21 @@ fn simple_binary_typecheck() {
|
|||||||
"[] + [];",
|
"[] + [];",
|
||||||
Shape::List(crate::ast::NarrowedShape::new(vec![], 1, 1, 0))
|
Shape::List(crate::ast::NarrowedShape::new(vec![], 1, 1, 0))
|
||||||
);
|
);
|
||||||
|
assert_type_success!(
|
||||||
|
"{} + {};",
|
||||||
|
Shape::Tuple(PositionedItem::new(vec![], Position::new(1, 1, 0)))
|
||||||
|
);
|
||||||
|
// TODO(jwall): + isn't valid for tuples.
|
||||||
|
assert_type_success!(
|
||||||
|
"{foo = 1} + {foo = 1};",
|
||||||
|
Shape::Tuple(PositionedItem::new(
|
||||||
|
vec![
|
||||||
|
(Token { typ: TokenType::BAREWORD, fragment: "foo".to_owned(), pos: Position::new(1, 2, 1)},
|
||||||
|
Shape::Int(PositionedItem::new_with_pos(1, Position::new(1, 8, 7)))),
|
||||||
|
],
|
||||||
|
Position::new(1, 1, 0)
|
||||||
|
))
|
||||||
|
);
|
||||||
assert_type_success!(
|
assert_type_success!(
|
||||||
"[1] + [2];",
|
"[1] + [2];",
|
||||||
Shape::List(crate::ast::NarrowedShape::new(
|
Shape::List(crate::ast::NarrowedShape::new(
|
||||||
@ -70,14 +86,8 @@ fn simple_binary_typecheck() {
|
|||||||
"[1, 1.0] + [1, 2.0];",
|
"[1, 1.0] + [1, 2.0];",
|
||||||
Shape::List(crate::ast::NarrowedShape::new(
|
Shape::List(crate::ast::NarrowedShape::new(
|
||||||
vec![
|
vec![
|
||||||
Shape::Int(PositionedItem::new_with_pos(
|
Shape::Int(PositionedItem::new_with_pos(1, Position::new(1, 1, 0))),
|
||||||
1,
|
Shape::Float(PositionedItem::new_with_pos(1.0, Position::new(1, 1, 0))),
|
||||||
Position::new(1, 1, 0)
|
|
||||||
)),
|
|
||||||
Shape::Float(PositionedItem::new_with_pos(
|
|
||||||
1.0,
|
|
||||||
Position::new(1, 1, 0)
|
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
@ -114,6 +124,17 @@ fn simple_binary_typefail() {
|
|||||||
"Incompatible List Shapes",
|
"Incompatible List Shapes",
|
||||||
Position::new(1, 7, 6)
|
Position::new(1, 7, 6)
|
||||||
);
|
);
|
||||||
|
// TODO(jwall): + isn't valid for tuples.
|
||||||
|
assert_type_fail!(
|
||||||
|
"{foo = 1} + {foo = 1.0};",
|
||||||
|
"Incompatible Tuple Shapes",
|
||||||
|
Position::new(1, 13, 12)
|
||||||
|
);
|
||||||
|
assert_type_fail!(
|
||||||
|
"{foo = 1} + {bar = 1};",
|
||||||
|
"Incompatible Tuple Shapes",
|
||||||
|
Position::new(1, 13, 12)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user