Skip to content

Commit 5d4c13c

Browse files
committed
Add var value
- this is actually a constant, so the function parameter case is a bit contrived
1 parent 37a41fa commit 5d4c13c

3 files changed

Lines changed: 34 additions & 27 deletions

File tree

src/ast.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,25 @@ use crate::token::Tokenizer;
55
use std::iter::Peekable;
66

77
pub struct Bindings {
8-
vars: Vec<String>,
8+
vars: Vec<(String, i32)>,
99
}
1010

1111
impl Bindings {
1212
pub fn new() -> Self {
1313
Self { vars: Vec::new(), }
1414
}
1515

16-
pub fn add_var(&mut self, var: &str) {
17-
self.vars.push(var.into());
16+
pub fn add_var(&mut self, var: &str, value: i32) {
17+
self.vars.push((var.into(), value));
1818
}
1919

2020
fn get_index(&self, var: &str) -> Option<usize> {
21-
self.vars.iter().position(|v| v == var)
21+
self.vars.iter().position(|(v,_)| v == var)
22+
}
23+
24+
fn get_value(&self, var: &str) -> Option<i32> {
25+
let tuple = self.vars.iter().find(|(v,_)| v == var)?;
26+
Some(tuple.1)
2227
}
2328
}
2429

@@ -180,7 +185,7 @@ impl ToWasm for Factor {
180185
},
181186
Self::Param(p) => {
182187
let mut out = vec![0x20]; // local.get
183-
if let Some(index) = bindings.get_index(&p) {
188+
if let Some(index) = bindings.get_index(p) {
184189
write_leb128(index as i128, &mut out);
185190
} else {
186191
panic!("Unknown binding for local '{p}'");
@@ -255,24 +260,24 @@ fn test_parse() {
255260
assert_eq!(compile("variable"), "local.get $variable");
256261
}
257262

258-
pub fn add_fluff(expr_wat: &str) -> String {
259-
let mut wat = r#"
263+
pub fn generate_wat(expr_wat: &str, bindings: &Bindings) -> String {
264+
let mut wat = format!(r#"
260265
(module
261266
(import "host" "log" (func $host_log (param i32)))
262267
(func (export "calc") (result i32)
263268
i32.const 123 ;; <-- Closure `param`
264269
call $host_log
265270
266-
i32.const 7 ;; <-- WASM function param `$x`
267-
i32.const 9 ;; <-- WASM function param `$yy`
271+
i32.const {} ;; <-- WASM function param `$x`
272+
i32.const {} ;; <-- WASM function param `$yy`
268273
call $eval_expr
269274
return)
270-
"#.to_string();
275+
"#, bindings.get_value("x").unwrap(), bindings.get_value("yy").unwrap());
271276

272277
wat.push_str("(func $eval_expr (param $x i32) (param $yy i32) (result i32)");
273278
wat.push_str(expr_wat);
274279
wat.push_str(" return)");
275-
wat.push_str(")");
280+
wat.push(')');
276281
wat
277282
}
278283

@@ -365,8 +370,8 @@ pub fn generate_wasm(expr: &impl ToWasm, bindings: &Bindings) -> Vec<u8> {
365370
0x00, // localdeclcount(0)
366371
0x41, 0xfb, 0x00, // i32.const 123
367372
0x10, 0x00, // call function index=0 (host_log)
368-
0x41, 0x07, // i32.const 7
369-
0x41, 0x09, // i32.const 9
373+
0x41, bindings.get_value("x").unwrap() as u8, // i32.const 7
374+
0x41, bindings.get_value("yy").unwrap() as u8, // i32.const 9
370375
0x10, 0x02, // call function index=2 (eval_expr)
371376
0x0f, // return
372377
0x0b, // end

src/main.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod ast;
22
mod token;
33

4-
use crate::ast::{Expr, add_fluff, Bindings, generate_wasm};
4+
use crate::ast::{Expr, Bindings, generate_wat, generate_wasm};
55
use crate::token::Tokenizer;
66

77
use wasmtime::{Caller, Engine, Func, Instance, Module, Result, Store};
@@ -10,9 +10,12 @@ use wasmtime::{Caller, Engine, Func, Instance, Module, Result, Store};
1010
fn test_eval() {
1111
fn evaluate(s: &str) -> i32 {
1212
let expr = Expr::parse(&mut Tokenizer::from_str(s).peekable());
13+
let mut bindings = Bindings::new();
14+
bindings.add_var("x", 7);
15+
bindings.add_var("yy", 9);
1316
eprintln!("{}", expr.to_wat());
1417
// eval_wat(&expr).expect("Failed to evaluate")
15-
eval_wasm(&expr).expect("Failed to evaluate")
18+
eval_wasm(&expr, &bindings).expect("Failed to evaluate")
1619
}
1720
assert_eq!(evaluate("1+2+3+4+5+6+7+8+9"), 45);
1821
assert_eq!(evaluate("1*2*3*4*5*6*7*8*9"), 362880);
@@ -25,9 +28,8 @@ fn test_eval() {
2528
assert_eq!(evaluate("100/3"), 33);
2629
}
2730

28-
fn eval_wat(expr: &Expr) -> Result<i32> {
29-
let wat = add_fluff(&expr.to_wat()); // wrap raw WAT in Module
30-
31+
fn eval_wat(expr: &Expr, bindings: &Bindings) -> Result<i32> {
32+
let wat = generate_wat(&expr.to_wat(), bindings); // wrap raw WAT in Module
3133
let engine = Engine::default();
3234
let module = Module::new(&engine, wat)?;
3335

@@ -46,11 +48,8 @@ fn eval_wat(expr: &Expr) -> Result<i32> {
4648
calc.call(&mut store, ())
4749
}
4850

49-
fn eval_wasm(expr: &Expr) -> Result<i32>{
50-
let mut bindings = Bindings::new();
51-
bindings.add_var("x");
52-
bindings.add_var("yy");
53-
let wasm = generate_wasm(expr, &bindings);
51+
fn eval_wasm(expr: &Expr, bindings: &Bindings) -> Result<i32> {
52+
let wasm = generate_wasm(expr, bindings);
5453
let engine = Engine::default();
5554
let module = Module::new(&engine, wasm)?;
5655

@@ -71,16 +70,19 @@ fn eval_wasm(expr: &Expr) -> Result<i32>{
7170

7271
fn main() -> Result<()> {
7372
let args = std::env::args();
73+
let mut bindings = Bindings::new();
74+
bindings.add_var("x", 7);
75+
bindings.add_var("yy", 42);
7476
for arg in args.skip(1) {
7577
println!();
7678
println!("Expression:\t{arg}");
7779
let tokens: Vec<_> = Tokenizer::from_str(&arg).collect();
7880
println!("Tokenized:\t{tokens:?}");
7981
let expr = Expr::parse(&mut tokens.into_iter().peekable());
8082
println!("WASM Text:\t{}", expr.to_wat().replace('\n', "\n\t\t"));
81-
let result = eval_wat(&expr)?;
83+
let result = eval_wat(&expr, &bindings)?;
8284
println!("Text result:\t{result}");
83-
let result = eval_wasm(&expr)?;
85+
let result = eval_wasm(&expr, &bindings)?;
8486
println!("Binary result:\t{result}");
8587
}
8688

src/token.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl<'a> Iterator for Tokenizer<'a> {
3131
'0'..='9' => {
3232
let mut v = c.to_digit(10).unwrap() as i32;
3333
while let Some(&c) = self.chars.peek() {
34-
if !('0'..='9').contains(&c) { break; }
34+
if !c.is_ascii_digit() { break; }
3535
self.chars.next();
3636
v = v * 10 + c.to_digit(10).unwrap() as i32;
3737
}
@@ -40,7 +40,7 @@ impl<'a> Iterator for Tokenizer<'a> {
4040
'a'..='z' => {
4141
let mut v = c.to_string();
4242
while let Some(&c) = self.chars.peek() {
43-
if !('a'..='z').contains(&c) { break; }
43+
if !c.is_ascii_lowercase() { break; }
4444
self.chars.next();
4545
v += &c.to_string();
4646
}

0 commit comments

Comments
 (0)