Skip to content

Commit

Permalink
pub refactor partial
Browse files Browse the repository at this point in the history
  • Loading branch information
dragazo committed Nov 11, 2023
1 parent 7d2a1e0 commit e979cd6
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 206 deletions.
4 changes: 2 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ fn run_proj_tty<C: CustomTypes<StdSystem<C>>>(project_name: &str, server: String
for _ in 0..STEPS_PER_IO_ITER {
let res = proj.step(mc);
if let ProjectStep::Error { error, proc } = &res {
print!("\r\n>>> runtime error in entity {:?}: {:?}\r\n\r\n", proc.get_call_stack().last().unwrap().entity.borrow().name, error.cause);
print!("\r\n>>> runtime error: {:?}\r\n\r\n", error.cause);
}
idle_sleeper.consume(&res);
}
Expand Down Expand Up @@ -326,7 +326,7 @@ fn run_proj_non_tty<C: CustomTypes<StdSystem<C>>>(project_name: &str, server: St
for _ in 0..STEPS_PER_IO_ITER {
let res = proj.step(mc);
if let ProjectStep::Error { error, proc } = &res {
println!("\n>>> runtime error in entity {:?}: {:?}\n", proc.get_call_stack().last().unwrap().entity.borrow().name, error.cause);
println!("\n>>> runtime error: {:?}\n", error.cause);
}
idle_sleeper.consume(&res);
}
Expand Down
10 changes: 9 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::{BufRead, Write, BufReader, BufWriter};

use netsblox_vm::cli::{run, Mode};
use netsblox_vm::template::SyscallMenu;
use netsblox_vm::runtime::{GetType, Value, Type, ErrorCause, EntityKind, Request, RequestStatus, Config, CustomTypes, Key, SimpleValue};
use netsblox_vm::runtime::{GetType, Value, Type, ErrorCause, EntityKind, Request, RequestStatus, Config, CustomTypes, Key, SimpleValue, Entity};
use netsblox_vm::std_system::StdSystem;
use netsblox_vm::gc::Mutation;
use clap::Parser;
Expand Down Expand Up @@ -47,6 +47,13 @@ impl From<EntityKind<'_, '_, C, StdSystem<C>>> for EntityState {
}
}

struct ProcessState;
impl From<&Entity<'_, C, StdSystem<C>>> for ProcessState {
fn from(_: &Entity<'_, C, StdSystem<C>>) -> Self {
ProcessState
}
}

