refactor: Get rid of the unecessary PositionedItem

This commit is contained in:
Jeremy Wall 2023-10-02 19:57:15 -04:00 committed by Jeremy Wall
parent d1e5d4129f
commit 76f1f0dee6
12 changed files with 149 additions and 177 deletions

View File

@ -278,10 +278,10 @@ impl NarrowedShape {
/// Shapes represent the types that UCG values or expressions can have.
#[derive(PartialEq, Debug, Clone)]
pub enum Shape {
Boolean(PositionedItem<bool>),
Int(PositionedItem<i64>),
Float(PositionedItem<f64>),
Str(PositionedItem<Rc<str>>),
Boolean(Position),
Int(Position),
Float(Position),
Str(Position),
Tuple(PositionedItem<TupleShape>),
List(NarrowedShape),
Func(FuncShapeDef),
@ -305,7 +305,7 @@ impl Shape {
symbol_table.insert(sym.val.clone(), other.clone().with_pos(sym.pos.clone()));
}
other.clone()
},
}
(Shape::Narrowed(left_slist), Shape::Narrowed(right_slist))
| (Shape::List(left_slist), Shape::List(right_slist)) => {
self.narrow_list_shapes(left_slist, right_slist, right, symbol_table)
@ -386,10 +386,10 @@ impl Shape {
pub fn pos(&self) -> &Position {
match self {
Shape::Str(s) => &s.pos,
Shape::Int(s) => &s.pos,
Shape::Float(s) => &s.pos,
Shape::Boolean(b) => &b.pos,
Shape::Str(p) => &p,
Shape::Int(p) => &p,
Shape::Float(p) => &p,
Shape::Boolean(p) => &p,
Shape::List(lst) => &lst.pos,
Shape::Tuple(flds) => &flds.pos,
Shape::Func(def) => def.ret.pos(),
@ -404,10 +404,10 @@ impl Shape {
pub fn with_pos(self, pos: Position) -> Self {
match self {
Shape::Str(s) => Shape::Str(PositionedItem::new(s.val, pos)),
Shape::Int(s) => Shape::Int(PositionedItem::new(s.val, pos)),
Shape::Float(s) => Shape::Float(PositionedItem::new(s.val, pos)),
Shape::Boolean(b) => Shape::Boolean(PositionedItem::new(b.val, pos)),
Shape::Str(_) => Shape::Str(pos.clone()),
Shape::Int(_) => Shape::Int(pos.clone()),
Shape::Float(_) => Shape::Float(pos.clone()),
Shape::Boolean(_) => Shape::Boolean(pos.clone()),
Shape::List(lst) => Shape::List(NarrowedShape::new_with_pos(lst.types, pos)),
Shape::Tuple(flds) => Shape::Tuple(PositionedItem::new(flds.val, pos)),
Shape::Func(_) | Shape::Module(_) => self.clone(),

View File

@ -16,7 +16,10 @@ use std::collections::BTreeMap;
use abortable_parser::iter::SliceIter;
use abortable_parser::Result as ParseResult;
use crate::ast::{Expression, ListDef, Position, PositionedItem, Shape, Token, TokenType, Value ,NarrowedShape, typecheck::DeriveShape};
use crate::ast::{
typecheck::DeriveShape, Expression, ListDef, NarrowedShape, Position, PositionedItem, Shape,
Token, TokenType, Value,
};
use crate::iter::OffsetStrIter;
use crate::parse::expression;
use crate::tokenizer::tokenize;
@ -26,29 +29,23 @@ fn derive_shape_values() {
let value_cases = vec![
(
Value::Boolean(PositionedItem::new(false, Position::new(0, 1, 2))),
Shape::Boolean(PositionedItem::new(false, Position::new(0, 1, 2))),
Shape::Boolean(Position::new(0, 1, 2)),
),
(
Value::Boolean(PositionedItem::new(true, Position::new(0, 1, 2))),
Shape::Boolean(PositionedItem::new(true, Position::new(0, 1, 2))),
Shape::Boolean(Position::new(0, 1, 2)),
),
(
Value::Int(PositionedItem::new(1, Position::new(0, 1, 2))),
Shape::Int(PositionedItem::new(1, Position::new(0, 1, 2))),
Shape::Int(Position::new(0, 1, 2)),
),
(
Value::Float(PositionedItem::new(2.0, Position::new(0, 1, 2))),
Shape::Float(PositionedItem::new(2.0, Position::new(0, 1, 2))),
Shape::Float(Position::new(0, 1, 2)),
),
(
Value::Str(PositionedItem::new(
"foo".into(),
Position::new(0, 1, 2),
)),
Shape::Str(PositionedItem::new(
"foo".into(),
Position::new(0, 1, 2),
)),
Value::Str(PositionedItem::new("foo".into(), Position::new(0, 1, 2))),
Shape::Str(Position::new(0, 1, 2)),
),
(
Value::Tuple(PositionedItem::new(
@ -61,7 +58,7 @@ fn derive_shape_values() {
Shape::Tuple(PositionedItem::new(
vec![(
Token::new("foo", TokenType::BAREWORD, Position::new(0, 0, 0)),
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
Shape::Int(Position::new(0, 0, 0)),
)],
Position::new(0, 0, 0),
)),
@ -75,7 +72,7 @@ fn derive_shape_values() {
pos: Position::new(0, 0, 0),
}),
Shape::List(NarrowedShape::new_with_pos(
vec![Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0)))],
vec![Shape::Int(Position::new(0, 0, 0))],
Position::new(0, 0, 0),
)),
),
@ -89,49 +86,22 @@ fn derive_shape_values() {
#[test]
fn derive_shape_expressions() {
let expr_cases = vec![
(
"3;",
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
),
(
"(3);",
Shape::Int(PositionedItem::new(3, Position::new(0, 0, 0))),
),
(
"\"foo {}\" % (1);",
Shape::Str(PositionedItem::new("".into(), Position::new(0, 0, 0))),
),
(
"not true;",
Shape::Boolean(PositionedItem::new(false, Position::new(1, 0, 0))),
),
("3;", Shape::Int(Position::new(0, 0, 0))),
("(3);", Shape::Int(Position::new(0, 0, 0))),
("\"foo {}\" % (1);", Shape::Str(Position::new(0, 0, 0))),
("not true;", Shape::Boolean(Position::new(1, 0, 0))),
(
"0:1;",
Shape::List(NarrowedShape::new_with_pos(
vec![Shape::Int(PositionedItem::new(0, Position::new(1, 1, 0)))],
vec![Shape::Int(Position::new(1, 1, 0))],
Position::new(1, 1, 0),
)),
),
(
"int(\"1\");",
Shape::Int(PositionedItem::new(0, Position::new(0, 0, 0))),
),
(
"float(1);",
Shape::Float(PositionedItem::new(0.0, Position::new(0, 0, 0))),
),
(
"str(1);",
Shape::Str(PositionedItem::new("".into(), Position::new(0, 0, 0))),
),
(
"bool(\"true\");",
Shape::Boolean(PositionedItem::new(true, Position::new(0, 0, 0))),
),
(
"1 + 1;",
Shape::Int(PositionedItem::new(1, Position::new(1, 1, 0))),
),
("int(\"1\");", Shape::Int(Position::new(0, 0, 0))),
("float(1);", Shape::Float(Position::new(0, 0, 0))),
("str(1);", Shape::Str(Position::new(0, 0, 0))),
("bool(\"true\");", Shape::Boolean(Position::new(0, 0, 0))),
("1 + 1;", Shape::Int(Position::new(1, 1, 0))),
];
for (expr, shape) in expr_cases {

View File

@ -38,7 +38,7 @@ impl DeriveShape for FuncDef {
let mut sym_table = self
.argdefs
.iter()
.map(|sym| (sym.val.clone(), Shape::Hole(sym.clone())))
.map(|sym| (sym.val.clone(), dbg!(Shape::Hole(sym.clone()))))
.collect::<BTreeMap<Rc<str>, Shape>>();
sym_table.append(&mut symbol_table.clone());
// 2.Then determine the shapes of those symbols in our expression.
@ -48,11 +48,20 @@ impl DeriveShape for FuncDef {
let table = self
.argdefs
.iter()
.map(|sym| (sym.val.clone(), sym_table.get(&sym.val).unwrap().clone()))
.map(|sym| {
(
sym.val.clone(),
dbg!(sym_table
.get(&sym.val)
.unwrap()
.clone()
.with_pos(sym.pos.clone())),
)
})
.collect::<BTreeMap<Rc<str>, Shape>>();
Shape::Func(FuncShapeDef {
args: table,
ret: shape.into(),
ret: shape.with_pos(self.pos.clone()).into(),
})
}
}
@ -75,14 +84,14 @@ fn derive_include_shape(
fn derive_not_shape(def: &NotDef, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
let shape = def.expr.as_ref().derive_shape(symbol_table);
if let Shape::Boolean(b) = &shape {
return Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()));
if let Shape::Boolean(_) = &shape {
return Shape::Boolean(def.pos.clone());
} else if let Shape::Hole(_) = &shape {
return Shape::Boolean(PositionedItem::new(true, def.pos.clone()));
return Shape::Boolean(def.pos.clone());
} else if let Shape::Narrowed(shape_list) = &shape {
for s in shape_list.types.iter() {
if let Shape::Boolean(b) = s {
return Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()));
if let Shape::Boolean(_) = s {
return Shape::Boolean(def.pos.clone());
}
}
};
@ -194,18 +203,18 @@ impl DeriveShape for Expression {
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
match self {
Expression::Simple(v) => v.derive_shape(symbol_table),
Expression::Format(def) => Shape::Str(PositionedItem::new("".into(), def.pos.clone())),
Expression::Format(def) => Shape::Str(def.pos.clone()),
Expression::Not(def) => derive_not_shape(def, symbol_table),
Expression::Grouped(v, _pos) => v.as_ref().derive_shape(symbol_table),
Expression::Range(def) => Shape::List(NarrowedShape::new_with_pos(
vec![Shape::Int(PositionedItem::new(0, def.start.pos().clone()))],
vec![Shape::Int(def.start.pos().clone())],
def.pos.clone(),
)),
Expression::Cast(def) => match def.cast_type {
CastType::Int => Shape::Int(PositionedItem::new(0, def.pos.clone())),
CastType::Str => Shape::Str(PositionedItem::new("".into(), def.pos.clone())),
CastType::Float => Shape::Float(PositionedItem::new(0.0, def.pos.clone())),
CastType::Bool => Shape::Boolean(PositionedItem::new(true, def.pos.clone())),
CastType::Int => Shape::Int(def.pos.clone()),
CastType::Str => Shape::Str(def.pos.clone()),
CastType::Float => Shape::Float(def.pos.clone()),
CastType::Bool => Shape::Boolean(def.pos.clone()),
},
Expression::Import(def) => Shape::Import(ImportShape::Unresolved(PositionedItem::new(
def.path.fragment.clone(),
@ -233,10 +242,10 @@ impl DeriveShape for Value {
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
match self {
Value::Empty(p) => Shape::Narrowed(NarrowedShape::new_with_pos(vec![], p.clone())),
Value::Boolean(p) => Shape::Boolean(p.clone()),
Value::Int(p) => Shape::Int(p.clone()),
Value::Float(p) => Shape::Float(p.clone()),
Value::Str(p) => Shape::Str(p.clone()),
Value::Boolean(p) => Shape::Boolean(p.pos.clone()),
Value::Int(p) => Shape::Int(p.pos.clone()),
Value::Float(p) => Shape::Float(p.pos.clone()),
Value::Str(p) => Shape::Str(p.pos.clone()),
Value::Symbol(p) => {
if let Some(s) = symbol_table.get(&p.val) {
s.clone()
@ -336,10 +345,10 @@ impl Visitor for Checker {
vec![],
p.clone(),
))),
Value::Boolean(p) => self.shape_stack.push(Shape::Boolean(p.clone())),
Value::Int(p) => self.shape_stack.push(Shape::Int(p.clone())),
Value::Float(p) => self.shape_stack.push(Shape::Float(p.clone())),
Value::Str(p) => self.shape_stack.push(Shape::Str(p.clone())),
Value::Boolean(p) => self.shape_stack.push(Shape::Boolean(p.pos.clone())),
Value::Int(p) => self.shape_stack.push(Shape::Int(p.pos.clone())),
Value::Float(p) => self.shape_stack.push(Shape::Float(p.pos.clone())),
Value::Str(p) => self.shape_stack.push(Shape::Str(p.pos.clone())),
// Symbols in a shape are placeholders. They allow a form of genericity
// in the shape. They can be any type and are only refined down.
// by their presence in an expression.

View File

@ -41,18 +41,9 @@ macro_rules! assert_type_success {
#[test]
fn simple_binary_typecheck() {
assert_type_success!(
"1 + 1;",
Shape::Int(PositionedItem::new(1, Position::new(1, 1, 0)))
);
assert_type_success!(
"\"\" + \"\";",
Shape::Str(PositionedItem::new("".into(), Position::new(1, 1, 0)))
);
assert_type_success!(
"1.0 + 1.0;",
Shape::Float(PositionedItem::new(1.0, Position::new(1, 1, 0)))
);
assert_type_success!("1 + 1;", Shape::Int(Position::new(1, 1, 0)));
assert_type_success!("\"\" + \"\";", Shape::Str(Position::new(1, 1, 0)));
assert_type_success!("1.0 + 1.0;", Shape::Float(Position::new(1, 1, 0)));
assert_type_success!(
"[] + [];",
Shape::List(crate::ast::NarrowedShape::new(vec![], 1, 1, 0))
@ -71,7 +62,7 @@ fn simple_binary_typecheck() {
fragment: "foo".into(),
pos: Position::new(1, 2, 1)
},
Shape::Int(PositionedItem::new_with_pos(1, Position::new(1, 8, 7)))
Shape::Int(Position::new(1, 8, 7))
),],
Position::new(1, 1, 0)
))
@ -79,10 +70,7 @@ fn simple_binary_typecheck() {
assert_type_success!(
"[1] + [2];",
Shape::List(crate::ast::NarrowedShape::new(
vec![Shape::Int(PositionedItem::new_with_pos(
1,
Position::new(1, 1, 0)
))],
vec![Shape::Int(Position::new(1, 2, 1))],
1,
1,
0
@ -92,8 +80,8 @@ fn simple_binary_typecheck() {
"[1, 1.0] + [1, 2.0];",
Shape::List(crate::ast::NarrowedShape::new(
vec![
Shape::Int(PositionedItem::new_with_pos(1, Position::new(1, 1, 0))),
Shape::Float(PositionedItem::new_with_pos(1.0, Position::new(1, 1, 0))),
Shape::Int(Position::new(1, 2, 1)),
Shape::Float(Position::new(1, 5, 4)),
],
1,
1,
@ -188,10 +176,7 @@ fn infer_symbol_type_test() {
let table = vec![
(
"1 + foo",
vec![(
foo.clone(),
Shape::Int(PositionedItem::new(1, Position::new(0, 0, 0))),
)],
vec![(foo.clone(), Shape::Int(Position::new(0, 0, 0)))],
vec![Shape::Hole(PositionedItem::new(
foo.clone(),
Position::new(0, 0, 0),
@ -200,18 +185,12 @@ fn infer_symbol_type_test() {
(
"bar + foo",
vec![
(
foo.clone(),
Shape::Float(PositionedItem::new(1.0, Position::new(0, 0, 0))),
),
(
bar.clone(),
Shape::Float(PositionedItem::new(1.0, Position::new(0, 0, 0))),
),
(foo.clone(), Shape::Float(Position::new(0, 0, 0))),
(bar.clone(), Shape::Float(Position::new(0, 0, 0))),
],
vec![
Shape::Hole(PositionedItem::new(foo.clone(), Position::new(0, 0, 0))),
Shape::Float(PositionedItem::new(1.0, Position::new(0, 0, 0))),
Shape::Float(Position::new(0, 0, 0)),
],
),
];
@ -227,24 +206,18 @@ fn infer_func_type_test() {
let bar = Into::<Rc<str>>::into("bar");
args.insert(
foo.clone(),
Shape::Int(PositionedItem {
pos: Position {
file: None,
line: 1,
column: 6,
offset: 5,
},
val: 1,
}),
);
let ret = Shape::Int(PositionedItem {
pos: Position {
Shape::Int(Position {
file: None,
line: 1,
column: 20,
offset: 19,
},
val: 1,
column: 6,
offset: 5,
}),
);
let ret = Shape::Int(Position {
file: None,
line: 1,
column: 1,
offset: 0,
})
.into();
assert_type_success!(
@ -254,44 +227,44 @@ fn infer_func_type_test() {
let mut symbol_table = BTreeMap::new();
symbol_table.insert(
bar.clone(),
Shape::Int(PositionedItem {
pos: Position {
Shape::Int(Position {
file: None,
line: 1,
column: 20,
offset: 19,
},
val: 1,
}),
);
let mut args = BTreeMap::new();
args.insert(
foo.clone(),
Shape::Int(PositionedItem {
pos: Position {
Shape::Int(Position {
file: None,
line: 1,
column: 6,
offset: 5,
},
val: 1,
}),
);
assert_type_success!(
"func(foo) => foo + bar;",
Shape::Func(FuncShapeDef {
args: args,
ret: Shape::Int(PositionedItem {
pos: Position {
ret: Shape::Int(Position {
file: None,
line: 1,
column: 20,
offset: 19,
},
val: 1,
column: 1,
offset: 0,
})
.into()
}),
symbol_table
);
}
//#[test]
//fn infer_select_shape() {
// assert_type_success!(
// r#"select () => { true = "foo", false = 1 }"#,
// Shape::Narrowed(NarrowedShape { pos: Position { file: None, line: 0, column: 0, offset: 0 }, types: vec![
// Shape::Str(PositionedItem { pos: , val: () })
// ] }))
//}

View File

@ -217,7 +217,8 @@ impl From<Val> for Rc<str> {
Val::Boolean(ref b) => format!("{}", b),
Val::Empty => "NULL".to_string(),
val => format!("{}", val),
}.into()
}
.into()
}
}

View File

@ -181,7 +181,11 @@ where
if found.contains(&link) {
continue;
}
let ops = match self.environment.borrow_mut().get_ops_for_path(link.as_ref()) {
let ops = match self
.environment
.borrow_mut()
.get_ops_for_path(link.as_ref())
{
Ok(ops) => ops,
Err(e) => return Err(Box::new(e.with_pos(path_pos))),
};

View File

@ -84,7 +84,8 @@ impl From<std::io::Error> for Error {
format!("OSError: Path not found: {}", e)
}
_ => format!("{}", e),
}.into();
}
.into();
Error {
message: msg,
pos: None,

View File

@ -114,7 +114,11 @@ impl Builtins {
stack.push((val, path_pos));
return Ok(());
}
if import_stack.iter().find(|p| p.as_ref() == path.as_ref()).is_some() {
if import_stack
.iter()
.find(|p| p.as_ref() == path.as_ref())
.is_some()
{
return Err(Error::new(
format!("Import cycle detected: {} in {:?}", path, import_stack).into(),
pos,
@ -127,15 +131,15 @@ impl Builtins {
}
None => {
let path_buf = PathBuf::from(path.as_ref());
let op_pointer =
decorate_error!(path_pos => env.borrow_mut().get_ops_for_path(path.as_ref()))?;
let op_pointer = decorate_error!(path_pos => env.borrow_mut().get_ops_for_path(path.as_ref()))?;
// TODO(jwall): What if we don't have a base path?
let mut vm =
VM::with_pointer(self.strict, op_pointer, path_buf.parent().unwrap())
.with_import_stack(import_stack.clone());
vm.run(env)?;
let result = Rc::new(vm.symbols_to_tuple(true));
env.borrow_mut().update_path_val(path.clone(), result.clone());
env.borrow_mut()
.update_path_val(path.clone(), result.clone());
stack.push((result, pos));
}
}
@ -163,7 +167,10 @@ impl Builtins {
if let &Value::P(Str(ref path)) = val.as_ref() {
path.clone()
} else {
return Err(Error::new(format!("Invalid Path {:?}", val).into(), path_pos));
return Err(Error::new(
format!("Invalid Path {:?}", val).into(),
path_pos,
));
}
} else {
unreachable!();
@ -201,7 +208,10 @@ impl Builtins {
}
}
None => {
return Err(Error::new(format!("No such conversion type {}", &typ).into(), pos))
return Err(Error::new(
format!("No such conversion type {}", &typ).into(),
pos,
))
}
}),
pos,
@ -355,9 +365,7 @@ impl Builtins {
match c.convert(Rc::new(val), &mut buf) {
Ok(_) => {
stack.push((
Rc::new(P(Str(
String::from_utf8_lossy(buf.as_slice()).into()
))),
Rc::new(P(Str(String::from_utf8_lossy(buf.as_slice()).into()))),
pos,
));
}

View File

@ -278,7 +278,8 @@ impl VM {
format!(
"Not a boolean condition {:?} in && expression at {}",
cond, pos
).into(),
)
.into(),
cond_pos.clone(),
));
}
@ -298,7 +299,8 @@ impl VM {
format!(
"Not a boolean condition {:?} in || expression at {}!",
cond, pos
).into(),
)
.into(),
cond_pos.clone(),
));
}
@ -530,7 +532,8 @@ impl VM {
format!(
"Func called with too many args expected {} args but got {}",
arity, arg_length
).into(),
)
.into(),
pos,
));
}
@ -539,7 +542,8 @@ impl VM {
format!(
"Func called with too few args expected {} args but got {}",
arity, arg_length
).into(),
)
.into(),
pos,
));
}
@ -568,7 +572,8 @@ impl VM {
format!(
"Expected Boolean but got {:?} in expression at {}",
operand, pos
).into(),
)
.into(),
operand_pos,
));
}
@ -1042,7 +1047,8 @@ impl VM {
fld.1.type_name(),
name,
value.type_name(),
).into(),
)
.into(),
val_pos.clone(),
));
}
@ -1115,7 +1121,10 @@ impl VM {
match tpl {
Some((v, pos)) => Ok((v, pos)),
None => {
return Err(Error::new(format!("No such binding {}", name).into(), pos.clone()));
return Err(Error::new(
format!("No such binding {}", name).into(),
pos.clone(),
));
}
}
}

View File

@ -152,10 +152,7 @@ fn test_expr_copy_no_such_tuple() {
test_expr_to_val(
vec![(
Expression::Copy(CopyDef {
selector: Value::Symbol(PositionedItem::new(
"tpl1".into(),
Position::new(1, 1, 1),
)),
selector: Value::Symbol(PositionedItem::new("tpl1".into(), Position::new(1, 1, 1))),
fields: Vec::new(),
pos: Position::new(1, 0, 0),
}),

View File

@ -39,7 +39,10 @@ impl YamlConverter {
fn convert_tuple(&self, items: &Vec<(Rc<str>, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
let mut mapping = serde_yaml::Mapping::new();
for &(ref k, ref v) in items.iter() {
mapping.insert(serde_yaml::Value::String(k.to_string()), self.convert_value(v)?);
mapping.insert(
serde_yaml::Value::String(k.to_string()),
self.convert_value(v)?,
);
}
Ok(serde_yaml::Value::Mapping(mapping))
}

View File

@ -83,10 +83,7 @@ make_fn!(
);
fn str_to_value(s: &Token) -> ConvertResult<Value> {
Ok(Value::Str(value_node!(
s.fragment.clone(),
s.pos.clone()
)))
Ok(Value::Str(value_node!(s.fragment.clone(), s.pos.clone())))
}
// quoted_value is a quoted string.