1
+ use clap:: { Parser , Subcommand } ;
1
2
use derive_more:: From ;
2
3
use eyre:: Result ;
3
4
use openvm_sdk:: { Sdk , StdIn } ;
4
5
use openvm_stark_backend:: p3_field:: PrimeField32 ;
5
6
use serde:: { Deserialize , Serialize } ;
6
- use std:: env:: args;
7
7
use std:: path:: Path ;
8
8
9
9
use openvm_circuit:: arch:: {
@@ -20,6 +20,8 @@ mod womir_translation;
20
20
21
21
use openvm_womir_circuit:: { self , WomirI , WomirIExecutor , WomirIPeriphery } ;
22
22
23
+ use crate :: womir_translation:: OpenVMSettings ;
24
+
23
25
#[ derive( Serialize , Deserialize , Clone ) ]
24
26
pub struct SpecializedConfig {
25
27
pub sdk_config : SdkVmConfig ,
@@ -89,41 +91,85 @@ impl VmConfig<F> for SpecializedConfig {
89
91
}
90
92
}
91
93
92
- fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
93
- // Create VM configuration
94
- let vm_config = SdkVmConfig :: builder ( )
95
- . system ( Default :: default ( ) )
96
- . rv32i ( Default :: default ( ) )
97
- . rv32m ( Default :: default ( ) )
98
- . io ( Default :: default ( ) )
99
- . build ( ) ;
100
- let vm_config = SpecializedConfig :: new ( vm_config) ;
101
- let sdk = Sdk :: new ( ) ;
102
-
103
- // Create and execute program
104
- let mut args = args ( ) ;
105
- if args. len ( ) < 3 {
106
- eprintln ! (
107
- "Usage: {} <wasm_path> <entry_point> [<32_bit_args>...]" ,
108
- args. next( ) . unwrap( )
109
- ) ;
110
- return Ok ( ( ) ) ;
111
- }
112
- let wasm_path = args. nth ( 1 ) . unwrap ( ) ;
113
- let entry_point = args. next ( ) . unwrap ( ) ;
114
- let exe = womir_translation:: program_from_wasm :: < F > ( & wasm_path, & entry_point) ;
94
+ #[ derive( Parser ) ]
95
+ struct CliArgs {
96
+ #[ command( subcommand) ]
97
+ command : Commands ,
98
+ }
115
99
116
- let inputs = args
117
- . flat_map ( |arg| {
118
- let val = arg. parse :: < u32 > ( ) . unwrap ( ) ;
119
- val. to_le_bytes ( ) . into_iter ( )
120
- } )
121
- . collect :: < Vec < _ > > ( ) ;
100
+ #[ derive( Subcommand ) ]
101
+ enum Commands {
102
+ /// Just prints the program WOM listing
103
+ PrintWom {
104
+ /// Path to the WASM program
105
+ program : String ,
106
+ } ,
107
+ /// Runs a function from the program with arguments
108
+ Run {
109
+ /// Path to the WASM program
110
+ program : String ,
111
+ /// Function name
112
+ function : String ,
113
+ /// Arguments to pass to the function
114
+ args : Vec < String > ,
115
+ } ,
116
+ }
122
117
123
- let stdin = StdIn :: from_bytes ( & inputs) ;
118
+ impl Commands {
119
+ fn get_program_path ( & self ) -> & str {
120
+ match self {
121
+ Commands :: PrintWom { program } => program,
122
+ Commands :: Run { program, .. } => program,
123
+ }
124
+ }
125
+ }
124
126
125
- let output = sdk. execute ( exe. clone ( ) , vm_config. clone ( ) , stdin. clone ( ) ) ?;
126
- println ! ( "output: {output:?}" ) ;
127
+ fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
128
+ // Parse command line arguments
129
+ let cli_args = CliArgs :: parse ( ) ;
130
+ let wasm_path = cli_args. command . get_program_path ( ) ;
131
+
132
+ // Load the program
133
+ let wasm_bytes = std:: fs:: read ( wasm_path) . expect ( "Failed to read WASM file" ) ;
134
+ let ir_program = womir:: loader:: load_wasm ( OpenVMSettings :: < F > :: new ( ) , & wasm_bytes) . unwrap ( ) ;
135
+
136
+ match cli_args. command {
137
+ Commands :: PrintWom { .. } => {
138
+ for func in & ir_program. functions {
139
+ println ! ( "Function {}:" , func. func_idx) ;
140
+ for directive in & func. directives {
141
+ println ! ( " {directive:?}" ) ;
142
+ }
143
+ }
144
+ }
145
+ Commands :: Run { function, args, .. } => {
146
+ // Create VM configuration
147
+ let vm_config = SdkVmConfig :: builder ( )
148
+ . system ( Default :: default ( ) )
149
+ . rv32i ( Default :: default ( ) )
150
+ . rv32m ( Default :: default ( ) )
151
+ . io ( Default :: default ( ) )
152
+ . build ( ) ;
153
+ let vm_config = SpecializedConfig :: new ( vm_config) ;
154
+ let sdk = Sdk :: new ( ) ;
155
+
156
+ // Create and execute program
157
+ let exe = womir_translation:: program_from_womir :: < F > ( ir_program, & function) ;
158
+
159
+ let inputs = args
160
+ . into_iter ( )
161
+ . flat_map ( |arg| {
162
+ let val = arg. parse :: < u32 > ( ) . unwrap ( ) ;
163
+ val. to_le_bytes ( ) . into_iter ( )
164
+ } )
165
+ . collect :: < Vec < _ > > ( ) ;
166
+
167
+ let stdin = StdIn :: from_bytes ( & inputs) ;
168
+
169
+ let output = sdk. execute ( exe. clone ( ) , vm_config. clone ( ) , stdin. clone ( ) ) ?;
170
+ println ! ( "output: {output:?}" ) ;
171
+ }
172
+ }
127
173
128
174
Ok ( ( ) )
129
175
}
@@ -1282,7 +1328,10 @@ mod tests {
1282
1328
1283
1329
#[ cfg( test) ]
1284
1330
mod wast_tests {
1331
+ use crate :: womir_translation:: program_from_womir;
1332
+
1285
1333
use super :: * ;
1334
+ use openvm_instructions:: exe:: VmExe ;
1286
1335
use openvm_sdk:: { Sdk , StdIn } ;
1287
1336
use openvm_stark_sdk:: config:: setup_tracing_with_log_level;
1288
1337
use serde:: Deserialize ;
@@ -1444,6 +1493,12 @@ mod wast_tests {
1444
1493
}
1445
1494
}
1446
1495
1496
+ fn program_from_wasm < F : PrimeField32 > ( wasm_path : & str , entry_point : & str ) -> VmExe < F > {
1497
+ let wasm_bytes = std:: fs:: read ( wasm_path) . expect ( "Failed to read WASM file" ) ;
1498
+ let ir_program = womir:: loader:: load_wasm ( OpenVMSettings :: new ( ) , & wasm_bytes) . unwrap ( ) ;
1499
+ program_from_womir ( ir_program, entry_point)
1500
+ }
1501
+
1447
1502
fn run_single_wast_test (
1448
1503
module_path : & str ,
1449
1504
function : & str ,
@@ -1463,7 +1518,7 @@ mod wast_tests {
1463
1518
let sdk = Sdk :: new ( ) ;
1464
1519
1465
1520
// Load and execute the module
1466
- let exe = womir_translation :: program_from_wasm :: < F > ( module_path, function) ;
1521
+ let exe = program_from_wasm :: < F > ( module_path, function) ;
1467
1522
1468
1523
// Prepare input
1469
1524
let mut stdin = StdIn :: default ( ) ;
0 commit comments