mirror of
https://github.com/urbit/ares.git
synced 2024-11-23 17:24:52 +03:00
Merge branch 'status' into msl/urcrypt
This commit is contained in:
commit
8a07ad5665
@ -22,7 +22,7 @@
|
|||||||
:: %mean hint
|
:: %mean hint
|
||||||
~_ [%leaf "I am a %mean hint via ~_ from +wack"]
|
~_ [%leaf "I am a %mean hint via ~_ from +wack"]
|
||||||
:: %hela hint
|
:: %hela hint
|
||||||
:: ~> %hela
|
~> %hela
|
||||||
:: %memo hint
|
:: %memo hint
|
||||||
~+
|
~+
|
||||||
?~ m +(n)
|
?~ m +(n)
|
||||||
@ -34,7 +34,7 @@
|
|||||||
!.
|
!.
|
||||||
|= [m=@ud n=@ud]
|
|= [m=@ud n=@ud]
|
||||||
:: %hela hint
|
:: %hela hint
|
||||||
:: ~> %hela
|
~> %hela
|
||||||
:: %memo hint
|
:: %memo hint
|
||||||
~+
|
~+
|
||||||
?~ m +(n)
|
?~ m +(n)
|
||||||
|
@ -24,6 +24,8 @@ static_assertions = "1.1.0"
|
|||||||
ibig = { path = "../ibig-rs" }
|
ibig = { path = "../ibig-rs" }
|
||||||
assert_no_alloc = "1.1.2"
|
assert_no_alloc = "1.1.2"
|
||||||
urcrypt-sys = "0.1.0"
|
urcrypt-sys = "0.1.0"
|
||||||
|
# use this when debugging requires allocation (e.g. eprintln)
|
||||||
|
# assert_no_alloc = {version="1.1.2", features=["warn_debug"]}
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
autotools = "0.2.6"
|
autotools = "0.2.6"
|
||||||
|
@ -189,6 +189,7 @@ struct Nock11D {
|
|||||||
tag: Atom,
|
tag: Atom,
|
||||||
hint: Noun,
|
hint: Noun,
|
||||||
body: Noun,
|
body: Noun,
|
||||||
|
tail: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -202,6 +203,7 @@ struct Nock11S {
|
|||||||
todo: Todo11S,
|
todo: Todo11S,
|
||||||
tag: Atom,
|
tag: Atom,
|
||||||
body: Noun,
|
body: Noun,
|
||||||
|
tail: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -242,16 +244,17 @@ pub fn interpret(
|
|||||||
formula: Noun,
|
formula: Noun,
|
||||||
) -> Result<Noun, NockErr> {
|
) -> Result<Noun, NockErr> {
|
||||||
let mut res: Noun = D(0);
|
let mut res: Noun = D(0);
|
||||||
let mut trace: Noun;
|
|
||||||
let mut cache = Hamt::<Noun>::new();
|
let mut cache = Hamt::<Noun>::new();
|
||||||
// XX: Should this come after initial frame_push()?
|
|
||||||
let virtual_frame = stack.get_frame_pointer();
|
let virtual_frame = stack.get_frame_pointer();
|
||||||
|
|
||||||
stack.frame_push(0);
|
// Setup stack for Nock computation
|
||||||
unsafe {
|
unsafe {
|
||||||
|
stack.frame_push(1);
|
||||||
|
// Bottom of mean stack
|
||||||
|
*(stack.local_noun_pointer(0)) = D(0);
|
||||||
*stack.push() = NockWork::Done;
|
*stack.push() = NockWork::Done;
|
||||||
};
|
};
|
||||||
push_formula(stack, formula, true)?;
|
|
||||||
// DO NOT REMOVE THIS ASSERTION
|
// DO NOT REMOVE THIS ASSERTION
|
||||||
//
|
//
|
||||||
// If you need to allocate for debugging, wrap the debugging code in
|
// If you need to allocate for debugging, wrap the debugging code in
|
||||||
@ -264,6 +267,8 @@ pub fn interpret(
|
|||||||
//
|
//
|
||||||
// (See https://docs.rs/assert_no_alloc/latest/assert_no_alloc/#advanced-use)
|
// (See https://docs.rs/assert_no_alloc/latest/assert_no_alloc/#advanced-use)
|
||||||
let tone = assert_no_alloc(|| unsafe {
|
let tone = assert_no_alloc(|| unsafe {
|
||||||
|
push_formula(stack, formula, true)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let work: NockWork = *stack.top();
|
let work: NockWork = *stack.top();
|
||||||
match work {
|
match work {
|
||||||
@ -328,7 +333,7 @@ pub fn interpret(
|
|||||||
vale.todo = Todo2::RestoreSubject;
|
vale.todo = Todo2::RestoreSubject;
|
||||||
std::mem::swap(&mut vale.subject, &mut subject);
|
std::mem::swap(&mut vale.subject, &mut subject);
|
||||||
*stack.top() = NockWork::Work2(vale);
|
*stack.top() = NockWork::Work2(vale);
|
||||||
stack.frame_push(0);
|
mean_frame_push(stack, 0);
|
||||||
*stack.push() = NockWork::Ret;
|
*stack.push() = NockWork::Ret;
|
||||||
push_formula(stack, res, true)?;
|
push_formula(stack, res, true)?;
|
||||||
}
|
}
|
||||||
@ -475,7 +480,7 @@ pub fn interpret(
|
|||||||
kale.core = subject;
|
kale.core = subject;
|
||||||
*stack.top() = NockWork::Work9(kale);
|
*stack.top() = NockWork::Work9(kale);
|
||||||
subject = res;
|
subject = res;
|
||||||
stack.frame_push(0);
|
mean_frame_push(stack, 0);
|
||||||
*stack.push() = NockWork::Ret;
|
*stack.push() = NockWork::Ret;
|
||||||
push_formula(stack, formula, true)?;
|
push_formula(stack, formula, true)?;
|
||||||
}
|
}
|
||||||
@ -536,8 +541,12 @@ pub fn interpret(
|
|||||||
stack.pop::<NockWork>();
|
stack.pop::<NockWork>();
|
||||||
} else {
|
} else {
|
||||||
dint.todo = Todo11D::Done;
|
dint.todo = Todo11D::Done;
|
||||||
|
if dint.tail {
|
||||||
|
stack.pop::<NockWork>();
|
||||||
|
} else {
|
||||||
*stack.top() = NockWork::Work11D(dint);
|
*stack.top() = NockWork::Work11D(dint);
|
||||||
push_formula(stack, dint.body, false)?;
|
}
|
||||||
|
push_formula(stack, dint.body, dint.tail)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Todo11D::Done => {
|
Todo11D::Done => {
|
||||||
@ -565,8 +574,12 @@ pub fn interpret(
|
|||||||
stack.pop::<NockWork>();
|
stack.pop::<NockWork>();
|
||||||
} else {
|
} else {
|
||||||
sint.todo = Todo11S::Done;
|
sint.todo = Todo11S::Done;
|
||||||
|
if sint.tail {
|
||||||
|
stack.pop::<NockWork>();
|
||||||
|
} else {
|
||||||
*stack.top() = NockWork::Work11S(sint);
|
*stack.top() = NockWork::Work11S(sint);
|
||||||
push_formula(stack, sint.body, false)?;
|
}
|
||||||
|
push_formula(stack, sint.body, sint.tail)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Todo11S::Done => {
|
Todo11S::Done => {
|
||||||
@ -584,11 +597,7 @@ pub fn interpret(
|
|||||||
|
|
||||||
match tone {
|
match tone {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(_err) => {
|
Err(_err) => Err(exit_early(stack, virtual_frame, &mut cache)),
|
||||||
trace = stack.get_mean_stack();
|
|
||||||
exit_early(stack, virtual_frame, &mut trace, &mut cache);
|
|
||||||
Err(NockErr::Error(trace))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,6 +760,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
|||||||
todo: Todo11S::ComputeResult,
|
todo: Todo11S::ComputeResult,
|
||||||
tag: tag_atom,
|
tag: tag_atom,
|
||||||
body: arg_cell.tail(),
|
body: arg_cell.tail(),
|
||||||
|
tail: tail && is_hint_tail(tag_atom),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Right(hint_cell) => {
|
Right(hint_cell) => {
|
||||||
@ -760,6 +770,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
|||||||
tag: tag_atom,
|
tag: tag_atom,
|
||||||
hint: hint_cell.tail(),
|
hint: hint_cell.tail(),
|
||||||
body: arg_cell.tail(),
|
body: arg_cell.tail(),
|
||||||
|
tail: tail && is_hint_tail(tag_atom),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Hint tag must be an atom
|
// Hint tag must be an atom
|
||||||
@ -791,18 +802,46 @@ fn push_formula(stack: &mut NockStack, formula: Noun, tail: bool) -> Result<(),
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit_early(
|
fn exit_early(stack: &mut NockStack, virtual_frame: *const u64, cache: &mut Hamt<Noun>) -> NockErr {
|
||||||
stack: &mut NockStack,
|
|
||||||
virtual_frame: *const u64,
|
|
||||||
trace: &mut Noun,
|
|
||||||
cache: &mut Hamt<Noun>,
|
|
||||||
) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut trace = *(stack.local_noun_pointer(0));
|
||||||
while stack.get_frame_pointer() != virtual_frame {
|
while stack.get_frame_pointer() != virtual_frame {
|
||||||
stack.preserve(trace);
|
stack.preserve(&mut trace);
|
||||||
stack.preserve(cache);
|
stack.preserve(cache);
|
||||||
stack.frame_pop();
|
stack.frame_pop();
|
||||||
}
|
}
|
||||||
|
NockErr::Error(trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push frame onto NockStack while preserving the mean stack.
|
||||||
|
*/
|
||||||
|
fn mean_frame_push(stack: &mut NockStack, slots: usize) {
|
||||||
|
unsafe {
|
||||||
|
let trace = *(stack.local_noun_pointer(0));
|
||||||
|
stack.frame_push(slots + 1);
|
||||||
|
*(stack.local_noun_pointer(0)) = trace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push onto the mean stack.
|
||||||
|
*/
|
||||||
|
fn mean_push(stack: &mut NockStack, noun: Noun) {
|
||||||
|
unsafe {
|
||||||
|
let cur_trace = *(stack.local_noun_pointer(0));
|
||||||
|
let new_trace = T(stack, &[noun, cur_trace]);
|
||||||
|
*(stack.local_noun_pointer(0)) = new_trace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pop off of the mean stack.
|
||||||
|
*/
|
||||||
|
fn mean_pop(stack: &mut NockStack) {
|
||||||
|
unsafe {
|
||||||
|
*(stack.local_noun_pointer(0)) = (*(stack.local_noun_pointer(0)))
|
||||||
|
.as_cell()
|
||||||
|
.expect("serf: unexpected end of mean stack\r")
|
||||||
|
.tail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -876,6 +915,19 @@ pub fn inc(stack: &mut NockStack, atom: Atom) -> Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_hint_tail(tag: Atom) -> bool {
|
||||||
|
// XX: handle IndirectAtom tags
|
||||||
|
match tag.direct() {
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
|
Some(dtag) => match dtag.data() {
|
||||||
|
tas!(b"fast") => false,
|
||||||
|
tas!(b"memo") => false,
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Match dynamic hints before the hint formula is evaluated */
|
/** Match dynamic hints before the hint formula is evaluated */
|
||||||
fn match_hint_pre_hint(
|
fn match_hint_pre_hint(
|
||||||
stack: &mut NockStack,
|
stack: &mut NockStack,
|
||||||
@ -956,30 +1008,14 @@ fn match_hint_pre_nock(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
||||||
let trace = Cell::new(stack, tag.as_noun(), res?).as_noun();
|
let noun = T(stack, &[tag.as_noun(), res?]);
|
||||||
stack.trace_push(trace);
|
mean_push(stack, noun);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// u3_serf_writ -> u3_serf_work -> _serf_work -> _serf_poke -> u3m_soft -> u3dc -> u3v_do -> u3v_wish -> +wish in Arvo
|
|
||||||
// |
|
|
||||||
// V
|
|
||||||
// mook
|
|
||||||
//
|
|
||||||
// No +wish in toy Arvo; missing +slap and a ton of parsing functions needed by +ream
|
|
||||||
//
|
|
||||||
// u3t_slog = print on thing directly
|
|
||||||
// u3t_slog_trace = print stack trace = - convert tone to toon
|
|
||||||
// - presume toon is [%2 tang]
|
|
||||||
// - print each tank in tang one at at time using u3t_slog
|
|
||||||
// u3t_slog_hela = print entire stack trace = - weld stacks from all roads together
|
|
||||||
// - call u3t_slog_trace on combined stack
|
|
||||||
// u3t_slog_nara = print home road stack trace = call u3t_slog_trace on home road stack
|
|
||||||
//
|
|
||||||
tas!(b"hela") => {
|
tas!(b"hela") => {
|
||||||
// XX: should this be virtualized?
|
// XX: should this be virtualized?
|
||||||
// pretty sure we should be bailing on error
|
// pretty sure we should be bailing on error
|
||||||
// might need to switch return type to Result<Option<Noun>, NockErr>
|
// might need to switch return type to Result<Option<Noun>, NockErr>
|
||||||
let stak = stack.get_mean_stack();
|
let stak = unsafe { *(stack.local_noun_pointer(0)) };
|
||||||
let tone = Cell::new(stack, D(2), stak);
|
let tone = Cell::new(stack, D(2), stak);
|
||||||
|
|
||||||
if let Ok(toon) = mook(stack, newt, tone, true) {
|
if let Ok(toon) = mook(stack, newt, tone, true) {
|
||||||
@ -1034,8 +1070,7 @@ fn match_hint_post_nock(
|
|||||||
*cache = cache.insert(stack, &mut key, res);
|
*cache = cache.insert(stack, &mut key, res);
|
||||||
}
|
}
|
||||||
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
||||||
// In the future, we should only do this if 11 is not in tail position
|
mean_pop(stack);
|
||||||
stack.trace_pop();
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@ use std::ptr::copy_nonoverlapping;
|
|||||||
use std::ptr::write_bytes;
|
use std::ptr::write_bytes;
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
|
// eprintln!("serf: pid {}", std::process::id());
|
||||||
|
// if unsafe { libc::kill(std::process::id() as i32, libc::SIGSTOP) } != 0 {
|
||||||
|
// panic!("Could not stop ourselves.");
|
||||||
|
// };
|
||||||
|
|
||||||
let filename = env::args().nth(1).expect("Must provide input filename");
|
let filename = env::args().nth(1).expect("Must provide input filename");
|
||||||
|
|
||||||
if filename == "see gdb! definition in lib.rs about this" {
|
if filename == "see gdb! definition in lib.rs about this" {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::assert_acyclic;
|
use crate::assert_acyclic;
|
||||||
use crate::noun::{Atom, Cell, CellMemory, DirectAtom, IndirectAtom, Noun, NounAllocator};
|
use crate::noun::{Atom, Cell, CellMemory, IndirectAtom, Noun, NounAllocator};
|
||||||
use crate::snapshot::pma::{pma_in_arena, pma_malloc_w};
|
use crate::snapshot::pma::{pma_in_arena, pma_malloc_w};
|
||||||
use either::Either::{self, Left, Right};
|
use either::Either::{self, Left, Right};
|
||||||
use ibig::Stack;
|
use ibig::Stack;
|
||||||
@ -46,8 +46,6 @@ pub struct NockStack {
|
|||||||
stack_pointer: *mut u64,
|
stack_pointer: *mut u64,
|
||||||
/** Alloc pointer for the current stack frame. */
|
/** Alloc pointer for the current stack frame. */
|
||||||
alloc_pointer: *mut u64,
|
alloc_pointer: *mut u64,
|
||||||
/** Pointer to top of mean stack; mean stack references previous frames */
|
|
||||||
mean_stack: *mut Noun,
|
|
||||||
/** MMap which must be kept alive as long as this NockStack is */
|
/** MMap which must be kept alive as long as this NockStack is */
|
||||||
memory: MmapMut,
|
memory: MmapMut,
|
||||||
/** Whether or not pre_copy() has been called on the current stack frame. */
|
/** Whether or not pre_copy() has been called on the current stack frame. */
|
||||||
@ -68,16 +66,13 @@ impl NockStack {
|
|||||||
let memory = MmapMut::map_anon(size << 3).expect("Mapping memory for nockstack failed");
|
let memory = MmapMut::map_anon(size << 3).expect("Mapping memory for nockstack failed");
|
||||||
let start = memory.as_ptr() as *const u64;
|
let start = memory.as_ptr() as *const u64;
|
||||||
// Here, frame_pointer < alloc_pointer, so the initial frame is West
|
// Here, frame_pointer < alloc_pointer, so the initial frame is West
|
||||||
let frame_pointer = unsafe { start.add(RESERVED + top_slots + 1) } as *mut u64;
|
let frame_pointer = unsafe { start.add(RESERVED + top_slots) } as *mut u64;
|
||||||
let stack_pointer = frame_pointer;
|
let stack_pointer = frame_pointer;
|
||||||
let alloc_pointer = unsafe { start.add(size) } as *mut u64;
|
let alloc_pointer = unsafe { start.add(size) } as *mut u64;
|
||||||
// The extra 1 in frame_pointer is for the base of the mean stack
|
|
||||||
let mean_stack = start as *mut Noun;
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*frame_pointer.sub(1) = ptr::null::<u64>() as u64; // "frame pointer" from "previous" frame
|
*frame_pointer.sub(FRAME + 1) = ptr::null::<u64>() as u64; // "frame pointer" from "previous" frame
|
||||||
*frame_pointer.sub(STACK + 1) = ptr::null::<u64>() as u64; // "stack pointer" from "previous" frame
|
*frame_pointer.sub(STACK + 1) = ptr::null::<u64>() as u64; // "stack pointer" from "previous" frame
|
||||||
*frame_pointer.sub(ALLOC + 1) = start as u64; // "alloc pointer" from "previous" frame
|
*frame_pointer.sub(ALLOC + 1) = ptr::null::<u64>() as u64; // "alloc pointer" from "previous" frame
|
||||||
*mean_stack = DirectAtom::new_unchecked(0).as_noun();
|
|
||||||
};
|
};
|
||||||
NockStack {
|
NockStack {
|
||||||
start,
|
start,
|
||||||
@ -85,7 +80,6 @@ impl NockStack {
|
|||||||
frame_pointer,
|
frame_pointer,
|
||||||
stack_pointer,
|
stack_pointer,
|
||||||
alloc_pointer,
|
alloc_pointer,
|
||||||
mean_stack,
|
|
||||||
memory,
|
memory,
|
||||||
pc: false,
|
pc: false,
|
||||||
}
|
}
|
||||||
@ -96,11 +90,6 @@ impl NockStack {
|
|||||||
self.frame_pointer
|
self.frame_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Current frame pointer of this NockStack */
|
|
||||||
pub fn get_mean_stack(&self) -> Noun {
|
|
||||||
unsafe { *self.mean_stack }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks if the current stack frame has West polarity */
|
/** Checks if the current stack frame has West polarity */
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_west(&self) -> bool {
|
pub fn is_west(&self) -> bool {
|
||||||
@ -677,23 +666,6 @@ impl NockStack {
|
|||||||
unsafe { self.stack_pointer == self.alloc_pointer.add(RESERVED) }
|
unsafe { self.stack_pointer == self.alloc_pointer.add(RESERVED) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Push onto the mean stack (for tracing) */
|
|
||||||
pub fn trace_push(&mut self, mon: Noun) {
|
|
||||||
unsafe {
|
|
||||||
*(self.mean_stack) = Cell::new(self, mon, *self.mean_stack).as_noun();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Pop from the mean stack (for tracing) */
|
|
||||||
pub fn trace_pop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
*(self.mean_stack) = (*self.mean_stack)
|
|
||||||
.as_cell()
|
|
||||||
.expect("mean stack should be non-null when popped")
|
|
||||||
.tail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Noun) -> bool {
|
pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Noun) -> bool {
|
||||||
@ -779,8 +751,8 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Right(x_cell), Right(y_cell)) => {
|
(Right(x_cell), Right(y_cell)) => {
|
||||||
let x_as_ptr = x_cell.to_raw_pointer();
|
let x_as_ptr = x_cell.to_raw_pointer() as *const u64;
|
||||||
let y_as_ptr = y_cell.to_raw_pointer();
|
let y_as_ptr = y_cell.to_raw_pointer() as *const u64;
|
||||||
if x_cell.head().raw_equals(y_cell.head())
|
if x_cell.head().raw_equals(y_cell.head())
|
||||||
&& x_cell.tail().raw_equals(y_cell.tail())
|
&& x_cell.tail().raw_equals(y_cell.tail())
|
||||||
{
|
{
|
||||||
@ -821,61 +793,71 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
|
|||||||
(*a).raw_equals(*b)
|
(*a).raw_equals(*b)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn senior_pointer_first<T>(
|
unsafe fn senior_pointer_first(
|
||||||
stack: &NockStack,
|
stack: &NockStack,
|
||||||
a: *const T,
|
a: *const u64,
|
||||||
b: *const T,
|
b: *const u64,
|
||||||
) -> (*const T, *const T) {
|
) -> (*const u64, *const u64) {
|
||||||
let mut frame_pointer = stack.frame_pointer as *const u64;
|
let mut frame_pointer: *const u64 = stack.frame_pointer;
|
||||||
let mut stack_pointer = stack.stack_pointer as *const u64;
|
let mut stack_pointer: *const u64 = stack.stack_pointer;
|
||||||
let mut alloc_pointer = stack.alloc_pointer as *const u64;
|
let mut alloc_pointer: *const u64 = stack.alloc_pointer;
|
||||||
let prev_stack_pointer = *(stack.prev_stack_pointer_pointer()) as *const u64;
|
let prev_stack_pointer = *(stack.prev_stack_pointer_pointer());
|
||||||
|
|
||||||
let (mut high_pointer, mut low_pointer) = if stack.is_west() {
|
let (mut high_pointer, mut low_pointer): (*const u64, *const u64) = if stack.is_west() {
|
||||||
(
|
(prev_stack_pointer, alloc_pointer)
|
||||||
prev_stack_pointer as *const T,
|
|
||||||
(stack.alloc_pointer as *const T),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
(alloc_pointer, prev_stack_pointer)
|
||||||
stack.alloc_pointer as *const T,
|
|
||||||
prev_stack_pointer as *const T,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
if low_pointer.is_null() || high_pointer.is_null() {
|
||||||
|
// we found the bottom of the stack; check entirety of the stack
|
||||||
|
low_pointer = stack.start;
|
||||||
|
high_pointer = stack.start.add(stack.size);
|
||||||
|
}
|
||||||
|
|
||||||
match (
|
match (
|
||||||
a < high_pointer && a >= low_pointer,
|
a < high_pointer && a >= low_pointer,
|
||||||
b < high_pointer && b >= low_pointer,
|
b < high_pointer && b >= low_pointer,
|
||||||
) {
|
) {
|
||||||
(true, true) => break (a, b), // both pointers are in the same frame, pick arbitrarily
|
(true, true) => {
|
||||||
|
// both pointers are in the same frame, pick arbitrarily (lower in mem)
|
||||||
|
break lower_pointer_first(a, b);
|
||||||
|
}
|
||||||
(true, false) => break (b, a), // a is in the frame, b is not, so b is senior
|
(true, false) => break (b, a), // a is in the frame, b is not, so b is senior
|
||||||
(false, true) => break (a, b), // b is in the frame, a is not, so a is senior
|
(false, true) => break (a, b), // b is in the frame, a is not, so a is senior
|
||||||
(false, false) => {
|
(false, false) => {
|
||||||
// chase up the stack
|
// chase up the stack
|
||||||
#[allow(clippy::comparison_chain)]
|
#[allow(clippy::comparison_chain)]
|
||||||
if frame_pointer.is_null() {
|
|
||||||
// we found the top of the stack
|
|
||||||
break (a, b); // both are in the bottom frame, pick arbitrarily
|
|
||||||
} else {
|
|
||||||
// test to see if the frame under consideration is a west frame
|
// test to see if the frame under consideration is a west frame
|
||||||
if stack_pointer < alloc_pointer {
|
if stack_pointer < alloc_pointer {
|
||||||
stack_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
|
stack_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
|
||||||
alloc_pointer = *(frame_pointer.sub(ALLOC + 1)) as *const u64;
|
alloc_pointer = *(frame_pointer.sub(ALLOC + 1)) as *const u64;
|
||||||
frame_pointer = *(frame_pointer.sub(FRAME + 1)) as *const u64;
|
frame_pointer = *(frame_pointer.sub(FRAME + 1)) as *const u64;
|
||||||
|
|
||||||
|
// both pointers are in the PMA, pick arbitrarily (lower in mem)
|
||||||
|
if frame_pointer.is_null() {
|
||||||
|
break lower_pointer_first(a, b);
|
||||||
|
};
|
||||||
|
|
||||||
// previous allocation pointer
|
// previous allocation pointer
|
||||||
high_pointer = alloc_pointer as *const T;
|
high_pointer = alloc_pointer;
|
||||||
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
|
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
|
||||||
low_pointer = (frame_pointer.add(STACK)) as *const T;
|
low_pointer = *(frame_pointer.add(STACK)) as *const u64;
|
||||||
continue;
|
|
||||||
} else if stack_pointer > alloc_pointer {
|
} else if stack_pointer > alloc_pointer {
|
||||||
stack_pointer = *(frame_pointer.add(STACK)) as *const u64;
|
stack_pointer = *(frame_pointer.add(STACK)) as *const u64;
|
||||||
alloc_pointer = *(frame_pointer.add(ALLOC)) as *const u64;
|
alloc_pointer = *(frame_pointer.add(ALLOC)) as *const u64;
|
||||||
frame_pointer = *(frame_pointer.add(FRAME)) as *const u64;
|
frame_pointer = *(frame_pointer.add(FRAME)) as *const u64;
|
||||||
|
|
||||||
|
// both pointers are in the PMA, pick arbitrarily (lower in mem)
|
||||||
|
if frame_pointer.is_null() {
|
||||||
|
break lower_pointer_first(a, b);
|
||||||
|
};
|
||||||
|
|
||||||
// previous allocation pointer
|
// previous allocation pointer
|
||||||
low_pointer = alloc_pointer as *const T;
|
low_pointer = alloc_pointer;
|
||||||
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
|
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
|
||||||
high_pointer = (frame_pointer.sub(STACK + 1)) as *const T;
|
high_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
|
||||||
} else {
|
} else {
|
||||||
panic!("senior_pointer_first: stack_pointer == alloc_pointer");
|
panic!("senior_pointer_first: stack_pointer == alloc_pointer");
|
||||||
}
|
}
|
||||||
@ -883,6 +865,13 @@ unsafe fn senior_pointer_first<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_pointer_first(a: *const u64, b: *const u64) -> (*const u64, *const u64) {
|
||||||
|
if a < b {
|
||||||
|
(a, b)
|
||||||
|
} else {
|
||||||
|
(b, a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NounAllocator for NockStack {
|
impl NounAllocator for NockStack {
|
||||||
|
@ -194,6 +194,11 @@ impl DirectAtom {
|
|||||||
pub fn as_byteslice_mut(&mut self) -> &mut [u8] {
|
pub fn as_byteslice_mut(&mut self) -> &mut [u8] {
|
||||||
unsafe { from_raw_parts_mut(&mut self.0 as *mut u64 as *mut u8, word_size_of::<Self>()) }
|
unsafe { from_raw_parts_mut(&mut self.0 as *mut u64 as *mut u8, word_size_of::<Self>()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
|
let bytes: &[u8; 8] = unsafe { std::mem::transmute(self.0) };
|
||||||
|
&bytes[..]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DirectAtom {
|
impl fmt::Display for DirectAtom {
|
||||||
@ -239,7 +244,6 @@ pub fn T<A: NounAllocator>(allocator: &mut A, tup: &[Noun]) -> Noun {
|
|||||||
pub fn tape<A: NounAllocator>(allocator: &mut A, text: &str) -> Noun {
|
pub fn tape<A: NounAllocator>(allocator: &mut A, text: &str) -> Noun {
|
||||||
// XX: Needs unit tests
|
// XX: Needs unit tests
|
||||||
let mut res = D(0);
|
let mut res = D(0);
|
||||||
// XX: Switch to using Cell::new_raw_mut
|
|
||||||
for c in text.bytes().rev() {
|
for c in text.bytes().rev() {
|
||||||
res = T(allocator, &[D(c as u64), res])
|
res = T(allocator, &[D(c as u64), res])
|
||||||
}
|
}
|
||||||
@ -605,6 +609,7 @@ impl Slots for Cell {}
|
|||||||
impl private::RawSlots for Cell {
|
impl private::RawSlots for Cell {
|
||||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||||
let mut noun: Noun = self.as_noun();
|
let mut noun: Noun = self.as_noun();
|
||||||
|
// Panic because all of the logic to guard against this is in Noun::RawSlots, Noun::Slots
|
||||||
let mut cursor = axis.last_one().expect("raw_slow somehow by-passed 0 check");
|
let mut cursor = axis.last_one().expect("raw_slow somehow by-passed 0 check");
|
||||||
|
|
||||||
while cursor != 0 {
|
while cursor != 0 {
|
||||||
@ -774,19 +779,11 @@ impl Atom {
|
|||||||
Noun { atom: self }
|
Noun { atom: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn word(self, a: u64) -> u64 {
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
if self.is_direct() {
|
if self.is_direct() {
|
||||||
if a > 0 {
|
unsafe { self.direct.as_bytes() }
|
||||||
0
|
|
||||||
} else {
|
} else {
|
||||||
self.as_direct().unwrap().data()
|
unsafe { self.indirect.as_bytes() }
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (a as usize) > self.size() {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
unsafe { *(self.data_pointer().add(a as usize)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1120,7 +1117,14 @@ impl private::RawSlots for Noun {
|
|||||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||||
match self.as_either_atom_cell() {
|
match self.as_either_atom_cell() {
|
||||||
Right(cell) => cell.raw_slot(axis),
|
Right(cell) => cell.raw_slot(axis),
|
||||||
Left(_atom) => Err(Error::NotCell), // Axis tried to descend through atom
|
Left(_atom) => {
|
||||||
|
if axis.last_one() == Some(0) {
|
||||||
|
Ok(*self)
|
||||||
|
} else {
|
||||||
|
// Axis tried to descend through atom
|
||||||
|
Err(Error::NotCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1160,17 +1164,7 @@ pub trait Slots: private::RawSlots {
|
|||||||
* Retrieve component Noun at axis given as Atom, or fail with descriptive error
|
* Retrieve component Noun at axis given as Atom, or fail with descriptive error
|
||||||
*/
|
*/
|
||||||
fn slot_atom(&self, atom: Atom) -> Result<Noun> {
|
fn slot_atom(&self, atom: Atom) -> Result<Noun> {
|
||||||
atom.as_either().either(
|
self.raw_slot(atom.as_bitslice())
|
||||||
|d| self.slot(d.data()),
|
|
||||||
|i| {
|
|
||||||
if unsafe { i.as_noun().raw_equals(D(0)) } {
|
|
||||||
// 0 is not allowed as an axis
|
|
||||||
Err(Error::NotRepresentable)
|
|
||||||
} else {
|
|
||||||
self.raw_slot(i.as_bitslice())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ impl DoubleJam {
|
|||||||
| ((*in_ptr.add(1) as u32) << 8)
|
| ((*in_ptr.add(1) as u32) << 8)
|
||||||
| ((*in_ptr.add(2) as u32) << 16)
|
| ((*in_ptr.add(2) as u32) << 16)
|
||||||
| ((*in_ptr.add(3) as u32) << 24);
|
| ((*in_ptr.add(3) as u32) << 24);
|
||||||
write_bytes(dest.add(word_len as usize - 1), 0, 8);
|
write_bytes(dest.add(word_len as usize - 1), 0, 1);
|
||||||
copy_nonoverlapping(in_ptr.add(8), dest as *mut u8, in_len as usize);
|
copy_nonoverlapping(in_ptr.add(8), dest as *mut u8, in_len as usize);
|
||||||
mem::drop(in_map);
|
mem::drop(in_map);
|
||||||
state.normalize(); // know it's not direct because first word is event number
|
state.normalize(); // know it's not direct because first word is event number
|
||||||
|
Loading…
Reference in New Issue
Block a user