send messages, motherfucker!
This commit is contained in:
parent
c144702b98
commit
888f5b62da
|
@ -1211,7 +1211,35 @@ fn penwidth {
|
||||||
|
|
||||||
box state = nil
|
box state = nil
|
||||||
|
|
||||||
|
fn self {
|
||||||
|
"Returns the current process's pid, as a keyword."
|
||||||
|
() -> base :process (:self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send {
|
||||||
|
"Sends a message to the specified process."
|
||||||
|
(pid as :keyword, msg) -> base :process (:send, pid, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn! {
|
||||||
|
"Spawns a new process running the function passed in."
|
||||||
|
(f as :fn) -> base :process (:spawn, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn yield! {
|
||||||
|
"Forces a process to yield."
|
||||||
|
() -> base :process (:yield)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msgs () -> base :process (:msgs)
|
||||||
|
|
||||||
#{
|
#{
|
||||||
|
self
|
||||||
|
send
|
||||||
|
msgs
|
||||||
|
spawn!
|
||||||
|
yield!
|
||||||
|
|
||||||
abs
|
abs
|
||||||
abs
|
abs
|
||||||
add
|
add
|
||||||
|
|
12
sandbox.ld
12
sandbox.ld
|
@ -1 +1,11 @@
|
||||||
let true = false
|
let pid = spawn! (fn () -> {
|
||||||
|
print! (self ())
|
||||||
|
print! (msgs ())
|
||||||
|
})
|
||||||
|
|
||||||
|
send (pid, :foo)
|
||||||
|
send (pid, :bar)
|
||||||
|
|
||||||
|
yield! ()
|
||||||
|
|
||||||
|
:done
|
||||||
|
|
|
@ -609,6 +609,7 @@ pub fn make_base() -> Value {
|
||||||
("number", Value::BaseFn(BaseFn::Unary("number", number))),
|
("number", Value::BaseFn(BaseFn::Unary("number", number))),
|
||||||
("pi", Value::Number(std::f64::consts::PI)),
|
("pi", Value::Number(std::f64::consts::PI)),
|
||||||
("print!", Value::BaseFn(BaseFn::Unary("print!", print))),
|
("print!", Value::BaseFn(BaseFn::Unary("print!", print))),
|
||||||
|
("process", Value::Process),
|
||||||
("random", Value::BaseFn(BaseFn::Nullary("random", random))),
|
("random", Value::BaseFn(BaseFn::Nullary("random", random))),
|
||||||
("range", Value::BaseFn(BaseFn::Binary("range", range))),
|
("range", Value::BaseFn(BaseFn::Binary("range", range))),
|
||||||
("rest", Value::BaseFn(BaseFn::Unary("rest", rest))),
|
("rest", Value::BaseFn(BaseFn::Unary("rest", rest))),
|
||||||
|
|
|
@ -20,6 +20,12 @@ pub struct Chunk {
|
||||||
pub msgs: Vec<String>,
|
pub msgs: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Chunk {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "Chunk.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub fn dissasemble_instr(&self, i: &mut usize) {
|
pub fn dissasemble_instr(&self, i: &mut usize) {
|
||||||
let op = Op::from_u8(self.bytecode[*i]).unwrap();
|
let op = Op::from_u8(self.bytecode[*i]).unwrap();
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -3,7 +3,7 @@ use imbl::HashMap;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
const DEBUG_SCRIPT_COMPILE: bool = false;
|
const DEBUG_SCRIPT_COMPILE: bool = false;
|
||||||
const DEBUG_SCRIPT_RUN: bool = false;
|
const DEBUG_SCRIPT_RUN: bool = true;
|
||||||
const DEBUG_PRELUDE_COMPILE: bool = false;
|
const DEBUG_PRELUDE_COMPILE: bool = false;
|
||||||
const DEBUG_PRELUDE_RUN: bool = false;
|
const DEBUG_PRELUDE_RUN: bool = false;
|
||||||
|
|
||||||
|
@ -84,8 +84,9 @@ fn prelude() -> HashMap<&'static str, Value> {
|
||||||
compiler.compile();
|
compiler.compile();
|
||||||
|
|
||||||
let chunk = compiler.chunk;
|
let chunk = compiler.chunk;
|
||||||
let mut vm = Creature::new(chunk, DEBUG_PRELUDE_RUN);
|
let mut world = World::new(chunk, DEBUG_PRELUDE_RUN);
|
||||||
let prelude = vm.run().clone().unwrap();
|
world.run();
|
||||||
|
let prelude = world.result.unwrap().unwrap();
|
||||||
match prelude {
|
match prelude {
|
||||||
Value::Dict(hashmap) => *hashmap,
|
Value::Dict(hashmap) => *hashmap,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -146,10 +147,8 @@ pub fn ludus(src: String) -> String {
|
||||||
|
|
||||||
let vm_chunk = compiler.chunk;
|
let vm_chunk = compiler.chunk;
|
||||||
|
|
||||||
let vm = Creature::new(vm_chunk, DEBUG_SCRIPT_RUN);
|
let mut world = World::new(vm_chunk, DEBUG_SCRIPT_RUN);
|
||||||
let grip = World::new(vm);
|
world.run();
|
||||||
grip.borrow_mut().run();
|
|
||||||
let world = grip.borrow();
|
|
||||||
let result = world.result.clone().unwrap();
|
let result = world.result.clone().unwrap();
|
||||||
|
|
||||||
let console = postlude.get("console").unwrap();
|
let console = postlude.get("console").unwrap();
|
||||||
|
|
141
src/vm.rs
141
src/vm.rs
|
@ -4,7 +4,7 @@ use crate::op::Op;
|
||||||
use crate::parser::Ast;
|
use crate::parser::Ast;
|
||||||
use crate::spans::Spanned;
|
use crate::spans::Spanned;
|
||||||
use crate::value::{LFn, Value};
|
use crate::value::{LFn, Value};
|
||||||
use crate::world::Grasp;
|
use crate::world::Zoo;
|
||||||
use imbl::{HashMap, Vector};
|
use imbl::{HashMap, Vector};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -77,26 +77,35 @@ fn combine_bytes(high: u8, low: u8) -> usize {
|
||||||
out as usize
|
out as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REGISTER_SIZE: usize = 8;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Creature {
|
pub struct Creature {
|
||||||
pub stack: Vec<Value>,
|
pub stack: Vec<Value>,
|
||||||
pub call_stack: Vec<CallFrame>,
|
pub call_stack: Vec<CallFrame>,
|
||||||
pub frame: CallFrame,
|
pub frame: CallFrame,
|
||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: [Value; 8],
|
pub register: [Value; REGISTER_SIZE],
|
||||||
pub matches: bool,
|
pub matches: bool,
|
||||||
pub match_depth: u8,
|
pub match_depth: u8,
|
||||||
pub result: Option<Result<Value, Panic>>,
|
pub result: Option<Result<Value, Panic>>,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
last_code: usize,
|
last_code: usize,
|
||||||
pub id: &'static str,
|
pub id: &'static str,
|
||||||
pub world: Grasp,
|
|
||||||
pub mbx: VecDeque<Value>,
|
pub mbx: VecDeque<Value>,
|
||||||
pub reductions: usize,
|
pub reductions: usize,
|
||||||
|
pub zoo: Rc<RefCell<Zoo>>,
|
||||||
|
pub r#yield: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Creature {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "Creature. {} @{}", self.id, self.ip)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Creature {
|
impl Creature {
|
||||||
pub fn new(chunk: Chunk, debug: bool) -> Creature {
|
pub fn new(chunk: Chunk, zoo: Rc<RefCell<Zoo>>, debug: bool) -> Creature {
|
||||||
let lfn = LFn::Defined {
|
let lfn = LFn::Defined {
|
||||||
name: "user script",
|
name: "user script",
|
||||||
doc: None,
|
doc: None,
|
||||||
|
@ -106,8 +115,12 @@ impl Creature {
|
||||||
closed: RefCell::new(vec![]),
|
closed: RefCell::new(vec![]),
|
||||||
};
|
};
|
||||||
let base_fn = Value::Fn(Rc::new(lfn));
|
let base_fn = Value::Fn(Rc::new(lfn));
|
||||||
|
Creature::spawn(base_fn, zoo, debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn(function: Value, zoo: Rc<RefCell<Zoo>>, debug: bool) -> Creature {
|
||||||
let base_frame = CallFrame {
|
let base_frame = CallFrame {
|
||||||
function: base_fn.clone(),
|
function,
|
||||||
stack_base: 0,
|
stack_base: 0,
|
||||||
ip: 0,
|
ip: 0,
|
||||||
arity: 0,
|
arity: 0,
|
||||||
|
@ -117,16 +130,17 @@ impl Creature {
|
||||||
call_stack: Vec::with_capacity(64),
|
call_stack: Vec::with_capacity(64),
|
||||||
frame: base_frame,
|
frame: base_frame,
|
||||||
ip: 0,
|
ip: 0,
|
||||||
return_register: [const { Value::Nothing }; 8],
|
register: [const { Value::Nothing }; REGISTER_SIZE],
|
||||||
matches: false,
|
matches: false,
|
||||||
match_depth: 0,
|
match_depth: 0,
|
||||||
result: None,
|
result: None,
|
||||||
debug,
|
debug,
|
||||||
last_code: 0,
|
last_code: 0,
|
||||||
id: "",
|
id: "",
|
||||||
world: None,
|
zoo,
|
||||||
mbx: VecDeque::new(),
|
mbx: VecDeque::new(),
|
||||||
reductions: 0,
|
reductions: 0,
|
||||||
|
r#yield: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +148,11 @@ impl Creature {
|
||||||
self.reductions += 1;
|
self.reductions += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset_reductions(&mut self) {
|
||||||
|
self.reductions = 0;
|
||||||
|
self.r#yield = false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn receive(&mut self, value: Value) {
|
pub fn receive(&mut self, value: Value) {
|
||||||
self.mbx.push_back(value);
|
self.mbx.push_back(value);
|
||||||
}
|
}
|
||||||
|
@ -165,12 +184,21 @@ impl Creature {
|
||||||
}
|
}
|
||||||
let inner = inner.join("|");
|
let inner = inner.join("|");
|
||||||
let register = self
|
let register = self
|
||||||
.return_register
|
.register
|
||||||
.iter()
|
.iter()
|
||||||
.map(|val| val.to_string())
|
.map(|val| val.to_string())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(",");
|
.join(",");
|
||||||
println!("{:04}: [{inner}] ({register})", self.last_code);
|
let mbx = self
|
||||||
|
.mbx
|
||||||
|
.iter()
|
||||||
|
.map(|val| val.show())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("/");
|
||||||
|
println!(
|
||||||
|
"{:04}: [{inner}] ({register}) {} {{{mbx}}}",
|
||||||
|
self.last_code, self.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_debug(&self) {
|
fn print_debug(&self) {
|
||||||
|
@ -179,12 +207,12 @@ impl Creature {
|
||||||
self.chunk().dissasemble_instr(&mut ip);
|
self.chunk().dissasemble_instr(&mut ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> &Result<Value, Panic> {
|
// pub fn run(&mut self) -> &Result<Value, Panic> {
|
||||||
while self.result.is_none() {
|
// while self.result.is_none() {
|
||||||
self.interpret();
|
// self.interpret();
|
||||||
}
|
// }
|
||||||
self.result.as_ref().unwrap()
|
// self.result.as_ref().unwrap()
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn call_stack(&mut self) -> String {
|
pub fn call_stack(&mut self) -> String {
|
||||||
let mut stack = format!(" calling {}", self.frame.function.show());
|
let mut stack = format!(" calling {}", self.frame.function.show());
|
||||||
|
@ -237,13 +265,54 @@ impl Creature {
|
||||||
self.ip >= self.chunk().bytecode.len()
|
self.ip >= self.chunk().bytecode.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_msg(&mut self, args: Vec<Value>) {
|
||||||
|
println!("message received! {}", args[0]);
|
||||||
|
let Value::Keyword(msg) = args.first().unwrap() else {
|
||||||
|
return self.panic("malformed message to Process");
|
||||||
|
};
|
||||||
|
match *msg {
|
||||||
|
"self" => self.push(Value::Keyword(self.id)),
|
||||||
|
"msgs" => {
|
||||||
|
let msgs = self.mbx.iter().cloned().collect::<Vec<_>>();
|
||||||
|
let msgs = Vector::from(msgs);
|
||||||
|
self.push(Value::List(Box::new(msgs)));
|
||||||
|
}
|
||||||
|
"send" => {
|
||||||
|
let Value::Keyword(pid) = args[1] else {
|
||||||
|
return self.panic("malformed pid");
|
||||||
|
};
|
||||||
|
if self.id == pid {
|
||||||
|
self.mbx.push_back(args[2].clone());
|
||||||
|
} else {
|
||||||
|
self.zoo
|
||||||
|
.as_ref()
|
||||||
|
.borrow_mut()
|
||||||
|
.send_msg(pid, args[2].clone());
|
||||||
|
}
|
||||||
|
self.push(Value::Nil);
|
||||||
|
}
|
||||||
|
"spawn" => {
|
||||||
|
println!("spawning new process!");
|
||||||
|
let f = args[1].clone();
|
||||||
|
let proc = Creature::spawn(f, self.zoo.clone(), self.debug);
|
||||||
|
let id = self.zoo.as_ref().borrow_mut().put(proc);
|
||||||
|
self.push(Value::Keyword(id));
|
||||||
|
}
|
||||||
|
"yield" => {
|
||||||
|
self.r#yield = true;
|
||||||
|
self.push(Value::Nil);
|
||||||
|
}
|
||||||
|
msg => panic!("Process does not understand message: {msg}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn interpret(&mut self) {
|
pub fn interpret(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
if self.at_end() {
|
if self.at_end() {
|
||||||
self.result = Some(Ok(self.stack.pop().unwrap()));
|
self.result = Some(Ok(self.stack.pop().unwrap()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if self.reductions >= MAX_REDUCTIONS {
|
if self.reductions >= MAX_REDUCTIONS || self.r#yield {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let code = self.read();
|
let code = self.read();
|
||||||
|
@ -321,27 +390,27 @@ impl Creature {
|
||||||
self.push(value.clone());
|
self.push(value.clone());
|
||||||
}
|
}
|
||||||
Store => {
|
Store => {
|
||||||
self.return_register[0] = self.pop();
|
self.register[0] = self.pop();
|
||||||
}
|
}
|
||||||
StoreN => {
|
StoreN => {
|
||||||
let n = self.read() as usize;
|
let n = self.read() as usize;
|
||||||
for i in (0..n).rev() {
|
for i in (0..n).rev() {
|
||||||
self.return_register[i] = self.pop();
|
self.register[i] = self.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Stash => {
|
Stash => {
|
||||||
self.return_register[0] = self.peek().clone();
|
self.register[0] = self.peek().clone();
|
||||||
}
|
}
|
||||||
Load => {
|
Load => {
|
||||||
let mut value = Value::Nothing;
|
let mut value = Value::Nothing;
|
||||||
swap(&mut self.return_register[0], &mut value);
|
swap(&mut self.register[0], &mut value);
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
LoadN => {
|
LoadN => {
|
||||||
let n = self.read() as usize;
|
let n = self.read() as usize;
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let mut value = Value::Nothing;
|
let mut value = Value::Nothing;
|
||||||
swap(&mut self.return_register[i], &mut value);
|
swap(&mut self.register[i], &mut value);
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -814,6 +883,7 @@ impl Creature {
|
||||||
self.push(Value::Partial(Rc::new(partial)));
|
self.push(Value::Partial(Rc::new(partial)));
|
||||||
}
|
}
|
||||||
TailCall => {
|
TailCall => {
|
||||||
|
self.reduce();
|
||||||
let arity = self.read();
|
let arity = self.read();
|
||||||
|
|
||||||
let called = self.pop();
|
let called = self.pop();
|
||||||
|
@ -826,6 +896,10 @@ impl Creature {
|
||||||
}
|
}
|
||||||
|
|
||||||
match called {
|
match called {
|
||||||
|
Value::Process => {
|
||||||
|
let args = self.stack.split_off(self.stack.len() - arity as usize);
|
||||||
|
self.handle_msg(args);
|
||||||
|
}
|
||||||
Value::Fn(_) => {
|
Value::Fn(_) => {
|
||||||
if !called.as_fn().accepts(arity) {
|
if !called.as_fn().accepts(arity) {
|
||||||
return self.panic_with(format!(
|
return self.panic_with(format!(
|
||||||
|
@ -835,7 +909,7 @@ impl Creature {
|
||||||
}
|
}
|
||||||
// first put the arguments in the register
|
// first put the arguments in the register
|
||||||
for i in 0..arity as usize {
|
for i in 0..arity as usize {
|
||||||
self.return_register[arity as usize - i - 1] = self.pop();
|
self.register[arity as usize - i - 1] = self.pop();
|
||||||
}
|
}
|
||||||
// self.print_stack();
|
// self.print_stack();
|
||||||
|
|
||||||
|
@ -843,9 +917,9 @@ impl Creature {
|
||||||
self.stack.truncate(self.frame.stack_base);
|
self.stack.truncate(self.frame.stack_base);
|
||||||
// then push the arguments back on the stack
|
// then push the arguments back on the stack
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < 8 && self.return_register[i] != Value::Nothing {
|
while i < 8 && self.register[i] != Value::Nothing {
|
||||||
let mut value = Value::Nothing;
|
let mut value = Value::Nothing;
|
||||||
swap(&mut self.return_register[i], &mut value);
|
swap(&mut self.register[i], &mut value);
|
||||||
self.push(value);
|
self.push(value);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -936,6 +1010,7 @@ impl Creature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Call => {
|
Call => {
|
||||||
|
self.reduce();
|
||||||
let arity = self.read();
|
let arity = self.read();
|
||||||
|
|
||||||
let called = self.pop();
|
let called = self.pop();
|
||||||
|
@ -945,6 +1020,10 @@ impl Creature {
|
||||||
}
|
}
|
||||||
|
|
||||||
match called {
|
match called {
|
||||||
|
Value::Process => {
|
||||||
|
let args = self.stack.split_off(self.stack.len() - arity as usize);
|
||||||
|
self.handle_msg(args);
|
||||||
|
}
|
||||||
Value::Fn(_) => {
|
Value::Fn(_) => {
|
||||||
if !called.as_fn().accepts(arity) {
|
if !called.as_fn().accepts(arity) {
|
||||||
return self.panic_with(format!(
|
return self.panic_with(format!(
|
||||||
|
@ -1030,12 +1109,20 @@ impl Creature {
|
||||||
if self.debug {
|
if self.debug {
|
||||||
println!("== returning from {} ==", self.frame.function.show())
|
println!("== returning from {} ==", self.frame.function.show())
|
||||||
}
|
}
|
||||||
self.frame = self.call_stack.pop().unwrap();
|
|
||||||
self.ip = self.frame.ip;
|
|
||||||
let mut value = Value::Nothing;
|
let mut value = Value::Nothing;
|
||||||
swap(&mut self.return_register[0], &mut value);
|
swap(&mut self.register[0], &mut value);
|
||||||
|
match self.call_stack.pop() {
|
||||||
|
Some(frame) => {
|
||||||
|
self.ip = frame.ip;
|
||||||
|
self.frame = frame;
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
self.result = Some(Ok(value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Print => {
|
Print => {
|
||||||
println!("{}", self.pop().show());
|
println!("{}", self.pop().show());
|
||||||
self.push(Value::Keyword("ok"));
|
self.push(Value::Keyword("ok"));
|
||||||
|
|
154
src/world.rs
154
src/world.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::chunk::Chunk;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::vm::{Creature, Panic};
|
use crate::vm::{Creature, Panic};
|
||||||
use ran::ran_u8;
|
use ran::ran_u8;
|
||||||
|
@ -39,12 +40,33 @@ enum Status {
|
||||||
Nested(Creature),
|
Nested(Creature),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Status {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Status::Empty => write!(f, "empty"),
|
||||||
|
Status::Borrowed => write!(f, "borrowed"),
|
||||||
|
Status::Nested(creature) => write!(f, "nested {creature}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Status {
|
||||||
|
pub fn receive(&mut self, msg: Value) {
|
||||||
|
match self {
|
||||||
|
Status::Nested(creature) => creature.receive(msg),
|
||||||
|
Status::Borrowed => println!("sending a message to a borrowed process"),
|
||||||
|
Status::Empty => println!("sending a message to a dead process"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
struct Zoo {
|
pub struct Zoo {
|
||||||
procs: Vec<Status>,
|
procs: Vec<Status>,
|
||||||
empty: Vec<usize>,
|
empty: Vec<usize>,
|
||||||
ids: HashMap<&'static str, usize>,
|
ids: HashMap<&'static str, usize>,
|
||||||
dead: Vec<&'static str>,
|
dead: Vec<&'static str>,
|
||||||
|
kill_list: Vec<&'static str>,
|
||||||
active: usize,
|
active: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +76,7 @@ impl Zoo {
|
||||||
procs: vec![],
|
procs: vec![],
|
||||||
empty: vec![],
|
empty: vec![],
|
||||||
ids: HashMap::new(),
|
ids: HashMap::new(),
|
||||||
|
kill_list: vec![],
|
||||||
dead: vec![],
|
dead: vec![],
|
||||||
active: 0,
|
active: 0,
|
||||||
}
|
}
|
||||||
|
@ -93,13 +116,19 @@ impl Zoo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(&mut self, id: &'static str) {
|
pub fn kill(&mut self, id: &'static str) {
|
||||||
|
self.kill_list.push(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clean_up(&mut self) {
|
||||||
|
while let Some(id) = self.kill_list.pop() {
|
||||||
if let Some(idx) = self.ids.get(id) {
|
if let Some(idx) = self.ids.get(id) {
|
||||||
self.procs[*idx] = Status::Empty;
|
self.procs[*idx] = Status::Empty;
|
||||||
self.empty.push(*idx);
|
self.empty.push(*idx);
|
||||||
self.ids.remove(&id);
|
self.ids.remove(id);
|
||||||
self.dead.push(id);
|
self.dead.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn catch(&mut self, id: &'static str) -> Creature {
|
pub fn catch(&mut self, id: &'static str) -> Creature {
|
||||||
if let Some(idx) = self.ids.get(id) {
|
if let Some(idx) = self.ids.get(id) {
|
||||||
|
@ -125,7 +154,18 @@ impl Zoo {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self, curr_id: &'static str) -> &'static str {
|
pub fn next(&mut self, curr_id: &'static str) -> &'static str {
|
||||||
|
println!("getting next process from {curr_id}");
|
||||||
|
println!(
|
||||||
|
"current procs in zoo:\n{}",
|
||||||
|
self.procs
|
||||||
|
.iter()
|
||||||
|
.map(|proc| proc.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("//")
|
||||||
|
);
|
||||||
|
println!("ids: {:?}", self.ids);
|
||||||
let idx = self.ids.get(curr_id).unwrap();
|
let idx = self.ids.get(curr_id).unwrap();
|
||||||
|
println!("current idx: {idx}");
|
||||||
if *idx != self.active {
|
if *idx != self.active {
|
||||||
panic!(
|
panic!(
|
||||||
"tried to get next creature after {curr_id} while {} is active",
|
"tried to get next creature after {curr_id} while {} is active",
|
||||||
|
@ -133,9 +173,14 @@ impl Zoo {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.active = (self.active + 1) % self.procs.len();
|
self.active = (self.active + 1) % self.procs.len();
|
||||||
while self.procs[self.active] != Status::Empty {
|
println!("active idx is now: {}", self.active);
|
||||||
|
while self.procs[self.active] == Status::Empty {
|
||||||
|
let new_active_idx = (self.active + 1) % self.procs.len();
|
||||||
|
println!("new active idx: {new_active_idx}");
|
||||||
|
println!("new active process is: {}", self.procs[new_active_idx]);
|
||||||
self.active = (self.active + 1) % self.procs.len();
|
self.active = (self.active + 1) % self.procs.len();
|
||||||
}
|
}
|
||||||
|
println!("found next proc: {}", &self.procs[self.active]);
|
||||||
match &self.procs[self.active] {
|
match &self.procs[self.active] {
|
||||||
Status::Empty => unreachable!(),
|
Status::Empty => unreachable!(),
|
||||||
Status::Borrowed => panic!(
|
Status::Borrowed => panic!(
|
||||||
|
@ -145,61 +190,63 @@ impl Zoo {
|
||||||
Status::Nested(proc) => proc.id,
|
Status::Nested(proc) => proc.id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub type Grasp = Option<Rc<RefCell<World>>>;
|
pub fn send_msg(&mut self, id: &'static str, msg: Value) {
|
||||||
|
let Some(idx) = self.ids.get(id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.procs[*idx].receive(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct World {
|
pub struct World {
|
||||||
zoo: Zoo,
|
zoo: Rc<RefCell<Zoo>>,
|
||||||
active: Option<Creature>,
|
active: Option<Creature>,
|
||||||
main: &'static str,
|
main: &'static str,
|
||||||
handle: Grasp,
|
|
||||||
pub result: Option<Result<Value, Panic>>,
|
pub result: Option<Result<Value, Panic>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub fn new(proc: Creature) -> Rc<RefCell<World>> {
|
pub fn new(chunk: Chunk, debug: bool) -> World {
|
||||||
let mut zoo = Zoo::new();
|
let zoo = Rc::new(RefCell::new(Zoo::new()));
|
||||||
let id = zoo.put(proc);
|
let main = Creature::new(chunk, zoo.clone(), debug);
|
||||||
let world = World {
|
let id = zoo.as_ref().borrow_mut().put(main);
|
||||||
|
|
||||||
|
World {
|
||||||
zoo,
|
zoo,
|
||||||
active: None,
|
active: None,
|
||||||
main: id,
|
main: id,
|
||||||
handle: None,
|
|
||||||
result: None,
|
result: None,
|
||||||
};
|
}
|
||||||
let handle = Rc::new(RefCell::new(world));
|
|
||||||
let grasped = handle.clone();
|
|
||||||
let mut world = grasped.as_ref().borrow_mut();
|
|
||||||
world.handle = Some(grasped.clone());
|
|
||||||
|
|
||||||
let mut caught = world.zoo.catch(id);
|
|
||||||
caught.world = world.handle.clone();
|
|
||||||
world.zoo.release(caught);
|
|
||||||
|
|
||||||
handle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(&mut self, proc: Creature) -> Value {
|
// pub fn spawn(&mut self, proc: Creature) -> Value {
|
||||||
let id = self.zoo.put(proc);
|
// let id = self.zoo.put(proc);
|
||||||
Value::Keyword(id)
|
// Value::Keyword(id)
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn send_msg(&mut self, id: &'static str, msg: Value) {
|
// pub fn send_msg(&mut self, id: &'static str, msg: Value) {
|
||||||
let mut proc = self.zoo.catch(id);
|
// let mut proc = self.zoo.catch(id);
|
||||||
proc.receive(msg);
|
// proc.receive(msg);
|
||||||
self.zoo.release(proc);
|
// self.zoo.release(proc);
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn next(&mut self) {
|
fn next(&mut self) {
|
||||||
let id = self.zoo.next(self.active.as_ref().unwrap().id);
|
let id = self
|
||||||
|
.zoo
|
||||||
|
.as_ref()
|
||||||
|
.borrow_mut()
|
||||||
|
.next(self.active.as_ref().unwrap().id);
|
||||||
|
println!("next id is {id}");
|
||||||
let mut active = None;
|
let mut active = None;
|
||||||
std::mem::swap(&mut active, &mut self.active);
|
std::mem::swap(&mut active, &mut self.active);
|
||||||
let mut holding_pen = self.zoo.catch(id);
|
let mut holding_pen = self.zoo.as_ref().borrow_mut().catch(id);
|
||||||
let mut active = active.unwrap();
|
let mut active = active.unwrap();
|
||||||
std::mem::swap(&mut active, &mut holding_pen);
|
std::mem::swap(&mut active, &mut holding_pen);
|
||||||
self.zoo.release(holding_pen);
|
println!("now in the holding pen: {}", holding_pen.id);
|
||||||
|
holding_pen.reset_reductions();
|
||||||
|
self.zoo.as_ref().borrow_mut().release(holding_pen);
|
||||||
let mut active = Some(active);
|
let mut active = Some(active);
|
||||||
std::mem::swap(&mut active, &mut self.active);
|
std::mem::swap(&mut active, &mut self.active);
|
||||||
}
|
}
|
||||||
|
@ -234,22 +281,47 @@ impl World {
|
||||||
// self.next(id);
|
// self.next(id);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn activate_main(&mut self) {
|
||||||
let main = self.zoo.catch(self.main);
|
let main = self.zoo.as_ref().borrow_mut().catch(self.main);
|
||||||
self.active = Some(main);
|
self.active = Some(main);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_id(&mut self) -> &'static str {
|
||||||
|
self.active.as_ref().unwrap().id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kill_active(&mut self) {
|
||||||
|
let id = self.active_id();
|
||||||
|
self.zoo.as_ref().borrow_mut().kill(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_result(&mut self) -> &Option<Result<Value, Panic>> {
|
||||||
|
&self.active.as_ref().unwrap().result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clean_up(&mut self) {
|
||||||
|
self.zoo.as_ref().borrow_mut().clean_up()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
self.activate_main();
|
||||||
loop {
|
loop {
|
||||||
|
println!("entering world loop");
|
||||||
self.active.as_mut().unwrap().interpret();
|
self.active.as_mut().unwrap().interpret();
|
||||||
match self.active.as_ref().unwrap().result {
|
println!("interpreted loop");
|
||||||
|
match self.active_result() {
|
||||||
None => (),
|
None => (),
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
if self.active.as_ref().unwrap().id == self.main {
|
if self.active_id() == self.main {
|
||||||
self.result = self.active.as_ref().unwrap().result.clone();
|
self.result = self.active_result().clone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.zoo.kill(self.active.as_ref().unwrap().id);
|
self.kill_active();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("getting next process");
|
||||||
self.next();
|
self.next();
|
||||||
|
self.clean_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user