From 5ae010fef48cc2bf83a0d366d2a1cfa74ecce278 Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 13 Apr 2023 00:20:06 -0700 Subject: major cleanups: extend Type, refactor Term, and switch to String errs --- src/ast.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 21 deletions(-) (limited to 'src/ast.rs') diff --git a/src/ast.rs b/src/ast.rs index bf34d19..0a0c042 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,4 +1,4 @@ -// Bidirectional type checking, simple types for effects (or perhaps subtyping?) and typeclasses +// Bidirectional type checking, subtyping, and typeclasses use core::fmt; use std::collections::HashMap; @@ -6,8 +6,8 @@ use std::collections::HashMap; pub type Identifier = String; pub type Context = HashMap; -// note: when comes the time, we'll put effects in here (i think) -#[derive(Clone, PartialEq, Eq)] +// note: built-in functions do NOT go here! +#[derive(Debug, Clone, PartialEq)] pub enum Expression { Annotation{expr: Box, kind: Type}, Constant{term: Term}, @@ -18,11 +18,7 @@ pub enum Expression { Conditional{if_cond: Box, if_then: Box, if_else: Box} } -// _every_ type in our language is represented as this and interpreted as a type. -// how to store more data than fits... hmm... a problem for later -pub type Value = u64; - -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Type { Empty, Error, @@ -30,29 +26,96 @@ pub enum Type { Boolean, Natural, Integer, - // Float, - // String, + Float, + String, Enum(Vec), Record(HashMap), Function{from: Box, to: Box}, } -// this means that functions cannot have types? unless we put them as empty values ig -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Term { - pub val: Value, - pub kind: Type, // currently useless / redundant: will be useful for casting +#[derive(Debug, Clone, PartialEq)] +pub enum Term { + Unit(), + Boolean(bool), + Natural(usize), + Integer(isize), + Float(f32), + String{len: usize, cap: usize, data: Vec}, + Enum{val: usize, data: Vec}, // is this right? + Record(HashMap), // is this right? + Function(Box) // this should allow us to bind functions } -impl fmt::Debug for Expression { +impl fmt::Display for Expression { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Expression::Annotation { expr, kind } => write!(f, "({:?}: {:?})", expr, kind), - Expression::Constant { term } => write!(f, "'{}", term.val), + Expression::Annotation { expr, kind } => write!(f, "({}: {})", expr, kind), + Expression::Constant { term } => write!(f, "'{:?}", term), Expression::Variable { id } => write!(f, "{}", id), - Expression::Abstraction { param, func } => write!(f, "(λ{}.{:?})", param, func), - Expression::Application { func, arg } => write!(f, "({:?} {:?})", func, arg), - Expression::Conditional { if_cond, if_then, if_else } => write!(f, "(if {:?} then {:?} else {:?})", if_cond, if_then, if_else), + Expression::Abstraction { param, func } => write!(f, "(λ{}.{})", param, func), + Expression::Application { func, arg } => write!(f, "({} {})", func, arg), + Expression::Conditional { if_cond, if_then, if_else } => write!(f, "(if {} then {} else {})", if_cond, if_then, if_else), + } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Type::Empty => write!(f, "⊤"), + Type::Error => write!(f, "⊥"), + Type::Unit => write!(f, "unit"), + Type::Boolean => write!(f, "bool"), + Type::Natural => write!(f, "nat"), + Type::Integer => write!(f, "int"), + Type::Float => write!(f, "float"), + Type::String => write!(f, "str"), + Type::Enum(data) => write!(f, "({:?})", data), + Type::Record(data) => write!(f, "{{{:?}}}", data), + Type::Function { from, to } => write!(f, "{}->{}", from, to), } } } + +impl fmt::Display for Term { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Term::Unit() => write!(f, "∅"), + Term::Boolean(term) => write!(f, "{}", term), + Term::Natural(term) => write!(f, "{}", term), + Term::Integer(term) => write!(f, "{}", term), + Term::Float(term) => write!(f, "{}", term), + Term::String { len, cap, data } => write!(f, "\"{:?}\"", data), + Term::Enum { val, data } => write!(f, "{:?}", data.get(*val)), + Term::Record(term) => write!(f, "{:?}", term), + Term::Function(expr) => write!(f, "{}", *expr), + } + } +} + +// hatehatehate that you can't implement a trait for foreign types +// impl fmt::Display for Vec where T: fmt::Display { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// for (i, val) in self.enumerate() { +// if i == 0 { +// write!(f, "{}", val); +// } else { +// write!(f, ",{}", val); +// } +// } +// return Ok(()); +// } +// } + +// impl fmt::Display for HashMap where T: fmt::Display, U: fmt::Display { +// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +// for (i, (key, val)) in self.enumerate() { +// if i == 0 { +// write!(f, "{}={}", key, val); +// } else { +// write!(f, ",{}={}", key, val); +// } +// } +// return Ok(()); +// } +// } -- cgit v1.2.3-70-g09d2