process now uses spans, for to give panic locations

This commit is contained in:
Scott Richmond 2024-12-11 18:58:59 -05:00
parent 5f154fe56f
commit ecc7b26b66
3 changed files with 75 additions and 121 deletions

View File

@ -63,8 +63,11 @@ use crate::process::*;
#[folder = "assets/"] #[folder = "assets/"]
struct Asset; struct Asset;
pub fn prelude<'src>() -> Process<'src> { pub fn prelude<'src>() -> (
let prelude = Asset::get("prelude.ld").unwrap().data.into_owned(); Vec<(String, Value<'src>)>,
std::collections::HashMap<*const Ast, FnInfo>,
) {
let prelude = Asset::get("test_prelude.ld").unwrap().data.into_owned();
// we know for sure Prelude should live through the whole run of the program // we know for sure Prelude should live through the whole run of the program
let leaked = Box::leak(Box::new(prelude)); let leaked = Box::leak(Box::new(prelude));
let prelude = std::str::from_utf8(leaked).unwrap(); let prelude = std::str::from_utf8(leaked).unwrap();
@ -87,19 +90,20 @@ pub fn prelude<'src>() -> Process<'src> {
panic!(); panic!();
} }
let (p_ast, p_span) = Box::leak(Box::new(p_ast.unwrap())); let prelude_parsed = Box::leak(Box::new(p_ast.unwrap()));
let base_pkg = base(); let base_pkg = base();
let base_names = base_pkg.iter().map(|binding| binding.0.clone()).collect(); let base_names = base_pkg.iter().map(|binding| binding.0.clone()).collect();
let mut v6or = Validator::new(p_ast, *p_span, &base_names); let mut v6or = Validator::new(&prelude_parsed.0, prelude_parsed.1, &base_names);
v6or.validate(); v6or.validate();
// dbg!(&v6or); // dbg!(&v6or);
let mut base_ctx = Process::<'src> { let mut base_ctx = Process::<'src> {
locals: base_pkg, locals: base_pkg,
ast: p_ast, ast: &prelude_parsed.0,
span: prelude_parsed.1,
prelude: vec![], prelude: vec![],
fn_info: v6or.fn_info, fn_info: v6or.fn_info,
}; };
@ -125,12 +129,7 @@ pub fn prelude<'src>() -> Process<'src> {
} }
}; };
Process { (p_ctx, base_ctx.fn_info)
locals: vec![],
ast: &Ast::Nil,
prelude: p_ctx,
fn_info: base_ctx.fn_info,
}
} }
pub fn run(src: &'static str) { pub fn run(src: &'static str) {
@ -150,21 +149,28 @@ pub fn run(src: &'static str) {
return; return;
} }
let (ast, span) = parse_result.unwrap(); let parsed = parse_result.unwrap();
let dummy_prelude = vec![]; let dummy_prelude = vec![];
let mut v6or = Validator::new(&ast, span, &dummy_prelude); let mut v6or = Validator::new(&parsed.0, parsed.1, &dummy_prelude);
v6or.validate(); v6or.validate();
// dbg!(&v6or); // dbg!(&v6or);
// dbg!(&v6or.fn_info); // dbg!(&v6or.fn_info);
let mut proc = prelude(); let (prelude_ctx, mut prelude_fn_info) = prelude();
proc.ast = &ast;
// dbg!(&proc.fn_info); prelude_fn_info.extend(&mut v6or.fn_info.into_iter());
proc.fn_info.extend(&mut v6or.fn_info.into_iter());
let mut proc = Process {
locals: vec![],
prelude: prelude_ctx,
ast: &parsed.0,
span: parsed.1,
fn_info: prelude_fn_info,
};
let result = proc.eval(); let result = proc.eval();
@ -176,7 +182,10 @@ pub fn run(src: &'static str) {
pub fn main() { pub fn main() {
let src = " let src = "
when {
false -> :false
true -> :true
}
"; ";
run(src); run(src);
// struct_scalpel::print_dissection_info::<value::Value>() // struct_scalpel::print_dissection_info::<value::Value>()

View File

@ -317,14 +317,17 @@ impl<'src> Process<'src> {
} }
} }
fn visit(&mut self, node: &'src Spanned<Ast>) { pub fn visit(&mut self, node: &'src Spanned<Ast>) -> LResult<'src> {
self.ast = &node.0; let (expr, span) = node;
self.span = node.1; self.ast = expr;
self.span = *span;
self.eval()
} }
pub fn eval(&mut self) -> LResult<'src> { pub fn eval(&mut self) -> LResult<'src> {
use Ast::*; use Ast::*;
let root = self.ast; let root_node = self.ast;
let root_span = self.span;
let result = match self.ast { let result = match self.ast {
Nil => Ok(Value::Nil), Nil => Ok(Value::Nil),
Boolean(b) => Ok(Value::Boolean(*b)), Boolean(b) => Ok(Value::Boolean(*b)),
@ -346,56 +349,42 @@ impl<'src> Process<'src> {
Ok(Value::AllocatedString(Rc::new(interpolated))) Ok(Value::AllocatedString(Rc::new(interpolated)))
} }
Block(exprs) => { Block(exprs) => {
let parent = self.ast;
let to = self.locals.len(); let to = self.locals.len();
let mut result = Value::Nil; let mut result = Value::Nil;
for (expr, _) in exprs { for expr in exprs {
self.ast = expr; result = self.visit(expr)?;
result = self.eval()?;
} }
self.pop_to(to); self.locals.truncate(to);
self.ast = parent;
Ok(result) Ok(result)
} }
If(cond, if_true, if_false) => { If(cond, if_true, if_false) => {
let parent = self.ast; let truthy = self.visit(cond)?;
self.ast = &cond.0; let to_visit = if truthy.bool() { if_true } else { if_false };
let truthy = self.eval()?.bool(); self.visit(to_visit)
self.ast = if truthy { &if_true.0 } else { &if_false.0 };
let result = self.eval();
self.ast = parent;
result
} }
List(members) => { List(members) => {
let parent = self.ast;
let mut vect = Vector::new(); let mut vect = Vector::new();
for member in members { for member in members {
self.ast = &member.0; let member_value = self.visit(member)?;
if let Ast::Splat(_) = self.ast { match member.0 {
let to_splat = self.eval()?; Ast::Splat(_) => match member_value {
match to_splat {
Value::List(list) => vect.append(list), Value::List(list) => vect.append(list),
_ => { _ => {
return Err(LErr::new( return Err(LErr::new(
"only lists may be splatted into lists".to_string(), "only lists may be splatted into lists".to_string(),
)) ))
} }
} },
} else { _ => vect.push_back(member_value),
vect.push_back(self.eval()?)
} }
} }
self.ast = parent;
Ok(Value::List(vect)) Ok(Value::List(vect))
} }
Tuple(members) => { Tuple(members) => {
let parent = self.ast;
let mut vect = Vec::new(); let mut vect = Vec::new();
for member in members { for member in members {
self.ast = &member.0; vect.push(self.visit(member)?);
vect.push(self.eval()?);
} }
self.ast = parent;
Ok(Value::Tuple(Rc::new(vect))) Ok(Value::Tuple(Rc::new(vect)))
} }
Word(w) | Ast::Splat(w) => { Word(w) | Ast::Splat(w) => {
@ -403,47 +392,35 @@ impl<'src> Process<'src> {
Ok(val) Ok(val)
} }
Let(patt, expr) => { Let(patt, expr) => {
let parent = self.ast; let val = self.visit(expr)?;
self.ast = &expr.0;
let val = self.eval()?;
let result = match self.match_pattern(&patt.0, &val) { let result = match self.match_pattern(&patt.0, &val) {
Some(_) => Ok(val), Some(_) => Ok(val),
None => Err(LErr::new("no match".to_string())), None => Err(LErr::new("no match".to_string())),
}; };
self.ast = parent;
result result
} }
Placeholder => Ok(Value::Placeholder), Placeholder => Ok(Value::Placeholder),
Arguments(a) => { Arguments(a) => {
let parent = self.ast;
let mut args = vec![]; let mut args = vec![];
for (arg, _) in a.iter() { for arg in a.iter() {
self.ast = arg; args.push(self.visit(arg)?)
let arg = self.eval()?;
args.push(arg);
} }
let result = if args.iter().any(|arg| matches!(arg, Value::Placeholder)) { let result = if args.iter().any(|arg| matches!(arg, Value::Placeholder)) {
Ok(Value::Args(Rc::new(args))) Ok(Value::Args(Rc::new(args)))
} else { } else {
Ok(Value::Tuple(Rc::new(args))) Ok(Value::Tuple(Rc::new(args)))
}; };
self.ast = parent;
result result
} }
Dict(terms) => { Dict(terms) => {
let parent = self.ast;
let mut dict = HashMap::new(); let mut dict = HashMap::new();
for term in terms { for term in terms {
let (term, _) = term;
match term { match term {
Ast::Pair(key, value) => { (Ast::Pair(key, value), _) => {
self.ast = &value.0; dict.insert(*key, self.visit(value)?);
let value = self.eval()?;
dict.insert(*key, value);
} }
Ast::Splat(_) => { (Ast::Splat(_), _) => {
self.ast = term; let resolved = self.visit(term)?;
let resolved = self.eval()?;
let Value::Dict(to_splat) = resolved else { let Value::Dict(to_splat) = resolved else {
return Err(LErr::new( return Err(LErr::new(
"cannot splat non-dict into dict".to_string(), "cannot splat non-dict into dict".to_string(),
@ -454,60 +431,42 @@ impl<'src> Process<'src> {
_ => unreachable!(), _ => unreachable!(),
} }
} }
self.ast = parent;
Ok(Value::Dict(dict)) Ok(Value::Dict(dict))
} }
LBox(name, expr) => { LBox(name, expr) => {
let parent = self.ast; let val = self.visit(expr)?;
self.ast = &expr.0;
let val = self.eval()?;
let boxed = Value::Box(name, Rc::new(RefCell::new(val))); let boxed = Value::Box(name, Rc::new(RefCell::new(val)));
self.bind(name.to_string(), &boxed); self.bind(name.to_string(), &boxed);
self.ast = parent;
Ok(boxed) Ok(boxed)
} }
Synthetic(root, first, rest) => { Synthetic(root, first, rest) => {
let parent = self.ast; let root_val = self.visit(root)?;
self.ast = &root.0; let first_val = self.visit(first)?;
let root = self.eval()?; let mut curr = self.apply(root_val, first_val)?;
self.ast = &first.0;
let first = self.eval()?;
let mut curr = self.apply(root, first)?;
for term in rest.iter() { for term in rest.iter() {
self.ast = &term.0; let next = self.visit(term)?;
let next = self.eval()?;
curr = self.apply(curr, next)?; curr = self.apply(curr, next)?;
} }
self.ast = parent;
Ok(curr) Ok(curr)
} }
When(clauses) => { When(clauses) => {
let parent = self.ast;
for clause in clauses.iter() { for clause in clauses.iter() {
let WhenClause(cond, body) = &clause.0 else { let WhenClause(cond, body) = &clause.0 else {
unreachable!() unreachable!()
}; };
self.ast = &cond.0; if self.visit(cond)?.bool() {
if self.eval()?.bool() { return self.visit(body);
self.ast = &body.0;
let result = self.eval();
self.ast = parent;
return result;
}; };
} }
Err(LErr::new("no match".to_string())) Err(LErr::new("no match".to_string()))
} }
Match(value, clauses) => { Match(scrutinee, clauses) => {
let parent = self.ast; let value = self.visit(scrutinee)?;
self.ast = &value.0; self.match_clauses(&value, clauses)
let value = self.eval()?;
let result = self.match_clauses(&value, clauses);
self.ast = parent;
result
} }
Fn(name, clauses, doc) => { Fn(name, clauses, doc) => {
let doc = doc.map(|s| s.to_string()); let doc = doc.map(|s| s.to_string());
let ptr: *const Ast = root; let ptr: *const Ast = root_node;
// dbg!(&root); // dbg!(&root);
// dbg!(&ptr); // dbg!(&ptr);
// dbg!(&self.fn_info); // dbg!(&self.fn_info);
@ -531,64 +490,50 @@ impl<'src> Process<'src> {
} }
FnDeclaration(_name) => Ok(Value::Nil), FnDeclaration(_name) => Ok(Value::Nil),
Panic(msg) => { Panic(msg) => {
self.ast = &msg.0; let msg = self.visit(msg)?;
let msg = self.eval()?;
Err(LErr::new(format!("{msg}"))) Err(LErr::new(format!("{msg}")))
} }
Repeat(times, body) => { Repeat(times, body) => {
let parent = self.ast; let times_num = match self.visit(times) {
self.ast = &times.0;
let times_num = match self.eval() {
Ok(Value::Number(n)) => n as usize, Ok(Value::Number(n)) => n as usize,
_ => return Err(LErr::new("`repeat` may only take numbers".to_string())), _ => return Err(LErr::new("`repeat` may only take numbers".to_string())),
}; };
self.ast = &body.0;
for _ in 0..times_num { for _ in 0..times_num {
self.eval()?; self.visit(body)?;
} }
self.ast = parent;
Ok(Value::Nil) Ok(Value::Nil)
} }
Do(terms) => { Do(terms) => {
let parent = self.ast; let mut result = self.visit(&terms[0])?;
self.ast = &terms[0].0; for term in terms.iter().skip(1) {
let mut result = self.eval()?; let next = self.visit(term)?;
for (term, _) in terms.iter().skip(1) {
self.ast = term;
let next = self.eval()?;
let arg = Value::Tuple(Rc::new(vec![result])); let arg = Value::Tuple(Rc::new(vec![result]));
result = self.apply(next, arg)?; result = self.apply(next, arg)?;
} }
self.ast = parent;
Ok(result) Ok(result)
} }
Loop(init, clauses) => { Loop(init, clauses) => {
let parent = self.ast; let mut args = self.visit(init)?;
self.ast = &init.0;
let mut args = self.eval()?;
loop { loop {
let result = self.match_clauses(&args, clauses)?; let result = self.match_clauses(&args, clauses)?;
if let Value::Recur(recur_args) = result { if let Value::Recur(recur_args) = result {
args = Value::Tuple(Rc::new(recur_args)); args = Value::Tuple(Rc::new(recur_args));
} else { } else {
self.ast = parent;
return Ok(result); return Ok(result);
} }
} }
} }
Recur(args) => { Recur(args) => {
let parent = self.ast;
let mut vect = Vec::new(); let mut vect = Vec::new();
for arg in args { for arg in args {
self.ast = &arg.0; vect.push(self.visit(arg)?);
vect.push(self.eval()?);
} }
self.ast = parent;
Ok(Value::Recur(vect)) Ok(Value::Recur(vect))
} }
_ => unreachable!(), _ => unreachable!(),
}; };
self.ast = root; self.ast = root_node;
self.span = root_span;
result result
} }
} }

View File

@ -118,7 +118,7 @@ impl fmt::Display for Value<'_> {
impl Value<'_> { impl Value<'_> {
pub fn bool(&self) -> bool { pub fn bool(&self) -> bool {
matches!(self, Value::Nil | Value::Boolean(false)) !matches!(self, Value::Nil | Value::Boolean(false))
} }
} }