Backup commit before crunch

This commit is contained in:
2023-05-16 18:32:25 +01:00
parent 33413b2b0f
commit 126494c63f
59 changed files with 847 additions and 236 deletions

View File

@@ -34,12 +34,14 @@ externfn_impl!(Equals1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct Equals0 { a: Literal, x: ExprInst }
atomic_redirect!(Equals0, x);
atomic_impl!(Equals0, |Self{ a, x }: &Self| {
atomic_impl!(Equals0, |Self{ a, x }: &Self, _| {
let eqls = with_lit(x, |l| Ok(match (a, l) {
(Literal::Char(c1), Literal::Char(c2)) => c1 == c2,
(Literal::Num(n1), Literal::Num(n2)) => n1 == n2,
(Literal::Str(s1), Literal::Str(s2)) => s1 == s2,
(Literal::Uint(i1), Literal::Uint(i2)) => i1 == i2,
(Literal::Num(n1), Literal::Uint(u1)) => *n1 == (*u1 as f64),
(Literal::Uint(u1), Literal::Num(n1)) => *n1 == (*u1 as f64),
(_, _) => AssertionError::fail(x.clone(), "the expected type")?,
}))?;
Ok(Boolean::from(eqls).to_atom_cls())

View File

@@ -22,7 +22,7 @@ externfn_impl!(IfThenElse1, |_: &Self, x: ExprInst| Ok(IfThenElse0{x}));
#[derive(Debug, Clone)]
pub struct IfThenElse0{ x: ExprInst }
atomic_redirect!(IfThenElse0, x);
atomic_impl!(IfThenElse0, |this: &Self| {
atomic_impl!(IfThenElse0, |this: &Self, _| {
let Boolean(b) = this.x.clone().try_into()
.map_err(|_| AssertionError::ext(this.x.clone(), "a boolean"))?;
Ok(if b { Clause::Lambda {

View File

@@ -9,6 +9,8 @@ use crate::{pipeline::ConstTree, interner::Interner};
pub fn bool(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("ifthenelse"), ConstTree::xfn(ifthenelse::IfThenElse1)),
(i.i("equals"), ConstTree::xfn(equals::Equals2))
(i.i("equals"), ConstTree::xfn(equals::Equals2)),
(i.i("true"), ConstTree::atom(Boolean(true))),
(i.i("false"), ConstTree::atom(Boolean(false)))
])
}

View File

@@ -24,7 +24,7 @@ externfn_impl!(ParseFloat1, |_: &Self, x: ExprInst| Ok(ParseFloat0{x}));
#[derive(Debug, Clone)]
pub struct ParseFloat0{ x: ExprInst }
atomic_redirect!(ParseFloat0, x);
atomic_impl!(ParseFloat0, |Self{ x }: &Self| {
atomic_impl!(ParseFloat0, |Self{ x }: &Self, _| {
let number = with_lit(x, |l| Ok(match l {
Literal::Str(s) => {
let parser = float_parser();

View File

@@ -23,7 +23,7 @@ externfn_impl!(ParseUint1, |_: &Self, x: ExprInst| Ok(ParseUint0{x}));
#[derive(Debug, Clone)]
pub struct ParseUint0{ x: ExprInst }
atomic_redirect!(ParseUint0, x);
atomic_impl!(ParseUint0, |Self{ x }: &Self| {
atomic_impl!(ParseUint0, |Self{ x }: &Self, _| {
let uint = with_lit(x, |l| Ok(match l {
Literal::Str(s) => {
let parser = int_parser();

View File

@@ -20,7 +20,7 @@ externfn_impl!(ToString1, |_: &Self, x: ExprInst| Ok(ToString0{x}));
#[derive(Debug, Clone)]
pub struct ToString0{ x: ExprInst }
atomic_redirect!(ToString0, x);
atomic_impl!(ToString0, |Self{ x }: &Self| {
atomic_impl!(ToString0, |Self{ x }: &Self, _| {
let string = with_lit(x, |l| Ok(match l {
Literal::Char(c) => c.to_string(),
Literal::Uint(i) => i.to_string(),

33
src/external/cpsio/debug.rs vendored Normal file
View File

@@ -0,0 +1,33 @@
use std::fmt::Debug;
use crate::foreign::{Atomic, AtomicReturn};
use crate::interner::InternedDisplay;
use crate::interpreter::Context;
use crate::{externfn_impl, atomic_defaults};
use crate::representations::interpreted::ExprInst;
/// Debug function
///
/// Next state: [Debug0]
#[derive(Clone)]
pub struct Debug2;
externfn_impl!(Debug2, |_: &Self, x: ExprInst| Ok(Debug1{x}));
/// Partially applied Print function
///
/// Prev state: [Debug1]
#[derive(Debug, Clone)]
pub struct Debug1{ x: ExprInst }
impl Atomic for Debug1 {
atomic_defaults!();
fn run(&self, ctx: Context) -> crate::foreign::AtomicResult {
println!("{}", self.x.bundle(&ctx.interner));
Ok(AtomicReturn{
clause: self.x.expr().clause.clone(),
gas: ctx.gas.map(|g| g - 1),
inert: false
})
}
}

View File

@@ -2,10 +2,14 @@ use crate::{interner::Interner, pipeline::ConstTree};
mod print;
mod readline;
mod debug;
mod panic;
pub fn cpsio(i: &Interner) -> ConstTree {
ConstTree::tree([
(i.i("print"), ConstTree::xfn(print::Print2)),
(i.i("readline"), ConstTree::xfn(readline::Readln2))
(i.i("readline"), ConstTree::xfn(readline::Readln2)),
(i.i("debug"), ConstTree::xfn(debug::Debug2)),
(i.i("panic"), ConstTree::xfn(panic::Panic1))
])
}

29
src/external/cpsio/panic.rs vendored Normal file
View File

@@ -0,0 +1,29 @@
use std::fmt::Display;
use crate::{atomic_impl, atomic_redirect, externfn_impl};
use crate::external::litconv::with_str;
use crate::representations::interpreted::ExprInst;
use crate::foreign::ExternError;
#[derive(Clone)]
pub struct Panic1;
externfn_impl!(Panic1, |_: &Self, x: ExprInst| Ok(Panic0{ x }));
#[derive(Debug, Clone)]
pub struct Panic0{ x: ExprInst }
atomic_redirect!(Panic0, x);
atomic_impl!(Panic0, |Self{ x }: &Self, _| {
with_str(x, |s| {
Err(OrchidPanic(s.clone()).into_extern())
})
});
pub struct OrchidPanic(String);
impl Display for OrchidPanic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Orchid code panicked: {}", self.0)
}
}
impl ExternError for OrchidPanic {}

View File

@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::io::{self, Write};
use std::rc::Rc;
use crate::external::litconv::with_str;
@@ -21,9 +22,10 @@ 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| {
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()

View File

@@ -21,7 +21,7 @@ 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| {
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"))?;

View File

@@ -48,7 +48,7 @@ impl Sub for Numeric {
fn sub(self, rhs: Self) -> Self::Output {
match (self, rhs) {
(Numeric::Uint(a), Numeric::Uint(b)) if b < a => Numeric::Uint(a - b),
(Numeric::Uint(a), Numeric::Uint(b)) if b <= a => Numeric::Uint(a - b),
(Numeric::Uint(a), Numeric::Uint(b))
=> Numeric::num(a as f64 - b as f64),
(Numeric::Num(a), Numeric::Num(b)) => Numeric::num(a - b),

View File

@@ -9,7 +9,6 @@ use crate::representations::interpreted::ExprInst;
/// Add function
///
/// Next state: [Add1]
#[derive(Clone)]
pub struct Add2;
externfn_impl!(Add2, |_: &Self, x: ExprInst| Ok(Add1{x}));
@@ -17,7 +16,6 @@ externfn_impl!(Add2, |_: &Self, x: ExprInst| Ok(Add1{x}));
/// Partially applied Add function
///
/// Prev state: [Add2]; Next state: [Add0]
#[derive(Debug, Clone)]
pub struct Add1{ x: ExprInst }
atomic_redirect!(Add1, x);
@@ -30,11 +28,12 @@ externfn_impl!(Add1, |this: &Self, x: ExprInst| {
/// Fully applied Add function.
///
/// Prev state: [Add1]
#[derive(Debug, Clone)]
pub struct Add0 { a: Numeric, x: ExprInst }
atomic_redirect!(Add0, x);
atomic_impl!(Add0, |Self{ a, x }: &Self| {
atomic_impl!(Add0, |Self{ a, x }: &Self, _| {
let b: Numeric = x.clone().try_into()?;
Ok((*a + b).into())
});

View File

@@ -34,7 +34,7 @@ externfn_impl!(Divide1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct Divide0 { a: Numeric, x: ExprInst }
atomic_redirect!(Divide0, x);
atomic_impl!(Divide0, |Self{ a, x }: &Self| {
atomic_impl!(Divide0, |Self{ a, x }: &Self, _| {
let b: Numeric = x.clone().try_into()?;
Ok((*a / b).into())
});

View File

@@ -34,7 +34,7 @@ externfn_impl!(Multiply1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct Multiply0 { a: Numeric, x: ExprInst }
atomic_redirect!(Multiply0, x);
atomic_impl!(Multiply0, |Self{ a, x }: &Self| {
atomic_impl!(Multiply0, |Self{ a, x }: &Self, _| {
let b: Numeric = x.clone().try_into()?;
Ok((*a * b).into())
});

View File

@@ -34,7 +34,7 @@ externfn_impl!(Remainder1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct Remainder0 { a: Numeric, x: ExprInst }
atomic_redirect!(Remainder0, x);
atomic_impl!(Remainder0, |Self{ a, x }: &Self| {
atomic_impl!(Remainder0, |Self{ a, x }: &Self, _| {
let b: Numeric = x.clone().try_into()?;
Ok((*a % b).into())
});

View File

@@ -34,7 +34,7 @@ externfn_impl!(Subtract1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct Subtract0 { a: Numeric, x: ExprInst }
atomic_redirect!(Subtract0, x);
atomic_impl!(Subtract0, |Self{ a, x }: &Self| {
atomic_impl!(Subtract0, |Self{ a, x }: &Self, _| {
let b: Numeric = x.clone().try_into()?;
Ok((*a - b).into())
});

View File

@@ -33,7 +33,7 @@ externfn_impl!(CharAt1, |this: &Self, x: ExprInst| {
#[derive(Debug, Clone)]
pub struct CharAt0 { s: String, x: ExprInst }
atomic_redirect!(CharAt0, x);
atomic_impl!(CharAt0, |Self{ s, x }: &Self| {
atomic_impl!(CharAt0, |Self{ s, x }: &Self, _| {
with_uint(x, |i| if let Some(c) = s.chars().nth(i as usize) {
Ok(Clause::P(Primitive::Literal(Literal::Char(c))))
} else {

View File

@@ -32,7 +32,7 @@ externfn_impl!(Concatenate1, |this: &Self, c: ExprInst| {
#[derive(Debug, Clone)]
pub struct Concatenate0 { a: String, c: ExprInst }
atomic_redirect!(Concatenate0, c);
atomic_impl!(Concatenate0, |Self{ a, c }: &Self| {
atomic_impl!(Concatenate0, |Self{ a, c }: &Self, _| {
with_str(c, |b| Ok(Clause::P(Primitive::Literal(
Literal::Str(a.to_owned() + b)
))))

View File

@@ -39,7 +39,7 @@ use std::fmt::Debug;
#[macro_export]
macro_rules! atomic_impl {
($typ:ident) => {
atomic_impl!{$typ, |this: &Self| {
atomic_impl!{$typ, |this: &Self, _: $crate::interpreter::Context| {
use $crate::foreign::ExternFn;
Ok(this.clone().to_xfn_cls())
}}
@@ -64,7 +64,7 @@ macro_rules! atomic_impl {
>::from((self, state));
// branch off or wrap up
let clause = if inert {
match ($next_phase)(&next_self) {
match ($next_phase)(&next_self, ctx) {
Ok(r) => r,
Err(e) => return Err(
$crate::interpreter::RuntimeError::Extern(e)

View File

@@ -82,7 +82,10 @@ pub fn apply(
(new_xpr.clause.clone(), (ctx.gas.map(|x| x - 1), false))
} else {(body.expr().clause.clone(), (ctx.gas, false))}),
Clause::Constant(name) => {
let symval = ctx.symbols.get(name).expect("missing symbol for function").clone();
let symval = if let Some(sym) = ctx.symbols.get(name) {sym.clone()}
else { panic!("missing symbol for function {}",
ctx.interner.extern_vec(*name).join("::")
)};
Ok((Clause::Apply { f: symval, x, }, (ctx.gas, false)))
}
Clause::P(Primitive::Atom(atom)) => { // take a step in expanding atom

View File

@@ -1,11 +1,12 @@
use hashbrown::HashMap;
use crate::representations::interpreted::ExprInst;
use crate::interner::Token;
use crate::interner::{Token, Interner};
#[derive(Clone)]
pub struct Context<'a> {
pub symbols: &'a HashMap<Token<Vec<Token<String>>>, ExprInst>,
pub interner: &'a Interner,
pub gas: Option<usize>,
}

View File

@@ -66,8 +66,8 @@ fn namespace_parser<'a>(
.ignore_then(filter_map_lex(enum_filter!(Lexeme::Name)))
.then(
any().repeated().delimited_by(
Lexeme::LP('{').parser(),
Lexeme::RP('{').parser()
Lexeme::LP('(').parser(),
Lexeme::RP('(').parser()
).try_map(move |body, _| {
split_lines(&body)
.map(|l| line.parse(l))
@@ -120,6 +120,7 @@ pub fn line_parser<'a>(ctx: impl Context + 'a)
pub fn split_lines(data: &[Entry]) -> impl Iterator<Item = &[Entry]> {
let mut source = data.iter().enumerate();
let mut last_slice = 0;
let mut finished = false;
iter::from_fn(move || {
let mut paren_count = 0;
while let Some((i, Entry{ lexeme, .. })) = source.next() {
@@ -134,6 +135,11 @@ pub fn split_lines(data: &[Entry]) -> impl Iterator<Item = &[Entry]> {
_ => (),
}
}
// Include last line even without trailing newline
if !finished {
finished = true;
return Some(&data[last_slice..])
}
None
}).filter(|s| s.len() > 0)
}

View File

@@ -6,6 +6,20 @@ use crate::{utils::Substack, interner::{Token, Interner}, pipeline::{ProjectModu
use super::{alias_map::AliasMap, decls::InjectedAsFn};
fn resolve(
token: Token<Vec<Token<String>>>,
alias_map: &AliasMap,
i: &Interner,
) -> Option<Vec<Token<String>>> {
if let Some(alias) = alias_map.resolve(token) {
Some(i.r(alias).clone())
} else if let Some((foot, body)) = i.r(token).split_last() {
let mut new_beginning = resolve(i.i(body), alias_map, i)?;
new_beginning.push(*foot);
Some(new_beginning)
} else {None}
}
fn process_expr(
expr: &Expr,
alias_map: &AliasMap,
@@ -14,9 +28,15 @@ fn process_expr(
) -> Expr {
expr.map_names(&|n| {
injected_as(&i.r(n)[..]).or_else(|| {
alias_map.resolve(n).map(|n| {
injected_as(&i.r(n)[..]).unwrap_or(n)
})
let next_v = resolve(n, alias_map, i)?;
// println!("Resolved alias {} to {}",
// i.extern_vec(n).join("::"),
// i.extern_all(&next_v).join("::")
// );
Some(
injected_as(&next_v)
.unwrap_or_else(|| i.i(&next_v))
)
})
}).unwrap_or_else(|| expr.clone())
}

View File

@@ -1,5 +1,7 @@
use std::rc::Rc;
use itertools::Itertools;
use crate::interner::Interner;
use crate::pipeline::error::ProjectError;
use crate::pipeline::project_tree::ProjectTree;
@@ -23,6 +25,14 @@ pub fn resolve_imports(
&project, &mut map,
i, injected_as
)?;
println!("Aliases: {{{:?}}}",
map.targets.iter()
.map(|(kt, vt)| format!("{} => {}",
i.extern_vec(*kt).join("::"),
i.extern_vec(*vt).join("::")
))
.join(", ")
);
let new_mod = apply_aliases(project.0.as_ref(), &map, i, injected_as);
Ok(ProjectTree(Rc::new(new_mod)))
}

View File

@@ -39,7 +39,7 @@ pub fn parse_layer<'a>(
))
};
let source = source_loader::load_source(
targets, i, loader, &|path| injected_as(path).is_some()
targets, prelude, i, loader, &|path| injected_as(path).is_some()
)?;
let tree = project_tree::build_tree(source, i, prelude, &injected_names)?;
let sum = ProjectTree(Rc::new(

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use hashbrown::HashMap;
use itertools::Itertools;
use crate::pipeline::error::ProjectError;
use crate::interner::{Token, Interner};
@@ -138,6 +139,11 @@ fn source_to_module(
_ => None,
})
.collect::<HashMap<_, _>>();
// println!(
// "Constructing file-module {} with members ({})",
// i.extern_all(&path_v[..]).join("::"),
// exports.keys().map(|t| i.r(*t)).join(", ")
// );
Rc::new(Module {
imports,
items,
@@ -174,10 +180,15 @@ fn files_to_module(
(namespace, ModEntry{ exported: true, member })
})
.collect::<HashMap<_, _>>();
let exports = items.keys()
let exports: HashMap<_, _> = items.keys()
.copied()
.map(|name| (name, i.i(&pushed(&path_v, name))))
.collect();
// println!(
// "Constructing module {} with items ({})",
// i.extern_all(&path_v[..]).join("::"),
// exports.keys().map(|t| i.r(*t)).join(", ")
// );
Rc::new(Module{
items,
imports: vec![],

View File

@@ -1,6 +1,8 @@
use std::println;
use std::rc::Rc;
use hashbrown::HashSet;
use itertools::Itertools;
use crate::representations::tree::WalkErrorKind;
use crate::pipeline::source_loader::LoadedSourceTable;
@@ -30,7 +32,13 @@ pub fn collect_exported_ops(
i: &Interner,
injected: &impl InjectedOperatorsFn
) -> OpsResult {
if let Some(i) = injected(path) {return Ok(i)}
if let Some(ops) = injected(path) {
if path == i.i(&[i.i("prelude")][..]) {
println!("%%% Prelude exported ops %%%");
println!("{}", ops.iter().map(|t| i.r(*t)).join(", "));
}
return Ok(ops)
}
let is_file = |n: &[Token<String>]| loaded.contains_key(&i.i(n));
let path_s = &i.r(path)[..];
let name_split = split_name(path_s, &is_file);
@@ -59,11 +67,15 @@ pub fn collect_exported_ops(
.collect()
}.rc(),
})?;
Ok(Rc::new(module.items.iter()
let out: HashSet<_> = module.items.iter()
.filter(|(_, v)| v.exported)
.map(|(k, _)| *k)
.collect()
))
.collect();
if path == i.i(&[i.i("prelude")][..]) {
println!("%%% Prelude exported ops %%%");
println!("{}", out.iter().map(|t| i.r(*t)).join(", "));
}
Ok(Rc::new(out))
}
pub fn mk_cache<'a>(
@@ -71,5 +83,7 @@ pub fn mk_cache<'a>(
i: &'a Interner,
injected: &'a impl InjectedOperatorsFn,
) -> ExportedOpsCache<'a> {
Cache::new(|path, _this| collect_exported_ops(path, loaded, i, injected))
Cache::new(|path, _this| {
collect_exported_ops(path, loaded, i, injected)
})
}

View File

@@ -1,6 +1,7 @@
use std::rc::Rc;
use hashbrown::HashSet;
use itertools::Itertools;
use crate::parse::is_op;
use crate::pipeline::error::ProjectError;
@@ -34,9 +35,11 @@ pub fn collect_ops_for(
) -> OpsResult {
let tree = &loaded[&i.i(file)].preparsed.0;
let mut ret = HashSet::new();
println!("collecting ops for {}", i.extern_all(file).join("::"));
tree_all_ops(tree.as_ref(), &mut ret);
tree.visit_all_imports(&mut |modpath, module, import| {
if let Some(n) = import.name { ret.insert(n); } else {
println!("\tglob import from {}", i.extern_vec(import.path).join("::"));
let path = import_abs_path(
&file, modpath, module, &i.r(import.path)[..], i
).expect("This error should have been caught during loading");
@@ -45,5 +48,9 @@ pub fn collect_ops_for(
Ok::<_, Rc<dyn ProjectError>>(())
})?;
ret.drain_filter(|t| !is_op(i.r(*t)));
if file == &[i.i("map")][..] {
println!(" %%% ops in map %%% ");
println!("{}", ret.iter().map(|t| i.r(*t)).join(", "))
}
Ok(Rc::new(ret))
}

View File

@@ -5,7 +5,7 @@ use hashbrown::HashMap;
use crate::representations::tree::{ModEntry, ModMember, Module};
use crate::representations::Primitive;
use crate::representations::location::Location;
use crate::foreign::ExternFn;
use crate::foreign::{ExternFn, Atomic, Atom};
use crate::interner::{Token, Interner};
use crate::ast::{Expr, Clause};
use crate::utils::{Substack, pushed};
@@ -17,12 +17,18 @@ pub enum ConstTree {
Tree(HashMap<Token<String>, ConstTree>)
}
impl ConstTree {
pub fn xfn(xfn: impl ExternFn + 'static) -> Self {
pub fn primitive(primitive: Primitive) -> Self {
Self::Const(Expr{
location: Location::Unknown,
value: Clause::P(Primitive::ExternFn(Box::new(xfn)))
value: Clause::P(primitive)
})
}
pub fn xfn(xfn: impl ExternFn + 'static) -> Self {
Self::primitive(Primitive::ExternFn(Box::new(xfn)))
}
pub fn atom(atom: impl Atomic + 'static) -> Self {
Self::primitive(Primitive::Atom(Atom(Box::new(atom))))
}
pub fn tree(
arr: impl IntoIterator<Item = (Token<String>, Self)>
) -> Self {

View File

@@ -7,6 +7,7 @@ use crate::pipeline::split_name::split_name;
use crate::interner::{Token, Interner};
use crate::pipeline::file_loader::{Loaded, load_text, IOResult};
use crate::representations::sourcefile::FileEntry;
use super::loaded_source::{LoadedSourceTable, LoadedSource};
use super::preparse::preparse;
@@ -15,6 +16,7 @@ use super::preparse::preparse;
fn load_abs_path_rec(
abs_path: Token<Vec<Token<String>>>,
table: &mut LoadedSourceTable,
prelude: &[FileEntry],
i: &Interner,
get_source: &impl Fn(Token<Vec<Token<String>>>) -> IOResult,
is_injected: &impl Fn(&[Token<String>]) -> bool
@@ -39,7 +41,7 @@ fn load_abs_path_rec(
.chain(iter::once(i.i(item)))
.collect::<Vec<_>>();
load_abs_path_rec(
i.i(&abs_subpath), table, i, get_source, is_injected
i.i(&abs_subpath), table, prelude, i, get_source, is_injected
)?
}
return Ok(());
@@ -48,7 +50,7 @@ fn load_abs_path_rec(
let text = load_text(i.i(filename), &get_source, i)?;
let preparsed = preparse(
filename.iter().map(|t| i.r(*t)).cloned().collect(),
text.as_str(), i
text.as_str(), prelude, i
)?;
table.insert(abs_path, LoadedSource{ text, preparsed: preparsed.clone() });
// recurse on all imported modules
@@ -58,7 +60,9 @@ fn load_abs_path_rec(
module, &import.nonglob_path(i), i
)?;
// recurse on imported module
load_abs_path_rec(i.i(&abs_pathv), table, i, get_source, is_injected)
load_abs_path_rec(
i.i(&abs_pathv), table, prelude, i, get_source, is_injected
)
})
}
@@ -66,6 +70,7 @@ fn load_abs_path_rec(
/// imports that aren't injected.
pub fn load_source(
targets: &[Token<Vec<Token<String>>>],
prelude: &[FileEntry],
i: &Interner,
get_source: &impl Fn(Token<Vec<Token<String>>>) -> IOResult,
is_injected: &impl Fn(&[Token<String>]) -> bool,
@@ -75,6 +80,7 @@ pub fn load_source(
load_abs_path_rec(
*target,
&mut table,
prelude,
i, get_source, is_injected
)?
}

View File

@@ -38,23 +38,27 @@ fn add_export<K: Eq + Hash>(
}
/// Convert source lines into a module
fn to_module(src: &[FileEntry], i: &Interner) -> Rc<Module<(), ()>>
{
let imports = imports(src.iter()).cloned().collect::<Vec<_>>();
let mut items = src.iter().filter_map(|ent| match ent {
fn to_module(
src: &[FileEntry],
prelude: &[FileEntry],
i: &Interner
) -> Rc<Module<(), ()>> {
let all_src = || src.iter().chain(prelude.iter());
let imports = imports(all_src()).cloned().collect::<Vec<_>>();
let mut items = all_src().filter_map(|ent| match ent {
FileEntry::Internal(Member::Namespace(name, data)) => {
let member = ModMember::Sub(to_module(data, i));
let member = ModMember::Sub(to_module(data, prelude, i));
let entry = ModEntry{ exported: false, member };
Some((*name, entry))
}
FileEntry::Exported(Member::Namespace(name, data)) => {
let member = ModMember::Sub(to_module(data, i));
let member = ModMember::Sub(to_module(data, prelude, i));
let entry = ModEntry{ exported: true, member };
Some((*name, entry))
}
_ => None
}).collect::<HashMap<_, _>>();
for file_entry in src { match file_entry {
for file_entry in all_src() { match file_entry {
FileEntry::Comment(_) | FileEntry::Import(_)
| FileEntry::Internal(Member::Namespace(..))
| FileEntry::Exported(Member::Namespace(..)) => (),
@@ -83,8 +87,12 @@ fn to_module(src: &[FileEntry], i: &Interner) -> Rc<Module<(), ()>>
/// Preparse the module. At this stage, only the imports and
/// names defined by the module can be parsed
pub fn preparse(file: Vec<String>, source: &str, i: &Interner)
-> Result<Preparsed, Rc<dyn ProjectError>> {
pub fn preparse(
file: Vec<String>,
source: &str,
prelude: &[FileEntry],
i: &Interner,
) -> Result<Preparsed, Rc<dyn ProjectError>> {
// Parse with no operators
let ctx = ParsingContext::<&str>::new(&[], i, Rc::new(file.clone()));
let entries = parse::parse(source, ctx)
@@ -98,5 +106,5 @@ pub fn preparse(file: Vec<String>, source: &str, i: &Interner)
namespace: ns.into_iter().map(|t| i.r(t)).cloned().collect(),
file: Rc::new(file.clone())
}.rc())?;
Ok(Preparsed(to_module(&normalized, i)))
Ok(Preparsed(to_module(&normalized, prelude, i)))
}

View File

@@ -8,6 +8,7 @@ pub fn any_match<'a>(matcher: &AnyMatcher, seq: &'a [Expr])
match matcher {
AnyMatcher::Scalar(scalv) => scalv_match(scalv, seq),
AnyMatcher::Vec{ left, mid, right } => {
if seq.len() < left.len() + right.len() {return None};
let left_split = left.len();
let right_split = seq.len() - right.len();
let mut state = scalv_match(left, &seq[..left_split])?;

View File

@@ -28,24 +28,26 @@ export ...$a / ...$b:1 =1000=> (divide (...$a) (...$b))
export ...$a == ...$b =1002=> (equals (...$a) (...$b))
export ...$a ++ ...$b =1003=> (concatenate (...$a) (...$b))
export do { ...$statement ; ...$rest:1 } =10_001=> (
export do { ...$statement ; ...$rest:1 } =0x2p543=> (
statement (...$statement) do { ...$rest }
)
export do { ...$return } =10_000=> (...$return)
export do { ...$return } =0x1p543=> (...$return)
export statement (let $name = ...$value) ...$next =10_000=> (
export statement (let $name = ...$value) ...$next =0x1p1000=> (
(\$name. ...$next) (...$value)
)
export statement (cps $name = ...$operation) ...$next =10_001=> (
export statement (cps $name = ...$operation) ...$next =0x2p1000=> (
(...$operation) \$name. ...$next
)
export statement (cps ...$operation) ...$next =10_000=> (
export statement (cps ...$operation) ...$next =0x1p1000=> (
(...$operation) (...$next)
)
export if ...$cond then ...$true else ...$false:1 =5_000=> (
export if ...$cond then ...$true else ...$false:1 =0x1p320=> (
ifthenelse (...$cond) (...$true) (...$false)
)
export ::(,)
"#;
fn prelude_path(i: &Interner) -> Token<Vec<Token<String>>>
@@ -100,7 +102,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];
@@ -125,6 +127,7 @@ pub fn run_dir(dir: &Path) {
println!("macro execution complete");
let ctx = interpreter::Context {
symbols: &exec_table,
interner: &i,
gas: None
};
let entrypoint = exec_table.get(&entrypoint(&i))