diff options
author | JJ | 2023-07-19 19:25:30 +0000 |
---|---|---|
committer | JJ | 2023-07-20 02:08:36 +0000 |
commit | f5e61572b217c5445c3cd593d1cc94697fa7ec48 (patch) | |
tree | 5ae7c5a95cac5c2a23c27ae10f48ebf4c0e4e684 /src/ast.rs | |
parent | 99769e9ebb94d1dcc12f2d1f6a6d899f7a229676 (diff) |
major cleanups: switch to dynamic Errors, impl Context, rename enums/records to unions/structs
Diffstat (limited to 'src/ast.rs')
-rw-r--r-- | src/ast.rs | 181 |
1 files changed, 86 insertions, 95 deletions
@@ -1,10 +1,10 @@ -// The abstract syntax tree. All supported types go here. - -use core::fmt; use std::collections::HashMap; +pub type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>; pub type Identifier = String; -pub type Context = HashMap<Identifier, Term>; + +#[derive(Debug, Clone, PartialEq)] +pub struct Context(HashMap<Identifier, Term>); // note: built-in functions do NOT go here! #[derive(Debug, Clone, PartialEq)] @@ -18,6 +18,7 @@ pub enum Expression { Conditional{if_cond: Box<Expression>, if_then: Box<Expression>, if_else: Box<Expression>} } +/// All supported types. #[derive(Debug, Clone, PartialEq)] pub enum Type { Empty, @@ -28,11 +29,12 @@ pub enum Type { Integer, Float, String, - Enum(Vec<Type>), - Record(HashMap<Identifier, Type>), + Union(Vec<Type>), + Struct(HashMap<Identifier, Type>), Function{from: Box<Type>, to: Box<Type>}, } +/// Data associated with a type. #[derive(Debug, Clone, PartialEq)] pub enum Term { Unit(), @@ -41,13 +43,71 @@ pub enum Term { Integer(isize), Float(f32), String{len: usize, cap: usize, data: Vec<usize>}, - Enum{val: usize, data: Box<Term>}, // is this right? - Record(HashMap<Identifier, Term>), // is this right? + Union{val: usize, data: Box<Term>}, // is this right? + Struct(HashMap<Identifier, Term>), // is this right? Function(Box<Expression>) // this should allow us to bind functions } -impl fmt::Display for Expression { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl Term { + /// Convert a term into its corresponding type. + pub fn convert(&self) -> Result<Type> { + match self { + Term::Unit() => Ok(Type::Unit), + Term::Boolean(_) => Ok(Type::Boolean), + Term::Natural(_) => Ok(Type::Natural), + Term::Integer(_) => Ok(Type::Integer), + Term::Float(_) => Ok(Type::Float), + Term::String { len, cap, data } => Ok(Type::String), + Term::Union { val, data } => data.convert(), + Term::Struct(data) => { + let mut result = HashMap::new(); + for (key, val) in data { + result.insert(key.clone(), val.convert()?); + } + return Ok(Type::Struct(result)); + }, + Term::Function(func) => match *func.clone() { + Expression::Annotation { expr, kind } => match kind { + Type::Function { from, to } => Ok(Type::Function { from, to }), + _ => Err("function term value not a function!".into()) + } + _ => Err("function term value does not have an annotation!".into()) + } + } + } +} + +impl Type { + /// Get the default value of a type. Throws an error if it doesn't exist. + pub fn default(&self) -> Result<Term> { + match self { + Type::Empty => Err("attempting to take the default term for empty".into()), + Type::Error => Err("attempting to take the default term for error".into()), + Type::Unit => Ok(Term::Unit()), + Type::Boolean => Ok(Term::Boolean(false)), + Type::Natural => Ok(Term::Natural(0)), + Type::Integer => Ok(Term::Integer(0)), + Type::Float => Ok(Term::Float(0.0)), + Type::String => Ok(Term::String { len: 0, cap: 0, data: vec!()}), + Type::Union(data) => match data.len() { + 0 => Err("attempting to get a default term of an enum with no variants!".into()), + _ => Ok(Term::Union { val: 0, data: Box::new(data.get(0).unwrap().default()?) }) + }, + Type::Struct(data) => { + let mut result = HashMap::new(); + for (key, val) in data { + result.insert(key.clone(), val.default()?); + } + return Ok(Term::Struct(result)); + }, + Type::Function { from, to } => + Err("attempting to take the default term of a function type".into()), + } + } +} + +impl core::fmt::Display for Expression { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Expression::Annotation { expr, kind } => write!(f, "({}: {})", expr, kind), Expression::Constant { term } => write!(f, "'{:?}", term), @@ -59,8 +119,8 @@ impl fmt::Display for Expression { } } -impl fmt::Display for Type { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl core::fmt::Display for Type { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Type::Empty => write!(f, "⊤"), Type::Error => write!(f, "⊥"), @@ -70,15 +130,15 @@ impl fmt::Display for Type { 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::Union(data) => write!(f, "({:?})", data), + Type::Struct(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 { +impl core::fmt::Display for Term { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Term::Unit() => write!(f, "∅"), Term::Boolean(term) => write!(f, "{}", term), @@ -86,90 +146,21 @@ impl fmt::Display for 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), - Term::Record(term) => write!(f, "{:?}", term), + Term::Union { val, data } => write!(f, "{:?}", data), + Term::Struct(term) => write!(f, "{:?}", term), Term::Function(expr) => write!(f, "{}", *expr), } } } -// hatehatehate that you can't implement a trait for foreign types -// impl<T> fmt::Display for Vec<T> 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<T, U> fmt::Display for HashMap<T, U> 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(()); -// } -// } - -/// Convert a term into its corresponding type. -pub fn convert(term: &Term) -> Result<Type, String> { - match term { - Term::Unit() => Ok(Type::Unit), - Term::Boolean(_) => Ok(Type::Boolean), - Term::Natural(_) => Ok(Type::Natural), - Term::Integer(_) => Ok(Type::Integer), - Term::Float(_) => Ok(Type::Float), - Term::String { len, cap, data } => Ok(Type::String), - Term::Enum { val, data } => convert(data), - Term::Record(data) => { - let mut result = HashMap::new(); - for (key, val) in data { - result.insert(key.clone(), convert(val)?); - } - return Ok(Type::Record(result)); - }, - Term::Function(func) => match *func.clone() { - Expression::Annotation { expr, kind } => match kind { - Type::Function { from, to } => Ok(Type::Function { from, to }), - _ => Err("function term value not a function!".to_string()) - } - _ => Err("function term value does not have an annotation!".to_string()) - } +impl Context { + pub fn new() -> Self { + Context(HashMap::new()) } -} - -/// Get the default value of a type. Throws an error if it doesn't exist. -pub fn default(kind: &Type) -> Result<Term, String> { - match kind { - Type::Empty => Err("attempting to take the default term for empty".to_string()), - Type::Error => Err("attempting to take the default term for error".to_string()), - Type::Unit => Ok(Term::Unit()), - Type::Boolean => Ok(Term::Boolean(false)), - Type::Natural => Ok(Term::Natural(0)), - Type::Integer => Ok(Term::Integer(0)), - Type::Float => Ok(Term::Float(0.0)), - Type::String => Ok(Term::String { len: 0, cap: 0, data: vec!()}), - Type::Enum(data) => match data.len() { - 0 => Err("attempting to get a default term of an enum with no variants!".to_string()), - _ => Ok(Term::Enum { val: 0, data: Box::new(default(data.get(0).unwrap())?) }) - }, - Type::Record(data) => { - let mut result = HashMap::new(); - for (key, val) in data { - result.insert(key.clone(), default(val)?); - } - return Ok(Term::Record(result)); - }, - Type::Function { from, to } => - Err("attempting to take the default term of a function type".to_string()), + pub fn get(&self, k: &Identifier) -> Option<&Term> { + self.0.get(k) + } + pub fn insert(&mut self, k: Identifier, v: Term) -> Option<Term> { + self.0.insert(k, v) } } |