forked from Orchid/orchid
pre-recording backup
This commit is contained in:
35
src/external/cpsio/io.rs
vendored
Normal file
35
src/external/cpsio/io.rs
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
use std::io::{self, Write, stdin};
|
||||
|
||||
use crate::{representations::{interpreted::{ExprInst, Clause}, Primitive, Literal}, atomic_inert, interpreter::{HandlerParm, HandlerRes}, unwrap_or, external::runtime_error::RuntimeError};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum IO {
|
||||
Print(String, ExprInst),
|
||||
Readline(ExprInst)
|
||||
}
|
||||
atomic_inert!(IO);
|
||||
|
||||
pub fn handle(effect: HandlerParm) -> HandlerRes {
|
||||
let io: &IO = unwrap_or!(
|
||||
effect.as_any().downcast_ref();
|
||||
return Err(effect)
|
||||
);
|
||||
match io {
|
||||
IO::Print(str, cont) => {
|
||||
print!("{}", str);
|
||||
io::stdout().flush().unwrap();
|
||||
Ok(Ok(cont.clone()))
|
||||
},
|
||||
IO::Readline(cont) => {
|
||||
let mut buf = String::new();
|
||||
if let Err(e) = stdin().read_line(&mut buf) {
|
||||
return Ok(Err(RuntimeError::ext(e.to_string(), "reading from stdin")));
|
||||
}
|
||||
buf.pop();
|
||||
Ok(Ok(Clause::Apply {
|
||||
f: cont.clone(),
|
||||
x: Clause::P(Primitive::Literal(Literal::Str(buf))).wrap()
|
||||
}.wrap()))
|
||||
}
|
||||
}
|
||||
}
|
||||
3
src/external/cpsio/mod.rs
vendored
3
src/external/cpsio/mod.rs
vendored
@@ -4,6 +4,9 @@ mod print;
|
||||
mod readline;
|
||||
mod debug;
|
||||
mod panic;
|
||||
mod io;
|
||||
|
||||
pub use io::{IO, handle};
|
||||
|
||||
pub fn cpsio(i: &Interner) -> ConstTree {
|
||||
ConstTree::tree([
|
||||
|
||||
35
src/external/cpsio/print.rs
vendored
35
src/external/cpsio/print.rs
vendored
@@ -1,11 +1,12 @@
|
||||
use std::fmt::Debug;
|
||||
use std::io::{self, Write};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::external::litconv::with_str;
|
||||
use crate::representations::PathSet;
|
||||
use crate::{atomic_impl, atomic_redirect, externfn_impl};
|
||||
use crate::representations::interpreted::{Clause, ExprInst};
|
||||
use crate::foreign::{Atomic, AtomicResult, AtomicReturn};
|
||||
use crate::interpreter::Context;
|
||||
use crate::{atomic_impl, atomic_redirect, externfn_impl, atomic_defaults};
|
||||
use crate::representations::interpreted::ExprInst;
|
||||
|
||||
use super::io::IO;
|
||||
|
||||
/// Print function
|
||||
///
|
||||
@@ -22,13 +23,21 @@ externfn_impl!(Print2, |_: &Self, x: ExprInst| Ok(Print1{x}));
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Print1{ x: ExprInst }
|
||||
atomic_redirect!(Print1, x);
|
||||
atomic_impl!(Print1, |Self{ x }: &Self, _| {
|
||||
with_str(x, |s| {
|
||||
print!("{}", s);
|
||||
io::stdout().flush().unwrap();
|
||||
Ok(Clause::Lambda {
|
||||
args: Some(PathSet{ steps: Rc::new(vec![]), next: None }),
|
||||
body: Clause::LambdaArg.wrap()
|
||||
})
|
||||
atomic_impl!(Print1);
|
||||
externfn_impl!(Print1, |this: &Self, x: ExprInst| {
|
||||
with_str(&this.x, |s| {
|
||||
Ok(Print0{ s: s.clone(), x })
|
||||
})
|
||||
});
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Print0{ s: String, x: ExprInst }
|
||||
impl Atomic for Print0 {
|
||||
atomic_defaults!();
|
||||
fn run(&self, ctx: Context) -> AtomicResult {
|
||||
Ok(AtomicReturn::from_data(
|
||||
IO::Print(self.s.clone(), self.x.clone()),
|
||||
ctx
|
||||
))
|
||||
}
|
||||
}
|
||||
31
src/external/cpsio/readline.rs
vendored
31
src/external/cpsio/readline.rs
vendored
@@ -1,10 +1,11 @@
|
||||
use std::fmt::Debug;
|
||||
use std::io::stdin;
|
||||
|
||||
use crate::external::runtime_error::RuntimeError;
|
||||
use crate::{atomic_impl, atomic_redirect, externfn_impl};
|
||||
use crate::representations::{Primitive, Literal};
|
||||
use crate::representations::interpreted::{Clause, ExprInst};
|
||||
use crate::foreign::{Atomic, AtomicResult, AtomicReturn};
|
||||
use crate::interpreter::Context;
|
||||
use crate::{externfn_impl, atomic_defaults};
|
||||
use crate::representations::interpreted::ExprInst;
|
||||
|
||||
use super::io::IO;
|
||||
|
||||
/// Readln function
|
||||
///
|
||||
@@ -20,14 +21,12 @@ externfn_impl!(Readln2, |_: &Self, x: ExprInst| Ok(Readln1{x}));
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Readln1{ x: ExprInst }
|
||||
atomic_redirect!(Readln1, x);
|
||||
atomic_impl!(Readln1, |Self{ x }: &Self, _| {
|
||||
let mut buf = String::new();
|
||||
stdin().read_line(&mut buf)
|
||||
.map_err(|e| RuntimeError::ext(e.to_string(), "reading from stdin"))?;
|
||||
buf.pop();
|
||||
Ok(Clause::Apply {
|
||||
f: x.clone(),
|
||||
x: Clause::P(Primitive::Literal(Literal::Str(buf))).wrap()
|
||||
})
|
||||
});
|
||||
impl Atomic for Readln1 {
|
||||
atomic_defaults!();
|
||||
fn run(&self, ctx: Context) -> AtomicResult {
|
||||
Ok(AtomicReturn::from_data(
|
||||
IO::Readline(self.x.clone()),
|
||||
ctx
|
||||
))
|
||||
}
|
||||
}
|
||||
2
src/external/mod.rs
vendored
2
src/external/mod.rs
vendored
@@ -7,3 +7,5 @@ mod cpsio;
|
||||
mod runtime_error;
|
||||
mod bool;
|
||||
mod litconv;
|
||||
|
||||
pub use cpsio::{IO, handle};
|
||||
@@ -17,6 +17,16 @@ pub struct AtomicReturn {
|
||||
pub gas: Option<usize>,
|
||||
pub inert: bool
|
||||
}
|
||||
impl AtomicReturn {
|
||||
/// Wrap an inert atomic for delivery to the supervisor
|
||||
pub fn from_data<D: Atomic>(d: D, c: Context) -> Self {
|
||||
AtomicReturn {
|
||||
clause: d.to_atom_cls(),
|
||||
gas: c.gas,
|
||||
inert: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aliases for concise macros
|
||||
pub type RcError = Rc<dyn ExternError>;
|
||||
|
||||
@@ -5,4 +5,4 @@ mod run;
|
||||
|
||||
pub use context::{Context, Return};
|
||||
pub use error::RuntimeError;
|
||||
pub use run::{run};
|
||||
pub use run::{run, run_handler, Handler, HandlerParm, HandlerRes};
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::foreign::AtomicReturn;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::foreign::{AtomicReturn, Atomic, ExternError, Atom};
|
||||
use crate::representations::Primitive;
|
||||
use crate::representations::interpreted::{Clause, ExprInst};
|
||||
|
||||
@@ -6,9 +9,10 @@ use super::apply::apply;
|
||||
use super::error::RuntimeError;
|
||||
use super::context::{Context, Return};
|
||||
|
||||
pub fn run(expr: ExprInst, mut ctx: Context)
|
||||
-> Result<Return, RuntimeError>
|
||||
{
|
||||
pub fn run(
|
||||
expr: ExprInst,
|
||||
mut ctx: Context
|
||||
) -> Result<Return, RuntimeError> {
|
||||
let (state, (gas, inert)) = expr.try_normalize(|cls| -> Result<(Clause, _), RuntimeError> {
|
||||
let mut i = cls.clone();
|
||||
while ctx.gas.map(|g| g > 0).unwrap_or(true) {
|
||||
@@ -39,4 +43,67 @@ pub fn run(expr: ExprInst, mut ctx: Context)
|
||||
Ok((i, (ctx.gas, false)))
|
||||
})?;
|
||||
Ok(Return { state, gas, inert })
|
||||
}
|
||||
|
||||
pub type HandlerParm = Box<dyn Atomic>;
|
||||
pub type HandlerRes = Result<
|
||||
Result<ExprInst, Rc<dyn ExternError>>,
|
||||
HandlerParm
|
||||
>;
|
||||
|
||||
pub trait Handler {
|
||||
fn resolve(&mut self, data: HandlerParm) -> HandlerRes;
|
||||
|
||||
fn then<T: Handler>(self, t: T) -> impl Handler
|
||||
where Self: Sized {
|
||||
Pair(self, t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Handler for F
|
||||
where F: FnMut(HandlerParm) -> HandlerRes
|
||||
{
|
||||
fn resolve(&mut self, data: HandlerParm) -> HandlerRes {
|
||||
self(data)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pair<T, U>(T, U);
|
||||
|
||||
impl<T: Handler, U: Handler> Handler for Pair<T, U> {
|
||||
fn resolve(&mut self, data: HandlerParm) -> HandlerRes {
|
||||
match self.0.resolve(data) {
|
||||
Ok(out) => Ok(out),
|
||||
Err(data) => self.1.resolve(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_handler(
|
||||
mut expr: ExprInst,
|
||||
mut handler: impl Handler,
|
||||
mut ctx: Context
|
||||
) -> Result<Return, RuntimeError> {
|
||||
loop {
|
||||
let ret = run(expr.clone(), ctx.clone())?;
|
||||
if ret.gas == Some(0) {
|
||||
return Ok(ret)
|
||||
}
|
||||
let state_ex = ret.state.expr();
|
||||
let a = if let Clause::P(Primitive::Atom(a)) = &state_ex.clause {a}
|
||||
else {
|
||||
mem::drop(state_ex);
|
||||
return Ok(ret)
|
||||
};
|
||||
let boxed = a.clone().0;
|
||||
expr = match handler.resolve(boxed) {
|
||||
Ok(r) => r.map_err(RuntimeError::Extern)?,
|
||||
Err(e) => return Ok(Return{
|
||||
gas: ret.gas,
|
||||
inert: ret.inert,
|
||||
state: Clause::P(Primitive::Atom(Atom(e))).wrap()
|
||||
})
|
||||
};
|
||||
ctx.gas = ret.gas;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(slice_group_by)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(return_position_impl_trait_in_trait)]
|
||||
|
||||
mod parse;
|
||||
mod interner;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::pipeline::error::ProjectError;
|
||||
use crate::interner::{Token, Interner};
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::format;
|
||||
use std::rc::Rc;
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::interner::{Token, Interner, InternedDisplay};
|
||||
use crate::utils::Substack;
|
||||
@@ -33,7 +35,7 @@ impl<M: InternedDisplay + Matcher> InternedDisplay for CachedRule<M> {
|
||||
|
||||
/// Manages a priority queue of substitution rules and allows to apply them
|
||||
pub struct Repository<M: Matcher> {
|
||||
cache: Vec<(CachedRule<M>, HashSet<Token<Vec<Token<String>>>>)>
|
||||
cache: Vec<(CachedRule<M>, HashSet<Token<Vec<Token<String>>>>, NotNan<f64>)>
|
||||
}
|
||||
impl<M: Matcher> Repository<M> {
|
||||
pub fn new(mut rules: Vec<Rule>, i: &Interner)
|
||||
@@ -42,6 +44,7 @@ impl<M: Matcher> Repository<M> {
|
||||
rules.sort_by_key(|r| -r.prio);
|
||||
let cache = rules.into_iter()
|
||||
.map(|r| {
|
||||
let prio = r.prio;
|
||||
let rule = prepare_rule(r.clone(), i)
|
||||
.map_err(|e| (r, e))?;
|
||||
let mut glossary = HashSet::new();
|
||||
@@ -56,7 +59,7 @@ impl<M: Matcher> Repository<M> {
|
||||
source: rule.source,
|
||||
template: rule.target
|
||||
};
|
||||
Ok((prep, glossary))
|
||||
Ok((prep, glossary, prio))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(Self{cache})
|
||||
@@ -67,7 +70,7 @@ impl<M: Matcher> Repository<M> {
|
||||
let mut glossary = HashSet::new();
|
||||
code.visit_names(Substack::Bottom, &mut |op| { glossary.insert(op); });
|
||||
// println!("Glossary for code: {:?}", print_nname_seq(glossary.iter(), i));
|
||||
for (rule, deps) in self.cache.iter() {
|
||||
for (rule, deps, _) in self.cache.iter() {
|
||||
if !deps.is_subset(&glossary) { continue; }
|
||||
let product = update_first_seq::expr(code, &mut |exprv| {
|
||||
let state = rule.matcher.apply(exprv.as_slice())?;
|
||||
@@ -122,11 +125,17 @@ impl<M: Debug + Matcher> Debug for Repository<M> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_hex(num: f64) -> String {
|
||||
let exponent = (num.log2() / 4_f64).floor();
|
||||
let mantissa = num / 16_f64.powf(exponent);
|
||||
format!("0x{:x}p{}", mantissa as i64, exponent as i64)
|
||||
}
|
||||
|
||||
impl<M: InternedDisplay + Matcher> InternedDisplay for Repository<M> {
|
||||
fn fmt_i(&self, f: &mut std::fmt::Formatter<'_>, i: &Interner) -> std::fmt::Result {
|
||||
writeln!(f, "Repository[")?;
|
||||
for (item, _) in self.cache.iter() {
|
||||
write!(f, "\t")?;
|
||||
for (item, _, p) in self.cache.iter() {
|
||||
write!(f, "\t{}", fmt_hex(f64::from(*p)))?;
|
||||
item.fmt_i(f, i)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::rc::Rc;
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::external::handle;
|
||||
use crate::interpreter::Return;
|
||||
use crate::representations::{ast_to_postmacro, postmacro_to_interpreted};
|
||||
use crate::{external, xloop, interpreter};
|
||||
@@ -20,30 +21,28 @@ import std::(
|
||||
concatenate
|
||||
)
|
||||
|
||||
export ...$a + ...$b =1001=> (add (...$a) (...$b))
|
||||
export ...$a - ...$b:1 =1001=> (subtract (...$a) (...$b))
|
||||
export ...$a * ...$b =1000=> (multiply (...$a) (...$b))
|
||||
export ...$a % ...$b:1 =1000=> (remainder (...$a) (...$b))
|
||||
export ...$a / ...$b:1 =1000=> (divide (...$a) (...$b))
|
||||
export ...$a == ...$b =1002=> (equals (...$a) (...$b))
|
||||
export ...$a ++ ...$b =1003=> (concatenate (...$a) (...$b))
|
||||
export ...$a + ...$b =0x2p36=> (add (...$a) (...$b))
|
||||
export ...$a - ...$b:1 =0x2p36=> (subtract (...$a) (...$b))
|
||||
export ...$a * ...$b =0x1p36=> (multiply (...$a) (...$b))
|
||||
export ...$a % ...$b:1 =0x1p36=> (remainder (...$a) (...$b))
|
||||
export ...$a / ...$b:1 =0x1p36=> (divide (...$a) (...$b))
|
||||
export ...$a == ...$b =0x3p36=> (equals (...$a) (...$b))
|
||||
export ...$a ++ ...$b =0x4p36=> (concatenate (...$a) (...$b))
|
||||
|
||||
export do { ...$statement ; ...$rest:1 } =0x2p543=> (
|
||||
statement (...$statement) do { ...$rest }
|
||||
)
|
||||
export do { ...$return } =0x1p543=> (...$return)
|
||||
export do { ...$statement ; ...$rest:1 } =0x2p130=> statement (...$statement) do { ...$rest }
|
||||
export do { ...$return } =0x1p130=> ...$return
|
||||
|
||||
export statement (let $name = ...$value) ...$next =0x1p1000=> (
|
||||
export statement (let $name = ...$value) ...$next =0x1p230=> (
|
||||
(\$name. ...$next) (...$value)
|
||||
)
|
||||
export statement (cps $name = ...$operation) ...$next =0x2p1000=> (
|
||||
export statement (cps $name = ...$operation) ...$next =0x2p230=> (
|
||||
(...$operation) \$name. ...$next
|
||||
)
|
||||
export statement (cps ...$operation) ...$next =0x1p1000=> (
|
||||
export statement (cps ...$operation) ...$next =0x1p230=> (
|
||||
(...$operation) (...$next)
|
||||
)
|
||||
|
||||
export if ...$cond then ...$true else ...$false:1 =0x1p320=> (
|
||||
export if ...$cond then ...$true else ...$false:1 =0x1p84=> (
|
||||
ifthenelse (...$cond) (...$true) (...$false)
|
||||
)
|
||||
|
||||
@@ -102,7 +101,7 @@ pub fn run_dir(dir: &Path) {
|
||||
rule.bundle(&i)
|
||||
)
|
||||
});
|
||||
// println!("Repo dump: {}", repo.bundle(&i));
|
||||
println!("Repo dump: {}", repo.bundle(&i));
|
||||
let mut exec_table = HashMap::new();
|
||||
for (name, source) in consts.iter() {
|
||||
// let nval = entrypoint(&i); let name = &nval; let source = &consts[name];
|
||||
@@ -114,7 +113,7 @@ pub fn run_dir(dir: &Path) {
|
||||
match repo.step(&tree) {
|
||||
None => break tree,
|
||||
Some(phase) => {
|
||||
println!("Step {idx}/{macro_timeout}: {}", phase.bundle(&i));
|
||||
// println!("Step {idx}/{macro_timeout}: {}", phase.bundle(&i));
|
||||
tree = phase;
|
||||
},
|
||||
}
|
||||
@@ -138,10 +137,11 @@ pub fn run_dir(dir: &Path) {
|
||||
.join(", ")
|
||||
)
|
||||
});
|
||||
let Return{ gas, state, inert } = interpreter::run(entrypoint.clone(), ctx)
|
||||
let io_handler = handle;
|
||||
let ret = interpreter::run_handler(entrypoint.clone(), io_handler, ctx);
|
||||
let Return{ gas, state, inert } = ret
|
||||
.unwrap_or_else(|e| panic!("Runtime error: {}", e));
|
||||
if inert {
|
||||
println!("Expression not reducible");
|
||||
println!("Settled at {}", state.expr().clause.bundle(&i));
|
||||
println!("Remaining gas: {}",
|
||||
gas.map(|g| g.to_string())
|
||||
@@ -149,5 +149,4 @@ pub fn run_dir(dir: &Path) {
|
||||
);
|
||||
}
|
||||
if gas == Some(0) {println!("Ran out of gas!")}
|
||||
else {println!("Expression not reducible.")}
|
||||
}
|
||||
Reference in New Issue
Block a user