mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-10-03 23:07:18 +03:00
Merge pull request #614 from HigherOrderCO/dont-allow-repeated-field-names
Dont allow repeated field names
This commit is contained in:
commit
4b0bdf506c
@ -35,6 +35,7 @@ and this project does not currently adhere to a particular versioning scheme.
|
||||
- Add `elif` chains to functional syntax. ([#596][gh-596])
|
||||
- Add local definitions to imperative syntax. ([#562][gh-562])
|
||||
- Add local definitions to functional syntax.
|
||||
- Add repeated field name error message.
|
||||
|
||||
## [0.2.35] - 2024-06-06
|
||||
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
display::DisplayFn, Adt, Book, CtrField, Definition, FanKind, HvmDefinition, MatchRule, Name, Num, Op,
|
||||
Pattern, Rule, Tag, Term, STRINGS,
|
||||
},
|
||||
imp::{parser::PyParser, Enum, Variant},
|
||||
imp::{parser::PyParser, Enum, RepeatedNames, Variant},
|
||||
maybe_grow,
|
||||
};
|
||||
use highlight_error::highlight_error;
|
||||
@ -166,8 +166,8 @@ impl<'a> TermParser<'a> {
|
||||
// name
|
||||
if self.try_consume("(") {
|
||||
self.skip_trivia();
|
||||
let name = self.parse_top_level_name()?;
|
||||
let name = Name::new(format!("{typ_name}/{name}"));
|
||||
let ctr_name = self.parse_top_level_name()?;
|
||||
let ctr_name = Name::new(format!("{typ_name}/{ctr_name}"));
|
||||
|
||||
fn parse_field(p: &mut TermParser) -> ParseResult<CtrField> {
|
||||
let rec = p.try_consume("~");
|
||||
@ -177,7 +177,10 @@ impl<'a> TermParser<'a> {
|
||||
}
|
||||
|
||||
let fields = self.list_like(parse_field, "", ")", "", false, 0)?;
|
||||
Ok((name, fields))
|
||||
if let Some(field) = fields.find_repeated_names().into_iter().next() {
|
||||
return Err(format!("Found a repeated field '{field}' in constructor {ctr_name}."));
|
||||
}
|
||||
Ok((ctr_name, fields))
|
||||
} else {
|
||||
// name
|
||||
let name = self.labelled(|p| p.parse_top_level_name(), "datatype constructor name")?;
|
||||
|
@ -4,6 +4,7 @@ pub mod parser;
|
||||
pub mod to_fun;
|
||||
|
||||
use crate::fun::{CtrField, Name, Num, Op};
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use interner::global::GlobalString;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -236,3 +237,23 @@ impl InPlaceOp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RepeatedNames {
|
||||
fn find_repeated_names(&self) -> IndexSet<Name>;
|
||||
}
|
||||
|
||||
impl RepeatedNames for Vec<CtrField> {
|
||||
fn find_repeated_names(&self) -> IndexSet<Name> {
|
||||
let mut count = IndexMap::new();
|
||||
for field in self.iter() {
|
||||
*count.entry(field.nam.clone()).or_insert(0) += 1;
|
||||
}
|
||||
count.into_iter().filter_map(|(name, count)| if count > 1 { Some(name) } else { None }).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl RepeatedNames for Variant {
|
||||
fn find_repeated_names(&self) -> IndexSet<Name> {
|
||||
self.fields.find_repeated_names()
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use crate::{
|
||||
};
|
||||
use TSPL::Parser;
|
||||
|
||||
use super::RepeatedNames;
|
||||
|
||||
pub struct PyParser<'i> {
|
||||
pub input: &'i str,
|
||||
pub index: usize,
|
||||
@ -1041,6 +1043,9 @@ impl<'a> PyParser<'a> {
|
||||
if self.starts_with("{") {
|
||||
fields = self.list_like(|p| p.parse_variant_field(), "{", "}", ",", true, 0)?;
|
||||
}
|
||||
if let Some(field) = fields.find_repeated_names().into_iter().next() {
|
||||
return Err(format!("Found a repeated field '{field}' in constructor {ctr_name}."));
|
||||
}
|
||||
Ok(Variant { name: ctr_name, fields })
|
||||
}
|
||||
|
||||
@ -1059,6 +1064,9 @@ impl<'a> PyParser<'a> {
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
if let Some(field) = fields.find_repeated_names().into_iter().next() {
|
||||
return Err(format!("Found a repeated field '{field}' in object {name}."));
|
||||
}
|
||||
if !self.is_eof() {
|
||||
self.consume_new_line()?;
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
type Expr
|
||||
= (Lit Int)
|
||||
| (Plus Expr Expr)
|
||||
|
||||
eval (Expr/Lit i) = i
|
||||
eval (Expr/Plus l r) = (+ (eval l) (eval r))
|
||||
|
||||
main = (eval (Expr/Plus (Expr/Lit 80) (Expr/Lit 90)))
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/parse_file/repeated_datatype_name.bend
|
||||
---
|
||||
[4m[1m[31mErrors:[0m
|
||||
In tests/golden_tests/parse_file/repeated_datatype_name.bend :
|
||||
Found a repeated field 'Expr' in constructor Expr/Plus.
|
Loading…
Reference in New Issue
Block a user