mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-25 18:49:50 -04:00
refactor: Make DeriveShape trait
This commit is contained in:
parent
bd9686128a
commit
1b0e076f94
212
src/ast/mod.rs
212
src/ast/mod.rs
@ -546,38 +546,6 @@ impl Value {
|
|||||||
&Value::List(_)
|
&Value::List(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
|
||||||
let shape = match self {
|
|
||||||
Value::Empty(p) => Shape::Empty(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::Symbol(p) => {
|
|
||||||
if let Some(s) = symbol_table.get(&p.val) {
|
|
||||||
s.clone()
|
|
||||||
} else {
|
|
||||||
Shape::Hole(p.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Tuple(flds) => {
|
|
||||||
let mut field_shapes = Vec::new();
|
|
||||||
for &(ref tok, ref expr) in &flds.val {
|
|
||||||
field_shapes.push((tok.clone(), expr.derive_shape(symbol_table)));
|
|
||||||
}
|
|
||||||
Shape::Tuple(PositionedItem::new(field_shapes, flds.pos.clone()))
|
|
||||||
}
|
|
||||||
Value::List(flds) => {
|
|
||||||
let mut field_shapes = Vec::new();
|
|
||||||
for f in &flds.elems {
|
|
||||||
field_shapes.push(f.derive_shape(symbol_table));
|
|
||||||
}
|
|
||||||
Shape::List(NarrowedShape::new_with_pos(field_shapes, flds.pos.clone()))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
shape
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an expansion of a Macro that is expected to already have been
|
/// Represents an expansion of a Macro that is expected to already have been
|
||||||
@ -715,20 +683,6 @@ pub struct FuncDef {
|
|||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FuncDef {
|
|
||||||
fn derive_shape(&self) -> Shape {
|
|
||||||
// 1. First set up our symbols.
|
|
||||||
let _table = self
|
|
||||||
.argdefs
|
|
||||||
.iter()
|
|
||||||
.map(|sym| (sym.val.clone(), Shape::Hole(sym.clone())))
|
|
||||||
.collect::<BTreeMap<Rc<str>, Shape>>();
|
|
||||||
// 2.Then determine the shapes of those symbols in our expression.
|
|
||||||
// 3. Finally determine what the return shape can be.
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Specifies the types of binary operations supported in
|
/// Specifies the types of binary operations supported in
|
||||||
/// UCG expression.
|
/// UCG expression.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -991,172 +945,6 @@ impl Expression {
|
|||||||
&Expression::Debug(ref def) => &def.pos,
|
&Expression::Debug(ref def) => &def.pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
|
||||||
let shape = match self {
|
|
||||||
Expression::Simple(v) => v.derive_shape(symbol_table),
|
|
||||||
Expression::Format(def) => {
|
|
||||||
Shape::Str(PositionedItem::new("".into(), 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()))],
|
|
||||||
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())),
|
|
||||||
},
|
|
||||||
Expression::Import(def) => Shape::Import(ImportShape::Unresolved(PositionedItem::new(
|
|
||||||
def.path.fragment.clone(),
|
|
||||||
def.path.pos.clone(),
|
|
||||||
))),
|
|
||||||
Expression::Binary(def) => {
|
|
||||||
let left_shape = def.left.derive_shape(symbol_table);
|
|
||||||
let right_shape = def.right.derive_shape(symbol_table);
|
|
||||||
left_shape.narrow(&right_shape)
|
|
||||||
}
|
|
||||||
Expression::Copy(def) => derive_copy_shape(def, symbol_table),
|
|
||||||
Expression::Include(def) => derive_include_shape(def),
|
|
||||||
Expression::Call(_) => todo!(),
|
|
||||||
Expression::Func(def) => def.derive_shape(),
|
|
||||||
Expression::Select(_) => todo!(),
|
|
||||||
Expression::FuncOp(_) => todo!(),
|
|
||||||
Expression::Module(_) => todo!(),
|
|
||||||
Expression::Fail(_) => todo!(),
|
|
||||||
Expression::Debug(_) => todo!(),
|
|
||||||
};
|
|
||||||
shape
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn derive_include_shape(
|
|
||||||
IncludeDef {
|
|
||||||
pos,
|
|
||||||
path: _path,
|
|
||||||
typ: _typ,
|
|
||||||
}: &IncludeDef,
|
|
||||||
) -> Shape {
|
|
||||||
Shape::Narrowed(NarrowedShape::new_with_pos(
|
|
||||||
vec![
|
|
||||||
Shape::Tuple(PositionedItem::new(vec![], pos.clone())),
|
|
||||||
Shape::List(NarrowedShape::new_with_pos(vec![], pos.clone())),
|
|
||||||
],
|
|
||||||
pos.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()))
|
|
||||||
} else {
|
|
||||||
// TODO(jwall): Display implementations for shapes.
|
|
||||||
Shape::TypeErr(
|
|
||||||
def.pos.clone(),
|
|
||||||
format!(
|
|
||||||
"Expected Boolean value in Not expression but got: {:?}",
|
|
||||||
shape
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn derive_copy_shape(def: &CopyDef, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
|
||||||
let base_shape = def.selector.derive_shape(symbol_table);
|
|
||||||
match &base_shape {
|
|
||||||
// TODO(jwall): Should we allow a stack of these?
|
|
||||||
Shape::TypeErr(_, _) => base_shape,
|
|
||||||
Shape::Empty(_)
|
|
||||||
| Shape::Boolean(_)
|
|
||||||
| Shape::Int(_)
|
|
||||||
| Shape::Float(_)
|
|
||||||
| Shape::Str(_)
|
|
||||||
| Shape::List(_)
|
|
||||||
| Shape::Func(_) => Shape::TypeErr(
|
|
||||||
def.pos.clone(),
|
|
||||||
format!("Not a Copyable type {}", base_shape.type_name()),
|
|
||||||
),
|
|
||||||
// This is an interesting one. Do we assume tuple or module here?
|
|
||||||
// TODO(jwall): Maybe we want a Shape::Narrowed?
|
|
||||||
Shape::Hole(pi) => Shape::Narrowed(NarrowedShape::new_with_pos(
|
|
||||||
vec![
|
|
||||||
Shape::Tuple(PositionedItem::new(vec![], pi.pos.clone())),
|
|
||||||
Shape::Module(ModuleShape {
|
|
||||||
items: vec![],
|
|
||||||
ret: Box::new(Shape::Empty(pi.pos.clone())),
|
|
||||||
}),
|
|
||||||
Shape::Import(ImportShape::Unresolved(pi.clone())),
|
|
||||||
],
|
|
||||||
pi.pos.clone(),
|
|
||||||
)),
|
|
||||||
Shape::Narrowed(potentials) => {
|
|
||||||
// 1. Do the possible shapes include tuple, module, or import?
|
|
||||||
let filtered = potentials
|
|
||||||
.types
|
|
||||||
.iter()
|
|
||||||
.filter_map(|v| match v {
|
|
||||||
Shape::Tuple(_) | Shape::Module(_) | Shape::Import(_) | Shape::Hole(_) => {
|
|
||||||
Some(v.clone())
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect::<Vec<Shape>>();
|
|
||||||
if !filtered.is_empty() {
|
|
||||||
// 1.1 Then return those and strip the others.
|
|
||||||
Shape::Narrowed(NarrowedShape::new_with_pos(filtered, def.pos.clone()))
|
|
||||||
} else {
|
|
||||||
// 2. Else return a type error
|
|
||||||
Shape::TypeErr(
|
|
||||||
def.pos.clone(),
|
|
||||||
format!("Not a Copyable type {}", base_shape.type_name()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// These have understandable ways to resolve the type.
|
|
||||||
Shape::Module(mdef) => {
|
|
||||||
let arg_fields = def
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.map(|(tok, expr)| (tok.fragment.clone(), expr.derive_shape(symbol_table)))
|
|
||||||
.collect::<BTreeMap<Rc<str>, Shape>>();
|
|
||||||
// 1. Do our copyable fields have the right names and shapes based on mdef.items.
|
|
||||||
for (tok, shape) in mdef.items.iter() {
|
|
||||||
if let Some(s) = arg_fields.get(&tok.fragment) {
|
|
||||||
if let Shape::TypeErr(pos, msg) = shape.narrow(s) {
|
|
||||||
return Shape::TypeErr(pos, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 1.1 If so then return the ret as our shape.
|
|
||||||
mdef.ret.as_ref().clone()
|
|
||||||
}
|
|
||||||
Shape::Tuple(t_def) => {
|
|
||||||
let mut base_fields = t_def.clone();
|
|
||||||
base_fields.val.extend(
|
|
||||||
def.fields
|
|
||||||
.iter()
|
|
||||||
.map(|(tok, expr)| (tok.clone(), expr.derive_shape(symbol_table))),
|
|
||||||
);
|
|
||||||
Shape::Tuple(base_fields).with_pos(def.pos.clone())
|
|
||||||
}
|
|
||||||
Shape::Import(ImportShape::Unresolved(_)) => Shape::Narrowed(NarrowedShape::new_with_pos(
|
|
||||||
vec![Shape::Tuple(PositionedItem::new(vec![], def.pos.clone()))],
|
|
||||||
def.pos.clone(),
|
|
||||||
)),
|
|
||||||
Shape::Import(ImportShape::Resolved(_, tuple_shape)) => {
|
|
||||||
let mut base_fields = tuple_shape.clone();
|
|
||||||
base_fields.extend(
|
|
||||||
def.fields
|
|
||||||
.iter()
|
|
||||||
.map(|(tok, expr)| (tok.clone(), expr.derive_shape(symbol_table))),
|
|
||||||
);
|
|
||||||
Shape::Tuple(PositionedItem::new(base_fields, def.pos.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Expression {
|
impl fmt::Display for Expression {
|
||||||
|
@ -16,7 +16,7 @@ use std::collections::BTreeMap;
|
|||||||
use abortable_parser::iter::SliceIter;
|
use abortable_parser::iter::SliceIter;
|
||||||
use abortable_parser::Result as ParseResult;
|
use abortable_parser::Result as ParseResult;
|
||||||
|
|
||||||
use crate::ast::{Expression, ListDef, Position, PositionedItem, Shape, Token, TokenType, Value ,NarrowedShape};
|
use crate::ast::{Expression, ListDef, Position, PositionedItem, Shape, Token, TokenType, Value ,NarrowedShape, typecheck::DeriveShape};
|
||||||
use crate::iter::OffsetStrIter;
|
use crate::iter::OffsetStrIter;
|
||||||
use crate::parse::expression;
|
use crate::parse::expression;
|
||||||
use crate::tokenizer::tokenize;
|
use crate::tokenizer::tokenize;
|
||||||
|
@ -13,20 +13,233 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
//! Implements typechecking for the parsed ucg AST.
|
//! Implements typechecking for the parsed ucg AST.
|
||||||
// FIXME(jwall): This probably just needs to disappear now.
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::ast::walk::Visitor;
|
use crate::ast::walk::Visitor;
|
||||||
use crate::ast::{Expression, FailDef, ImportDef, IncludeDef, Position, Shape, Statement, Value};
|
use crate::ast::{Expression, FailDef, ImportDef, IncludeDef, Shape, Statement, Value};
|
||||||
use crate::error::{BuildError, ErrorType};
|
use crate::error::{BuildError, ErrorType};
|
||||||
|
|
||||||
use Expression::{
|
use super::{PositionedItem, NarrowedShape, ImportShape, CastType, NotDef, CopyDef, ModuleShape, FuncDef};
|
||||||
Binary, Call, Cast, Copy, Debug, Fail, Format, Func, FuncOp, Grouped, Import, Include, Module,
|
|
||||||
Not, Range, Select, Simple,
|
/// Trait for shape derivation.
|
||||||
};
|
pub trait DeriveShape {
|
||||||
use Statement::Let;
|
/// Derive a shape using a provided symbol table.
|
||||||
use Value::{Boolean, Empty, Float, Int, List, Str, Symbol, Tuple};
|
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeriveShape for FuncDef {
|
||||||
|
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
||||||
|
// 1. First set up our symbols.
|
||||||
|
let _table = self
|
||||||
|
.argdefs
|
||||||
|
.iter()
|
||||||
|
.map(|sym| (sym.val.clone(), Shape::Hole(sym.clone())))
|
||||||
|
.collect::<BTreeMap<Rc<str>, Shape>>();
|
||||||
|
// 2.Then determine the shapes of those symbols in our expression.
|
||||||
|
// 3. Finally determine what the return shape can be.
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_include_shape(
|
||||||
|
IncludeDef {
|
||||||
|
pos,
|
||||||
|
path: _path,
|
||||||
|
typ: _typ,
|
||||||
|
}: &IncludeDef,
|
||||||
|
) -> Shape {
|
||||||
|
Shape::Narrowed(NarrowedShape::new_with_pos(
|
||||||
|
vec![
|
||||||
|
Shape::Tuple(PositionedItem::new(vec![], pos.clone())),
|
||||||
|
Shape::List(NarrowedShape::new_with_pos(vec![], pos.clone())),
|
||||||
|
],
|
||||||
|
pos.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()))
|
||||||
|
} else {
|
||||||
|
// TODO(jwall): Display implementations for shapes.
|
||||||
|
Shape::TypeErr(
|
||||||
|
def.pos.clone(),
|
||||||
|
format!(
|
||||||
|
"Expected Boolean value in Not expression but got: {:?}",
|
||||||
|
shape
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_copy_shape(def: &CopyDef, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
||||||
|
let base_shape = def.selector.derive_shape(symbol_table);
|
||||||
|
match &base_shape {
|
||||||
|
// TODO(jwall): Should we allow a stack of these?
|
||||||
|
Shape::TypeErr(_, _) => base_shape,
|
||||||
|
Shape::Empty(_)
|
||||||
|
| Shape::Boolean(_)
|
||||||
|
| Shape::Int(_)
|
||||||
|
| Shape::Float(_)
|
||||||
|
| Shape::Str(_)
|
||||||
|
| Shape::List(_)
|
||||||
|
| Shape::Func(_) => Shape::TypeErr(
|
||||||
|
def.pos.clone(),
|
||||||
|
format!("Not a Copyable type {}", base_shape.type_name()),
|
||||||
|
),
|
||||||
|
// This is an interesting one. Do we assume tuple or module here?
|
||||||
|
Shape::Hole(pi) => Shape::Narrowed(NarrowedShape::new_with_pos(
|
||||||
|
vec![
|
||||||
|
Shape::Tuple(PositionedItem::new(vec![], pi.pos.clone())),
|
||||||
|
Shape::Module(ModuleShape {
|
||||||
|
items: vec![],
|
||||||
|
ret: Box::new(Shape::Empty(pi.pos.clone())),
|
||||||
|
}),
|
||||||
|
Shape::Import(ImportShape::Unresolved(pi.clone())),
|
||||||
|
],
|
||||||
|
pi.pos.clone(),
|
||||||
|
)),
|
||||||
|
Shape::Narrowed(potentials) => {
|
||||||
|
// 1. Do the possible shapes include tuple, module, or import?
|
||||||
|
let filtered = potentials
|
||||||
|
.types
|
||||||
|
.iter()
|
||||||
|
.filter_map(|v| match v {
|
||||||
|
Shape::Tuple(_) | Shape::Module(_) | Shape::Import(_) | Shape::Hole(_) => {
|
||||||
|
Some(v.clone())
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<Vec<Shape>>();
|
||||||
|
if !filtered.is_empty() {
|
||||||
|
// 1.1 Then return those and strip the others.
|
||||||
|
Shape::Narrowed(NarrowedShape::new_with_pos(filtered, def.pos.clone()))
|
||||||
|
} else {
|
||||||
|
// 2. Else return a type error
|
||||||
|
Shape::TypeErr(
|
||||||
|
def.pos.clone(),
|
||||||
|
format!("Not a Copyable type {}", base_shape.type_name()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// These have understandable ways to resolve the type.
|
||||||
|
Shape::Module(mdef) => {
|
||||||
|
let arg_fields = def
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.map(|(tok, expr)| (tok.fragment.clone(), expr.derive_shape(symbol_table)))
|
||||||
|
.collect::<BTreeMap<Rc<str>, Shape>>();
|
||||||
|
// 1. Do our copyable fields have the right names and shapes based on mdef.items.
|
||||||
|
for (tok, shape) in mdef.items.iter() {
|
||||||
|
if let Some(s) = arg_fields.get(&tok.fragment) {
|
||||||
|
if let Shape::TypeErr(pos, msg) = shape.narrow(s) {
|
||||||
|
return Shape::TypeErr(pos, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 1.1 If so then return the ret as our shape.
|
||||||
|
mdef.ret.as_ref().clone()
|
||||||
|
}
|
||||||
|
Shape::Tuple(t_def) => {
|
||||||
|
let mut base_fields = t_def.clone();
|
||||||
|
base_fields.val.extend(
|
||||||
|
def.fields
|
||||||
|
.iter()
|
||||||
|
.map(|(tok, expr)| (tok.clone(), expr.derive_shape(symbol_table))),
|
||||||
|
);
|
||||||
|
Shape::Tuple(base_fields).with_pos(def.pos.clone())
|
||||||
|
}
|
||||||
|
Shape::Import(ImportShape::Unresolved(_)) => Shape::Narrowed(NarrowedShape::new_with_pos(
|
||||||
|
vec![Shape::Tuple(PositionedItem::new(vec![], def.pos.clone()))],
|
||||||
|
def.pos.clone(),
|
||||||
|
)),
|
||||||
|
Shape::Import(ImportShape::Resolved(_, tuple_shape)) => {
|
||||||
|
let mut base_fields = tuple_shape.clone();
|
||||||
|
base_fields.extend(
|
||||||
|
def.fields
|
||||||
|
.iter()
|
||||||
|
.map(|(tok, expr)| (tok.clone(), expr.derive_shape(symbol_table))),
|
||||||
|
);
|
||||||
|
Shape::Tuple(PositionedItem::new(base_fields, def.pos.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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()))],
|
||||||
|
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())),
|
||||||
|
},
|
||||||
|
Expression::Import(def) => Shape::Import(ImportShape::Unresolved(PositionedItem::new(
|
||||||
|
def.path.fragment.clone(),
|
||||||
|
def.path.pos.clone(),
|
||||||
|
))),
|
||||||
|
Expression::Binary(def) => {
|
||||||
|
let left_shape = def.left.derive_shape(symbol_table);
|
||||||
|
let right_shape = def.right.derive_shape(symbol_table);
|
||||||
|
left_shape.narrow(&right_shape)
|
||||||
|
}
|
||||||
|
Expression::Copy(def) => derive_copy_shape(def, symbol_table),
|
||||||
|
Expression::Include(def) => derive_include_shape(def),
|
||||||
|
Expression::Call(_) => todo!(),
|
||||||
|
Expression::Func(def) => def.derive_shape(symbol_table),
|
||||||
|
Expression::Select(_) => todo!(),
|
||||||
|
Expression::FuncOp(_) => todo!(),
|
||||||
|
Expression::Module(_) => todo!(),
|
||||||
|
Expression::Fail(_) => todo!(),
|
||||||
|
Expression::Debug(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeriveShape for Value {
|
||||||
|
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
|
||||||
|
match self {
|
||||||
|
Value::Empty(p) => Shape::Empty(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::Symbol(p) => {
|
||||||
|
if let Some(s) = symbol_table.get(&p.val) {
|
||||||
|
s.clone()
|
||||||
|
} else {
|
||||||
|
Shape::Hole(p.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Tuple(flds) => {
|
||||||
|
let mut field_shapes = Vec::new();
|
||||||
|
for &(ref tok, ref expr) in &flds.val {
|
||||||
|
field_shapes.push((tok.clone(), expr.derive_shape(symbol_table)));
|
||||||
|
}
|
||||||
|
Shape::Tuple(PositionedItem::new(field_shapes, flds.pos.clone()))
|
||||||
|
}
|
||||||
|
Value::List(flds) => {
|
||||||
|
let mut field_shapes = Vec::new();
|
||||||
|
for f in &flds.elems {
|
||||||
|
field_shapes.push(f.derive_shape(symbol_table));
|
||||||
|
}
|
||||||
|
Shape::List(NarrowedShape::new_with_pos(field_shapes, flds.pos.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Checker {
|
pub struct Checker {
|
||||||
symbol_table: BTreeMap<Rc<str>, Shape>,
|
symbol_table: BTreeMap<Rc<str>, Shape>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user