mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-09-11 08:45:32 +03:00
feat: made everything, only needs the error messages
This commit is contained in:
parent
0acf7ad79b
commit
a87a04d5c6
@ -291,9 +291,9 @@ impl<'a> Visitor for Subst<'a> {
|
||||
ExprKind::SeqRecord(sec) => {
|
||||
use kind_tree::concrete::SeqOperation::*;
|
||||
|
||||
self.visit_ident(&mut sec.ident[0]);
|
||||
self.visit_ident(&mut sec.name);
|
||||
|
||||
self.visit_expr(&mut sec.typ_);
|
||||
self.visit_expr(&mut sec.typ);
|
||||
|
||||
match &mut sec.operation {
|
||||
Set(expr) => self.visit_expr(expr),
|
||||
|
@ -879,6 +879,46 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_seq(&mut self) -> Result<Box<Expr>, SyntaxDiagnostic> {
|
||||
let start = self.range();
|
||||
|
||||
self.eat_variant(Token::Bang)?;
|
||||
|
||||
let typ = self.parse_atom()?;
|
||||
|
||||
let name = self.parse_id()?;
|
||||
|
||||
let mut fields = vec![];
|
||||
|
||||
let mut end = self.range();
|
||||
|
||||
while let Token::Dot = &self.get() {
|
||||
self.advance();
|
||||
end = self.range();
|
||||
fields.push(self.parse_id()?);
|
||||
}
|
||||
|
||||
let operation = if self.check_and_eat(Token::Eq) {
|
||||
SeqOperation::Set(self.parse_expr(false)?)
|
||||
} else if self.check_and_eat(Token::AtEq) {
|
||||
SeqOperation::Mut(self.parse_expr(false)?)
|
||||
} else {
|
||||
SeqOperation::Get
|
||||
};
|
||||
|
||||
Ok(Box::new(Expr {
|
||||
data: ExprKind::SeqRecord(
|
||||
SeqRecord {
|
||||
typ,
|
||||
name,
|
||||
fields,
|
||||
operation,
|
||||
}
|
||||
),
|
||||
range: start.mix(end),
|
||||
}))
|
||||
}
|
||||
|
||||
/// The infinite hell of else ifs. But it's the most readable way
|
||||
/// to check if the queue of tokens match a pattern as we need
|
||||
/// some looakhead tokens.
|
||||
@ -904,6 +944,8 @@ impl<'a> Parser<'a> {
|
||||
self.parse_pi_or_lambda(false)
|
||||
} else if self.is_sigma_type() {
|
||||
self.parse_sigma_type()
|
||||
} else if self.check_actual(Token::Bang) {
|
||||
self.parse_seq()
|
||||
} else if self.check_actual(Token::Tilde) {
|
||||
self.parse_erased()
|
||||
} else {
|
||||
|
@ -175,7 +175,20 @@ impl<'a> Lexer<'a> {
|
||||
';' => self.single_token(Token::Semi, start),
|
||||
'$' => self.single_token(Token::Dollar, start),
|
||||
',' => self.single_token(Token::Comma, start),
|
||||
'+' => self.single_token(Token::Plus, start),
|
||||
'+' => {
|
||||
self.next_char();
|
||||
match self.peekable.peek() {
|
||||
Some('=') => self.single_token(Token::PlusEq, start),
|
||||
_ => (Token::Plus, self.mk_range(start)),
|
||||
}
|
||||
}
|
||||
'@' => {
|
||||
self.next_char();
|
||||
match self.peekable.peek() {
|
||||
Some('=') => self.single_token(Token::AtEq, start),
|
||||
_ => (Token::At, self.mk_range(start)),
|
||||
}
|
||||
}
|
||||
'-' => {
|
||||
self.next_char();
|
||||
match self.peekable.peek() {
|
||||
|
@ -75,6 +75,10 @@ pub enum Token {
|
||||
BangEq,
|
||||
Bang,
|
||||
|
||||
PlusEq,
|
||||
AtEq,
|
||||
At,
|
||||
|
||||
HashHash,
|
||||
Hash,
|
||||
|
||||
@ -181,6 +185,9 @@ impl fmt::Display for Token {
|
||||
Token::With => write!(f, "with"),
|
||||
Token::Return => write!(f, "return"),
|
||||
Token::Ask => write!(f, "ask"),
|
||||
Token::PlusEq => write!(f, "+="),
|
||||
Token::AtEq => write!(f, "@="),
|
||||
Token::At => write!(f, "@"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use kind_span::{Locatable, Range};
|
||||
use kind_tree::concrete::{self, expr, Literal, TopLevel};
|
||||
use kind_tree::desugared::{self};
|
||||
use kind_tree::desugared::{self, Expr};
|
||||
use kind_tree::symbol::{Ident, QualifiedIdent};
|
||||
|
||||
use crate::diagnostic::{PassDiagnostic, Sugar};
|
||||
@ -79,7 +79,78 @@ impl<'a> DesugarState<'a> {
|
||||
range: Range,
|
||||
sub: &expr::SeqRecord,
|
||||
) -> Box<desugared::Expr> {
|
||||
todo!()
|
||||
use concrete::SeqOperation::*;
|
||||
|
||||
let typ = self.desugar_expr(&sub.typ);
|
||||
|
||||
let mut value = vec![];
|
||||
self.desugar_record_field_sequence(&mut value, typ, &sub.fields);
|
||||
|
||||
match &sub.operation {
|
||||
Set(expr) => {
|
||||
let value_ident = Ident::generate("_value");
|
||||
let expr = self.desugar_expr(&expr);
|
||||
|
||||
let mut result = value.iter().rfold(expr, |acc, (name, field)| {
|
||||
let name = name.add_segment(field.to_str()).add_segment("mut");
|
||||
self.mk_desugared_ctr(
|
||||
range,
|
||||
name,
|
||||
vec![Expr::var(value_ident.clone()), Expr::lambda(range.clone(), value_ident.clone(), acc, false)],
|
||||
false,
|
||||
)
|
||||
});
|
||||
|
||||
match &mut result.data {
|
||||
desugared::ExprKind::Ctr { args, .. } => {
|
||||
if let desugared::ExprKind::Var { name } = &mut args[0].data {
|
||||
*name = sub.name.clone()
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
result
|
||||
},
|
||||
Mut(expr) => {
|
||||
let value_ident = Ident::generate("_value");
|
||||
let expr = self.desugar_expr(&expr);
|
||||
|
||||
let mut result = value.iter().rfold(expr, |acc, (name, field)| {
|
||||
let name = name.add_segment(field.to_str()).add_segment("mut");
|
||||
Expr::lambda(name.range.clone(), value_ident.clone(), self.mk_desugared_ctr(
|
||||
range,
|
||||
name,
|
||||
vec![Expr::var(value_ident.clone()), acc],
|
||||
false,
|
||||
), false)
|
||||
});
|
||||
|
||||
let mut result = match result.data {
|
||||
desugared::ExprKind::Lambda { body, .. } => {
|
||||
body
|
||||
}
|
||||
_ => panic!()
|
||||
};
|
||||
|
||||
match &mut result.data {
|
||||
desugared::ExprKind::Ctr { args, .. } => {
|
||||
if let desugared::ExprKind::Var { name } = &mut args[0].data {
|
||||
*name = sub.name.clone()
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
Get => value
|
||||
.iter()
|
||||
.fold(Expr::var(sub.name.clone()), |acc, (name, field)| {
|
||||
let name = name.add_segment(field.to_str()).add_segment("get");
|
||||
self.mk_desugared_ctr(range, name, vec![acc], false)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn desugar_sttm(
|
||||
|
@ -23,6 +23,7 @@ pub mod attributes;
|
||||
pub mod destruct;
|
||||
pub mod expr;
|
||||
pub mod top_level;
|
||||
pub mod record_field;
|
||||
|
||||
pub struct DesugarState<'a> {
|
||||
pub errors: Sender<Box<dyn Diagnostic>>,
|
||||
|
91
crates/kind-pass/src/desugar/record_field.rs
Normal file
91
crates/kind-pass/src/desugar/record_field.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use fxhash::FxHashMap;
|
||||
use kind_tree::{
|
||||
concrete::{self, TopLevel},
|
||||
desugared::{self, Expr},
|
||||
symbol::{Ident, QualifiedIdent},
|
||||
telescope::Telescope,
|
||||
};
|
||||
|
||||
use crate::subst::subst_on_expr;
|
||||
|
||||
use super::DesugarState;
|
||||
|
||||
impl<'a> DesugarState<'a> {
|
||||
pub fn specialize_on_field(
|
||||
&mut self,
|
||||
typ: Box<desugared::Expr>,
|
||||
) -> Option<(
|
||||
QualifiedIdent,
|
||||
&Telescope<concrete::Argument>,
|
||||
Telescope<concrete::Argument>,
|
||||
Vec<Box<Expr>>,
|
||||
)> {
|
||||
match typ.data {
|
||||
desugared::ExprKind::Ctr { name, args } => {
|
||||
let Some(TopLevel::RecordType(record)) = self.old_book.entries.get(name.to_str()) else { return None };
|
||||
let entry_constructor = self.old_book.meta.get(
|
||||
record
|
||||
.name
|
||||
.add_segment(record.constructor.to_str())
|
||||
.to_str(),
|
||||
)?;
|
||||
Some((
|
||||
name,
|
||||
&record.parameters,
|
||||
entry_constructor
|
||||
.arguments
|
||||
.clone()
|
||||
.drop(record.parameters.len()),
|
||||
args,
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn desugar_record_field_sequence(
|
||||
&mut self,
|
||||
res: &mut Vec<(QualifiedIdent, Ident)>,
|
||||
typ: Box<desugared::Expr>,
|
||||
fields: &[Ident],
|
||||
) {
|
||||
if fields.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some((name, params, record_fields, args)) = self.specialize_on_field(typ.clone()) {
|
||||
if let Some(field) = record_fields
|
||||
.iter()
|
||||
.find(|x| x.name.to_str() == fields[0].to_str())
|
||||
{
|
||||
let key = field.name.clone();
|
||||
|
||||
let pair = params
|
||||
.iter()
|
||||
.zip(args)
|
||||
.map(|(k, v)| (k.name.to_string(), v))
|
||||
.collect::<FxHashMap<_, _>>();
|
||||
|
||||
let mut val = self.desugar_expr(
|
||||
&field
|
||||
.typ
|
||||
.clone()
|
||||
.unwrap_or_else(|| concrete::expr::Expr::typ(field.range.clone())),
|
||||
);
|
||||
|
||||
|
||||
subst_on_expr(&mut val, pair);
|
||||
|
||||
println!("{}", val);
|
||||
|
||||
res.push((name, key));
|
||||
|
||||
self.desugar_record_field_sequence(res, val, &fields[1..])
|
||||
} else {
|
||||
panic!("no field")
|
||||
}
|
||||
} else {
|
||||
panic!("no record {}", typ)
|
||||
}
|
||||
}
|
||||
}
|
@ -11,3 +11,4 @@ mod diagnostic;
|
||||
pub mod expand;
|
||||
pub mod inline;
|
||||
pub mod unbound;
|
||||
pub mod subst;
|
61
crates/kind-pass/src/subst.rs
Normal file
61
crates/kind-pass/src/subst.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use fxhash::FxHashMap;
|
||||
use kind_tree::desugared::*;
|
||||
|
||||
pub fn subst_on_expr(expr: &mut Expr, substs: FxHashMap<String, Box<Expr>>) {
|
||||
subst(Default::default(), expr, &substs)
|
||||
}
|
||||
|
||||
fn subst(bindings: im_rc::HashSet<String>, expr: &mut Expr, substs: &FxHashMap<String, Box<Expr>>) {
|
||||
use ExprKind::*;
|
||||
|
||||
match &mut expr.data {
|
||||
Var { name } => {
|
||||
if !bindings.contains(name.to_str()) {
|
||||
if let Some(res) = substs.get(name.to_str()) {
|
||||
*expr = *res.clone();
|
||||
}
|
||||
}
|
||||
},
|
||||
All { param, typ, body, .. } => {
|
||||
subst(bindings.clone(), typ, substs);
|
||||
let mut on_body = bindings.clone();
|
||||
on_body.insert(param.to_string());
|
||||
subst(on_body.clone(), body, substs);
|
||||
},
|
||||
Lambda { param, body, .. } => {
|
||||
let mut on_body = bindings.clone();
|
||||
on_body.insert(param.to_string());
|
||||
subst(on_body.clone(), body, substs);
|
||||
},
|
||||
App { fun, args } => {
|
||||
subst(bindings.clone(), fun, substs);
|
||||
for arg in args.iter_mut() {
|
||||
subst(bindings.clone(), &mut arg.data, substs);
|
||||
}
|
||||
},
|
||||
Fun { name: _, args } | Ctr { name: _, args } => {
|
||||
for arg in args.iter_mut() {
|
||||
subst(bindings.clone(), arg, substs);
|
||||
}
|
||||
},
|
||||
Let { name, val, next } => {
|
||||
subst(bindings.clone(), val, substs);
|
||||
let mut on_body = bindings.clone();
|
||||
on_body.insert(name.to_string());
|
||||
subst(on_body.clone(), next, substs);
|
||||
},
|
||||
Ann { expr, typ } => {
|
||||
subst(bindings.clone(), expr, substs);
|
||||
subst(bindings.clone(), typ, substs);
|
||||
},
|
||||
Sub { expr, .. } => {
|
||||
subst(bindings.clone(), expr, substs);
|
||||
},
|
||||
Binary { left, right, .. } => {
|
||||
subst(bindings.clone(), left, substs);
|
||||
subst(bindings.clone(), right, substs);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -638,9 +638,9 @@ impl Visitor for UnboundCollector {
|
||||
ExprKind::SeqRecord(sec) => {
|
||||
use kind_tree::concrete::SeqOperation::*;
|
||||
|
||||
self.visit_expr(&mut sec.typ_);
|
||||
self.visit_expr(&mut sec.typ);
|
||||
|
||||
self.visit_ident(&mut sec.ident[0]);
|
||||
self.visit_ident(&mut sec.name);
|
||||
|
||||
match &mut sec.operation {
|
||||
Set(expr) => self.visit_expr(expr),
|
||||
|
@ -145,8 +145,9 @@ pub enum SeqOperation {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SeqRecord {
|
||||
pub typ_: Box<Expr>,
|
||||
pub ident: Vec<Ident>,
|
||||
pub typ: Box<Expr>,
|
||||
pub name: Ident,
|
||||
pub fields: Vec<Ident>,
|
||||
pub operation: SeqOperation
|
||||
}
|
||||
|
||||
@ -592,7 +593,7 @@ impl Display for Expr {
|
||||
Hole => write!(f, "_"),
|
||||
SeqRecord(rec) => {
|
||||
use SeqOperation::*;
|
||||
write!(f, "(!({}) {}", rec.typ_, rec.ident.iter().map(|x| x.to_str()).collect::<Vec<_>>().join(","))?;
|
||||
write!(f, "(!({}) {} {}", rec.typ, rec.name, rec.fields.iter().map(|x| format!(".{}", x.to_str())).collect::<Vec<_>>().join(","))?;
|
||||
match &rec.operation {
|
||||
Set(expr) => write!(f, "+= {})", expr),
|
||||
Mut(expr) => write!(f, "@= {})", expr),
|
||||
|
@ -492,6 +492,15 @@ pub fn walk_expr<T: Visitor>(ctx: &mut T, expr: &mut Expr) {
|
||||
ExprKind::Hole => {}
|
||||
ExprKind::Subst(subst) => ctx.visit_substitution(subst),
|
||||
ExprKind::Match(matcher) => ctx.visit_match(matcher),
|
||||
ExprKind::SeqRecord(_) => todo!(),
|
||||
ExprKind::SeqRecord(seq) => {
|
||||
ctx.visit_ident(&mut seq.name);
|
||||
ctx.visit_expr(&mut seq.typ);
|
||||
|
||||
match &mut seq.operation {
|
||||
SeqOperation::Set(expr) => ctx.visit_expr(expr),
|
||||
SeqOperation::Mut(expr) => ctx.visit_expr(expr),
|
||||
SeqOperation::Get => (),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user