@@ -233,6 +233,11 @@ impl<'a> Compiler<'a> {
233233 self . compile_expression ( value) ;
234234 self . emit ( Instruction :: SetIndex , line) ;
235235 }
236+ Statement :: TryCatch ( tc) => self . compile_try_catch ( tc) ,
237+ Statement :: Throw { value, line } => {
238+ self . compile_expression ( value) ;
239+ self . emit ( Instruction :: Throw , line) ;
240+ }
236241 }
237242 }
238243
@@ -603,4 +608,102 @@ impl<'a> Compiler<'a> {
603608 } ,
604609 ) ;
605610 }
611+
612+ fn compile_try_catch ( & mut self , tc : TryCatch ) {
613+ let line = tc. line ;
614+ let unique_id = self . unique_id ( ) ;
615+ let catch_label = format ! ( "catch_{}" , unique_id) ;
616+ let finally_label = format ! ( "finally_{}" , unique_id) ;
617+ let end_label = format ! ( "end_try_{}" , unique_id) ;
618+
619+ // Set up exception handler
620+ self . emit ( Instruction :: PushExceptionHandler ( catch_label. clone ( ) ) , line) ;
621+
622+ // Compile try block
623+ self . begin_scope ( ) ;
624+ for stmt in tc. try_body {
625+ self . compile_statement ( stmt) ;
626+ }
627+ self . end_scope ( ) ;
628+
629+ // Pop exception handler if no exception occurred
630+ self . emit ( Instruction :: PopExceptionHandler , line) ;
631+
632+ // Jump to finally or end
633+ if tc. finally_body . is_some ( ) {
634+ self . emit ( Instruction :: Jump ( finally_label. clone ( ) ) , line) ;
635+ } else {
636+ self . emit ( Instruction :: Jump ( end_label. clone ( ) ) , line) ;
637+ }
638+
639+ // Catch block
640+ self . program . syms . insert (
641+ catch_label. clone ( ) ,
642+ Symbol {
643+ location : self . program . instructions . len ( ) as i32 ,
644+ narguments : 0 ,
645+ nlocals : 0 ,
646+ } ,
647+ ) ;
648+
649+ self . begin_scope ( ) ;
650+
651+ // Define error variable if provided
652+ if let Some ( error_name) = tc. error_name {
653+ let var_location = self . define_variable ( error_name) ;
654+ match var_location {
655+ VarLocation :: Local ( offset) => {
656+ self . emit ( Instruction :: MovePlusFP ( offset as usize ) , line) ;
657+ }
658+ VarLocation :: Global ( name) => {
659+ self . emit ( Instruction :: Store ( name) , line) ;
660+ }
661+ }
662+ } else {
663+ // Pop the error value if no variable to store it
664+ self . emit ( Instruction :: Pop , line) ;
665+ }
666+
667+ // Compile catch block
668+ for stmt in tc. catch_body {
669+ self . compile_statement ( stmt) ;
670+ }
671+
672+ self . end_scope ( ) ;
673+
674+ // Jump to finally or end after catch
675+ if tc. finally_body . is_some ( ) {
676+ self . emit ( Instruction :: Jump ( finally_label. clone ( ) ) , line) ;
677+ } else {
678+ self . emit ( Instruction :: Jump ( end_label. clone ( ) ) , line) ;
679+ }
680+
681+ // Finally block (if present)
682+ if let Some ( finally_body) = tc. finally_body {
683+ self . program . syms . insert (
684+ finally_label. clone ( ) ,
685+ Symbol {
686+ location : self . program . instructions . len ( ) as i32 ,
687+ narguments : 0 ,
688+ nlocals : 0 ,
689+ } ,
690+ ) ;
691+
692+ self . begin_scope ( ) ;
693+ for stmt in finally_body {
694+ self . compile_statement ( stmt) ;
695+ }
696+ self . end_scope ( ) ;
697+ }
698+
699+ // End label
700+ self . program . syms . insert (
701+ end_label,
702+ Symbol {
703+ location : self . program . instructions . len ( ) as i32 ,
704+ narguments : 0 ,
705+ nlocals : 0 ,
706+ } ,
707+ ) ;
708+ }
606709}
0 commit comments