enum Intermediate {
Simple(SimpleValue),
Native(NativeValue),
Expand All @@ -63,6 +70,7 @@ impl CustomTypes<StdSystem<C>> for C {
type Intermediate = Intermediate;

type EntityState = EntityState;
type ProcessState = ProcessState;

fn from_intermediate<'gc>(mc: &Mutation<'gc>, value: Self::Intermediate) -> Result<Value<'gc, C, StdSystem<C>>, ErrorCause<C, StdSystem<C>>> {
Ok(match value {
Expand Down
75 changes: 24 additions & 51 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,13 @@ impl ErrorSummary {
let globals = summarize_symbols(&process.get_global_context().borrow().globals);
let fields = summarize_symbols(&raw_entity.borrow().fields);

let call_stack = process.get_call_stack();
let mut trace = Vec::with_capacity(call_stack.len());
for (pos, locals) in iter::zip(call_stack[1..].iter().map(|x| x.called_from).chain(iter::once(error.pos)), call_stack.iter().map(|x| &x.locals)) {
let mut trace = Vec::with_capacity(process.call_stack.len());
for (pos, locals) in iter::zip(process.call_stack[1..].iter().map(|x| x.called_from).chain(iter::once(error.pos)), process.call_stack.iter().map(|x| &x.locals)) {
if let Some(loc) = locations.lookup(pos) {
trace.push(TraceEntry { location: loc.clone(), locals: summarize_symbols(locals) });
}
}
debug_assert_eq!(trace.len(), call_stack.len());
debug_assert_eq!(trace.len(), process.call_stack.len());

Self { entity, cause, globals, fields, trace }
}
Expand Down Expand Up @@ -146,10 +145,10 @@ pub enum ProcessStep<'gc, C: CustomTypes<S>, S: System<C>> {
#[derive(Collect)]
#[collect(no_drop, bound = "")]
pub struct CallStackEntry<'gc, C: CustomTypes<S>, S: System<C>> {
#[collect(require_static)] pub called_from: usize,
#[collect(require_static)] return_to: usize,
pub entity: Gc<'gc, RefLock<Entity<'gc, C, S>>>,
pub locals: SymbolTable<'gc, C, S>,
#[collect(require_static)] called_from: usize,
#[collect(require_static)] return_to: usize,
entity: Gc<'gc, RefLock<Entity<'gc, C, S>>>,
locals: SymbolTable<'gc, C, S>,

#[collect(require_static)] warp_counter: usize,
#[collect(require_static)] value_stack_size: usize,
Expand Down Expand Up @@ -178,9 +177,12 @@ enum RequestAction {
/// A collection of context info for starting a new [`Process`].
#[derive(Collect, Educe)]
#[collect(no_drop, bound = "")]
#[educe(Clone, Default)]
#[educe(Clone)]
pub struct ProcContext<'gc, C: CustomTypes<S>, S: System<C>> {
pub global_context: Gc<'gc, RefLock<GlobalContext<'gc, C, S>>>,
pub entity: Gc<'gc, RefLock<Entity<'gc, C, S>>>,
pub locals: SymbolTable<'gc, C, S>,
#[collect(require_static)] pub start_pos: usize,
#[collect(require_static)] pub barrier: Option<Barrier>,
#[collect(require_static)] pub reply_key: Option<S::InternReplyKey>,
#[collect(require_static)] pub local_message: Option<String>,
Expand All @@ -194,12 +196,12 @@ pub struct ProcContext<'gc, C: CustomTypes<S>, S: System<C>> {
#[collect(no_drop, bound = "")]
pub struct Process<'gc, C: CustomTypes<S>, S: System<C>> {
global_context: Gc<'gc, RefLock<GlobalContext<'gc, C, S>>>,
#[collect(require_static)] start_pos: usize,
#[collect(require_static)] pos: usize,
#[collect(require_static)] running: bool,
#[collect(require_static)] barrier: Option<Barrier>,
#[collect(require_static)] reply_key: Option<S::InternReplyKey>,
#[collect(require_static)] warp_counter: usize,
#[collect(require_static)] state: C::ProcessState,
call_stack: Vec<CallStackEntry<'gc, C, S>>,
value_stack: Vec<Value<'gc, C, S>>,
#[collect(require_static)] handler_stack: Vec<Handler>,
Expand All @@ -212,31 +214,31 @@ pub struct Process<'gc, C: CustomTypes<S>, S: System<C>> {
impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
/// Creates a new [`Process`] that is tied to a given `start_pos` (entry point) in the [`ByteCode`] and associated with the specified `entity` and `system`.
/// The created process is initialized to an idle (non-running) state; use [`Process::initialize`] to begin execution.
pub fn new(global_context: Gc<'gc, RefLock<GlobalContext<'gc, C, S>>>, entity: Gc<'gc, RefLock<Entity<'gc, C, S>>>, start_pos: usize) -> Self {
pub fn new(context: ProcContext<'gc, C, S>) -> Self {
Self {
global_context,
start_pos,
running: false,
barrier: None,
reply_key: None,
pos: 0,
global_context: context.global_context,
running: true,
barrier: context.barrier,
reply_key: context.reply_key,
pos: context.start_pos,
warp_counter: 0,
state: C::ProcessState::from(&*context.entity.borrow()),
call_stack: vec![CallStackEntry {
called_from: usize::MAX,
return_to: usize::MAX,
warp_counter: 0,
value_stack_size: 0,
handler_stack_size: 0,
locals: Default::default(),
entity,
locals: context.locals,
entity: context.entity,
}],
value_stack: vec![],
handler_stack: vec![],
defer: None,
last_syscall_error: None,
last_rpc_error: None,
last_answer: None,
last_message: None,
last_message: context.local_message.map(|x| Rc::new(x).into()),
}
}
/// Checks if the process is currently running.
Expand All @@ -248,35 +250,6 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
pub fn get_global_context(&self) -> Gc<'gc, RefLock<GlobalContext<'gc, C, S>>> {
self.global_context
}
/// Gets a reference to the current call stack.
/// This gives access to stack trace information including all local scopes in the call chain.
/// Note that the call stack is never empty, and that the always-present first element (denoting the initial execution request) is a special
/// entry which has an invalid value for [`CallStackEntry::called_from`], namely [`usize::MAX`].
pub fn get_call_stack(&self) -> &[CallStackEntry<'gc, C, S>] {
&self.call_stack
}
/// Prepares the process to execute starting at the main entry point (see [`Process::new`]) with the provided input local variables.
/// A [`Barrier`] may also be set, which will be destroyed upon termination, either due to completion or an error.
///
/// Any previous process state is wiped when performing this action.
pub fn initialize(&mut self, context: ProcContext<'gc, C, S>) {
self.pos = self.start_pos;
self.running = true;
self.barrier = context.barrier;
self.reply_key = context.reply_key;
self.warp_counter = 0;
self.call_stack.drain(1..);
self.call_stack[0].locals = context.locals;
self.value_stack.clear();
self.handler_stack.clear();
self.defer = None;
self.last_syscall_error = None;
self.last_rpc_error = None;
self.last_answer = None;
self.last_message = context.local_message.map(|x| Rc::new(x).into());

debug_assert_eq!(self.call_stack.len(), 1);
}
/// Executes a single bytecode instruction.
/// The return value can be used to determine what additional effects the script has requested,
/// as well as to retrieve the return value or execution error in the event that the process terminates.
Expand Down Expand Up @@ -487,7 +460,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
self.value_stack.push(lookup_var!(var).get().clone());
self.pos = aft_pos;
}
Instruction::PushEntity { name } => match global_context.entities.get(name) {
Instruction::PushEntity { name } => match global_context.entities.iter().find(|&x| x.borrow().name.as_str() == name) {
Some(x) => {
self.value_stack.push(Value::Entity(*x));
self.pos = aft_pos;
Expand Down Expand Up @@ -1247,7 +1220,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Process<'gc, C, S> {
costume: target.costume.clone(),
state: C::EntityState::from(EntityKind::Clone { parent: &*target }),
alive: true,
root: Some(target.root.unwrap_or(target_cell)),
original: Some(target.original.unwrap_or(target_cell)),
fields: target.fields.clone(),
}));
self.value_stack.push(new_entity.into());
Expand Down
7 changes: 3 additions & 4 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Project<'gc, C, S> {
ProjectStep::Pause
}
ProcessStep::Fork { pos, locals, entity } => {
let mut proc = Process::new(self.state.global_context, entity, pos);
proc.initialize(ProcContext { locals, barrier: None, reply_key: None, local_message: None });
let mut proc = Process::new(ProcContext { global_context: self.state.global_context, entity, start_pos: pos, locals, barrier: None, reply_key: None, local_message: None });
let fork_proc_key = self.state.processes.insert(proc);

all_contexts_consumer.do_once(self); // need to consume all contexts before scheduling things in the future
Expand All @@ -327,10 +326,10 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Project<'gc, C, S> {
ProjectStep::Normal
}
ProcessStep::CreatedClone { new_entity } => {
let root = new_entity.borrow().root.unwrap();
let original = new_entity.borrow().original.unwrap();
let mut new_scripts = vec![];
for script in self.scripts.iter() {
if Gc::ptr_eq(script.entity, root) {
if Gc::ptr_eq(script.entity, original) {
new_scripts.push(Script {
event: script.event.clone(),
entity: new_entity,
Expand Down
33 changes: 19 additions & 14 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,9 +1064,9 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> Value<'gc, C, S> {
#[derive(Collect)]
#[collect(no_drop, bound = "")]
pub struct Closure<'gc, C: CustomTypes<S>, S: System<C>> {
#[collect(require_static)] pub pos: usize,
#[collect(require_static)] pub params: Vec<String>,
pub captures: SymbolTable<'gc, C, S>,
#[collect(require_static)] pub(crate) pos: usize,
#[collect(require_static)] pub(crate) params: Vec<String>,
pub(crate) captures: SymbolTable<'gc, C, S>,
}
impl<C: CustomTypes<S>, S: System<C>> fmt::Debug for Closure<'_, C, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -1085,14 +1085,14 @@ pub enum EntityKind<'gc, 'a, C: CustomTypes<S>, S: System<C>> {
#[derive(Collect)]
#[collect(no_drop, bound = "")]
pub struct Entity<'gc, C: CustomTypes<S>, S: System<C>> {
#[collect(require_static)] pub name: Rc<String>,
#[collect(require_static)] pub sound_list: Rc<Vec<(String, Rc<Audio>)>>,
#[collect(require_static)] pub costume_list: Rc<Vec<(String, Rc<Image>)>>,
#[collect(require_static)] pub costume: Option<Rc<Image>>,
#[collect(require_static)] pub state: C::EntityState,
#[collect(require_static)] pub alive: bool,
pub root: Option<Gc<'gc, RefLock<Entity<'gc, C, S>>>>,
pub fields: SymbolTable<'gc, C, S>,
#[collect(require_static)] pub(crate) name: Rc<String>,
#[collect(require_static)] pub(crate) sound_list: Rc<Vec<(String, Rc<Audio>)>>,
#[collect(require_static)] pub(crate) costume_list: Rc<Vec<(String, Rc<Image>)>>,
#[collect(require_static)] pub(crate) costume: Option<Rc<Image>>,
#[collect(require_static)] pub(crate) state: C::EntityState,
#[collect(require_static)] pub(crate) alive: bool,
pub(crate) original: Option<Gc<'gc, RefLock<Entity<'gc, C, S>>>>,
pub(crate) fields: SymbolTable<'gc, C, S>,
}
impl<C: CustomTypes<S>, S: System<C>> fmt::Debug for Entity<'_, C, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -1341,7 +1341,7 @@ pub struct GlobalContext<'gc, C: CustomTypes<S>, S: System<C>> {
#[collect(require_static)] pub timer_start: u64,
#[collect(require_static)] pub proj_name: String,
pub globals: SymbolTable<'gc, C, S>,
pub entities: BTreeMap<String, Gc<'gc, RefLock<Entity<'gc, C, S>>>>,
pub entities: Vec<Gc<'gc, RefLock<Entity<'gc, C, S>>>>,
}
impl<'gc, C: CustomTypes<S>, S: System<C>> GlobalContext<'gc, C, S> {
pub fn from_init(mc: &Mutation<'gc>, init_info: &InitInfo, bytecode: Rc<ByteCode>, settings: Settings, system: Rc<S>) -> Self {
Expand Down Expand Up @@ -1381,7 +1381,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> GlobalContext<'gc, C, S> {
globals.define_or_redefine(global, Shared::Unique(get_value(value, &allocated_refs)));
}

let mut entities = BTreeMap::new();
let mut entities = Vec::with_capacity(init_info.entities.len());
for (i, entity_info) in init_info.entities.iter().enumerate() {
let mut fields = SymbolTable::default();
for (field, value) in entity_info.fields.iter() {
Expand Down Expand Up @@ -1431,7 +1431,7 @@ impl<'gc, C: CustomTypes<S>, S: System<C>> GlobalContext<'gc, C, S> {
let name = Rc::new(entity_info.name.clone());
let state = kind.into();

entities.insert(entity_info.name.clone(), Gc::new(mc, RefLock::new(Entity { alive: true, root: None, name, fields, sound_list, costume_list, costume, state })));
entities.push(Gc::new(mc, RefLock::new(Entity { alive: true, original: None, name, fields, sound_list, costume_list, costume, state })));
}

let proj_name = init_info.proj_name.clone();
Expand Down Expand Up @@ -1740,6 +1740,11 @@ pub trait CustomTypes<S: System<Self>>: 'static + Sized {
/// This type should be constructable from [`EntityKind`], which is used to initialize a new entity in the runtime.
type EntityState: 'static + for<'gc, 'a> From<EntityKind<'gc, 'a, Self, S>>;

/// Type used to represent a process's system-specific state.
/// This should include any details outside of core process functionality (e.g., external script-locals).
/// This type should be constructable from [`Entity`], which is used to initialize a new process in the runtime.
type ProcessState: 'static + for<'gc, 'a> From<&'a Entity<'gc, Self, S>>;

/// Converts a [`Value`] into a [`CustomTypes::Intermediate`] for use outside of gc context.
fn from_intermediate<'gc>(mc: &Mutation<'gc>, value: Self::Intermediate) -> Result<Value<'gc, Self, S>, ErrorCause<Self, S>>;
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ impl From<EntityKind<'_, '_, C, StdSystem<C>>> for EntityState {
}
}

struct ProcessState;
impl From<&Entity<'_, C, StdSystem<C>>> for ProcessState {
fn from(_: &Entity<'_, C, StdSystem<C>>) -> Self {
ProcessState
}
}

fn default_properties_config() -> Config<C, StdSystem<C>> {
Config {
request: Some(Rc::new(|_, _, key, request, entity| match request {
Expand All @@ -61,6 +68,7 @@ impl CustomTypes<StdSystem<C>> for C {
type Intermediate = SimpleValue;

type EntityState = EntityState;
type ProcessState = ProcessState;

fn from_intermediate<'gc>(mc: &Mutation<'gc>, value: Self::Intermediate) -> Result<Value<'gc, C, StdSystem<C>>, ErrorCause<C, StdSystem<C>>> {
Ok(Value::from_simple(mc, value))
Expand Down
Loading

0 comments on commit e979cd6

Please sign in to comment.