1- use crate :: { ir:: * , mayberc:: MaybeRc } ;
1+ use crate :: impl_display_using_prettyir;
2+ use crate :: { ir:: pretty:: PrettyIR , ir:: * , mayberc:: MaybeRc } ;
23use std:: { collections:: HashMap , rc:: Rc } ;
34
45#[ derive( Clone , Debug , Default ) ]
@@ -39,6 +40,68 @@ macro_rules! both_sides {
3940 } ;
4041}
4142
43+ #[ derive( Debug , Clone ) ]
44+ pub enum InferError {
45+ CannotDeref ( MaybeRc < Type > ) ,
46+ CannotAccessMember ( MaybeRc < Type > ) ,
47+ VariableNotFound ( Rc < Ident > ) ,
48+ NotAField ( Rc < Ident > , Rc < Ident > ) ,
49+ NotAFunction ( Rc < Ident > ) ,
50+ CannotIndex ( MaybeRc < Type > ) ,
51+ }
52+
53+ impl_display_using_prettyir ! ( InferError ) ;
54+ impl PrettyIR for InferError {
55+ fn to_doc ( & self ) -> :: pretty:: RcDoc < ' _ , ( ) > {
56+ use :: pretty:: * ;
57+ ( match self {
58+ InferError :: CannotDeref ( ty) => docs ! [
59+ & RcAllocator ,
60+ "cannot dereference" ,
61+ RcDoc :: line( ) ,
62+ ty. to_doc( ) ,
63+ ] ,
64+ InferError :: CannotAccessMember ( ty) => docs ! [
65+ & RcAllocator ,
66+ ty. to_doc( ) ,
67+ RcDoc :: line( ) ,
68+ "has no members (not a structure)" ,
69+ ] ,
70+ InferError :: VariableNotFound ( name) => docs ! [
71+ & RcAllocator ,
72+ "variable" ,
73+ RcDoc :: line( ) ,
74+ name. to_doc( ) ,
75+ RcDoc :: line( ) ,
76+ "not found" ,
77+ ] ,
78+ InferError :: NotAField ( struct_name, field_name) => docs ! [
79+ & RcAllocator ,
80+ struct_name. to_doc( ) ,
81+ RcDoc :: line( ) ,
82+ "does not have a field" ,
83+ RcDoc :: line( ) ,
84+ field_name. to_doc( ) ,
85+ ] ,
86+ InferError :: NotAFunction ( name) => docs ! [
87+ & RcAllocator ,
88+ name. to_doc( ) ,
89+ RcDoc :: line( ) ,
90+ "is not a function" ,
91+ ] ,
92+ InferError :: CannotIndex ( ty) => docs ! [
93+ & RcAllocator ,
94+ "cannot index into" ,
95+ RcDoc :: line( ) ,
96+ ty. to_doc( ) ,
97+ ] ,
98+ } )
99+ . group ( )
100+ . nest ( 2 )
101+ . into_doc ( )
102+ }
103+ }
104+
42105impl Env {
43106 pub fn new ( ) -> Env {
44107 Env :: default ( )
@@ -159,73 +222,73 @@ impl Env {
159222 id
160223 }
161224
162- pub fn infer_rvalue ( & self , rvalue : & Expr ) -> Option < MaybeRc < Type > > {
163- self . infer_expr ( rvalue)
164- }
165-
166- pub fn infer_lvalue ( & self , lvalue : & Expr ) -> Option < MaybeRc < Type > > {
167- self . infer_expr ( lvalue)
168- }
169-
170- pub fn infer_expr ( & self , expr : & Expr ) -> Option < MaybeRc < Type > > {
225+ pub fn infer_expr ( & self , expr : & Expr ) -> Result < MaybeRc < Type > , InferError > {
171226 match & expr. val {
172- ExprT :: Var ( ident) => Some ( self . lookup_var_type ( ident) ?. clone ( ) . into ( ) ) ,
227+ ExprT :: Var ( ident) => {
228+ let Some ( var_type) = self . lookup_var_type ( ident) else {
229+ return Err ( InferError :: VariableNotFound ( ident. clone ( ) ) ) ;
230+ } ;
231+ Ok ( var_type. clone ( ) . into ( ) )
232+ }
173233 ExprT :: Deref ( x) => {
174234 let x_ty = self . vtype_whnf ( self . infer_expr ( x) ?) ;
175235 match & x_ty. val {
176- TypeT :: Pointer ( to, _) => Some ( to. clone ( ) . into ( ) ) ,
177- _ => None ,
236+ TypeT :: Pointer ( to, _) => Ok ( to. clone ( ) . into ( ) ) ,
237+ _ => Err ( InferError :: CannotDeref ( x_ty ) ) ,
178238 }
179239 }
180240 ExprT :: Member ( x, a) => {
181241 let x_ty = self . vtype_whnf ( self . infer_expr ( x) ?) ;
182242 match & x_ty. val {
183243 TypeT :: Pointer ( _, PointerKind :: Array ) if & * a. val == "_length" => {
184- Some ( TypeT :: SpecInt . with_loc_core ( expr. loc . clone ( ) ) . into ( ) )
244+ Ok ( TypeT :: SpecInt . with_loc_core ( expr. loc . clone ( ) ) . into ( ) )
185245 }
186- TypeT :: TypeRef ( TypeRefKind :: Struct ( s) ) => {
187- Some ( self . lookup_struct ( s) ?. get_field ( a) ?. clone ( ) . into ( ) )
246+ TypeT :: TypeRef ( TypeRefKind :: Struct ( s_name) ) => {
247+ let Some ( s) = self . lookup_struct ( s_name) else {
248+ return Err ( InferError :: CannotAccessMember ( x_ty. clone ( ) ) ) ;
249+ } ;
250+ let Some ( f) = s. get_field ( a) else {
251+ return Err ( InferError :: NotAField ( s_name. clone ( ) , a. clone ( ) ) ) ;
252+ } ;
253+ Ok ( f. clone ( ) . into ( ) )
188254 }
189- _ => None ,
255+ _ => Err ( InferError :: CannotAccessMember ( x_ty ) ) ,
190256 }
191257 }
192258 ExprT :: Index ( arr, _idx) => {
193259 let arr_ty = self . vtype_whnf ( self . infer_expr ( arr) ?) ;
194260 match & arr_ty. val {
195- TypeT :: Pointer ( elem, PointerKind :: Array ) => Some ( elem. clone ( ) . into ( ) ) ,
196- _ => None ,
261+ TypeT :: Pointer ( elem, PointerKind :: Array ) => Ok ( elem. clone ( ) . into ( ) ) ,
262+ _ => Err ( InferError :: CannotIndex ( arr_ty ) ) ,
197263 }
198264 }
199- ExprT :: IntLit ( _, ty) => Some ( ty. clone ( ) . into ( ) ) ,
200- ExprT :: Ref ( v) => Some (
201- expr . reuse_loc ( TypeT :: Pointer (
265+ ExprT :: IntLit ( _, ty) => Ok ( ty. clone ( ) . into ( ) ) ,
266+ ExprT :: Ref ( v) => Ok ( expr
267+ . reuse_loc ( TypeT :: Pointer (
202268 self . infer_expr ( v) ?. to_rc ( ) ,
203269 PointerKind :: Ref ,
204270 ) )
205- . into ( ) ,
206- ) ,
271+ . into ( ) ) ,
207272 ExprT :: FnCall ( f, _args) => match self . globals . fns . get ( & f. val ) {
208- Some ( f_decl) => Some ( f_decl. ret_type . clone ( ) . into ( ) ) ,
209- None => None ,
273+ Some ( f_decl) => Ok ( f_decl. ret_type . clone ( ) . into ( ) ) ,
274+ None => Err ( InferError :: NotAFunction ( f . clone ( ) ) ) ,
210275 } ,
211- ExprT :: Cast ( _, ty) => Some ( ty. clone ( ) . into ( ) ) ,
212- ExprT :: Error ( ty) => Some ( ty. clone ( ) . into ( ) ) ,
213- ExprT :: Malloc ( ty) => Some (
214- expr. reuse_loc ( TypeT :: Pointer ( ty. clone ( ) , PointerKind :: Ref ) )
215- . into ( ) ,
216- ) ,
217- ExprT :: MallocArray ( ty, _) => Some (
218- expr. reuse_loc ( TypeT :: Pointer ( ty. clone ( ) , PointerKind :: Array ) )
219- . into ( ) ,
220- ) ,
221- ExprT :: Free ( _) => Some ( TypeT :: Void . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
222- ExprT :: InlinePulse ( _, ty) => Some ( ty. clone ( ) . into ( ) ) ,
276+ ExprT :: Cast ( _, ty) => Ok ( ty. clone ( ) . into ( ) ) ,
277+ ExprT :: Error ( ty) => Ok ( ty. clone ( ) . into ( ) ) ,
278+ ExprT :: Malloc ( ty) => Ok ( expr
279+ . reuse_loc ( TypeT :: Pointer ( ty. clone ( ) , PointerKind :: Ref ) )
280+ . into ( ) ) ,
281+ ExprT :: MallocArray ( ty, _) => Ok ( expr
282+ . reuse_loc ( TypeT :: Pointer ( ty. clone ( ) , PointerKind :: Array ) )
283+ . into ( ) ) ,
284+ ExprT :: Free ( _) => Ok ( TypeT :: Void . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
285+ ExprT :: InlinePulse ( _, ty) => Ok ( ty. clone ( ) . into ( ) ) ,
223286 ExprT :: UnOp ( UnOp :: Not , _)
224287 | ExprT :: BinOp (
225288 BinOp :: Eq | BinOp :: LEq | BinOp :: Lt | BinOp :: LogOr | BinOp :: Implies ,
226289 _,
227290 _,
228- ) => Some ( TypeT :: Bool . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
291+ ) => Ok ( TypeT :: Bool . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
229292 ExprT :: UnOp ( UnOp :: Neg | UnOp :: BitNot , lhs)
230293 | ExprT :: BinOp (
231294 BinOp :: LogAnd
@@ -242,14 +305,13 @@ impl Env {
242305 lhs,
243306 _,
244307 ) => self . infer_expr ( lhs) ,
245- ExprT :: BoolLit ( _) => Some ( TypeT :: Bool . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
246- ExprT :: Live ( _) => Some ( TypeT :: SLProp . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
308+ ExprT :: BoolLit ( _) => Ok ( TypeT :: Bool . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
309+ ExprT :: Live ( _) => Ok ( TypeT :: SLProp . with_loc_core ( expr. loc . clone ( ) ) . into ( ) ) ,
247310 ExprT :: Old ( v) => self . infer_expr ( v) ,
248311 ExprT :: Forall ( _, _, body) | ExprT :: Exists ( _, _, body) => self . infer_expr ( body) ,
249- ExprT :: StructInit ( name, _) => Some (
250- expr. reuse_loc ( TypeT :: TypeRef ( TypeRefKind :: Struct ( name. clone ( ) ) ) )
251- . into ( ) ,
252- ) ,
312+ ExprT :: StructInit ( name, _) => Ok ( expr
313+ . reuse_loc ( TypeT :: TypeRef ( TypeRefKind :: Struct ( name. clone ( ) ) ) )
314+ . into ( ) ) ,
253315 }
254316 }
255317
@@ -403,3 +465,34 @@ impl Env {
403465 }
404466 }
405467}
468+
469+ impl_display_using_prettyir ! ( Env ) ;
470+
471+ impl PrettyIR for Env {
472+ fn to_doc ( & self ) -> :: pretty:: RcDoc < ' _ , ( ) > {
473+ use :: pretty:: * ;
474+ RcDoc :: intersperse (
475+ self . locals . iter ( ) . map ( |( local, LocalDecl { ty, kind } ) | {
476+ local
477+ . to_doc ( )
478+ . append ( RcDoc :: space ( ) )
479+ . append ( ":" )
480+ . append ( RcDoc :: line ( ) )
481+ . append ( ty. to_doc ( ) )
482+ . group ( )
483+ . append (
484+ RcDoc :: line ( )
485+ . append ( match kind {
486+ LocalDeclKind :: LValue => "(lvalue)" ,
487+ LocalDeclKind :: RValue => "(rvalue)" ,
488+ } )
489+ . group ( ) ,
490+ )
491+ . nest ( 2 )
492+ . group ( )
493+ } ) ,
494+ RcDoc :: hardline ( ) ,
495+ )
496+ . group ( )
497+ }
498+ }
0 commit comments