@@ -16,20 +16,54 @@ pub fn check_stmt(
1616 Statement :: IfThenElse ( cond, stmt_then, stmt_else_opt) => {
1717 check_if_then_else_stmt ( cond, stmt_then, stmt_else_opt, env)
1818 }
19+ Statement :: IfChain {
20+ branches,
21+ else_branch,
22+ } => check_if_chain_stmt ( branches, else_branch, env) ,
1923 Statement :: While ( cond, stmt) => check_while_stmt ( cond, stmt, env) ,
2024 Statement :: For ( var, expr, stmt) => check_for_stmt ( var, expr, stmt, env) ,
2125 Statement :: FuncDef ( function) => check_func_def_stmt ( function, env) ,
2226 Statement :: TypeDeclaration ( name, cons) => check_adt_declarations_stmt ( name, cons, env) ,
2327 Statement :: Return ( exp) => check_return_stmt ( exp, env) ,
2428
29+ // Blocos no nível de statement: empilham escopo e checam internamente.
30+ Statement :: Block ( stmts) => {
31+ let mut block_env = env. clone ( ) ;
32+ block_env. push ( ) ;
33+
34+ for s in stmts {
35+ block_env = check_stmt ( s, & block_env) ?;
36+ }
37+ block_env. pop ( ) ;
38+ Ok ( block_env)
39+ }
40+
2541 Statement :: Assert ( expr1, errmsg) => check_assert ( expr1, errmsg, env) ,
2642 Statement :: AssertTrue ( expr1, errmsg) => check_assert_true ( expr1, errmsg, env) ,
2743 Statement :: AssertFalse ( expr1, errmsg) => check_assert_false ( expr1, errmsg, env) ,
2844 Statement :: AssertEQ ( lhs, rhs, errmsg) => check_assert_eq ( lhs, rhs, errmsg, env) ,
2945 Statement :: AssertNEQ ( lhs, rhs, errmsg) => check_assert_neq ( lhs, rhs, errmsg, env) ,
3046 Statement :: TestDef ( function) => check_test_function_stmt ( function, env) ,
3147
32- _ => Err ( "Not implemented yet" . to_string ( ) ) ,
48+ // Statement de expressão: só garante que a expressão é bem-tipada.
49+ Statement :: ExprStmt ( exp) => {
50+ let _ = check_expr ( * exp, env) ?;
51+ Ok ( env. clone ( ) )
52+ }
53+
54+ // Metabuiltins são tratados apenas em tempo de execução; do ponto de vista
55+ // de tipos, não alteram o ambiente.
56+ Statement :: MetaStmt ( _) => Ok ( env. clone ( ) ) ,
57+
58+ // AssertFails carrega apenas uma mensagem literal; não há expressão a checar.
59+ Statement :: AssertFails ( _) => Ok ( env. clone ( ) ) ,
60+
61+ // ModTestDef agrupa um statement de teste por módulo; checamos o corpo,
62+ // mas não expomos nada novo no ambiente global.
63+ Statement :: ModTestDef ( _, stmt) => {
64+ let _ = check_stmt ( * stmt, env) ?;
65+ Ok ( env. clone ( ) )
66+ }
3367 }
3468}
3569
@@ -152,6 +186,45 @@ fn check_if_then_else_stmt(
152186 Ok ( new_env)
153187}
154188
189+ fn check_if_chain_stmt (
190+ branches : Vec < ( Box < Expression > , Box < Statement > ) > ,
191+ else_branch : Option < Box < Statement > > ,
192+ env : & Environment < Type > ,
193+ ) -> Result < Environment < Type > , ErrorMessage > {
194+ if branches. is_empty ( ) {
195+ return Err ( "[Type Error] if-chain must have at least one branch." . to_string ( ) ) ;
196+ }
197+
198+ let mut branch_envs: Vec < Environment < Type > > = Vec :: new ( ) ;
199+
200+ for ( cond, stmt) in branches {
201+ let mut local_env = env. clone ( ) ;
202+ let cond_type = check_expr ( * cond, & local_env) ?;
203+ if cond_type != Type :: TBool {
204+ return Err (
205+ "[Type Error] a condition in an 'if/elif' branch must be of type boolean."
206+ . to_string ( ) ,
207+ ) ;
208+ }
209+ local_env = check_stmt ( * stmt, & local_env) ?;
210+ branch_envs. push ( local_env) ;
211+ }
212+
213+ if let Some ( stmt) = else_branch {
214+ let else_env = check_stmt ( * stmt, env) ?;
215+ branch_envs. push ( else_env) ;
216+ }
217+
218+ // Mescla progressivamente todos os ambientes resultantes,
219+ // começando do ambiente original.
220+ let mut acc_env = env. clone ( ) ;
221+ for branch_env in branch_envs {
222+ acc_env = merge_environments ( & acc_env, & branch_env) ?;
223+ }
224+
225+ Ok ( acc_env)
226+ }
227+
155228fn check_while_stmt (
156229 cond : Box < Expression > ,
157230 stmt : Box < Statement > ,
0 commit comments