Skip to content

Commit

Permalink
reference steps by ids and not Rcs
Browse files Browse the repository at this point in the history
  • Loading branch information
pufferfish101007 committed Aug 22, 2023
1 parent 438c831 commit b348667
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 56 deletions.
82 changes: 47 additions & 35 deletions src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct IrProject {
pub threads: Vec<Thread>,
pub vars: Rc<Vec<IrVar>>,
pub targets: Vec<String>,
pub steps: BTreeMap<String, Step>,
}

impl From<Sb3Project> for IrProject {
Expand All @@ -32,7 +33,8 @@ impl From<Sb3Project> for IrProject {
})
.collect(),
);


let mut steps: BTreeMap<String, Step> = Default::default();
let mut threads: Vec<Thread> = vec![];
for (target_index, target) in sb3.targets.iter().enumerate() {
for (id, block) in
Expand All @@ -56,7 +58,7 @@ impl From<Sb3Project> for IrProject {
}),
vars: Rc::clone(&vars),
});
let thread = Thread::from_hat(block.clone(), target.blocks.clone(), context);
let thread = Thread::from_hat(block.clone(), target.blocks.clone(), context, &mut steps);
threads.push(thread);
}
}
Expand All @@ -69,6 +71,7 @@ impl From<Sb3Project> for IrProject {
vars,
threads,
targets,
steps,
}
}
}
Expand Down Expand Up @@ -137,11 +140,11 @@ pub enum IrOpcode {
event_whenbroadcastreceived,
hq_drop(usize),
hq_goto {
step: Option<Rc<Step>>,
step: Option<String>,
does_yield: bool,
},
hq_goto_if {
step: Option<Rc<Step>>,
step: Option<String>,
does_yield: bool,
},
looks_say,
Expand Down Expand Up @@ -474,7 +477,7 @@ pub struct ThreadContext {
#[derive(Debug, Clone, PartialEq)]
pub struct Thread {
start: ThreadStart,
first_step: Rc<Step>,
first_step: String,
}

trait IrBlockVec {
Expand All @@ -484,6 +487,7 @@ trait IrBlockVec {
blocks: &BTreeMap<String, Block>,
context: Rc<ThreadContext>,
last_nexts: Vec<String>,
steps: &mut BTreeMap<String, Step>,
);
fn add_block_arr(&mut self, block_arr: &BlockArray);
}
Expand Down Expand Up @@ -544,6 +548,7 @@ impl IrBlockVec for Vec<IrBlock> {
blocks: &BTreeMap<String, Block>,
context: Rc<ThreadContext>,
last_nexts: Vec<String>,
steps: &mut BTreeMap<String, Step>,
) {
let block = blocks.get(&block_id).unwrap();
match block {
Expand All @@ -563,6 +568,7 @@ impl IrBlockVec for Vec<IrBlock> {
blocks,
Rc::clone(&context),
last_nexts.clone(), // this probably isn't needed bc inputs donpt have a next? passing an empty vec would save some memory and overhead
steps,
);
}
BlockArrayOrId::Array(arr) => {
Expand Down Expand Up @@ -648,7 +654,9 @@ impl IrBlockVec for Vec<IrBlock> {
if let Some(ref next) = block_info.next {
new_nexts.push(next.clone());
}
vec![IrOpcode::hq_goto_if { step: Some(step_from_top_block(substack_id, new_nexts, blocks, Rc::clone(&context))), does_yield: false, }, IrOpcode::hq_goto { step: if block_info.next.is_some() { Some(step_from_top_block(block_info.next.clone().unwrap(), last_nexts, blocks, Rc::clone(&context))) } else { None }, does_yield: false, }]
step_from_top_block(substack_id.clone(), new_nexts, blocks, Rc::clone(&context), steps);
step_from_top_block(block_info.next.clone().unwrap(), last_nexts, blocks, Rc::clone(&context), steps);
vec![IrOpcode::hq_goto_if { step: Some(substack_id), does_yield: false, }, IrOpcode::hq_goto { step: if block_info.next.is_some() { Some(block_info.next.clone().unwrap()) } else { None }, does_yield: false, }]
}
BlockOpcode::control_if_else => {
let substack_id = if let BlockArrayOrId::Id(id) = block_info.inputs.get("SUBSTACK").expect("missing SUBSTACK input for control_if").get_1().unwrap().clone().unwrap() { id } else { panic!("malformed SUBSTACK input") };
Expand All @@ -657,7 +665,9 @@ impl IrBlockVec for Vec<IrBlock> {
if let Some(ref next) = block_info.next {
new_nexts.push(next.clone());
}
vec![IrOpcode::hq_goto_if { step: Some(step_from_top_block(substack_id, new_nexts.clone(), blocks, Rc::clone(&context))), does_yield: false, }, IrOpcode::hq_goto { step: Some(step_from_top_block(substack2_id, new_nexts.clone(), blocks, Rc::clone(&context))), does_yield: false, }]
step_from_top_block(substack_id.clone(), new_nexts.clone(), blocks, Rc::clone(&context), steps);
step_from_top_block(substack2_id.clone(), new_nexts.clone(), blocks, Rc::clone(&context), steps);
vec![IrOpcode::hq_goto_if { step: Some(substack_id), does_yield: false, }, IrOpcode::hq_goto { step: Some(substack2_id), does_yield: false, }]
}
BlockOpcode::control_repeat => vec![IrOpcode::hq_drop(1)],
BlockOpcode::control_repeat_until => vec![IrOpcode::hq_drop(1)],
Expand All @@ -669,21 +679,26 @@ impl IrBlockVec for Vec<IrBlock> {
}
}

pub fn step_from_top_block(
pub fn step_from_top_block<'a>(
top_id: String,
mut last_nexts: Vec<String>,
blocks: &BTreeMap<String, Block>,
context: Rc<ThreadContext>,
) -> Rc<Step> {
steps: &'a mut BTreeMap<String, Step>,
) -> &'a Step {
if steps.contains_key(&top_id) {
return steps.get(&top_id).unwrap();
}
let mut ops: Vec<IrBlock> = vec![];
let mut next_block = blocks.get(&top_id).unwrap();
let mut next_id = Some(top_id);
let mut next_id = Some(top_id.clone());
loop {
ops.add_block(
next_id.clone().unwrap(),
blocks,
Rc::clone(&context),
last_nexts.clone(),
steps,
);
if next_block.block_info().unwrap().next.is_none() {
next_id = last_nexts.pop();
Expand Down Expand Up @@ -736,47 +751,44 @@ pub fn step_from_top_block(
.set_expected_output(ty.clone());
}
let mut step = Step::new(ops.clone(), Rc::clone(&context));
step.opcodes_mut()
.push(if let Some(ref id) = next_id {
IrBlock::from(IrOpcode::hq_goto {
step: Some(Rc::clone(&step_from_top_block(
id.clone(),
last_nexts,
blocks,
Rc::clone(&context),
))),
does_yield: true,
})
} else {
IrBlock::from(IrOpcode::hq_goto {
step: None,
does_yield: false,
})
});
Rc::from(step)
step.opcodes_mut().push(if let Some(ref id) = next_id {
step_from_top_block(id.clone(), last_nexts, blocks, Rc::clone(&context), steps);
IrBlock::from(IrOpcode::hq_goto {
step: Some(id.clone()),
does_yield: true,
})
} else {
IrBlock::from(IrOpcode::hq_goto {
step: None,
does_yield: false,
})
});
steps.insert(top_id.clone(), step);
steps.get(&top_id).unwrap()
}

impl Thread {
pub fn new(start: ThreadStart, first_step: Rc<Step>) -> Thread {
pub fn new(start: ThreadStart, first_step: String) -> Thread {
Thread {
start,
first_step: Rc::clone(&first_step),
first_step,
}
}
pub fn start(&self) -> &ThreadStart {
&self.start
}
pub fn first_step(&self) -> Rc<Step> {
Rc::clone(&self.first_step)
pub fn first_step(&self) -> &String {
&self.first_step
}
pub fn from_hat(
hat: Block,
blocks: BTreeMap<String, Block>,
context: Rc<ThreadContext>,
steps: &mut BTreeMap<String, Step>,
) -> Thread {
let first_step = if let Block::Normal { block_info, .. } = &hat {
let (first_step_id, _first_step) = if let Block::Normal { block_info, .. } = &hat {
if let Some(next_id) = &block_info.next {
step_from_top_block(next_id.clone(), vec![], &blocks, Rc::clone(&context))
(next_id.clone(), step_from_top_block(next_id.clone(), vec![], &blocks, Rc::clone(&context), steps))
} else {
unreachable!();
}
Expand All @@ -791,7 +803,7 @@ impl Thread {
} else {
unreachable!()
};
Self::new(start_type, first_step)
Self::new(start_type, first_step_id)
}
}

Expand Down
50 changes: 29 additions & 21 deletions src/targets/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use wasm_encoder::{
fn instructions(
op: &IrBlock,
context: Rc<ThreadContext>,
step_funcs: &mut IndexMap<Option<Rc<Step>>, Function, BuildHasherDefault<FNV1aHasher64>>,
step_funcs: &mut IndexMap<Option<String>, Function, BuildHasherDefault<FNV1aHasher64>>,
string_consts: &mut Vec<String>,
steps: &BTreeMap<String, Step>,
) -> Vec<Instruction<'static>> {
use Instruction::*;
use IrBlockType::*;
Expand Down Expand Up @@ -192,8 +193,9 @@ fn instructions(
step,
does_yield: true,
} => {
if let Some(next_step) = step {
let next_step_index = next_step.compile_wasm(step_funcs, string_consts);
if let Some(next_step_id) = step {
let next_step = steps.get(next_step_id).unwrap();
let next_step_index = (next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps);
let thread_indices: u64 = byte_offset::THREADS
.try_into()
.expect("THREAD_INDICES out of bounds (E018)");
Expand Down Expand Up @@ -271,8 +273,9 @@ fn instructions(
step,
does_yield: false,
} => {
if let Some(next_step) = step {
let next_step_index = next_step.compile_wasm(step_funcs, string_consts);
if let Some(next_step_id) = step {
let next_step = steps.get(next_step_id).unwrap();
let next_step_index = (next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps);
vec![
LocalGet(step_func_locals::MEM_LOCATION),
I32Const(
Expand Down Expand Up @@ -345,8 +348,9 @@ fn instructions(
step,
does_yield: true,
} => {
if let Some(next_step) = step {
let next_step_index = next_step.compile_wasm(step_funcs, string_consts);
if let Some(next_step_id) = step {
let next_step = steps.get(next_step_id).unwrap();
let next_step_index = (next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps);
let thread_indices: u64 = byte_offset::THREADS
.try_into()
.expect("THREAD_INDICES out of bounds (E018)");
Expand Down Expand Up @@ -430,8 +434,9 @@ fn instructions(
step,
does_yield: false,
} => {
if let Some(next_step) = step {
let next_step_index = next_step.compile_wasm(step_funcs, string_consts);
if let Some(next_step_id) = step {
let next_step = steps.get(next_step_id).unwrap();
let next_step_index = (next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps);
vec![
I32WrapI64,
If(WasmBlockType::Empty), //WasmBlockType::FunctionType(types::NOPARAM_I32)),
Expand Down Expand Up @@ -555,30 +560,33 @@ fn instructions(
pub trait CompileToWasm {
fn compile_wasm(
&self,
step_funcs: &mut IndexMap<Option<Rc<Step>>, Function, BuildHasherDefault<FNV1aHasher64>>,
step_funcs: &mut IndexMap<Option<String>, Function, BuildHasherDefault<FNV1aHasher64>>,
string_consts: &mut Vec<String>,
steps: &BTreeMap<String, Step>,
) -> u32;
}

impl CompileToWasm for Thread {
fn compile_wasm(
&self,
step_funcs: &mut IndexMap<Option<Rc<Step>>, Function, BuildHasherDefault<FNV1aHasher64>>,
step_funcs: &mut IndexMap<Option<String>, Function, BuildHasherDefault<FNV1aHasher64>>,
string_consts: &mut Vec<String>,
steps: &BTreeMap<String, Step>,
) -> u32 {
self.first_step().compile_wasm(step_funcs, string_consts)
(self.first_step(), steps.get(self.first_step()).unwrap()).compile_wasm(step_funcs, string_consts, steps)
}
}

impl CompileToWasm for Rc<Step> {
impl CompileToWasm for (&String, &Step) {
fn compile_wasm(
&self,
step_funcs: &mut IndexMap<Option<Rc<Step>>, Function, BuildHasherDefault<FNV1aHasher64>>,
step_funcs: &mut IndexMap<Option<String>, Function, BuildHasherDefault<FNV1aHasher64>>,
string_consts: &mut Vec<String>,
steps: &BTreeMap<String, Step>,
) -> u32 {
if step_funcs.contains_key(&Some(Rc::clone(self))) {
if step_funcs.contains_key(&Some(self.0.clone())) {
return step_funcs
.get_index_of(&Some(Rc::clone(self)))
.get_index_of(&Some(self.0.clone()))
.unwrap()
.try_into()
.expect("IndexMap index out of bounds");
Expand All @@ -591,14 +599,14 @@ impl CompileToWasm for Rc<Step> {
ValType::I32,
];
let mut func = Function::new_with_locals_types(locals);
for op in self.opcodes() {
let instrs = instructions(op, self.context(), step_funcs, string_consts);
for op in self.1.opcodes() {
let instrs = instructions(op, self.1.context(), step_funcs, string_consts, steps);
for instr in instrs {
func.instruction(&instr);
}
}
func.instruction(&Instruction::End);
step_funcs.insert(Some(Rc::clone(self)), func);
step_funcs.insert(Some(self.0.clone()), func);
(step_funcs.len() - 1)
.try_into()
.expect("step_funcs length out of bounds")
Expand Down Expand Up @@ -1097,11 +1105,11 @@ impl From<IrProject> for WebWasmFile {

let mut string_consts = vec![String::from("false"), String::from("true")];

let mut step_funcs: IndexMap<Option<Rc<Step>>, Function, _> = Default::default();
let mut step_funcs: IndexMap<Option<String>, Function, _> = Default::default();
step_funcs.insert(None, noop_func);

for thread in project.threads {
let first_idx = thread.compile_wasm(&mut step_funcs, &mut string_consts);
let first_idx = thread.compile_wasm(&mut step_funcs, &mut string_consts, &project.steps);
thread_indices.push((thread.start().clone(), first_idx));
}

Expand Down

0 comments on commit b348667

Please sign in to comment.