Skip to content

Commit 82ea923

Browse files
implement yielding
1 parent e410653 commit 82ea923

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+970
-393
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ If you experience runtime stack overflow errors in debug mode, try using the `-s
2828
To add a new block named `category_opcode`, if it cannot be reduced to simpler blocks:
2929
1. create `src/instructions/category/opcode.rs`. Make sure to `use super::super::prelude::*` and create the relevant `pub` items:
3030
- (optional) `pub struct Fields` (must be `Debug` and `Clone`)
31-
- `pub fn wasm(func: &StepFunc, inputs: Rc<[IrType]>, (fields: &Fields)?) -> HQResult<Vec<Instruction<'static>>>;`
31+
- `pub fn wasm(func: &StepFunc, inputs: Rc<[IrType]>, (fields: &Fields)?) -> HQResult<Vec<InternalInstruction>>;`
3232
- - wasm is generated using the `wasm_gen::wasm` macro. See [its README](./wasm-gen/README.md) for usage instructions, or e.g. [say.rs](./src/instructions/looks/say.rs) for an example.
3333
- `pub fn acceptable_inputs() -> Rc<[IrType]>;`
3434
- - these should really be base types (see BASE_TYPES in [types.rs](./src/ir/types.rs))

build.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,14 @@ fn main() {
3838
let fields_name =
3939
format!("{}_{}_fields", category, opcode).to_case(Case::Pascal);
4040
paths.push((
41-
format!("{}::{}", category, opcode),
41+
format!(
42+
"{}::{}",
43+
category,
44+
match opcode {
45+
"yield" | "loop" => format!("r#{opcode}"),
46+
_ => opcode.to_string(),
47+
}
48+
),
4249
format!("{}_{}", category, opcode,),
4350
fields,
4451
fields_name,
@@ -116,21 +123,28 @@ pub enum IrOpcode {{
116123
117124
impl IrOpcode {{
118125
/// maps an opcode to its acceptable input types
119-
pub fn acceptable_inputs(&self) -> Rc<[crate::ir::Type]> {{
126+
pub fn acceptable_inputs(&self) -> Rc<[crate::ir::Type]> {{
120127
match self {{
121128
{}
122129
}}
123130
}}
124131
125132
/// maps an opcode to its WASM instructions
126-
pub fn wasm(&self, step_func: &crate::wasm::StepFunc, inputs: Rc<[crate::ir::Type]>) -> HQResult<Vec<wasm_encoder::Instruction<'static>>> {{
133+
pub fn wasm(&self, step_func: &crate::wasm::StepFunc, inputs: Rc<[crate::ir::Type]>) -> HQResult<Vec<crate::wasm::InternalInstruction>> {{
127134
match self {{
128135
{}
129136
}}
130137
}}
131138
132139
/// maps an opcode to its output type
133-
pub fn output_type(&self, inputs: Rc<[crate::ir::Type]>) -> HQResult<Option<crate::ir::Type>> {{
140+
pub fn output_type(&self, inputs: Rc<[crate::ir::Type]>) -> HQResult<Option<crate::ir::Type>> {{
141+
match self {{
142+
{}
143+
}}
144+
}}
145+
146+
/// does this opcode request a screen refresh (and by extension yields)?
147+
pub const fn yields(&self) -> bool {{
134148
match self {{
135149
{}
136150
}}
@@ -170,6 +184,13 @@ pub use fields::*;
170184
format!("IrOpcode::{} => {}::output_type(inputs),", id, path)
171185
}
172186
}).collect::<Vec<_>>().join("\n\t\t\t"),
187+
paths.iter().map(|(path, id, fields, _)| {
188+
if *fields {
189+
format!("IrOpcode::{}(_) => {}::YIELDS,", id, path)
190+
} else {
191+
format!("IrOpcode::{} => {}::YIELDS,", id, path)
192+
}
193+
}).collect::<Vec<_>>().join("\n\t\t\t"),
173194
paths.iter().filter(|(_, _, fields, _)| *fields)
174195
.map(|(path, _, _, fields_name)|
175196
format!("pub use {}::Fields as {};", path, fields_name)

playground/views/HomeView.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ import ProjectInput from '../components/ProjectInput.vue'
5050
id: 1050568991,
5151
name: 'fibonacci benchmark',
5252
author: 'pufferfish_test',
53+
},
54+
{
55+
id: 1116438829,
56+
name: 'HQ test project 2.0',
57+
author: 'pufferfish_test'
5358
}
5459
];
5560
</script>

src/instructions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ include!(concat!(env!("OUT_DIR"), "/ir-opcodes.rs"));
1818
mod input_switcher;
1919
pub use input_switcher::wrap_instruction;
2020

21-
pub use hq::_yield::YieldMode;
21+
pub use hq::r#yield::YieldMode;
2222

2323
mod prelude {
2424
pub(crate) use crate::ir::Type as IrType;
2525
pub use crate::prelude::*;
26-
pub(crate) use crate::wasm::StepFunc;
27-
pub use wasm_encoder::{Instruction, RefType, ValType};
26+
pub(crate) use crate::wasm::{InternalInstruction, StepFunc};
27+
pub use wasm_encoder::{RefType, ValType};
2828
pub use wasm_gen::wasm;
2929

3030
/// Canonical NaN + bit 33, + string pointer in bits 1-32

src/instructions/control.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
pub mod _if;
2-
pub mod repeat;
1+
pub mod if_else;
2+
pub mod r#loop;

src/instructions/control/_if.rs

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/instructions/control/if_else.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use super::super::prelude::*;
2+
use crate::ir::Step;
3+
use wasm_encoder::BlockType;
4+
5+
#[derive(Clone, Debug)]
6+
pub struct Fields {
7+
pub branch_if: Rc<Step>,
8+
pub branch_else: Rc<Step>,
9+
}
10+
11+
pub fn wasm(
12+
func: &StepFunc,
13+
_inputs: Rc<[IrType]>,
14+
Fields {
15+
branch_if,
16+
branch_else,
17+
}: &Fields,
18+
) -> HQResult<Vec<InternalInstruction>> {
19+
let if_instructions = func.compile_inner_step(Rc::clone(branch_if))?;
20+
let else_instructions = func.compile_inner_step(Rc::clone(branch_else))?;
21+
let block_type = func
22+
.registries()
23+
.types()
24+
.register_default((vec![ValType::I32], vec![]))?;
25+
Ok(wasm![
26+
Block(BlockType::FunctionType(block_type)),
27+
Block(BlockType::FunctionType(block_type)),
28+
I32Eqz,
29+
BrIf(0)
30+
]
31+
.into_iter()
32+
.chain(if_instructions)
33+
.chain(wasm![Br(1), End,])
34+
.chain(else_instructions)
35+
.chain(wasm![End])
36+
.collect())
37+
}
38+
39+
pub fn acceptable_inputs(_fields: &Fields) -> Rc<[IrType]> {
40+
Rc::new([IrType::Boolean])
41+
}
42+
43+
pub fn output_type(_inputs: Rc<[IrType]>, _fields: &Fields) -> HQResult<Option<IrType>> {
44+
Ok(None)
45+
}
46+
47+
pub const YIELDS: bool = false;
48+
49+
// crate::instructions_test! {none; hq__if; @ super::Fields(None)}

src/instructions/control/loop.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// for use in warped contexts only.
2+
3+
use super::super::prelude::*;
4+
use crate::ir::Step;
5+
use wasm_encoder::BlockType;
6+
7+
#[derive(Clone, Debug)]
8+
pub struct Fields {
9+
pub first_condition: Option<Rc<Step>>,
10+
pub condition: Rc<Step>,
11+
pub body: Rc<Step>,
12+
}
13+
14+
pub fn wasm(
15+
func: &StepFunc,
16+
_inputs: Rc<[IrType]>,
17+
Fields {
18+
first_condition,
19+
condition,
20+
body,
21+
}: &Fields,
22+
) -> HQResult<Vec<InternalInstruction>> {
23+
let inner_instructions = func.compile_inner_step(Rc::clone(body))?;
24+
let first_condition_instructions = func.compile_inner_step(Rc::clone(
25+
&first_condition.clone().unwrap_or(Rc::clone(condition)),
26+
))?;
27+
let condition_instructions = func.compile_inner_step(Rc::clone(condition))?;
28+
Ok(wasm![Block(BlockType::Empty),]
29+
.into_iter()
30+
.chain(first_condition_instructions)
31+
.chain(wasm![I32Eqz, BrIf(0), Loop(BlockType::Empty)])
32+
.chain(inner_instructions)
33+
.chain(condition_instructions)
34+
.chain(wasm![BrIf(0), End, End])
35+
.collect())
36+
}
37+
38+
pub fn acceptable_inputs(_fields: &Fields) -> Rc<[IrType]> {
39+
Rc::new([])
40+
}
41+
42+
pub fn output_type(_inputs: Rc<[IrType]>, _fields: &Fields) -> HQResult<Option<IrType>> {
43+
Ok(None)
44+
}
45+
46+
pub const YIELDS: bool = false;
47+
48+
// crate::instructions_test! {none; hq_repeat; @ super::Fields(None)}

src/instructions/control/repeat.rs

Lines changed: 0 additions & 45 deletions
This file was deleted.

src/instructions/data.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod setvariableto;
2+
pub mod teevariable;
23
pub mod variable;

src/instructions/data/setvariableto.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub fn wasm(
88
func: &StepFunc,
99
inputs: Rc<[IrType]>,
1010
Fields(variable): &Fields,
11-
) -> HQResult<Vec<Instruction<'static>>> {
11+
) -> HQResult<Vec<InternalInstruction>> {
1212
let global_index: u32 = func
1313
.registries()
1414
.variables()
@@ -36,6 +36,8 @@ pub fn output_type(_inputs: Rc<[IrType]>, _fields: &Fields) -> HQResult<Option<I
3636
Ok(None)
3737
}
3838

39+
pub const YIELDS: bool = false;
40+
3941
crate::instructions_test!(
4042
any;
4143
data_setvariableto;

0 commit comments

Comments
 (0)