mirror of
https://github.com/urbit/ares.git
synced 2024-11-23 09:06:23 +03:00
add nock 12 to interpreter
This commit is contained in:
parent
fe54fef2e8
commit
7082393d8d
@ -6,6 +6,7 @@ use crate::newt::Newt;
|
||||
use crate::noun;
|
||||
use crate::noun::{Atom, Cell, IndirectAtom, Noun, Slots, D, T};
|
||||
use crate::serf::TERMINATOR;
|
||||
use ares_macros::tas;
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use either::Either::*;
|
||||
@ -208,6 +209,22 @@ struct Nock11S {
|
||||
tail: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Todo12 {
|
||||
ComputeReff,
|
||||
ComputePath,
|
||||
Scry,
|
||||
Done,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Nock12 {
|
||||
todo: Todo12,
|
||||
reff: Noun,
|
||||
path: Noun,
|
||||
hand: Noun,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum NockWork {
|
||||
Done,
|
||||
@ -226,6 +243,7 @@ enum NockWork {
|
||||
Work10(Nock10),
|
||||
Work11D(Nock11D),
|
||||
Work11S(Nock11S),
|
||||
Work12(Nock12),
|
||||
}
|
||||
|
||||
pub struct Context<'a, 'b, 'c> {
|
||||
@ -235,16 +253,19 @@ pub struct Context<'a, 'b, 'c> {
|
||||
// Per-event cache; option to share cache with virtualized events
|
||||
pub cache: &'c mut Hamt<Noun>,
|
||||
// XX: persistent memo cache
|
||||
pub scry_stack: Noun,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Tone {
|
||||
Blocked(Noun),
|
||||
Error(NockErr, Noun),
|
||||
Deterministic(Noun),
|
||||
NonDeterministic(Noun),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NockErr {
|
||||
Blocked(Noun),
|
||||
Deterministic,
|
||||
NonDeterministic,
|
||||
}
|
||||
@ -637,6 +658,67 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
context.stack.pop::<NockWork>();
|
||||
}
|
||||
},
|
||||
NockWork::Work12(mut scry) => match scry.todo {
|
||||
Todo12::ComputeReff => {
|
||||
scry.todo = Todo12::ComputePath;
|
||||
*context.stack.top() = NockWork::Work12(scry);
|
||||
push_formula(context.stack, scry.reff, false)?;
|
||||
}
|
||||
Todo12::ComputePath => {
|
||||
scry.todo = Todo12::Scry;
|
||||
scry.reff = res;
|
||||
*context.stack.top() = NockWork::Work12(scry);
|
||||
push_formula(context.stack, scry.path, false)?;
|
||||
}
|
||||
Todo12::Scry => {
|
||||
if let Some(cell) = context.scry_stack.cell() {
|
||||
let scry_handler = cell.head();
|
||||
let scry_gate = scry_handler.as_cell()?;
|
||||
let payload = T(context.stack, &[scry.reff, res]);
|
||||
let scry_core = T(
|
||||
context.stack,
|
||||
&[
|
||||
scry_gate.head(),
|
||||
payload,
|
||||
scry_gate.tail().as_cell()?.tail(),
|
||||
],
|
||||
);
|
||||
let scry_form = T(context.stack, &[D(9), D(2), D(1), scry_core]);
|
||||
|
||||
scry.todo = Todo12::Done;
|
||||
scry.path = res;
|
||||
scry.hand = context.scry_stack;
|
||||
context.scry_stack = cell.tail();
|
||||
*context.stack.top() = NockWork::Work12(scry);
|
||||
push_formula(context.stack, scry_form, false)?;
|
||||
} else {
|
||||
// No scry handler
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
}
|
||||
Todo12::Done => match res.as_either_atom_cell() {
|
||||
Left(atom) => {
|
||||
if atom.as_noun().raw_equals(D(0)) {
|
||||
break Err(NockErr::Blocked(scry.path));
|
||||
} else {
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
}
|
||||
Right(cell) => match cell.tail().as_either_atom_cell() {
|
||||
Left(_) => {
|
||||
let hunk =
|
||||
T(context.stack, &[D(tas!(b"hunk")), scry.reff, scry.path]);
|
||||
mean_push(context.stack, hunk);
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
Right(cell) => {
|
||||
res = cell.tail();
|
||||
context.scry_stack = scry.hand;
|
||||
context.stack.pop::<NockWork>();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -829,6 +911,19 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
||||
return Err(NockErr::Deterministic);
|
||||
};
|
||||
}
|
||||
12 => {
|
||||
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
|
||||
*stack.push() = NockWork::Work12(Nock12 {
|
||||
todo: Todo12::ComputeReff,
|
||||
reff: arg_cell.head(),
|
||||
path: arg_cell.tail(),
|
||||
hand: D(0),
|
||||
});
|
||||
} else {
|
||||
// Argument for Nock 12 must be cell
|
||||
return Err(NockErr::Deterministic);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Invalid formula opcode
|
||||
return Err(NockErr::Deterministic);
|
||||
@ -856,12 +951,31 @@ pub fn exit_early(
|
||||
) -> Tone {
|
||||
unsafe {
|
||||
let mut trace = *(stack.local_noun_pointer(0));
|
||||
while stack.get_frame_pointer() != virtual_frame {
|
||||
stack.preserve(&mut trace);
|
||||
stack.preserve(cache);
|
||||
stack.frame_pop();
|
||||
match error {
|
||||
NockErr::Blocked(mut path) => {
|
||||
while stack.get_frame_pointer() != virtual_frame {
|
||||
stack.preserve(&mut path);
|
||||
stack.preserve(cache);
|
||||
stack.frame_pop();
|
||||
}
|
||||
Tone::Blocked(path)
|
||||
}
|
||||
NockErr::Deterministic => {
|
||||
while stack.get_frame_pointer() != virtual_frame {
|
||||
stack.preserve(&mut trace);
|
||||
stack.preserve(cache);
|
||||
stack.frame_pop();
|
||||
}
|
||||
Tone::Deterministic(trace)
|
||||
}
|
||||
NockErr::NonDeterministic => {
|
||||
while stack.get_frame_pointer() != virtual_frame {
|
||||
stack.preserve(&mut trace);
|
||||
stack.frame_pop();
|
||||
}
|
||||
Tone::NonDeterministic(trace)
|
||||
}
|
||||
}
|
||||
Tone::Error(error, trace)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1034,21 +1148,24 @@ mod hint {
|
||||
Ok(Some(nock_res))
|
||||
}
|
||||
}
|
||||
Err(Tone::Error(err, _)) => {
|
||||
Err(tone) => {
|
||||
let stack = &mut context.stack;
|
||||
// XX: need string interpolation without allocation, then delete eprintln
|
||||
// let tape = tape(stack, "jet mismatch in {}, raw: {}, jetted: {}", jet_name, err, jet_res);
|
||||
eprintln!(
|
||||
"\rjet {} failed, raw: {:?}, jetted: {}",
|
||||
jet_name, err, jet_res
|
||||
jet_name, tone, jet_res
|
||||
);
|
||||
let tape = tape(*stack, "jet mismatch");
|
||||
let mean = T(*stack, &[D(tas!(b"mean")), tape]);
|
||||
mean_push(stack, mean);
|
||||
Err(err)
|
||||
}
|
||||
Err(Tone::Blocked(_)) => {
|
||||
panic!("jet test mode: no scry handling")
|
||||
|
||||
match tone {
|
||||
Tone::NonDeterministic(_) => {
|
||||
Err(NockErr::NonDeterministic)
|
||||
}
|
||||
_ => Err(NockErr::Deterministic),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -313,6 +313,7 @@ pub mod util {
|
||||
stack,
|
||||
newt: None,
|
||||
cache: &mut Hamt::<Noun>::new(),
|
||||
scry_stack: D(0),
|
||||
};
|
||||
let sam = T(context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = assert_no_alloc(|| jet(&mut context, sam).unwrap());
|
||||
@ -334,6 +335,7 @@ pub mod util {
|
||||
stack,
|
||||
newt: None,
|
||||
cache: &mut Hamt::<Noun>::new(),
|
||||
scry_stack: D(0),
|
||||
};
|
||||
let sam = T(context.stack, &[D(0), sam, D(0)]);
|
||||
let jet_res = jet(&mut context, sam);
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::interpreter::Context;
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::Result;
|
||||
use crate::noun::Noun;
|
||||
use crate::noun::{Noun, T};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
@ -14,12 +14,17 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
// = [[subject formula] scry_namespace]
|
||||
let v_subject = slot(arg, 4)?;
|
||||
let v_formula = slot(arg, 5)?;
|
||||
let _scry = slot(arg, 3)?;
|
||||
util::mink(context, v_subject, v_formula)
|
||||
let scry_handler = slot(arg, 3)?;
|
||||
let new_scry_stack = T(context.stack, &[scry_handler, context.scry_stack]);
|
||||
context.scry_stack = new_scry_stack;
|
||||
|
||||
let res = util::mink(context, v_subject, v_formula);
|
||||
context.scry_stack = context.scry_stack.as_cell()?.tail();
|
||||
res
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::interpreter::{interpret, Context, NockErr, Tone};
|
||||
use crate::interpreter::{interpret, Context, Tone};
|
||||
use crate::jets;
|
||||
use crate::jets::form::util::scow;
|
||||
use crate::jets::util::rip;
|
||||
@ -38,10 +43,8 @@ pub mod util {
|
||||
Ok(res) => Ok(T(context.stack, &[D(0), res])),
|
||||
Err(err) => match err {
|
||||
Tone::Blocked(block) => Ok(T(context.stack, &[D(1), block])),
|
||||
Tone::Error(err, trace) => match err {
|
||||
NockErr::Deterministic => Ok(T(context.stack, &[D(2), trace])),
|
||||
NockErr::NonDeterministic => Err(JetErr::NonDeterministic),
|
||||
},
|
||||
Tone::Deterministic(trace) => Ok(T(context.stack, &[D(2), trace])),
|
||||
Tone::NonDeterministic(_) => Err(JetErr::NonDeterministic),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use ares::hamt::Hamt;
|
||||
use ares::interpreter::{interpret, Context};
|
||||
use ares::mem::NockStack;
|
||||
use ares::noun::{IndirectAtom, Noun};
|
||||
use ares::noun::{IndirectAtom, Noun, D};
|
||||
use ares::serf::serf;
|
||||
use ares::serialization::{cue, jam};
|
||||
use memmap::Mmap;
|
||||
@ -66,6 +66,7 @@ fn main() -> io::Result<()> {
|
||||
stack: &mut stack,
|
||||
newt: None,
|
||||
cache: &mut Hamt::<Noun>::new(),
|
||||
scry_stack: D(0),
|
||||
};
|
||||
let result =
|
||||
interpret(&mut context, input_cell.head(), input_cell.tail()).expect("nock failed");
|
||||
|
@ -84,6 +84,7 @@ impl Context {
|
||||
stack: &mut self.stack,
|
||||
newt: Some(&mut self.newt),
|
||||
cache: &mut self.cache,
|
||||
scry_stack: D(0),
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,8 +271,10 @@ fn goof(context: &mut Context, trace: Noun) -> Noun {
|
||||
fn soft(context: &mut Context, ovo: Noun) -> Result<Noun, Noun> {
|
||||
match slam(context, POKE_AXIS, ovo) {
|
||||
Ok(res) => Ok(res),
|
||||
Err(Tone::Error(_, trace)) => Err(goof(context, trace)),
|
||||
Err(Tone::Blocked(_)) => panic!("soft: blocked err handling unimplemented"),
|
||||
Err(tone) => match tone {
|
||||
Tone::Deterministic(trace) | Tone::NonDeterministic(trace) => Err(goof(context, trace)),
|
||||
Tone::Blocked(_) => panic!("serf: soft: .^ invalid outside of virtual Nock"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,13 +289,15 @@ fn play_life(context: &mut Context, eve: Noun) {
|
||||
context.event_update(eved, arvo);
|
||||
context.play_done();
|
||||
}
|
||||
Err(Tone::Error(_, trace)) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
Err(Tone::Blocked(_)) => {
|
||||
panic!("play: blocked err handling unimplemented")
|
||||
}
|
||||
Err(tone) => match tone {
|
||||
Tone::Deterministic(trace) | Tone::NonDeterministic(trace) => {
|
||||
let goof = goof(context, trace);
|
||||
context.play_bail(goof);
|
||||
}
|
||||
Tone::Blocked(_) => {
|
||||
panic!("serf: soft: .^ invalid outside of virtual Nock")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user