forked from Orchid/orchid
Versioning fuckup
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -108,6 +108,12 @@ dependencies = [
|
|||||||
"ahash 0.7.6",
|
"ahash 0.7.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "implicit-clone"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "40fc102e70475c320b185cd18c1e48bba2d7210b63970a4d581ef903e4368ef7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
@@ -157,6 +163,7 @@ dependencies = [
|
|||||||
"chumsky",
|
"chumsky",
|
||||||
"derivative",
|
"derivative",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"implicit-clone",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"mappable-rc",
|
"mappable-rc",
|
||||||
|
|||||||
@@ -15,3 +15,4 @@ ordered-float = "3.0"
|
|||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
smallvec = { version = "1.10.0", features = ['const_generics'] }
|
smallvec = { version = "1.10.0", features = ['const_generics'] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
implicit-clone = "0.3.5"
|
||||||
|
|||||||
@@ -38,17 +38,28 @@ impl Debug for Expr {
|
|||||||
/// An S-expression as read from a source file
|
/// An S-expression as read from a source file
|
||||||
#[derive(PartialEq, Eq, Hash)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
pub enum Clause {
|
pub enum Clause {
|
||||||
|
/// A literal value, eg. `1`, `"hello"`
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
|
/// A c-style name or an operator, eg. `+`, `i`, `foo::bar`
|
||||||
Name{
|
Name{
|
||||||
local: Option<String>,
|
local: Option<String>,
|
||||||
qualified: Mrc<[String]>
|
qualified: Mrc<[String]>
|
||||||
},
|
},
|
||||||
|
/// A parenthesized expression, eg. `(print out "hello")`, `[1, 2, 3]`, `{Some(t) => t}`
|
||||||
S(char, Mrc<[Expr]>),
|
S(char, Mrc<[Expr]>),
|
||||||
|
/// An explicit expression associated with the leftmost, outermost [Clause::Auto], eg. `read @Int`
|
||||||
Explicit(Mrc<Expr>),
|
Explicit(Mrc<Expr>),
|
||||||
|
/// A function expression, eg. `\x. x + 1`
|
||||||
Lambda(String, Mrc<[Expr]>, Mrc<[Expr]>),
|
Lambda(String, Mrc<[Expr]>, Mrc<[Expr]>),
|
||||||
|
/// A parameterized expression with type inference, eg. `@T. T -> T`
|
||||||
Auto(Option<String>, Mrc<[Expr]>, Mrc<[Expr]>),
|
Auto(Option<String>, Mrc<[Expr]>, Mrc<[Expr]>),
|
||||||
|
/// An opaque function, eg. an effectful function employing CPS.
|
||||||
|
/// Preferably wrap these in an Orchid monad.
|
||||||
ExternFn(ExternFn),
|
ExternFn(ExternFn),
|
||||||
|
/// An opaque non-callable value, eg. a file handle.
|
||||||
|
/// Preferably wrap these in an Orchid structure.
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
|
/// A placeholder for macros, eg. `$name`, `...$body`, `...$lhs:1`
|
||||||
Placeh{
|
Placeh{
|
||||||
key: String,
|
key: String,
|
||||||
/// None => matches one token
|
/// None => matches one token
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use mappable_rc::Mrc;
|
|||||||
|
|
||||||
use crate::utils::{Stackframe, to_mrc_slice, mrc_empty_slice, ProtoMap};
|
use crate::utils::{Stackframe, to_mrc_slice, mrc_empty_slice, ProtoMap};
|
||||||
|
|
||||||
use super::{ast, typed};
|
use super::{ast, typed, get_name::get_name};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@@ -33,43 +33,42 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Try to convert an expression from AST format to typed lambda
|
/// Try to convert an expression from AST format to typed lambda
|
||||||
pub fn expr(expr: &ast::Expr) -> Result<typed::Expr, Error> {
|
pub fn expr(expr: &ast::Expr) -> Result<typed::Expr, Error> {
|
||||||
Ok(expr_rec(expr, ProtoMap::new(), &mut 0, None)?.0)
|
Ok(expr_rec(expr, ProtoMap::new(), None)?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try and convert a single clause from AST format to typed lambda
|
/// Try and convert a single clause from AST format to typed lambda
|
||||||
pub fn clause(clause: &ast::Clause) -> Result<typed::Clause, Error> {
|
pub fn clause(clause: &ast::Clause) -> Result<typed::Clause, Error> {
|
||||||
Ok(clause_rec(clause, ProtoMap::new(), &mut 0, None)?.0)
|
Ok(clause_rec(clause, ProtoMap::new(), None)?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try and convert a sequence of expressions from AST format to typed lambda
|
/// Try and convert a sequence of expressions from AST format to typed lambda
|
||||||
pub fn exprv(exprv: &[ast::Expr]) -> Result<typed::Expr, Error> {
|
pub fn exprv(exprv: &[ast::Expr]) -> Result<typed::Expr, Error> {
|
||||||
Ok(exprv_rec(exprv, ProtoMap::new(), &mut 0, None)?.0)
|
Ok(exprv_rec(exprv, ProtoMap::new(), None)?.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NAMES_INLINE_COUNT:usize = 3;
|
const NAMES_INLINE_COUNT:usize = 3;
|
||||||
|
|
||||||
/// Recursive state of [exprv]
|
/// Recursive state of [exprv]
|
||||||
fn exprv_rec(
|
fn exprv_rec<'a>(
|
||||||
v: &[ast::Expr],
|
v: &'a [ast::Expr],
|
||||||
names: ProtoMap<&str, u64, NAMES_INLINE_COUNT>,
|
names: ProtoMap<&'a str, u64, NAMES_INLINE_COUNT>,
|
||||||
next_id: &mut u64,
|
|
||||||
explicits: Option<&Stackframe<Mrc<typed::Expr>>>,
|
explicits: Option<&Stackframe<Mrc<typed::Expr>>>,
|
||||||
) -> Result<(typed::Expr, usize), Error> {
|
) -> Result<(typed::Expr, usize), Error> {
|
||||||
let (last, rest) = v.split_last().ok_or(Error::EmptyS)?;
|
let (last, rest) = v.split_last().ok_or(Error::EmptyS)?;
|
||||||
if rest.len() == 0 {return expr_rec(&v[0], names, next_id, explicits)}
|
if rest.len() == 0 {return expr_rec(&v[0], names, explicits)}
|
||||||
if let ast::Expr(ast::Clause::Explicit(inner), empty_slice) = last {
|
if let ast::Expr(ast::Clause::Explicit(inner), empty_slice) = last {
|
||||||
assert!(empty_slice.len() == 0,
|
assert!(empty_slice.len() == 0,
|
||||||
"It is assumed that Explicit nodes can never have type annotations as the \
|
"It is assumed that Explicit nodes can never have type annotations as the \
|
||||||
wrapped expression node matches all trailing colons."
|
wrapped expression node matches all trailing colons."
|
||||||
);
|
);
|
||||||
let (x, _) = expr_rec(inner.as_ref(), names, next_id, None)?;
|
let (x, _) = expr_rec(inner.as_ref(), names.clone(), None)?;
|
||||||
let new_explicits = Some(&Stackframe::opush(explicits, Mrc::new(x)));
|
let new_explicits = Stackframe::opush(explicits, Mrc::new(x));
|
||||||
let (body, used_expls) = exprv_rec(rest, names, next_id, new_explicits)?;
|
let (body, used_expls) = exprv_rec(rest, names, Some(&new_explicits))?;
|
||||||
Ok((body, used_expls.saturating_sub(1)))
|
Ok((body, used_expls.saturating_sub(1)))
|
||||||
} else {
|
} else {
|
||||||
let (f, f_used_expls) = exprv_rec(rest, names, next_id, explicits)?;
|
let (f, f_used_expls) = exprv_rec(rest, names.clone(), explicits)?;
|
||||||
let x_explicits = Stackframe::opop(explicits, f_used_expls);
|
let x_explicits = Stackframe::opop(explicits, f_used_expls);
|
||||||
let (x, x_used_expls) = expr_rec(last, names, next_id, x_explicits)?;
|
let (x, x_used_expls) = expr_rec(last, names, x_explicits)?;
|
||||||
Ok((typed::Expr(
|
Ok((typed::Expr(
|
||||||
typed::Clause::Apply(Mrc::new(f), Mrc::new(x)),
|
typed::Clause::Apply(Mrc::new(f), Mrc::new(x)),
|
||||||
mrc_empty_slice()
|
mrc_empty_slice()
|
||||||
@@ -78,19 +77,18 @@ fn exprv_rec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Recursive state of [expr]
|
/// Recursive state of [expr]
|
||||||
fn expr_rec(
|
fn expr_rec<'a>(
|
||||||
ast::Expr(val, typ): &ast::Expr,
|
ast::Expr(val, typ): &'a ast::Expr,
|
||||||
names: ProtoMap<&str, u64, NAMES_INLINE_COUNT>,
|
names: ProtoMap<&'a str, u64, NAMES_INLINE_COUNT>,
|
||||||
next_id: &mut u64,
|
|
||||||
explicits: Option<&Stackframe<Mrc<typed::Expr>>> // known explicit values
|
explicits: Option<&Stackframe<Mrc<typed::Expr>>> // known explicit values
|
||||||
) -> Result<(typed::Expr, usize), Error> { // (output, used_explicits)
|
) -> Result<(typed::Expr, usize), Error> { // (output, used_explicits)
|
||||||
let typ: Vec<typed::Clause> = typ.iter()
|
let typ: Vec<typed::Clause> = typ.iter()
|
||||||
.map(|c| Ok(clause_rec(c, names, next_id, None)?.0))
|
.map(|c| Ok(clause_rec(c, names.clone(), None)?.0))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
if let ast::Clause::S(paren, body) = val {
|
if let ast::Clause::S(paren, body) = val {
|
||||||
if *paren != '(' {return Err(Error::BadGroup(*paren))}
|
if *paren != '(' {return Err(Error::BadGroup(*paren))}
|
||||||
let (typed::Expr(inner, inner_t), used_expls) = exprv_rec(
|
let (typed::Expr(inner, inner_t), used_expls) = exprv_rec(
|
||||||
body.as_ref(), names, next_id, explicits
|
body.as_ref(), names, explicits
|
||||||
)?;
|
)?;
|
||||||
let new_t = if typ.len() == 0 { inner_t } else {
|
let new_t = if typ.len() == 0 { inner_t } else {
|
||||||
to_mrc_slice(if inner_t.len() == 0 { typ } else {
|
to_mrc_slice(if inner_t.len() == 0 { typ } else {
|
||||||
@@ -99,16 +97,15 @@ fn expr_rec(
|
|||||||
};
|
};
|
||||||
Ok((typed::Expr(inner, new_t), used_expls))
|
Ok((typed::Expr(inner, new_t), used_expls))
|
||||||
} else {
|
} else {
|
||||||
let (cls, used_expls) = clause_rec(&val, names, next_id, explicits)?;
|
let (cls, used_expls) = clause_rec(&val, names, explicits)?;
|
||||||
Ok((typed::Expr(cls, to_mrc_slice(typ)), used_expls))
|
Ok((typed::Expr(cls, to_mrc_slice(typ)), used_expls))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursive state of [clause]
|
/// Recursive state of [clause]
|
||||||
fn clause_rec(
|
fn clause_rec<'a>(
|
||||||
cls: &ast::Clause,
|
cls: &'a ast::Clause,
|
||||||
names: ProtoMap<&str, u64, NAMES_INLINE_COUNT>,
|
mut names: ProtoMap<&'a str, u64, NAMES_INLINE_COUNT>,
|
||||||
next_id: &mut u64,
|
|
||||||
mut explicits: Option<&Stackframe<Mrc<typed::Expr>>>
|
mut explicits: Option<&Stackframe<Mrc<typed::Expr>>>
|
||||||
) -> Result<(typed::Clause, usize), Error> {
|
) -> Result<(typed::Clause, usize), Error> {
|
||||||
match cls { // (\t:(@T. Pair T T). t \left.\right. left) @number -- this will fail
|
match cls { // (\t:(@T. Pair T T). t \left.\right. left) @number -- this will fail
|
||||||
@@ -116,8 +113,7 @@ fn clause_rec(
|
|||||||
ast::Clause::Atom(a) => Ok((typed::Clause::Atom(a.clone()), 0)),
|
ast::Clause::Atom(a) => Ok((typed::Clause::Atom(a.clone()), 0)),
|
||||||
ast::Clause::Auto(no, t, b) => {
|
ast::Clause::Auto(no, t, b) => {
|
||||||
// Allocate id
|
// Allocate id
|
||||||
let id = *next_id;
|
let id = get_name();
|
||||||
*next_id += 1;
|
|
||||||
// Pop an explicit if available
|
// Pop an explicit if available
|
||||||
let (value, rest_explicits) = explicits.map(
|
let (value, rest_explicits) = explicits.map(
|
||||||
|Stackframe{ prev, item, .. }| {
|
|Stackframe{ prev, item, .. }| {
|
||||||
@@ -128,7 +124,7 @@ fn clause_rec(
|
|||||||
// Convert the type
|
// Convert the type
|
||||||
let typ = if t.len() == 0 {None} else {
|
let typ = if t.len() == 0 {None} else {
|
||||||
let (typed::Expr(c, t), _) = exprv_rec(
|
let (typed::Expr(c, t), _) = exprv_rec(
|
||||||
t.as_ref(), names, next_id, None
|
t.as_ref(), names.clone(), None
|
||||||
)?;
|
)?;
|
||||||
if t.len() > 0 {return Err(Error::ExplicitBottomKind)}
|
if t.len() > 0 {return Err(Error::ExplicitBottomKind)}
|
||||||
else {Some(Mrc::new(c))}
|
else {Some(Mrc::new(c))}
|
||||||
@@ -136,7 +132,7 @@ fn clause_rec(
|
|||||||
// Traverse body with extended context
|
// Traverse body with extended context
|
||||||
if let Some(name) = no {names.set(&&**name, id)}
|
if let Some(name) = no {names.set(&&**name, id)}
|
||||||
let (body, used_expls) = exprv_rec(
|
let (body, used_expls) = exprv_rec(
|
||||||
b.as_ref(), names, next_id, explicits
|
b.as_ref(), names, explicits
|
||||||
)?;
|
)?;
|
||||||
// Produce a binding instead of an auto if explicit was available
|
// Produce a binding instead of an auto if explicit was available
|
||||||
if let Some(known_value) = value {
|
if let Some(known_value) = value {
|
||||||
@@ -150,20 +146,15 @@ fn clause_rec(
|
|||||||
}
|
}
|
||||||
ast::Clause::Lambda(n, t, b) => {
|
ast::Clause::Lambda(n, t, b) => {
|
||||||
// Allocate id
|
// Allocate id
|
||||||
let id = *next_id;
|
let id = get_name();
|
||||||
*next_id += 1;
|
|
||||||
// Convert the type
|
// Convert the type
|
||||||
let typ = if t.len() == 0 {None} else {
|
let typ = if t.len() == 0 {None} else {
|
||||||
let (typed::Expr(c, t), _) = exprv_rec(
|
let (typed::Expr(c, t), _) = exprv_rec(t.as_ref(), names.clone(), None)?;
|
||||||
t.as_ref(), names, next_id, None
|
|
||||||
)?;
|
|
||||||
if t.len() > 0 {return Err(Error::ExplicitBottomKind)}
|
if t.len() > 0 {return Err(Error::ExplicitBottomKind)}
|
||||||
else {Some(Mrc::new(c))}
|
else {Some(Mrc::new(c))}
|
||||||
};
|
};
|
||||||
names.set(&&**n, id);
|
names.set(&&**n, id);
|
||||||
let (body, used_expls) = exprv_rec(
|
let (body, used_expls) = exprv_rec(b.as_ref(), names, explicits)?;
|
||||||
b.as_ref(), names, next_id, explicits
|
|
||||||
)?;
|
|
||||||
Ok((typed::Clause::Lambda(id, typ, Mrc::new(body)), used_expls))
|
Ok((typed::Clause::Lambda(id, typ, Mrc::new(body)), used_expls))
|
||||||
}
|
}
|
||||||
ast::Clause::Literal(l) => Ok((typed::Clause::Literal(l.clone()), 0)),
|
ast::Clause::Literal(l) => Ok((typed::Clause::Literal(l.clone()), 0)),
|
||||||
@@ -175,7 +166,7 @@ fn clause_rec(
|
|||||||
ast::Clause::S(paren, entries) => {
|
ast::Clause::S(paren, entries) => {
|
||||||
if *paren != '(' {return Err(Error::BadGroup(*paren))}
|
if *paren != '(' {return Err(Error::BadGroup(*paren))}
|
||||||
let (typed::Expr(val, typ), used_expls) = exprv_rec(
|
let (typed::Expr(val, typ), used_expls) = exprv_rec(
|
||||||
entries.as_ref(), names, next_id, explicits
|
entries.as_ref(), names, explicits
|
||||||
)?;
|
)?;
|
||||||
if typ.len() == 0 {Ok((val, used_expls))}
|
if typ.len() == 0 {Ok((val, used_expls))}
|
||||||
else {Err(Error::ExprToClause(typed::Expr(val, typ)))}
|
else {Err(Error::ExprToClause(typed::Expr(val, typ)))}
|
||||||
|
|||||||
10
src/representations/get_name.rs
Normal file
10
src/representations/get_name.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
use std::sync::atomic::AtomicU64;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref NEXT_NAME: AtomicU64 = AtomicU64::new(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_name() -> u64 {
|
||||||
|
NEXT_NAME.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
||||||
|
}
|
||||||
@@ -2,4 +2,5 @@ pub mod ast;
|
|||||||
pub mod typed;
|
pub mod typed;
|
||||||
pub mod literal;
|
pub mod literal;
|
||||||
pub mod ast_to_typed;
|
pub mod ast_to_typed;
|
||||||
|
pub mod get_name;
|
||||||
pub use literal::Literal;
|
pub use literal::Literal;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ impl<'a, T: 'a> Stackframe<'a, T> {
|
|||||||
len: self.len + 1
|
len: self.len + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn opush(prev: Option<&Self>, item: T) -> Self {
|
pub fn opush(prev: Option<&'a Self>, item: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
item,
|
item,
|
||||||
prev,
|
prev,
|
||||||
|
|||||||
Reference in New Issue
Block a user