diff --git a/src/report.rs b/src/report.rs index a1c019a..2dab48d 100644 --- a/src/report.rs +++ b/src/report.rs @@ -171,21 +171,48 @@ impl ToSnippet for crate::types::ExprToTypeError { use crate::types::ExprToTypeError::*; match self { + InvalidArity { name, expected, actual, location } => { + let source = sourcer.source(*location).unwrap(); + let range = source.span_range(location.span); + + Snippet { + title: Some(Annotation { + annotation_type: AnnotationType::Error, + label: Some("invalid arity".to_owned()), + id: None, + }), + footer: vec![ + Annotation { + label: Some(format!( + "`{}` takes {} arguments, but {} were passed", + name, expected, actual + )), + id: None, + annotation_type: AnnotationType::Note + } + ], + slices: vec![ + Slice { + source: source.content, + line_start: source.line_start, + origin: Some(source.file_name), + fold: false, + annotations: vec![ + SourceAnnotation { + label: "".to_owned(), + annotation_type: AnnotationType::Error, + range, + } + ] + } + ], + } + }, InvalidType(loc) => { let source = sourcer.source(*loc).unwrap(); basic_error(source, loc.span, "invalid type") }, - InvalidArr(loc) => { - let source = sourcer.source(*loc).unwrap(); - - basic_error(source, loc.span, "invalid array") - }, - InvalidStr(loc) => { - let source = sourcer.source(*loc).unwrap(); - - basic_error(source, loc.span, "invalid string") - }, InvalidSize(loc) => { let source = sourcer.source(*loc).unwrap(); @@ -213,9 +240,9 @@ impl ToSnippet for crate::types::ExprToTypeError { use crate::types::ExprToTypeError::*; match self { + InvalidArity { location, .. } => + location.file_id, InvalidType(loc) - | InvalidArr(loc) - | InvalidStr(loc) | InvalidSize(loc) | InvalidRel(loc) | InvalidRelExpr(loc) diff --git a/src/types.rs b/src/types.rs index b9dbe11..735a1d8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -24,8 +24,8 @@ pub enum TypeExpr { U(usize, Endianness), S(usize, Endianness), - Arr(Box>, Vec>), - Str(Vec>), + Arr(Box>, Ranged), + Str(Ranged), And(Vec>), Or(Vec>), @@ -34,10 +34,13 @@ pub enum TypeExpr { Ref(RzPath), Liq(Box, Vec>), - Size(Vec>), + // Size(Vec>), Val(Value, Box), } +#[derive(Debug, Clone, PartialEq)] +pub enum Size {} + #[derive(Debug, Clone, PartialEq)] pub enum Rel { Lt(Ranged, Ranged), @@ -61,17 +64,6 @@ pub enum Value { Integer(SmolStr), } -#[derive(Clone, Copy, Debug, PartialEq,)] -pub enum ExprToTypeError { - InvalidType(Location), - InvalidArr(Location), - InvalidStr(Location), - InvalidSize(Location), - InvalidRel(Location), - InvalidRelExpr(Location), - UnsupportedList(Location), -} - fn is_rel_name(name: &str) -> bool { ["lt", "le", "eq", "ge", "gt"] .contains(&name) @@ -148,6 +140,10 @@ fn as_rel_list(expr: &Ranged) -> Result>, ExprToTypeErr } } +fn as_size(expr: &Ranged) -> Result, ExprToTypeError> { + return Err(ExprToTypeError::InvalidSize(expr.range.unwrap())) +} + fn as_simple_type(expr: &Ranged) -> Option> { use Endianness::*; @@ -222,6 +218,21 @@ fn as_simple_type(expr: &Ranged) -> Option> { }) } +#[derive(Clone, Copy, Debug, PartialEq,)] +pub enum ExprToTypeError { + InvalidType(Location), + InvalidArity { + name: &'static str, + expected: usize, + actual: usize, + location: Location, + }, + InvalidSize(Location), + InvalidRel(Location), + InvalidRelExpr(Location), + UnsupportedList(Location), +} + #[derive(Clone, Default)] pub struct ExprToType { errors: Vec @@ -284,40 +295,72 @@ impl ExprToType { RawExpr::Apply { head, body } if &head.data == "arr" => { if body.len() != 2 { self.errors.push( - ExprToTypeError::InvalidArr(expr.range.unwrap()) + ExprToTypeError::InvalidArity { + name: "arr", + expected: 2, + actual: body.len(), + location: expr.range.unwrap() + } ); return None } let (ty, num) = (&body[0], &body[1]); let ty = Box::new(self.as_type(ty)?); - let num = self.push_err(as_rel_list(num)).ok()?; + let num = self.push_err(as_size(num)).ok()?; TypeExpr::Arr(ty, num) }, RawExpr::Apply { head, body } if &head.data == "str" => { if body.len() != 1 { self.errors.push( - ExprToTypeError::InvalidStr(expr.range.unwrap()) + ExprToTypeError::InvalidArity { + name: "str", + expected: 1, + actual: body.len(), + location: expr.range.unwrap() + } ); return None } - let num = self.push_err(as_rel_list(&body[0])).ok()?; + let num = self.push_err(as_size(&body[0])).ok()?; TypeExpr::Str(num) }, + RawExpr::Apply { head, body } if &head.data == "bytes" => { + if body.len() != 1 { + self.errors.push( + ExprToTypeError::InvalidArity { + name: "bytes", + expected: 1, + actual: body.len(), + location: expr.range.unwrap() + } + ); + return None + } + + let num = self.push_err(as_size(&body[0])).ok()?; + + todo!() + }, RawExpr::Apply { head, body } if &head.data == "size" => { if body.len() != 1 { self.errors.push( - ExprToTypeError::InvalidSize(expr.range.unwrap()) + ExprToTypeError::InvalidArity { + name: "size", + expected: 1, + actual: body.len(), + location: expr.range.unwrap() + } ); return None } - let size = self.push_err(as_rel_list(&body[0])).ok()?; + let size = self.push_err(as_size(&body[0])).ok()?; - TypeExpr::Size(size) + todo!() }, RawExpr::Path(path) => TypeExpr::Ref(path.clone()), @@ -362,20 +405,14 @@ pub fn as_makam_ty(ty: &TypeExpr) -> String { format!("(s {} little_endian)", s), Arr(ty, num) => { let ty = as_makam_ty(&ty.data); - let num = num.iter() - .map(|n| as_makam_rel(&n.data)) - .collect::>() - .join(", "); + let num = todo!(); - format!("(arr {} [{}])", ty, num) + // format!("(arr {} [{}])", ty, num) }, Str(len) => { - let len = len.iter() - .map(|l| as_makam_rel(&l.data)) - .collect::>() - .join(", "); + let len = todo!(); - format!("(str [{}])", len) + // format!("(str [{}])", len) }, And(list) => { let list = list.iter() @@ -406,21 +443,12 @@ pub fn as_makam_ty(ty: &TypeExpr) -> String { format!("(liq {} [{}])", ty, rels) }, - Size(len) => { - let len = len.iter() - .map(|l| as_makam_rel(&l.data)) - .collect::>() - .join(", "); - - format!("(size [{}])", len) - }, Val(value, ty) => { let value = as_makam_value(value); let ty = as_makam_ty(ty); format!("(val {} {})", value, ty) }, - // _ => todo!() } }