Skip to content

Commit

Permalink
make nested loops work
Browse files Browse the repository at this point in the history
  • Loading branch information
x86y committed Oct 1, 2023
1 parent 06bee05 commit 4747133
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 42 deletions.
5 changes: 4 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@
<textarea id="inputVal" placeholder="Write rust code here">
fn main() {
for i in 0..5 {
println!("For loop");
println!("Out");
for i in 0..15 {
println!("In");
}
}
loop {
println!("Forever loop");
Expand Down
Binary file modified pkg/lib_bg.wasm
Binary file not shown.
86 changes: 45 additions & 41 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use wasm_bindgen::prelude::wasm_bindgen;
use quote::quote;
use syn::parse_quote;
use syn::{ItemFn, Stmt};
Expand Down Expand Up @@ -247,53 +248,56 @@ pub const T: bool = true;
pub const F: bool = false;
pub type Sstr = &'static str;

use wasm_bindgen::prelude::*;
pub fn transform_loop_with_macro(item: ItemFn) -> ItemFn {
let mut transformed_stmts = Vec::new();

for stmt in &item.block.stmts {
match stmt {
// For range loop: for i in 0..x { ... }
Stmt::Expr(syn::Expr::ForLoop(loop_expr), _) => {
if let syn::Expr::Range(range_expr) = &*loop_expr.expr {
if let (syn::Expr::Lit(start), syn::Expr::Lit(end)) = (
range_expr.start.clone().unwrap().as_ref(),
range_expr.end.clone().unwrap().as_ref(),
) {
let loop_body = &loop_expr.body;
let start_val = if let syn::Lit::Int(val) = &start.lit {
val.base10_parse::<usize>().unwrap()
} else {
0
};
let end_val = if let syn::Lit::Int(val) = &end.lit {
val.base10_parse::<usize>().unwrap()
} else {
0
};
let times = end_val - start_val;
let new_stmt: Stmt = parse_quote! { DO!(#loop_body, #times); };
transformed_stmts.push(new_stmt);
}
fn transform_stmt(stmt: &Stmt) -> Vec<Stmt> {
match stmt {
Stmt::Expr(syn::Expr::ForLoop(loop_expr), _) => {
if let syn::Expr::Range(range_expr) = &*loop_expr.expr {
if let (syn::Expr::Lit(start), syn::Expr::Lit(end)) = (
range_expr.start.clone().unwrap().as_ref(),
range_expr.end.clone().unwrap().as_ref(),
) {
let loop_body = &loop_expr.body;
let start_val = if let syn::Lit::Int(val) = &start.lit {
val.base10_parse::<usize>().unwrap_or(0)
} else {
0
};
let end_val = if let syn::Lit::Int(val) = &end.lit {
val.base10_parse::<usize>().unwrap_or(0)
} else {
0
};
let times = end_val - start_val;
let new_body = transform_block(loop_body);
return vec![parse_quote! { DO!(#new_body, #times); }];
}
}
// Unconditional loop: loop { ... }
Stmt::Expr(syn::Expr::Loop(loop_expr), _) => {
let loop_body = &loop_expr.body;
let new_stmt: Stmt = parse_quote! { DO!(#loop_body); };
transformed_stmts.push(new_stmt);
}
_ => {
transformed_stmts.push(stmt.clone());
}
}
Stmt::Expr(syn::Expr::Loop(loop_expr), _) => {
let new_body = transform_block(&loop_expr.body);
return vec![parse_quote! { DO!(#new_body); }];
}
_ => return vec![stmt.clone()],
}
vec![]
}

fn transform_block(block: &syn::Block) -> syn::Block {
let mut transformed_stmts = Vec::new();
for stmt in &block.stmts {
transformed_stmts.extend(transform_stmt(stmt));
}

syn::Block {
stmts: transformed_stmts,
..block.clone()
}
}

pub fn transform_loop_with_macro(item: ItemFn) -> ItemFn {
let transformed_block = transform_block(&item.block);
ItemFn {
block: Box::new(syn::Block {
stmts: transformed_stmts,
brace_token: item.block.brace_token,
}),
block: Box::new(transformed_block),
..item
}
}
Expand Down

0 comments on commit 4747133

Please sign in to comment.