mirror of
https://github.com/urbit/ares.git
synced 2024-12-24 13:55:23 +03:00
Merge branch 'status' into msl/parse-jets
This commit is contained in:
commit
b7cb624b85
@ -254,20 +254,36 @@ enum NockWork {
|
||||
Work12(Nock12),
|
||||
}
|
||||
|
||||
pub struct ContextSnapshot {
|
||||
cold: Cold,
|
||||
warm: Warm,
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
pub stack: NockStack,
|
||||
// For printing slogs; if None, print to stdout; Option slated to be removed
|
||||
pub newt: Newt,
|
||||
pub cold: Cold,
|
||||
pub warm: Warm,
|
||||
pub hot: Hot,
|
||||
// XX: persistent memo cache
|
||||
// Per-event cache; option to share cache with virtualized events
|
||||
pub cache: Hamt<Noun>,
|
||||
pub scry_stack: Noun,
|
||||
pub trace_info: Option<TraceInfo>,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn save(&self) -> ContextSnapshot {
|
||||
ContextSnapshot {
|
||||
cold: self.cold,
|
||||
warm: self.warm,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restore(&mut self, saved: &ContextSnapshot) {
|
||||
self.cold = saved.cold;
|
||||
self.warm = saved.warm;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Error {
|
||||
ScryBlocked(Noun), // path
|
||||
@ -301,6 +317,7 @@ fn debug_assertions(stack: &mut NockStack, noun: Noun) {
|
||||
pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Result {
|
||||
let terminator = Arc::clone(&TERMINATOR);
|
||||
let orig_subject = subject; // for debugging
|
||||
let snapshot = context.save();
|
||||
let virtual_frame: *const u64 = context.stack.get_frame_pointer();
|
||||
let mut res: Noun = D(0);
|
||||
|
||||
@ -858,7 +875,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res
|
||||
|
||||
match nock {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => Err(exit(context, virtual_frame, err)),
|
||||
Err(err) => Err(exit(context, &snapshot, virtual_frame, err)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1075,10 +1092,16 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> result::Res
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exit(context: &mut Context, virtual_frame: *const u64, error: Error) -> Error {
|
||||
fn exit(
|
||||
context: &mut Context,
|
||||
snapshot: &ContextSnapshot,
|
||||
virtual_frame: *const u64,
|
||||
error: Error,
|
||||
) -> Error {
|
||||
unsafe {
|
||||
let stack = &mut context.stack;
|
||||
context.restore(snapshot);
|
||||
|
||||
let stack = &mut context.stack;
|
||||
let mut preserve = match error {
|
||||
Error::ScryBlocked(path) => path,
|
||||
Error::Deterministic(t) | Error::NonDeterministic(t) | Error::ScryCrashed(t) => {
|
||||
@ -1088,10 +1111,9 @@ fn exit(context: &mut Context, virtual_frame: *const u64, error: Error) -> Error
|
||||
}
|
||||
};
|
||||
|
||||
while (stack).get_frame_pointer() != virtual_frame {
|
||||
(stack).preserve(&mut preserve);
|
||||
// (stack).preserve(&mut context.cold);
|
||||
(stack).frame_pop();
|
||||
while stack.get_frame_pointer() != virtual_frame {
|
||||
stack.preserve(&mut preserve);
|
||||
stack.frame_pop();
|
||||
}
|
||||
|
||||
match error {
|
||||
|
@ -20,7 +20,7 @@ use crate::jets::bits::*;
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::form::*;
|
||||
use crate::jets::hash::*;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::hot::{Hot, URBIT_HOT_STATE};
|
||||
use crate::jets::list::*;
|
||||
use crate::jets::lock::aes::*;
|
||||
use crate::jets::lock::ed::*;
|
||||
@ -301,7 +301,7 @@ pub mod util {
|
||||
let newt = Newt::new_mock();
|
||||
let cold = Cold::new(&mut stack);
|
||||
let warm = Warm::new();
|
||||
let hot = Hot::init(&mut stack);
|
||||
let hot = Hot::init(&mut stack, URBIT_HOT_STATE);
|
||||
let cache = Hamt::<Noun>::new();
|
||||
|
||||
Context {
|
||||
|
@ -267,6 +267,7 @@ impl Iterator for NounList {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cold(*mut ColdMem);
|
||||
|
||||
struct ColdMem {
|
||||
|
@ -4,8 +4,9 @@ use ares_macros::tas;
|
||||
use either::Either::{self, Left, Right};
|
||||
use std::ptr::null_mut;
|
||||
|
||||
// const A_50: Either<u64, (u64, u64)> = Right((b"a", 50));
|
||||
const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
|
||||
/** Root for Hoon %k.139
|
||||
*/
|
||||
pub const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
|
||||
|
||||
// // This is the const state all in one spot as literals
|
||||
// #[allow(clippy::complexity)]
|
||||
@ -57,8 +58,14 @@ const K_139: Either<&[u8], (u64, u64)> = Right((tas!(b"k"), 139));
|
||||
// (&[A_50, Left(b"mink")], 1, jet_mink),
|
||||
// ];
|
||||
|
||||
/**
|
||||
* (path, axis in battery, jet function pointer)
|
||||
* see the [Jet] typedef in ares::jets for the proper prototype
|
||||
*/
|
||||
pub type HotEntry = (&'static [Either<&'static [u8], (u64, u64)>], u64, Jet);
|
||||
|
||||
#[allow(clippy::complexity)]
|
||||
const TRUE_HOT_STATE: &[(&[Either<&[u8], (u64, u64)>], u64, Jet)] = &[
|
||||
pub const URBIT_HOT_STATE: &[HotEntry] = &[
|
||||
(&[K_139, Left(b"one"), Left(b"add")], 1, jet_add),
|
||||
(&[K_139, Left(b"one"), Left(b"dec")], 1, jet_dec),
|
||||
(&[K_139, Left(b"one"), Left(b"div")], 1, jet_div),
|
||||
@ -759,10 +766,10 @@ const TRUE_HOT_STATE: &[(&[Either<&[u8], (u64, u64)>], u64, Jet)] = &[
|
||||
pub struct Hot(*mut HotMem);
|
||||
|
||||
impl Hot {
|
||||
pub fn init(stack: &mut NockStack) -> Self {
|
||||
pub fn init(stack: &mut NockStack, constant_hot_state: &[HotEntry]) -> Self {
|
||||
unsafe {
|
||||
let mut next = Hot(null_mut());
|
||||
for (htap, axe, jet) in TRUE_HOT_STATE {
|
||||
for (htap, axe, jet) in constant_hot_state {
|
||||
let mut a_path = D(0);
|
||||
for i in *htap {
|
||||
match i {
|
||||
|
@ -1,33 +1,12 @@
|
||||
/** Virtualization jets
|
||||
*/
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::interpreter::Context;
|
||||
use crate::jets::util::slot;
|
||||
use crate::jets::{JetErr, Result};
|
||||
use crate::noun::{Cell, Noun, D, NO, T, YES};
|
||||
use crate::noun::{Noun, D, NO, T};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
// Deterministic scry crashes should have the following behaviour:
|
||||
//
|
||||
// root <-- bail, %crud
|
||||
// mink <-- return Deterministic
|
||||
// scry <-- return ScryCrashed
|
||||
//
|
||||
// root <-- bail, %crud
|
||||
// mink <-- return Deterministic
|
||||
// mink <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
//
|
||||
// root
|
||||
// mink <-- return Tone
|
||||
// mink <-- return Deterministic
|
||||
// mink <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry
|
||||
//
|
||||
pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
// mink sample = [nock scry_namespace]
|
||||
@ -36,45 +15,8 @@ pub fn jet_mink(context: &mut Context, subject: Noun) -> Result {
|
||||
let v_formula = slot(arg, 5)?;
|
||||
let scry_handler = slot(arg, 3)?;
|
||||
|
||||
let old_cache = context.cache;
|
||||
let old_scry_stack = context.scry_stack;
|
||||
|
||||
context.cache = Hamt::<Noun>::new();
|
||||
context.scry_stack = T(&mut context.stack, &[scry_handler, old_scry_stack]);
|
||||
|
||||
match util::mink(context, v_subject, v_formula) {
|
||||
Ok(noun) => {
|
||||
context.cache = old_cache;
|
||||
context.scry_stack = old_scry_stack;
|
||||
Ok(noun)
|
||||
}
|
||||
Err(error) => match error {
|
||||
Error::NonDeterministic(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryCrashed(trace) => {
|
||||
// When we enter a +mink call, we record the state of the scry handler stack at the
|
||||
// time (i.e. the Noun representing (list scry)). Each scry will pop the head off of
|
||||
// this scry handler stack and calls interpret(), using the rest of the scry handler
|
||||
// stack in the event that it scries again recursively. When a scry succeeds, it
|
||||
// replaces the scry handler that it used by pushing it back onto the top of the
|
||||
// scry handler stack. However, it never does so when it fails. Therefore, we can
|
||||
// tell which particular virtualization instance failed by comparing the scry
|
||||
// handler stack at the time of failure (i.e. the scry handler stack in the context
|
||||
// after a failed scry) with the scry handler stack at the time of the virtualization
|
||||
// call. Thus, whenever a virtualized interpret() call fails with a
|
||||
// Error::ScryCrashed, jet_mink() compares the two scry handler stack Nouns> If they
|
||||
// are identical, jet_mink() bails with Error::Deterministic. Otherwise, it forwards
|
||||
// the Error::ScryCrashed to the senior virtualization call.
|
||||
if unsafe { context.scry_stack.raw_equals(old_scry_stack) } {
|
||||
Err(JetErr::Fail(Error::Deterministic(trace)))
|
||||
} else {
|
||||
Err(JetErr::Fail(error))
|
||||
}
|
||||
}
|
||||
Error::Deterministic(_) | Error::ScryBlocked(_) => {
|
||||
panic!("scry: mink: unhandled errors in helper")
|
||||
}
|
||||
},
|
||||
}
|
||||
// Implicit error conversion
|
||||
Ok(util::mink(context, v_subject, v_formula, scry_handler)?)
|
||||
}
|
||||
|
||||
pub fn jet_mole(context: &mut Context, subject: Noun) -> Result {
|
||||
@ -90,18 +32,15 @@ pub fn jet_mure(context: &mut Context, subject: Noun) -> Result {
|
||||
let fol = util::slam_gate_fol(&mut context.stack);
|
||||
let scry = util::pass_thru_scry(&mut context.stack);
|
||||
|
||||
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
|
||||
match interpret(context, tap, fol) {
|
||||
Ok(res) => {
|
||||
context.scry_stack = context.scry_stack.as_cell()?.tail();
|
||||
Ok(T(&mut context.stack, &[D(0), res]))
|
||||
match util::mink(context, tap, fol, scry) {
|
||||
Ok(tone) => {
|
||||
if unsafe { tone.as_cell()?.head().raw_equals(D(0)) } {
|
||||
Ok(tone)
|
||||
} else {
|
||||
Ok(D(0))
|
||||
}
|
||||
}
|
||||
Err(error) => match error {
|
||||
// Since we are using the pass-through scry handler, we know for a fact that a scry
|
||||
// crash must have come from a senior virtualization context.
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
|
||||
Error::Deterministic(_) | Error::ScryBlocked(_) => Ok(D(0)),
|
||||
},
|
||||
Err(err) => Err(JetErr::Fail(err)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,37 +49,32 @@ pub fn jet_mute(context: &mut Context, subject: Noun) -> Result {
|
||||
let fol = util::slam_gate_fol(&mut context.stack);
|
||||
let scry = util::pass_thru_scry(&mut context.stack);
|
||||
|
||||
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
|
||||
match interpret(context, tap, fol) {
|
||||
Ok(res) => {
|
||||
context.scry_stack = context.scry_stack.as_cell()?.tail();
|
||||
Ok(T(&mut context.stack, &[YES, res]))
|
||||
let tone = util::mink(context, tap, fol, scry);
|
||||
|
||||
match util::mook(context, tone?.as_cell()?, false) {
|
||||
Ok(toon) => {
|
||||
match toon.head() {
|
||||
x if unsafe { x.raw_equals(D(0)) } => Ok(toon.as_noun()),
|
||||
x if unsafe { x.raw_equals(D(1)) } => {
|
||||
// XX: Need to check that result is actually of type path
|
||||
// return [[%leaf "mute.hunk"] ~] if not
|
||||
let bon = util::smyt(&mut context.stack, toon.tail())?;
|
||||
Ok(T(&mut context.stack, &[NO, bon, D(0)]))
|
||||
}
|
||||
x if unsafe { x.raw_equals(D(2)) } => Ok(T(&mut context.stack, &[NO, toon.tail()])),
|
||||
_ => panic!("serf: mook: invalid toon"),
|
||||
}
|
||||
}
|
||||
Err(error) => match error {
|
||||
// Since we are using the pass-through scry handler, we know for a fact that a scry
|
||||
// crash must have come from a senior virtualization context.
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(JetErr::Fail(error)),
|
||||
Error::ScryBlocked(path) => {
|
||||
// XX: Need to check that result is actually of type path
|
||||
// return [[%leaf "mute.hunk"] ~] if not
|
||||
let bon = util::smyt(&mut context.stack, path)?;
|
||||
Ok(T(&mut context.stack, &[NO, bon, D(0)]))
|
||||
}
|
||||
Error::Deterministic(trace) => {
|
||||
let ton = Cell::new(&mut context.stack, D(2), trace);
|
||||
let tun = util::mook(context, ton, false)?;
|
||||
Ok(T(&mut context.stack, &[NO, tun.tail()]))
|
||||
}
|
||||
},
|
||||
Err(err) => Err(JetErr::Fail(err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
use crate::hamt::Hamt;
|
||||
use crate::interpreter::{interpret, Context, Error};
|
||||
use crate::jets;
|
||||
use crate::jets::bits::util::rip;
|
||||
use crate::jets::form::util::scow;
|
||||
use crate::jets::JetErr;
|
||||
use crate::mem::NockStack;
|
||||
use crate::noun::{tape, Cell, Noun, D, T};
|
||||
use ares_macros::tas;
|
||||
@ -157,7 +91,7 @@ pub mod util {
|
||||
|
||||
/// The classic "pass-through" scry handler.
|
||||
pub fn pass_thru_scry(stack: &mut NockStack) -> Noun {
|
||||
// > .* 0 != => ~ |=(a=^ ``.*(a [%12 [%0 2] %0 3]))
|
||||
// .* 0 != => ~ |=(a=^ ``.*(a [%12 [%0 2] %0 3]))
|
||||
// [[[1 0] [1 0] 2 [0 6] 1 12 [0 2] 0 3] [0 0] 0]
|
||||
let sig = T(stack, &[D(1), D(0)]);
|
||||
let sam = T(stack, &[D(0), D(6)]);
|
||||
@ -176,13 +110,94 @@ pub mod util {
|
||||
T(stack, &[dos, gat])
|
||||
}
|
||||
|
||||
pub fn mink(context: &mut Context, subject: Noun, formula: Noun) -> Result<Noun, Error> {
|
||||
/// The "always-fail" scry
|
||||
pub fn null_scry(stack: &mut NockStack) -> Noun {
|
||||
// .* 0 != => ~ |=(^ ~)
|
||||
// [[1 0] [0 0] 0]
|
||||
let sig = T(stack, &[D(1), D(0)]);
|
||||
let zap = T(stack, &[D(0), D(0)]);
|
||||
|
||||
T(stack, &[sig, zap, D(0)])
|
||||
}
|
||||
|
||||
// Deterministic scry crashes should have the following behaviour:
|
||||
//
|
||||
// root <-- bail, %crud
|
||||
// mink <-- return Deterministic
|
||||
// scry <-- return ScryCrashed
|
||||
//
|
||||
// root <-- bail, %crud
|
||||
// mink <-- return Deterministic
|
||||
// mink <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
//
|
||||
// root
|
||||
// mink <-- return Tone
|
||||
// mink <-- return Deterministic
|
||||
// mink <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry <-- return ScryCrashed
|
||||
// scry
|
||||
//
|
||||
pub fn mink(
|
||||
context: &mut Context,
|
||||
subject: Noun,
|
||||
formula: Noun,
|
||||
scry: Noun,
|
||||
) -> Result<Noun, Error> {
|
||||
let cache_snapshot = context.cache;
|
||||
let scry_snapshot = context.scry_stack;
|
||||
|
||||
context.cache = Hamt::<Noun>::new();
|
||||
context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]);
|
||||
|
||||
match interpret(context, subject, formula) {
|
||||
Ok(res) => Ok(T(&mut context.stack, &[D(0), res])),
|
||||
Ok(res) => {
|
||||
context.cache = cache_snapshot;
|
||||
context.scry_stack = scry_snapshot;
|
||||
Ok(T(&mut context.stack, &[D(0), res]))
|
||||
}
|
||||
Err(err) => match err {
|
||||
Error::ScryBlocked(path) => Ok(T(&mut context.stack, &[D(1), path])),
|
||||
Error::Deterministic(trace) => Ok(T(&mut context.stack, &[D(2), trace])),
|
||||
Error::NonDeterministic(_) | Error::ScryCrashed(_) => Err(err),
|
||||
Error::ScryBlocked(path) => {
|
||||
context.cache = cache_snapshot;
|
||||
context.scry_stack = scry_snapshot;
|
||||
Ok(T(&mut context.stack, &[D(1), path]))
|
||||
}
|
||||
Error::Deterministic(trace) => {
|
||||
context.cache = cache_snapshot;
|
||||
context.scry_stack = scry_snapshot;
|
||||
Ok(T(&mut context.stack, &[D(2), trace]))
|
||||
}
|
||||
Error::ScryCrashed(trace) => {
|
||||
context.cache = cache_snapshot;
|
||||
// When we enter a +mink call, we record the state of the scry handler stack at the
|
||||
// time (i.e. the Noun representing (list scry)). Each scry will pop the head off of
|
||||
// this scry handler stack and calls interpret(), using the rest of the scry handler
|
||||
// stack in the event that it scries again recursively. When a scry succeeds, it
|
||||
// replaces the scry handler that it used by pushing it back onto the top of the
|
||||
// scry handler stack. However, it never does so when it fails. Therefore, we can
|
||||
// tell which particular virtualization instance failed by comparing the scry
|
||||
// handler stack at the time of failure (i.e. the scry handler stack in the context
|
||||
// after a failed scry) with the scry handler stack at the time of the virtualization
|
||||
// call. Thus, whenever a virtualized interpret() call fails with a
|
||||
// Error::ScryCrashed, jet_mink() compares the two scry handler stack Nouns> If they
|
||||
// are identical, jet_mink() bails with Error::Deterministic. Otherwise, it forwards
|
||||
// the Error::ScryCrashed to the senior virtualization call.
|
||||
if unsafe { context.scry_stack.raw_equals(scry_snapshot) } {
|
||||
Err(Error::Deterministic(trace))
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
Error::NonDeterministic(_) => {
|
||||
// We choose to restore the cache and scry stack even on NonDeterministic errors
|
||||
// to keep the logic all in one place (as opposed to having the serf reset them
|
||||
// manually ONLY for NonDeterministic errors).
|
||||
context.cache = cache_snapshot;
|
||||
context.scry_stack = scry_snapshot;
|
||||
Err(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -190,14 +205,14 @@ pub mod util {
|
||||
/** Consume $tone, produce $toon
|
||||
*/
|
||||
// XX: should write a jet_mook wrapper for this function
|
||||
pub fn mook(context: &mut Context, tone: Cell, flop: bool) -> result::Result<Cell, JetErr> {
|
||||
pub fn mook(context: &mut Context, tone: Cell, flop: bool) -> result::Result<Cell, Error> {
|
||||
let tag = tone.head().as_direct()?;
|
||||
let original_list = tone.tail();
|
||||
|
||||
if (tag.data() != 2) | unsafe { original_list.raw_equals(D(0)) } {
|
||||
return Ok(tone);
|
||||
} else if original_list.atom().is_some() {
|
||||
return Err(JetErr::Fail(Error::Deterministic(D(0))));
|
||||
return Err(Error::Deterministic(D(0)));
|
||||
}
|
||||
|
||||
// XX: trim traces longer than 1024 frames
|
||||
@ -235,17 +250,17 @@ pub mod util {
|
||||
}
|
||||
Right(_cell) => {
|
||||
// 'tank: {
|
||||
// if let Ok(tone) = mink(context, dat, cell.head()) {
|
||||
// if let Some(cell) = tone.cell() {
|
||||
// if cell.head().raw_equals(D(0)) {
|
||||
// // XX: need to check that this is
|
||||
// // actually a path;
|
||||
// // return leaf+"mook.mean" if not
|
||||
// break 'tank cell.tail();
|
||||
// let scry = null_scry(context);
|
||||
// if let Ok(tone) = mink(context, dat, cell.head(), scry) {
|
||||
// if let Some(cell) = tone.cell() {
|
||||
// if cell.head().raw_equals(D(0)) {
|
||||
// // XX: need to check that this is
|
||||
// // actually a path;
|
||||
// // return leaf+"mook.mean" if not
|
||||
// break 'tank cell.tail();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
{
|
||||
let stack = &mut context.stack;
|
||||
let tape = tape(stack, "####");
|
||||
|
@ -7,6 +7,7 @@ use crate::noun::{Noun, Slots};
|
||||
use std::ptr::{copy_nonoverlapping, null_mut};
|
||||
|
||||
/// key = formula
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Warm(Hamt<WarmEntry>);
|
||||
|
||||
impl Preserve for Warm {
|
||||
|
@ -1,22 +1,7 @@
|
||||
use ares::hamt::Hamt;
|
||||
use ares::interpreter::{interpret, Context};
|
||||
use ares::jets::cold::Cold;
|
||||
use ares::jets::hot::Hot;
|
||||
use ares::jets::warm::Warm;
|
||||
use ares::mem::NockStack;
|
||||
use ares::newt::Newt;
|
||||
use ares::noun::{IndirectAtom, Noun, D};
|
||||
use ares::jets::hot::URBIT_HOT_STATE;
|
||||
use ares::serf::serf;
|
||||
use ares::serialization::{cue, jam};
|
||||
use memmap::Mmap;
|
||||
use memmap::MmapMut;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
use std::ptr::write_bytes;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
// debug
|
||||
@ -47,61 +32,8 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
|
||||
if filename == "serf" {
|
||||
return serf();
|
||||
return serf(URBIT_HOT_STATE);
|
||||
}
|
||||
|
||||
let output_filename = format!("{}.out", filename);
|
||||
let f = File::open(filename)?;
|
||||
let in_len = f.metadata()?.len();
|
||||
let mut stack = NockStack::new(8 << 10 << 10, 0);
|
||||
let jammed_input = unsafe {
|
||||
let in_map = Mmap::map(&f)?;
|
||||
let word_len = (in_len + 7) >> 3;
|
||||
let (mut atom, dest) = IndirectAtom::new_raw_mut(&mut stack, word_len as usize);
|
||||
write_bytes(dest.add(word_len as usize - 1), 0, 1);
|
||||
copy_nonoverlapping(in_map.as_ptr(), dest as *mut u8, in_len as usize);
|
||||
mem::drop(in_map);
|
||||
atom.normalize_as_atom()
|
||||
};
|
||||
let input = cue(&mut stack, jammed_input);
|
||||
let input_cell = input
|
||||
.as_cell()
|
||||
.expect("Input must be jam of subject/formula pair");
|
||||
let newt = Newt::new_mock();
|
||||
let cache = Hamt::<Noun>::new();
|
||||
let cold = Cold::new(&mut stack);
|
||||
let warm = Warm::new();
|
||||
let hot = Hot::init(&mut stack);
|
||||
let mut context = Context {
|
||||
stack,
|
||||
newt,
|
||||
cache,
|
||||
cold,
|
||||
warm,
|
||||
hot,
|
||||
scry_stack: D(0),
|
||||
trace_info: None,
|
||||
};
|
||||
let result =
|
||||
interpret(&mut context, input_cell.head(), input_cell.tail()).expect("nock failed");
|
||||
if let Ok(atom) = result.as_atom() {
|
||||
println!("Result: {}", atom);
|
||||
}
|
||||
let jammed_result = jam(&mut context.stack, result);
|
||||
let f_out = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(output_filename)?;
|
||||
f_out.set_len((jammed_result.size() << 3) as u64)?;
|
||||
unsafe {
|
||||
let mut out_map = MmapMut::map_mut(&f_out)?;
|
||||
copy_nonoverlapping(
|
||||
jammed_result.data_pointer() as *mut u8,
|
||||
out_map.as_mut_ptr(),
|
||||
jammed_result.size() << 3,
|
||||
);
|
||||
out_map.flush()?;
|
||||
};
|
||||
Ok(())
|
||||
panic!("Ares can only run as a serf!");
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use crate::hamt::Hamt;
|
||||
use crate::interpreter;
|
||||
use crate::interpreter::{inc, interpret, Error};
|
||||
use crate::jets::cold::Cold;
|
||||
use crate::jets::hot::Hot;
|
||||
use crate::jets::hot::{Hot, HotEntry};
|
||||
use crate::jets::list::util::{lent, zing};
|
||||
use crate::jets::nock::util::mook;
|
||||
use crate::jets::warm::Warm;
|
||||
@ -38,28 +38,29 @@ struct Context {
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn new(snap_path: &PathBuf, trace_info: Option<TraceInfo>) -> Self {
|
||||
pub fn new(
|
||||
snap_path: &PathBuf,
|
||||
trace_info: Option<TraceInfo>,
|
||||
constant_hot_state: &[HotEntry],
|
||||
) -> Self {
|
||||
// TODO: switch to Pma when ready
|
||||
// let snap = &mut snapshot::pma::Pma::new(snap_path);
|
||||
let mut snapshot = DoubleJam::new(snap_path);
|
||||
let mut stack = NockStack::new(1024 << 10 << 10, 0);
|
||||
let newt = Newt::new();
|
||||
let cache = Hamt::<Noun>::new();
|
||||
let mut stack = NockStack::new(512 << 10 << 10, 0);
|
||||
|
||||
let cold = Cold::new(&mut stack);
|
||||
let warm = Warm::new();
|
||||
let hot = Hot::init(&mut stack);
|
||||
let hot = Hot::init(&mut stack, constant_hot_state);
|
||||
|
||||
let (epoch, event_num, arvo) = snapshot.load(&mut stack).unwrap_or((0, 0, D(0)));
|
||||
let mug = mug_u32(&mut stack, arvo);
|
||||
|
||||
let nock_context = interpreter::Context {
|
||||
stack,
|
||||
newt,
|
||||
newt: Newt::new(),
|
||||
cold,
|
||||
warm,
|
||||
warm: Warm::new(),
|
||||
hot,
|
||||
cache,
|
||||
cache: Hamt::<Noun>::new(),
|
||||
scry_stack: D(0),
|
||||
trace_info,
|
||||
};
|
||||
@ -179,7 +180,7 @@ lazy_static! {
|
||||
* This is suitable for talking to the king process. To test, change the arg_c[0] line in
|
||||
* u3_lord_init in vere to point at this binary and start vere like normal.
|
||||
*/
|
||||
pub fn serf() -> io::Result<()> {
|
||||
pub fn serf(constant_hot_state: &[HotEntry]) -> io::Result<()> {
|
||||
// Register SIGINT signal hook to set flag first time, shutdown second time
|
||||
signal_hook::flag::register_conditional_shutdown(SIGINT, 1, Arc::clone(&TERMINATOR))?;
|
||||
signal_hook::flag::register(SIGINT, Arc::clone(&TERMINATOR))?;
|
||||
@ -215,7 +216,7 @@ pub fn serf() -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut context = Context::new(&snap_path, trace_info);
|
||||
let mut context = Context::new(&snap_path, trace_info, constant_hot_state);
|
||||
context.ripe();
|
||||
|
||||
// Can't use for loop because it borrows newt
|
||||
@ -450,6 +451,7 @@ fn work_swap(context: &mut Context, job: Noun, goof: Noun) {
|
||||
clear_interrupt();
|
||||
|
||||
let stack = &mut context.nock_context.stack;
|
||||
context.nock_context.cache = Hamt::<Noun>::new();
|
||||
// crud ovo = [+(now) [%$ %arvo ~] [%crud goof ovo]]
|
||||
let job_cell = job.as_cell().expect("serf: work: job not a cell");
|
||||
let job_now = job_cell.head().as_atom().expect("serf: work: now not atom");
|
||||
|
@ -29,7 +29,6 @@
|
||||
"rustfmt"
|
||||
"rust-src"
|
||||
])
|
||||
pkgs.autoconf-archive
|
||||
pkgs.cargo-watch
|
||||
pkgs.iconv
|
||||
pkgs.llvmPackages.clang
|
||||
|
@ -1,5 +1,5 @@
|
||||
{ stdenv, fetchFromGitHub, autoreconfHook, pkg-config, openssl, cryptopp, secp256k1, libaes_siv }:
|
||||
let rev = "375fa7e6a730d8aa517ca981b2b7b505bf4e1103";
|
||||
{ stdenv, fetchFromGitHub, autoreconfHook, autoconf-archive, pkg-config, openssl, cryptopp, secp256k1, libaes_siv }:
|
||||
let rev = "43479c3262a11e20da5f6218f3b0b3d63931ceea";
|
||||
in stdenv.mkDerivation {
|
||||
pname = "urcrypt";
|
||||
version = "git-${rev}";
|
||||
@ -7,14 +7,14 @@ in stdenv.mkDerivation {
|
||||
inherit rev;
|
||||
owner = "urbit";
|
||||
repo = "urcrypt";
|
||||
hash = "sha256:1c3cqmwr5mys4v9y0834hxqfr6aynm2gav7730bjzfvrdc21ijqa";
|
||||
hash = "sha256-GkhqvhDyhsdzjWpR8uqmhdRdhxdpmLGWXtIUZPAbWZs=";
|
||||
};
|
||||
|
||||
preConfigure = ''
|
||||
./autogen.sh
|
||||
'';
|
||||
# preConfigure = ''
|
||||
# ./autogen.sh
|
||||
# '';
|
||||
|
||||
nativeBuildInputs = [autoreconfHook pkg-config];
|
||||
nativeBuildInputs = [autoreconfHook autoconf-archive pkg-config];
|
||||
|
||||
buildInputs = [openssl cryptopp secp256k1 libaes_siv];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user