diff --git a/src/ir.rs b/src/ir.rs index 1bf1b9f..2ec435c 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -411,7 +411,6 @@ impl IrOpcode { | math_positive_number { .. } => BlockDescriptor::new(vec![], Number), data_variable { .. } => BlockDescriptor::new(vec![], Any), data_setvariableto { .. } => BlockDescriptor::new(vec![Any], Stack), - //data_changevariableby { .. } => BlockDescriptor::new(vec![Number], Stack), text { .. } => BlockDescriptor::new(vec![], Text), operator_lt | operator_gt => BlockDescriptor::new(vec![Number, Number], Boolean), operator_equals | operator_contains => BlockDescriptor::new(vec![Any, Any], Boolean), @@ -489,7 +488,7 @@ impl Step { pub struct ThreadContext { pub target_index: u32, pub dbg: bool, - pub vars: Rc>, // hopefully there can't be two variables with the same id in differwnt sprites, otherwise this will break horrendously + pub vars: Rc>, // todo: fix variable id collisions between targets } #[derive(Debug, Clone, PartialEq)] @@ -637,7 +636,6 @@ impl IrBlockVec for Vec { let block = blocks.get(&block_id).unwrap(); match block { Block::Normal { block_info, .. } => { - //println!("{}: {:?}", &block_id, &block_info.opcode); self.add_inputs(&block_info.inputs, blocks, Rc::clone(&context), steps); self.append(&mut (match block_info.opcode { @@ -733,32 +731,26 @@ impl IrBlockVec for Vec { BlockOpcode::control_repeat => vec![IrOpcode::hq_drop(1)], BlockOpcode::control_repeat_until => { 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") }; + let condition_opcodes = vec![ + IrOpcode::hq_goto_if { step: Some(block_info.next.clone().unwrap()), does_yield: false }.into(), + IrOpcode::hq_goto { step: Some(substack_id.clone()), does_yield: false }.into(), + ]; let looper_id = block_id.clone() + &mut block_id.clone(); if !steps.contains_key(&looper_id) { let mut looper_opcodes = vec![]; looper_opcodes.add_inputs(&block_info.inputs, blocks, Rc::clone(&context), steps); - looper_opcodes.append(&mut vec![ - IrOpcode::hq_goto_if { step: Some(block_info.next.clone().unwrap()), does_yield: false }.into(), - IrOpcode::hq_goto { step: Some(substack_id.clone()), does_yield: false }.into(), - ]); + looper_opcodes.append(&mut condition_opcodes.clone()); looper_opcodes.fixup_types(); steps.insert(looper_id.clone(), Step::new(looper_opcodes, Rc::clone(&context))); } - step_from_top_block(block_info.next.clone().unwrap(), last_nexts.clone(), blocks, Rc::clone(&context), steps); - step_from_top_block(substack_id.clone(), vec![looper_id], blocks, Rc::clone(&context), steps); + step_from_top_block(block_info.next.clone().unwrap(), last_nexts, blocks, Rc::clone(&context), steps); + step_from_top_block(substack_id, vec![looper_id], blocks, Rc::clone(&context), steps); let mut opcodes = vec![]; opcodes.add_inputs(&block_info.inputs, blocks, Rc::clone(&context), steps); - opcodes.append(&mut vec![ - IrOpcode::hq_goto_if { step: Some(block_info.next.clone().unwrap()), does_yield: false }.into(), - IrOpcode::hq_goto { step: Some(substack_id.clone()), does_yield: false }.into(), - ]); + opcodes.append(&mut condition_opcodes.clone()); opcodes.fixup_types(); steps.insert(block_id.clone(), Step::new(opcodes.clone(), Rc::clone(&context))); - //step_from_top_block(block_id.clone(), last_nexts.clone(), blocks, Rc::clone(&context), steps); - vec![ - IrOpcode::hq_goto_if { step: Some(block_info.next.clone().unwrap()), does_yield: false }.into(), - IrOpcode::hq_goto { step: Some(substack_id.clone()), does_yield: false }.into(), - ] + condition_opcodes.into_iter().map(|block| block.opcode().clone()).collect::<_>() } _ => todo!(), }).into_iter().map(IrBlock::from).collect()); diff --git a/src/targets/wasm.rs b/src/targets/wasm.rs index c7d6af9..894b360 100644 --- a/src/targets/wasm.rs +++ b/src/targets/wasm.rs @@ -17,7 +17,6 @@ use wasm_encoder::{ fn instructions( op: &IrBlock, context: Rc, - _step_funcs: &mut IndexMap, Function, BuildHasherDefault>, string_consts: &mut Vec, steps: &IndexMap>, ) -> Vec> { @@ -248,7 +247,6 @@ fn instructions( } => { let _next_step = steps.get(next_step_id).unwrap(); let next_step_index = steps.get_index_of(next_step_id).unwrap(); - //(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)"); @@ -274,7 +272,6 @@ fn instructions( } => { let _next_step = steps.get(next_step_id).unwrap(); let next_step_index = steps.get_index_of(next_step_id).unwrap(); - //(next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps); vec![ LocalGet(step_func_locals::MEM_LOCATION), I32Const( @@ -298,7 +295,7 @@ fn instructions( vec![ I32WrapI64, - If(WasmBlockType::Empty), //WasmBlockType::FunctionType(types::NOPARAM_I32)), + If(WasmBlockType::Empty), LocalGet(0), I32Const(byte_offset::THREADS), I32Add, // destination (= current thread pos in memory) @@ -352,13 +349,12 @@ fn instructions( } => { let _next_step = steps.get(next_step_id).unwrap(); let next_step_index = steps.get_index_of(next_step_id).unwrap(); - //(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)"); vec![ I32WrapI64, - If(WasmBlockType::Empty), //WasmBlockType::FunctionType(types::NOPARAM_I32)), + If(WasmBlockType::Empty), LocalGet(0), I32Const( next_step_index @@ -381,10 +377,9 @@ fn instructions( } => { let _next_step = steps.get(next_step_id).unwrap(); let next_step_index = steps.get_index_of(next_step_id).unwrap(); - //(next_step_id, next_step).compile_wasm(step_funcs, string_consts, steps); vec![ I32WrapI64, - If(WasmBlockType::Empty), //WasmBlockType::FunctionType(types::NOPARAM_I32)), + If(WasmBlockType::Empty), LocalGet(step_func_locals::MEM_LOCATION), I32Const( next_step_index @@ -477,7 +472,7 @@ impl CompileToWasm for (&String, &Step) { ]; let mut func = Function::new_with_locals_types(locals); for op in self.1.opcodes() { - let instrs = instructions(op, self.1.context(), step_funcs, string_consts, steps); + let instrs = instructions(op, self.1.context(), string_consts, steps); for instr in instrs { func.instruction(&instr); } @@ -519,7 +514,7 @@ pub mod func_indices { pub const DBG_ASSERT: u32 = 1; pub const LOOKS_SAY: u32 = 2; pub const LOOKS_THINK: u32 = 3; - pub const CAST_PRIMITIVE_FLOAT_STRING: u32 = 4; // js functions can only rwturm 1 value so need wrapper functions for casting + pub const CAST_PRIMITIVE_FLOAT_STRING: u32 = 4; // js functions can only return 1 value so need wrapper functions for casting pub const CAST_PRIMITIVE_STRING_FLOAT: u32 = 5; pub const CAST_PRIMITIVE_STRING_BOOL: u32 = 6; pub const DBG_LOGI32: u32 = 7; @@ -987,7 +982,7 @@ impl From for WebWasmFile { for step in &project.steps { // make sure to skip the 0th (noop) step because we've added the noop step function 3 lines above - if step.0 == "" { + if step.0.is_empty() { continue; }; step.compile_wasm(&mut step_funcs, &mut string_consts, &project.steps); @@ -1357,7 +1352,8 @@ mod tests { let ir: IrProject = proj.into(); let wasm: WebWasmFile = ir.into(); fs::write("./bad.wasm", wasm.wasm_bytes()).expect("failed to write to bad.wasm"); - fs::write("./bad.mjs", format!("export default {};", wasm.js_string())).expect("failed to write to bad.js"); + fs::write("./bad.mjs", format!("export default {};", wasm.js_string())) + .expect("failed to write to bad.js"); let output = Command::new("node") .arg("-e") .arg(format!("({})().catch(console.error)", wasm.js_string()))