refactor to have a world run a process
This commit is contained in:
parent
b5528ced8f
commit
b35657e698
|
@ -1,4 +1 @@
|
||||||
repeat 1 {
|
:foobar
|
||||||
fd! (100)
|
|
||||||
rt! (0.25)
|
|
||||||
}
|
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -8,7 +8,9 @@ const DEBUG_PRELUDE_COMPILE: bool = false;
|
||||||
const DEBUG_PRELUDE_RUN: bool = false;
|
const DEBUG_PRELUDE_RUN: bool = false;
|
||||||
|
|
||||||
mod base;
|
mod base;
|
||||||
|
|
||||||
mod world;
|
mod world;
|
||||||
|
use crate::world::World;
|
||||||
|
|
||||||
mod spans;
|
mod spans;
|
||||||
use crate::spans::Spanned;
|
use crate::spans::Spanned;
|
||||||
|
@ -144,8 +146,11 @@ pub fn ludus(src: String) -> String {
|
||||||
|
|
||||||
let vm_chunk = compiler.chunk;
|
let vm_chunk = compiler.chunk;
|
||||||
|
|
||||||
let mut vm = Creature::new(vm_chunk, DEBUG_SCRIPT_RUN);
|
let vm = Creature::new(vm_chunk, DEBUG_SCRIPT_RUN);
|
||||||
let result = vm.run();
|
let grip = World::new(vm);
|
||||||
|
grip.borrow_mut().run();
|
||||||
|
let world = grip.borrow();
|
||||||
|
let result = world.result.clone().unwrap();
|
||||||
|
|
||||||
let console = postlude.get("console").unwrap();
|
let console = postlude.get("console").unwrap();
|
||||||
let Value::Box(console) = console else {
|
let Value::Box(console) = console else {
|
||||||
|
@ -165,7 +170,6 @@ pub fn ludus(src: String) -> String {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let commands = commands.borrow();
|
let commands = commands.borrow();
|
||||||
dbg!(&commands);
|
|
||||||
let commands = commands.to_json().unwrap();
|
let commands = commands.to_json().unwrap();
|
||||||
|
|
||||||
let output = match result {
|
let output = match result {
|
||||||
|
@ -176,7 +180,7 @@ pub fn ludus(src: String) -> String {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if DEBUG_SCRIPT_RUN {
|
if DEBUG_SCRIPT_RUN {
|
||||||
vm.print_stack();
|
// vm.print_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use serde_json to make this more robust?
|
// TODO: use serde_json to make this more robust?
|
||||||
|
|
21
src/vm.rs
21
src/vm.rs
|
@ -4,13 +4,17 @@ 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 imbl::{HashMap, Vector};
|
use imbl::{HashMap, Vector};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
const MAX_REDUCTIONS: usize = 100;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Panic {
|
pub enum Panic {
|
||||||
Str(&'static str),
|
Str(&'static str),
|
||||||
|
@ -86,6 +90,9 @@ pub struct Creature {
|
||||||
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 reductions: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Creature {
|
impl Creature {
|
||||||
|
@ -117,9 +124,20 @@ impl Creature {
|
||||||
debug,
|
debug,
|
||||||
last_code: 0,
|
last_code: 0,
|
||||||
id: "",
|
id: "",
|
||||||
|
world: None,
|
||||||
|
mbx: VecDeque::new(),
|
||||||
|
reductions: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reduce(&mut self) {
|
||||||
|
self.reductions += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(&mut self, value: Value) {
|
||||||
|
self.mbx.push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn chunk(&self) -> &Chunk {
|
pub fn chunk(&self) -> &Chunk {
|
||||||
self.frame.chunk()
|
self.frame.chunk()
|
||||||
}
|
}
|
||||||
|
@ -225,6 +243,9 @@ impl Creature {
|
||||||
self.result = Some(Ok(self.stack.pop().unwrap()));
|
self.result = Some(Ok(self.stack.pop().unwrap()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if self.reductions >= MAX_REDUCTIONS {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let code = self.read();
|
let code = self.read();
|
||||||
if self.debug {
|
if self.debug {
|
||||||
self.last_code = self.ip - 1;
|
self.last_code = self.ip - 1;
|
||||||
|
|
181
src/world.rs
181
src/world.rs
|
@ -1,10 +1,11 @@
|
||||||
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;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
const ANIMALS: [&str; 24] = [
|
const ANIMALS: [&str; 24] = [
|
||||||
"turtle",
|
|
||||||
"tortoise",
|
"tortoise",
|
||||||
"hare",
|
"hare",
|
||||||
"squirrel",
|
"squirrel",
|
||||||
|
@ -28,6 +29,7 @@ const ANIMALS: [&str; 24] = [
|
||||||
"giraffe",
|
"giraffe",
|
||||||
"leopard",
|
"leopard",
|
||||||
"lion",
|
"lion",
|
||||||
|
"hippopotamus",
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -43,6 +45,7 @@ struct Zoo {
|
||||||
empty: Vec<usize>,
|
empty: Vec<usize>,
|
||||||
ids: HashMap<&'static str, usize>,
|
ids: HashMap<&'static str, usize>,
|
||||||
dead: Vec<&'static str>,
|
dead: Vec<&'static str>,
|
||||||
|
active: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Zoo {
|
impl Zoo {
|
||||||
|
@ -52,14 +55,28 @@ impl Zoo {
|
||||||
empty: vec![],
|
empty: vec![],
|
||||||
ids: HashMap::new(),
|
ids: HashMap::new(),
|
||||||
dead: vec![],
|
dead: vec![],
|
||||||
|
active: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn random_id(&self) -> String {
|
||||||
|
let rand = ran_u8() as usize % 24;
|
||||||
|
let idx = self.procs.len();
|
||||||
|
format!("{}_{idx}", ANIMALS[rand])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_id(&self) -> &'static str {
|
||||||
|
let mut new = self.random_id();
|
||||||
|
while self.dead.iter().any(|old| *old == new) {
|
||||||
|
new = self.random_id();
|
||||||
|
}
|
||||||
|
new.leak()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn put(&mut self, mut proc: Creature) -> &'static str {
|
pub fn put(&mut self, mut proc: Creature) -> &'static str {
|
||||||
if self.empty.is_empty() {
|
if self.empty.is_empty() {
|
||||||
let rand = ran_u8() as usize % 24;
|
let id = self.new_id();
|
||||||
let idx = self.procs.len();
|
let idx = self.procs.len();
|
||||||
let id = format!("{}_{idx}", ANIMALS[rand]).leak();
|
|
||||||
proc.id = id;
|
proc.id = id;
|
||||||
self.procs.push(Status::Nested(proc));
|
self.procs.push(Status::Nested(proc));
|
||||||
self.ids.insert(id, idx);
|
self.ids.insert(id, idx);
|
||||||
|
@ -106,76 +123,136 @@ impl Zoo {
|
||||||
unreachable!("tried to return a process the world doesn't know about");
|
unreachable!("tried to return a process the world doesn't know about");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self, curr_id: &'static str) -> &'static str {
|
||||||
|
let idx = self.ids.get(curr_id).unwrap();
|
||||||
|
if *idx != self.active {
|
||||||
|
panic!(
|
||||||
|
"tried to get next creature after {curr_id} while {} is active",
|
||||||
|
self.active
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.active = (self.active + 1) % self.procs.len();
|
||||||
|
while self.procs[self.active] != Status::Empty {
|
||||||
|
self.active = (self.active + 1) % self.procs.len();
|
||||||
|
}
|
||||||
|
match &self.procs[self.active] {
|
||||||
|
Status::Empty => unreachable!(),
|
||||||
|
Status::Borrowed => panic!(
|
||||||
|
"encountered unexpectedly borrowed process at idx {}",
|
||||||
|
self.active
|
||||||
|
),
|
||||||
|
Status::Nested(proc) => proc.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type Grasp = Option<Rc<RefCell<World>>>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct World {
|
pub struct World {
|
||||||
procs: Zoo,
|
zoo: Zoo,
|
||||||
mbxes: HashMap<String, VecDeque<Value>>,
|
active: Option<Creature>,
|
||||||
active: Creature,
|
|
||||||
// TODO: we need a lifetime here
|
|
||||||
main: &'static str,
|
main: &'static str,
|
||||||
|
handle: Grasp,
|
||||||
|
pub result: Option<Result<Value, Panic>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub fn new(proc: Creature) -> World {
|
pub fn new(proc: Creature) -> Rc<RefCell<World>> {
|
||||||
let mut creatures = Zoo::new();
|
let mut zoo = Zoo::new();
|
||||||
let id = creatures.put(proc);
|
let id = zoo.put(proc);
|
||||||
let caught = creatures.catch(id);
|
let world = World {
|
||||||
World {
|
zoo,
|
||||||
procs: creatures,
|
active: None,
|
||||||
mbxes: HashMap::new(),
|
|
||||||
active: caught,
|
|
||||||
main: id,
|
main: id,
|
||||||
}
|
handle: 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.procs.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 mbx = self.mbxes.get_mut(id).unwrap();
|
let mut proc = self.zoo.catch(id);
|
||||||
mbx.push_back(msg);
|
proc.receive(msg);
|
||||||
|
self.zoo.release(proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(&mut self, id: &'static str) {
|
fn next(&mut self) {
|
||||||
// check if the id is the actually active process
|
let id = self.zoo.next(self.active.as_ref().unwrap().id);
|
||||||
// return it to the nursery
|
let mut active = None;
|
||||||
// get the next process from the nursery
|
std::mem::swap(&mut active, &mut self.active);
|
||||||
|
let mut holding_pen = self.zoo.catch(id);
|
||||||
|
let mut active = active.unwrap();
|
||||||
|
std::mem::swap(&mut active, &mut holding_pen);
|
||||||
|
self.zoo.release(holding_pen);
|
||||||
|
let mut active = Some(active);
|
||||||
|
std::mem::swap(&mut active, &mut self.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_msg(&self, id: &'static str) -> Option<(usize, Value)> {
|
// pub fn sleep(&mut self, id: &'static str) {
|
||||||
// check if the id is of the active process
|
// // check if the id is the actually active process
|
||||||
todo!()
|
// if self.active.id != id {
|
||||||
}
|
// panic!("attempted to sleep a process from outside that process: active = {}; to sleep: = {id}", self.active.id);
|
||||||
|
// }
|
||||||
|
// self.next(id);
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn match_msg(&mut self, id: &'static str, idx: usize) {
|
// pub fn panic(&mut self, id: &'static str, panic: Panic) {
|
||||||
// again, check for activity
|
// // TODO: devise some way of linking processes (study the BEAM on this)
|
||||||
// delete the message at idx, which we gave along with the value as the tuple in get_msg
|
// // check if the id is active
|
||||||
}
|
// if self.active.id != id {
|
||||||
|
// panic!("attempted to panic from a process from outside that process: active = {}; panicking = {id}; panic = {panic}", self.active.id);
|
||||||
|
// }
|
||||||
|
// // check if the process is `main`, and crash the program if it is
|
||||||
|
// if self.main == id {
|
||||||
|
// self.result = self.active.result.clone();
|
||||||
|
// }
|
||||||
|
// // kill the process
|
||||||
|
// self.zoo.kill(id);
|
||||||
|
// self.next(id);
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn r#yield(&mut self, id: &'static str) {
|
// pub fn complete(&mut self) {
|
||||||
// check if the id is active
|
// if self.main == self.active.id {
|
||||||
// swap out the currently active process for the next one
|
// self.result = self.active.result.clone();
|
||||||
}
|
// }
|
||||||
|
// self.next(id);
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn panic(&mut self, id: &'static str) {
|
pub fn run(&mut self) {
|
||||||
// TODO: devise some way of linking processes (study the BEAM on this)
|
loop {
|
||||||
// check if the id is active
|
if self.active.is_none() {
|
||||||
// check if the process is `main`, and crash the program if it is
|
let main = self.zoo.catch(self.main);
|
||||||
// kill the process
|
self.active = Some(main);
|
||||||
// swap out this process for the next one
|
}
|
||||||
}
|
self.active.as_mut().unwrap().interpret();
|
||||||
|
match self.active.as_ref().unwrap().result {
|
||||||
pub fn complete(&mut self, id: &'static str, value: Value) {
|
None => (),
|
||||||
// check if the id is active
|
Some(_) => {
|
||||||
// check if the process is main
|
if self.active.as_ref().unwrap().id == self.main {
|
||||||
// if it is: stash the value somehow and exit the program cleanly
|
self.result = self.active.as_ref().unwrap().result.clone();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
pub fn run(&mut self) -> Result<Value, Panic> {
|
self.zoo.kill(self.active.as_ref().unwrap().id);
|
||||||
todo!()
|
}
|
||||||
|
}
|
||||||
|
self.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user