cl-ast: Cleanup

- Function bind is now one Pattern
- TyRef now allows &Ty (i.e. &[i32], &(char, bool)
- Range patterns (they cannot bind, only check whether a value is in range
- ArrayRep repeat has been reverted to usize, for now, until early consteval is implemented.
This commit is contained in:
2025-04-21 04:17:45 -04:00
parent ef92d8b798
commit 7ba808594c
15 changed files with 252 additions and 134 deletions

View File

@@ -57,9 +57,6 @@ impl Callable for Function {
let FnDecl { name, bind, body, sign: _ } = &*self.decl;
// Check arg mapping
if args.len() != bind.len() {
return Err(Error::ArgNumber(bind.len(), args.len()));
}
if self.is_constructor {
return Ok(ConValue::TupleStruct(Box::new((
name.to_ref(),
@@ -73,14 +70,10 @@ impl Callable for Function {
let upvars = self.upvars.take();
env.push_frame("upvars", upvars);
eprintln!("{name}{args:?}");
// TODO: completely refactor data storage
let mut frame = env.frame("fn args");
for (bind, value) in bind.iter().zip(args) {
for (name, value) in pattern::substitution(bind, value.clone())? {
frame.insert(*name, Some(value));
}
for (name, value) in pattern::substitution(bind, ConValue::Tuple(args.into()))? {
frame.insert(*name, Some(value));
}
let res = body.interpret(&mut frame);
drop(frame);

View File

@@ -1,6 +1,6 @@
//! Collects the "Upvars" of a function at the point of its creation, allowing variable capture
use crate::{convalue::ConValue, env::Environment};
use cl_ast::{ast_visitor::visit::*, Function, Let, Path, PathPart, Pattern, Sym};
use cl_ast::{Function, Let, Path, PathPart, Pattern, Sym, ast_visitor::visit::*};
use std::collections::{HashMap, HashSet};
pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars {
@@ -67,7 +67,7 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
fn visit_function(&mut self, f: &'a cl_ast::Function) {
let Function { name: _, sign: _, bind, body } = f;
// parameters can never be upvars
bind.iter().for_each(|pat| self.visit_pattern(pat));
self.visit_pattern(bind);
if let Some(body) = body {
self.visit_expr(body);
}
@@ -115,6 +115,8 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
self.visit_mutability(mutability);
self.visit_pattern(pattern);
}
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) => {
patterns.iter().for_each(|p| self.visit_pattern(p));
}

View File

@@ -134,11 +134,12 @@ impl Interpret for Struct {
.into(),
),
},
bind: args
.iter()
.enumerate()
.map(|(idx, _)| Pattern::Name(idx.to_string().into()))
.collect(),
bind: Pattern::Tuple(
args.iter()
.enumerate()
.map(|(idx, _)| Pattern::Name(idx.to_string().into()))
.collect(),
),
body: None,
};
let constructor = crate::function::Function::new_constructor(constructor);
@@ -814,12 +815,8 @@ impl Interpret for Array {
impl Interpret for ArrayRep {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { value, repeat } = self;
let repeat = match repeat.interpret(env)? {
ConValue::Int(v) => v,
_ => Err(Error::TypeError())?,
};
let value = value.interpret(env)?;
Ok(ConValue::Array(vec![value; repeat as usize].into()))
Ok(ConValue::Array(vec![value; *repeat].into()))
}
}
impl Interpret for AddrOf {

View File

@@ -20,6 +20,8 @@ pub fn variables(pat: &Pattern) -> Vec<&Sym> {
Pattern::Rest(Some(pattern)) => patvars(set, pattern),
Pattern::Rest(None) => {}
Pattern::Ref(_, pattern) => patvars(set, pattern),
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) | Pattern::Array(patterns) => {
patterns.iter().for_each(|pat| patvars(set, pat))
}
@@ -127,6 +129,70 @@ pub fn append_sub<'pat>(
todo!("Dereference <{r}> in pattern matching {pat}")
}
(Pattern::RangeExc(head, tail), value) => match (head.as_ref(), tail.as_ref(), value) {
(
Pattern::Literal(Literal::Int(a)),
Pattern::Literal(Literal::Int(c)),
ConValue::Int(b),
) => (*a as isize <= b as _ && b < *c as isize)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Char(a)),
Pattern::Literal(Literal::Char(c)),
ConValue::Char(b),
) => (*a <= b && b < *c)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Float(a)),
Pattern::Literal(Literal::Float(c)),
ConValue::Float(b),
) => (f64::from_bits(*a) <= b && b < f64::from_bits(*c))
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::String(a)),
Pattern::Literal(Literal::String(c)),
ConValue::String(b),
) => (a.as_str() <= b.to_ref() && b.to_ref() < c.as_str())
.then_some(())
.ok_or(Error::NotAssignable()),
_ => Err(Error::NotAssignable()),
},
(Pattern::RangeInc(head, tail), value) => match (head.as_ref(), tail.as_ref(), value) {
(
Pattern::Literal(Literal::Int(a)),
Pattern::Literal(Literal::Int(c)),
ConValue::Int(b),
) => (*a as isize <= b && b <= *c as isize)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Char(a)),
Pattern::Literal(Literal::Char(c)),
ConValue::Char(b),
) => (*a <= b && b <= *c)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Float(a)),
Pattern::Literal(Literal::Float(c)),
ConValue::Float(b),
) => (f64::from_bits(*a) <= b && b <= f64::from_bits(*c))
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::String(a)),
Pattern::Literal(Literal::String(c)),
ConValue::String(b),
) => (a.as_str() <= b.to_ref() && b.to_ref() <= c.as_str())
.then_some(())
.ok_or(Error::NotAssignable()),
_ => Err(Error::NotAssignable()),
},
(Pattern::Array(patterns), ConValue::Array(values)) => {
match rest_binding(sub, patterns, values.into_vec().into())? {
Some((pattern, values)) => {