pubify stuff in preparation for typed-sexp

This commit is contained in:
mehbark 2023-06-14 19:15:07 -04:00
parent e3c75ec22b
commit 87e5bdad48
2 changed files with 69 additions and 47 deletions

View file

@ -19,14 +19,14 @@ static CONCRETE: Lazy<Symbol> = Lazy::new(|| TABLE.lock().unwrap().intern("def")
const DEFAULT_COMPLEXITY_LIMIT: usize = 200_000; const DEFAULT_COMPLEXITY_LIMIT: usize = 200_000;
const DEFAULT_STEP_LIMIT: usize = 20_000; const DEFAULT_STEP_LIMIT: usize = 20_000;
fn main() { pub fn main() {
match do_it() { match do_it() {
Some(out) => println!("{out}"), Some(out) => println!("{out}"),
None => println!("error :("), None => println!("error :("),
} }
} }
fn do_it() -> Option<String> { pub fn do_it() -> Option<String> {
let buf = if let Some(buf) = env::args().nth(1) { let buf = if let Some(buf) = env::args().nth(1) {
buf buf
} else { } else {
@ -42,13 +42,13 @@ fn do_it() -> Option<String> {
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Sexp { pub enum Sexp {
Atom(Symbol), Atom(Symbol),
List(Vec<Sexp>), List(Vec<Sexp>),
} }
impl Sexp { impl Sexp {
fn nil() -> Self { pub fn nil() -> Self {
Self::List(Vec::new()) Self::List(Vec::new())
} }
@ -56,7 +56,7 @@ impl Sexp {
/// ///
/// [`Atom`]: Sexp::Atom /// [`Atom`]: Sexp::Atom
#[must_use] #[must_use]
fn is_atom(&self) -> bool { pub fn is_atom(&self) -> bool {
matches!(self, Self::Atom(..)) matches!(self, Self::Atom(..))
} }
@ -64,12 +64,12 @@ impl Sexp {
/// ///
/// [`List`]: Sexp::List /// [`List`]: Sexp::List
#[must_use] #[must_use]
fn is_list(&self) -> bool { pub fn is_list(&self) -> bool {
matches!(self, Self::List(..)) matches!(self, Self::List(..))
} }
#[must_use] #[must_use]
fn atom(&self) -> Option<&Symbol> { pub fn atom(&self) -> Option<&Symbol> {
match self { match self {
Sexp::Atom(at) => Some(at), Sexp::Atom(at) => Some(at),
Sexp::List(_) => None, Sexp::List(_) => None,
@ -77,7 +77,7 @@ impl Sexp {
} }
#[must_use] #[must_use]
fn list(&self) -> Option<&[Sexp]> { pub fn list(&self) -> Option<&[Sexp]> {
match self { match self {
Sexp::Atom(_) => None, Sexp::Atom(_) => None,
Sexp::List(xs) => Some(&xs), Sexp::List(xs) => Some(&xs),
@ -85,7 +85,7 @@ impl Sexp {
} }
#[must_use] #[must_use]
fn unwrap_atom(&self) -> Symbol { pub fn unwrap_atom(&self) -> Symbol {
match self { match self {
Sexp::Atom(sym) => *sym, Sexp::Atom(sym) => *sym,
Sexp::List(_) => unreachable!(), Sexp::List(_) => unreachable!(),
@ -93,19 +93,19 @@ impl Sexp {
} }
/// Push a sexp to the end of a sexp. Does nothing if the sexp is an atom. /// Push a sexp to the end of a sexp. Does nothing if the sexp is an atom.
fn push(&mut self, item: Self) { pub fn push(&mut self, item: Self) {
match self { match self {
Sexp::Atom(_) => (), Sexp::Atom(_) => (),
Sexp::List(xs) => xs.push(item), Sexp::List(xs) => xs.push(item),
} }
} }
fn rw(&self, rule: &Rule) -> Sexp { pub fn rw(&self, rule: &Rule) -> Sexp {
rw(rule, self) rw(rule, self)
} }
#[must_use] #[must_use]
fn pertinent(&self) -> HashSet<Symbol> { pub fn pertinent(&self) -> HashSet<Symbol> {
match self { match self {
Sexp::Atom(sym) => { Sexp::Atom(sym) => {
let mut set = HashSet::with_capacity(1); let mut set = HashSet::with_capacity(1);
@ -121,7 +121,7 @@ impl Sexp {
} }
} }
fn concretion_targets(&self) -> HashSet<&Sexp> { pub fn concretion_targets(&self) -> HashSet<&Sexp> {
match self { match self {
at @ Sexp::Atom(_) => { at @ Sexp::Atom(_) => {
let mut out = HashSet::with_capacity(1); let mut out = HashSet::with_capacity(1);
@ -138,7 +138,7 @@ impl Sexp {
} }
#[must_use] #[must_use]
fn contains_sym(&self, sym: Symbol) -> bool { pub fn contains_sym(&self, sym: Symbol) -> bool {
match self { match self {
Sexp::Atom(at) => *at == sym, Sexp::Atom(at) => *at == sym,
Sexp::List(xs) => xs.iter().any(|s| s.contains_sym(sym)), Sexp::List(xs) => xs.iter().any(|s| s.contains_sym(sym)),
@ -146,7 +146,7 @@ impl Sexp {
} }
#[must_use] #[must_use]
fn complexity(&self) -> usize { pub fn complexity(&self) -> usize {
match self { match self {
Sexp::Atom(_) => 1, Sexp::Atom(_) => 1,
Sexp::List(xs) => 10 + xs.iter().map(Sexp::complexity).sum::<usize>(), Sexp::List(xs) => 10 + xs.iter().map(Sexp::complexity).sum::<usize>(),
@ -154,7 +154,7 @@ impl Sexp {
} }
// #[must_use] // #[must_use]
// fn apply_lets(&self) -> Sexp { // pub fn apply_lets(&self) -> Sexp {
// match self { // match self {
// Sexp::Atom(_) => self.clone(), // Sexp::Atom(_) => self.clone(),
// Sexp::List(xs) => match Let::from_sexp(self) { // Sexp::List(xs) => match Let::from_sexp(self) {
@ -165,7 +165,7 @@ impl Sexp {
// } // }
#[must_use] #[must_use]
fn apply_special_form<'src, F: SpecialForm<'src>>(&'src self) -> Sexp { pub fn apply_special_form<'src, F: SpecialForm<'src>>(&'src self) -> Sexp {
match self { match self {
Sexp::Atom(_) => match F::from_sexp(self) { Sexp::Atom(_) => match F::from_sexp(self) {
Some(form) => form.eval(), Some(form) => form.eval(),
@ -189,13 +189,13 @@ impl fmt::Display for Sexp {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Token<'src> { pub enum Token<'src> {
LParen, LParen,
RParen, RParen,
Atom(&'src str), Atom(&'src str),
} }
fn lex(src: &str) -> Vec<Token> { pub fn lex(src: &str) -> Vec<Token> {
// maybe a bad idea? // maybe a bad idea?
let mut out = Vec::with_capacity(src.len()); let mut out = Vec::with_capacity(src.len());
@ -260,7 +260,7 @@ fn lex(src: &str) -> Vec<Token> {
out out
} }
fn at_depth(depth: usize, sexp: &mut Sexp) -> &mut Sexp { pub fn at_depth(depth: usize, sexp: &mut Sexp) -> &mut Sexp {
if depth == 0 { if depth == 0 {
sexp sexp
} else { } else {
@ -271,7 +271,7 @@ fn at_depth(depth: usize, sexp: &mut Sexp) -> &mut Sexp {
} }
} }
fn parse<'src>(tokens: &'src [Token<'src>]) -> Option<Vec<Sexp>> { pub fn parse<'src>(tokens: &'src [Token<'src>]) -> Option<Vec<Sexp>> {
let mut out = Sexp::nil(); let mut out = Sexp::nil();
let mut depth = 0; let mut depth = 0;
@ -301,7 +301,7 @@ fn parse<'src>(tokens: &'src [Token<'src>]) -> Option<Vec<Sexp>> {
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Rule { pub enum Rule {
Forall { Forall {
vars: Vec<Symbol>, vars: Vec<Symbol>,
lhs: Sexp, lhs: Sexp,
@ -314,15 +314,15 @@ enum Rule {
} }
impl Rule { impl Rule {
fn forall(vars: Vec<Symbol>, lhs: Sexp, rhs: Sexp) -> Rule { pub fn forall(vars: Vec<Symbol>, lhs: Sexp, rhs: Sexp) -> Rule {
Rule::Forall { vars, lhs, rhs } Rule::Forall { vars, lhs, rhs }
} }
fn concrete(lhs: Sexp, rhs: Sexp) -> Rule { pub fn concrete(lhs: Sexp, rhs: Sexp) -> Rule {
Rule::Concrete { lhs, rhs } Rule::Concrete { lhs, rhs }
} }
fn concrify(&self, sexp: &Sexp) -> Rule { pub fn concrify(&self, sexp: &Sexp) -> Rule {
match self { match self {
Rule::Forall { vars, lhs, rhs } => { Rule::Forall { vars, lhs, rhs } => {
if vars.is_empty() { if vars.is_empty() {
@ -350,7 +350,7 @@ impl Rule {
} }
} }
fn concretions(&self, targets: &HashSet<&Sexp>) -> HashSet<Rule> { pub fn concretions(&self, targets: &HashSet<&Sexp>) -> HashSet<Rule> {
if self.is_concrete() { if self.is_concrete() {
let mut out = HashSet::with_capacity(1); let mut out = HashSet::with_capacity(1);
out.insert(self.clone()); out.insert(self.clone());
@ -374,26 +374,26 @@ impl Rule {
} }
} }
// fn matches(&self, expr: &Sexp) -> bool { // pub fn matches(&self, expr: &Sexp) -> bool {
// could_match(self.vars(), self.lhs(), expr) // could_match(self.vars(), self.lhs(), expr)
// } // }
#[must_use] #[must_use]
fn lhs(&self) -> &Sexp { pub fn lhs(&self) -> &Sexp {
match self { match self {
Rule::Concrete { lhs, .. } | Rule::Forall { lhs, .. } => lhs, Rule::Concrete { lhs, .. } | Rule::Forall { lhs, .. } => lhs,
} }
} }
#[must_use] #[must_use]
fn rhs(&self) -> &Sexp { pub fn rhs(&self) -> &Sexp {
match self { match self {
Rule::Forall { rhs, .. } | Rule::Concrete { rhs, .. } => rhs, Rule::Forall { rhs, .. } | Rule::Concrete { rhs, .. } => rhs,
} }
} }
#[must_use] #[must_use]
fn vars(&self) -> Option<&Vec<Symbol>> { pub fn vars(&self) -> Option<&Vec<Symbol>> {
match self { match self {
Rule::Forall { vars, .. } => Some(vars), Rule::Forall { vars, .. } => Some(vars),
Rule::Concrete { .. } => None, Rule::Concrete { .. } => None,
@ -401,7 +401,7 @@ impl Rule {
} }
#[must_use] #[must_use]
fn num_vars(&self) -> usize { pub fn num_vars(&self) -> usize {
match self.vars() { match self.vars() {
Some(xs) => xs.len(), Some(xs) => xs.len(),
None => 0, None => 0,
@ -409,7 +409,7 @@ impl Rule {
} }
#[must_use] #[must_use]
fn rw(&self, sexp: &Sexp) -> Sexp { pub fn rw(&self, sexp: &Sexp) -> Sexp {
rw(self, sexp) rw(self, sexp)
} }
@ -417,7 +417,7 @@ impl Rule {
/// ///
/// [`Forall`]: Rule::Forall /// [`Forall`]: Rule::Forall
#[must_use] #[must_use]
fn is_forall(&self) -> bool { pub fn is_forall(&self) -> bool {
matches!(self, Self::Forall { .. }) matches!(self, Self::Forall { .. })
} }
@ -425,11 +425,11 @@ impl Rule {
/// ///
/// [`Concrete`]: Rule::Concrete /// [`Concrete`]: Rule::Concrete
#[must_use] #[must_use]
fn is_concrete(&self) -> bool { pub fn is_concrete(&self) -> bool {
matches!(self, Self::Concrete { .. }) matches!(self, Self::Concrete { .. })
} }
fn var_replace(from: Symbol, to: &Sexp) -> Rule { pub fn var_replace(from: Symbol, to: &Sexp) -> Rule {
Rule::Concrete { Rule::Concrete {
lhs: Sexp::Atom(from), lhs: Sexp::Atom(from),
rhs: to.clone(), rhs: to.clone(),
@ -437,7 +437,7 @@ impl Rule {
} }
#[must_use] #[must_use]
fn concrete_with_matches(&self, matches: &Matches<'_>) -> Rule { pub fn concrete_with_matches(&self, matches: &Matches<'_>) -> Rule {
match self { match self {
Rule::Forall { vars, .. } => { Rule::Forall { vars, .. } => {
let mut out = self.clone(); let mut out = self.clone();
@ -471,7 +471,7 @@ impl fmt::Display for Rule {
} }
} }
fn could_match(vars: Option<&[Symbol]>, lhs: &Sexp, expr: &Sexp) -> bool { pub fn could_match(vars: Option<&[Symbol]>, lhs: &Sexp, expr: &Sexp) -> bool {
let is_var = |var: &Symbol| -> bool { let is_var = |var: &Symbol| -> bool {
match vars { match vars {
Some(vars) => vars.contains(var), Some(vars) => vars.contains(var),
@ -493,7 +493,7 @@ type Matches<'src> = HashMap<Symbol, &'src Sexp>;
// DONE?: there. can. be. at most. one. match. // DONE?: there. can. be. at most. one. match.
// i'm happy that this is faster, but it might be worth going back to the per-variable thing // i'm happy that this is faster, but it might be worth going back to the per-variable thing
fn matches<'src>(vars: &[Symbol], lhs: &Sexp, expr: &'src Sexp) -> Option<Matches<'src>> { pub fn matches<'src>(vars: &[Symbol], lhs: &Sexp, expr: &'src Sexp) -> Option<Matches<'src>> {
match (lhs, expr) { match (lhs, expr) {
(Sexp::Atom(a), Sexp::Atom(b)) => { (Sexp::Atom(a), Sexp::Atom(b)) => {
if a == b { if a == b {
@ -534,7 +534,7 @@ fn matches<'src>(vars: &[Symbol], lhs: &Sexp, expr: &'src Sexp) -> Option<Matche
} }
} }
fn merge_matches<'src>( pub fn merge_matches<'src>(
vars: &[Symbol], vars: &[Symbol],
a: Matches<'src>, a: Matches<'src>,
b: Matches<'src>, b: Matches<'src>,
@ -559,7 +559,7 @@ fn merge_matches<'src>(
Some(out) Some(out)
} }
// fn absorb_matches<'src>(from: Matches<'src>, into: &mut Matches<'src>) { // pub fn absorb_matches<'src>(from: Matches<'src>, into: &mut Matches<'src>) {
// for (var, matches) in from { // for (var, matches) in from {
// let insert_into = into.entry(var).or_default(); // let insert_into = into.entry(var).or_default();
// for matc in matches { // for matc in matches {
@ -568,7 +568,7 @@ fn merge_matches<'src>(
// } // }
// } // }
fn rw(rule: &Rule, sexp: &Sexp) -> Sexp { pub fn rw(rule: &Rule, sexp: &Sexp) -> Sexp {
if rule.lhs() == rule.rhs() { if rule.lhs() == rule.rhs() {
return sexp.clone(); return sexp.clone();
} }
@ -597,8 +597,8 @@ fn rw(rule: &Rule, sexp: &Sexp) -> Sexp {
} }
} }
fn simp(rules: &[Rule], mut expr: Sexp, step_limit: usize, complexity_limit: usize) -> Sexp { pub fn simp(rules: &[Rule], mut expr: Sexp, step_limit: usize, complexity_limit: usize) -> Sexp {
for i in 0..step_limit { for _ in 0..step_limit {
expr = expr expr = expr
.apply_special_form::<Genslop>() .apply_special_form::<Genslop>()
.apply_special_form::<Log>() .apply_special_form::<Log>()
@ -619,7 +619,7 @@ fn simp(rules: &[Rule], mut expr: Sexp, step_limit: usize, complexity_limit: usi
expr expr
} }
trait SpecialForm<'src>: Sized { pub trait SpecialForm<'src>: Sized {
fn from_sexp(sexp: &'src Sexp) -> Option<Self>; fn from_sexp(sexp: &'src Sexp) -> Option<Self>;
fn eval(self) -> Sexp; fn eval(self) -> Sexp;
@ -692,7 +692,7 @@ static GENSLOP: Lazy<Symbol> = Lazy::new(|| TABLE.lock().unwrap().intern("genslo
struct Genslop; struct Genslop;
impl Genslop { impl Genslop {
fn gen() -> String { pub fn gen() -> String {
format!( format!(
"slop-{}", "slop-{}",
rand::thread_rng() rand::thread_rng()
@ -743,7 +743,7 @@ impl<'src> SpecialForm<'src> for Log<'src> {
} }
} }
fn make_rule(sexp: &Sexp) -> Option<Rule> { pub fn make_rule(sexp: &Sexp) -> Option<Rule> {
match sexp { match sexp {
Sexp::List(xs) => match &xs[..] { Sexp::List(xs) => match &xs[..] {
[Sexp::Atom(forall), Sexp::List(vars), lhs, rhs] [Sexp::Atom(forall), Sexp::List(vars), lhs, rhs]
@ -764,7 +764,7 @@ fn make_rule(sexp: &Sexp) -> Option<Rule> {
} }
} }
fn run_program(src: &str, step_limit: usize, complexity_limit: usize) -> Option<Sexp> { pub fn run_program(src: &str, step_limit: usize, complexity_limit: usize) -> Option<Sexp> {
let mut parsed = parse(&lex(src))?; let mut parsed = parse(&lex(src))?;
let expr = parsed.pop()?; let expr = parsed.pop()?;

22
vec.slimp Normal file
View file

@ -0,0 +1,22 @@
(forall (name arg type out f) ((the (Pi name type out) f) (the type arg)) (let name arg (the out (f arg))))
(forall (in out) (-> in out) (Pi _ in out))
(forall (var body arg) ((lambda var body) arg) (let var arg body))
(def _ genslop)
(def succ (the (-> nat nat) 1+))
(def cons (the (Pi A U (Pi B U (-> A (-> B (Pair A B))))) (lambda _ (lambda _ (lambda a (lambda b (pair a b)))))))
(def car (the (Pi A U (Pi B U (-> (Pair A B) A))) (lambda _ (lambda _ (lambda p (car' p))))))
(forall (a b) (car' (pair a b)) a)
(def vecnil (the (Pi T U (Vec 0 T)) (lambda _ Vecnil)))
; ordering is bad
(def veccons
(the (Pi len nat (Pi T U (-> T (-> (Vec len T) (Vec (1+ len) T)))))
(lambda _ (lambda _ (lambda x (lambda xs (Veccons x xs)))))))
(let sym-nil (vecnil (the U symbol))
(let our-cons-1 ((veccons (the nat 0)) (the U symbol))
(let our-cons-2 ((veccons (succ (the nat 0))) (the U symbol))
((our-cons-2 (the symbol h)) ((our-cons-1 (the symbol i)) sym-nil))
)))