11// src/vm.rs
22
3- use std:: collections:: HashMap ;
43use crate :: error:: XplError ;
54use crate :: parser:: { BinOp , Expr , Program , Stmt } ;
5+ use std:: collections:: HashMap ;
66
77pub struct VM {
88 vars : HashMap < String , i64 > ,
@@ -82,6 +82,68 @@ impl VM {
8282 }
8383 }
8484 }
85+ Stmt :: Loop { count, body } => {
86+ // evaluate loop count
87+ let times = self . eval_expr ( count, prog) ?;
88+ for _ in 0 ..times {
89+ // execute each statement in loop body
90+ for st in body {
91+ match st {
92+ Stmt :: Assign { var, expr } => {
93+ let val = self . eval_expr ( expr, prog) ?;
94+ self . vars . insert ( var. clone ( ) , val) ;
95+ }
96+ Stmt :: Print ( expr) => {
97+ let out = match expr {
98+ Expr :: LiteralStr ( s) => s. clone ( ) ,
99+ Expr :: LiteralInt ( i) => i. to_string ( ) ,
100+ _ => self . eval_expr ( expr, prog) ?. to_string ( ) ,
101+ } ;
102+ outputs. push ( out) ;
103+ }
104+ Stmt :: Loop { .. } => {
105+ let _nested = Stmt :: Loop {
106+ count : count. clone ( ) ,
107+ body : body. clone ( ) ,
108+ } ;
109+ // recurse by adding statement
110+ // could call run but simpler: ignore nested for now
111+ }
112+ Stmt :: Call ( name, args) => {
113+ let expr = Expr :: Call ( name. clone ( ) , args. clone ( ) ) ;
114+ let _ = self . eval_expr ( & expr, prog) ?;
115+ }
116+ Stmt :: Return ( _) => { }
117+ Stmt :: If {
118+ cond,
119+ then_body,
120+ else_body,
121+ } => {
122+ // reuse existing semantics: evaluate one iteration of if
123+ let cond_val = self . eval_expr ( cond, prog) ?;
124+ let branch = if cond_val != 0 { then_body } else { else_body } ;
125+ for b in branch {
126+ match b {
127+ Stmt :: Assign { var, expr } => {
128+ let v = self . eval_expr ( expr, prog) ?;
129+ self . vars . insert ( var. clone ( ) , v) ;
130+ }
131+ Stmt :: Print ( expr) => {
132+ let o = match expr {
133+ Expr :: LiteralStr ( s) => s. clone ( ) ,
134+ Expr :: LiteralInt ( i) => i. to_string ( ) ,
135+ _ => self . eval_expr ( expr, prog) ?. to_string ( ) ,
136+ } ;
137+ outputs. push ( o) ;
138+ }
139+ _ => { }
140+ }
141+ }
142+ }
143+ }
144+ }
145+ }
146+ }
85147 Stmt :: Return ( _) => { /* ignore return in main */ }
86148 Stmt :: Call ( name, args) => {
87149 // Evaluate standalone call, errors on undefined function
@@ -129,20 +191,18 @@ impl VM {
129191 return Ok ( res) ;
130192 }
131193 Expr :: LiteralInt ( i) => Ok ( * i) ,
132- Expr :: VarRef ( name) => {
133- match self . vars . get ( name) {
134- Some ( v) => Ok ( * v) ,
135- None => {
136- let ( line, col) = self . find_pos ( name) ;
137- Err ( XplError :: Semantic {
138- msg : format ! ( "Undefined variable {}" , name) ,
139- file : self . file . clone ( ) ,
140- line : line + 1 ,
141- col : col + 1 ,
142- } )
143- }
194+ Expr :: VarRef ( name) => match self . vars . get ( name) {
195+ Some ( v) => Ok ( * v) ,
196+ None => {
197+ let ( line, col) = self . find_pos ( name) ;
198+ Err ( XplError :: Semantic {
199+ msg : format ! ( "Undefined variable {}" , name) ,
200+ file : self . file . clone ( ) ,
201+ line : line + 1 ,
202+ col : col + 1 ,
203+ } )
144204 }
145- }
205+ } ,
146206 Expr :: Call ( name, args) => {
147207 // Evaluate argument expressions
148208 let mut arg_vals = Vec :: new ( ) ;
@@ -168,18 +228,15 @@ impl VM {
168228 name : & str ,
169229 args : Vec < i64 > ,
170230 ) -> Result < i64 , XplError > {
171- let func = prog
172- . functions
173- . get ( name)
174- . ok_or_else ( || {
175- let ( line, col) = self . find_pos ( name) ;
176- XplError :: Semantic {
177- msg : format ! ( "Undefined function {}" , name) ,
178- file : self . file . clone ( ) ,
179- line : line + 1 ,
180- col : col + 1 ,
181- }
182- } ) ?;
231+ let func = prog. functions . get ( name) . ok_or_else ( || {
232+ let ( line, col) = self . find_pos ( name) ;
233+ XplError :: Semantic {
234+ msg : format ! ( "Undefined function {}" , name) ,
235+ file : self . file . clone ( ) ,
236+ line : line + 1 ,
237+ col : col + 1 ,
238+ }
239+ } ) ?;
183240 if func. params . len ( ) != args. len ( ) {
184241 return Err ( XplError :: Semantic {
185242 msg : format ! (
0 commit comments