makepad_shader_compiler/
ty_check.rs

1#![allow(unused_variables)]
2use{
3    std::{
4        cell::Cell,
5        collections::BTreeSet,
6        fmt::Write,
7        rc::Rc,
8    },
9    crate::{
10        makepad_live_compiler::*,
11        shader_ast::*,
12        lhs_check::LhsChecker,
13        swizzle::Swizzle,
14        util::CommaSep,
15        shader_registry::ShaderRegistry
16    }
17};
18
19#[derive(Clone)]
20pub struct TyChecker<'a> {
21    pub scopes: &'a Scopes,
22    pub live_registry: &'a LiveRegistry, 
23    pub shader_registry: &'a ShaderRegistry
24}
25
26impl<'a> TyChecker<'a> {
27    fn lhs_checker(&self) -> LhsChecker {
28        LhsChecker {scopes: self.scopes, shader_registry: self.shader_registry,}
29    }
30    
31    pub fn ty_check_ty_expr(&mut self, ty_expr: &TyExpr) -> Result<Ty, LiveError> {
32        let ty = match &ty_expr.kind {
33            TyExprKind::Array {
34                ref elem_ty_expr,
35                len,
36            } => self.ty_check_array_ty_expr(ty_expr.span, elem_ty_expr, *len),
37            TyExprKind::Lit {ty_lit} => self.ty_check_lit_ty_expr(ty_expr.span, *ty_lit),
38            TyExprKind::Struct(struct_ptr) => Ok(Ty::Struct(*struct_ptr)),
39            TyExprKind::Enum(live_type) => Ok(Ty::Enum(*live_type)),
40            TyExprKind::DrawShader(shader_ptr) => Ok(Ty::DrawShader(*shader_ptr)),
41            TyExprKind::ClosureDecl {return_ty_expr, params, return_ty} => {
42                // check the closure
43                let checked_return_ty = if let Some(return_ty) = return_ty_expr.as_ref().as_ref(){
44                    self.ty_check_ty_expr(return_ty).unwrap_or(Ty::Void)
45                }
46                else{
47                     Ty::Void
48                };
49                *return_ty.borrow_mut() = Some(checked_return_ty);
50                for param in params {
51                    self.ty_check_ty_expr(&param.ty_expr) ?;
52                }
53                Ok(Ty::ClosureDecl)
54            }
55        } ?;
56        *ty_expr.ty.borrow_mut() = Some(ty.clone());
57        Ok(ty)
58    }
59    
60    fn ty_check_array_ty_expr(
61        &mut self,
62        _span: TokenSpan,
63        elem_ty_expr: &TyExpr,
64        len: u32,
65    ) -> Result<Ty, LiveError> {
66        let elem_ty = Rc::new(self.ty_check_ty_expr(elem_ty_expr) ?);
67        let len = len as usize;
68        Ok(Ty::Array {elem_ty, len})
69    }
70    
71    fn ty_check_lit_ty_expr(&mut self, _span: TokenSpan, ty_lit: TyLit) -> Result<Ty, LiveError> {
72        Ok(ty_lit.to_ty())
73    }
74    
75    pub fn ty_check_expr_with_expected_ty(
76        &mut self,
77        span: TokenSpan,
78        expr: &Expr,
79        expected_ty: &Ty,
80    ) -> Result<Ty, LiveError> {
81        let actual_ty = self.ty_check_expr(expr) ?;
82        if &actual_ty != expected_ty {
83            return Err(LiveError {
84                origin: live_error_origin!(),
85                span:span.into(),
86                message: format!(
87                    "can't match expected type `{}` with actual type `{}",
88                    expected_ty,
89                    actual_ty
90                ),
91            });
92        }
93        Ok(actual_ty)
94    }
95    
96    pub fn ty_check_expr(&mut self, expr: &Expr) -> Result<Ty, LiveError> {
97        let ty = match expr.kind {
98            ExprKind::Cond {
99                span,
100                ref expr,
101                ref expr_if_true,
102                ref expr_if_false,
103                ..
104            } => self.ty_check_cond_expr(span, expr, expr_if_true, expr_if_false),
105            ExprKind::Bin {
106                span,
107                op,
108                ref left_expr,
109                ref right_expr,
110                ..
111            } => self.ty_check_bin_expr(span, op, left_expr, right_expr),
112            ExprKind::Un {span, op, ref expr} => self.ty_check_un_expr(span, op, expr),
113            ExprKind::PlainCall {
114                span,
115                ident,
116                fn_ptr,
117                ref arg_exprs,
118                ref closure_site_index,
119                ref param_index,
120                ..
121            } => self.ty_check_plain_call_expr(span, ident, arg_exprs, fn_ptr, closure_site_index, param_index),
122            ExprKind::MethodCall {
123                span,
124                ident,
125                ref arg_exprs,
126                ref closure_site_index,
127                ..
128            } => self.ty_check_method_call_expr(span, ident, arg_exprs, closure_site_index),
129            ExprKind::BuiltinCall {
130                span,
131                ident,
132                ref arg_exprs,
133            } => self.ty_check_builtin_call_expr(span, ident, arg_exprs),
134            ExprKind::ClosureDef(index) => self.ty_check_closure_def(index),
135            ExprKind::ConsCall {
136                span,
137                ty_lit,
138                ref arg_exprs,
139            } => self.ty_check_cons_call_expr(span, ty_lit, arg_exprs),
140            ExprKind::Field {
141                span,
142                ref expr,
143                field_ident,
144            } => self.ty_check_field_expr(span, expr, field_ident),
145            ExprKind::Index {
146                span,
147                ref expr,
148                ref index_expr,
149            } => self.ty_check_index_expr(span, expr, index_expr),
150            
151            ExprKind::Var {
152                span,
153                ref kind,
154                var_resolve,
155                ident,
156            } => self.ty_check_var_expr(span, kind, var_resolve, ident),
157            ExprKind::StructCons {
158                struct_ptr,
159                span,
160                ref args
161            } => self.ty_check_struct_cons(struct_ptr, span, args),
162            ExprKind::Lit {span, lit} => self.ty_check_lit_expr(span, lit),
163        } ?;
164        *expr.ty.borrow_mut() = Some(ty.clone());
165        Ok(ty)
166    }
167    
168    fn ty_check_closure_def(
169        &mut self,
170        index: ClosureDefIndex,
171    ) -> Result<Ty, LiveError> {
172        // we kinda need to capture the scope here.
173        self.scopes.capture_closure_scope(index);
174        Ok(Ty::ClosureDef(index))
175    }
176    
177    fn ty_check_cond_expr(
178        &mut self,
179        span: TokenSpan,
180        expr: &Expr,
181        expr_if_true: &Expr,
182        expr_if_false: &Expr,
183    ) -> Result<Ty, LiveError> {
184        self.ty_check_expr_with_expected_ty(span, expr, &Ty::Bool) ?;
185        let ty_if_true = self.ty_check_expr(expr_if_true) ?;
186        self.ty_check_expr_with_expected_ty(span, expr_if_false, &ty_if_true) ?;
187        Ok(ty_if_true)
188    }
189    
190    fn ty_check_bin_expr(
191        &mut self,
192        span: TokenSpan,
193        op: BinOp,
194        left_expr: &Expr,
195        right_expr: &Expr,
196    ) -> Result<Ty, LiveError> {
197        let left_ty = self.ty_check_expr(left_expr) ?;
198        let right_ty = self.ty_check_expr(right_expr) ?;
199        match op {
200            BinOp::Assign
201                | BinOp::AddAssign
202                | BinOp::SubAssign
203                | BinOp::MulAssign
204                | BinOp::DivAssign => {
205                self.lhs_checker().lhs_check_expr(left_expr) ?;
206            }
207            _ => {}
208        }
209        match op {
210            BinOp::Assign => {
211                if left_ty == right_ty {
212                    Some(left_ty.clone())
213                } else {
214                    None
215                }
216            }
217            BinOp::AddAssign | BinOp::SubAssign | BinOp::DivAssign => match (&left_ty, &right_ty) {
218                (Ty::Int, Ty::Int) => Some(Ty::Int),
219                (Ty::Float, Ty::Float) => Some(Ty::Float),
220                (Ty::Ivec2, Ty::Int) => Some(Ty::Ivec2),
221                (Ty::Ivec2, Ty::Ivec2) => Some(Ty::Ivec2),
222                (Ty::Ivec3, Ty::Int) => Some(Ty::Ivec3),
223                (Ty::Ivec3, Ty::Ivec3) => Some(Ty::Ivec3),
224                (Ty::Ivec4, Ty::Int) => Some(Ty::Ivec4),
225                (Ty::Ivec4, Ty::Ivec4) => Some(Ty::Ivec4),
226                (Ty::Vec2, Ty::Float) => Some(Ty::Vec2),
227                (Ty::Vec2, Ty::Vec2) => Some(Ty::Vec2),
228                (Ty::Vec3, Ty::Float) => Some(Ty::Vec3),
229                (Ty::Vec3, Ty::Vec3) => Some(Ty::Vec3),
230                (Ty::Vec4, Ty::Float) => Some(Ty::Vec4),
231                (Ty::Vec4, Ty::Vec4) => Some(Ty::Vec4),
232                (Ty::Mat2, Ty::Float) => Some(Ty::Mat2),
233                (Ty::Mat2, Ty::Mat2) => Some(Ty::Mat2),
234                (Ty::Mat3, Ty::Float) => Some(Ty::Mat3),
235                (Ty::Mat3, Ty::Mat3) => Some(Ty::Mat3),
236                (Ty::Mat4, Ty::Float) => Some(Ty::Mat4),
237                (Ty::Mat4, Ty::Mat4) => Some(Ty::Mat4),
238                _ => None,
239            },
240            BinOp::MulAssign => match (&left_ty, &right_ty) {
241                (Ty::Int, Ty::Int) => Some(Ty::Int),
242                (Ty::Float, Ty::Float) => Some(Ty::Float),
243                (Ty::Ivec2, Ty::Int) => Some(Ty::Ivec2),
244                (Ty::Ivec2, Ty::Ivec2) => Some(Ty::Ivec2),
245                (Ty::Ivec3, Ty::Int) => Some(Ty::Ivec3),
246                (Ty::Ivec3, Ty::Ivec3) => Some(Ty::Ivec3),
247                (Ty::Ivec4, Ty::Int) => Some(Ty::Ivec4),
248                (Ty::Ivec4, Ty::Ivec4) => Some(Ty::Ivec4),
249                (Ty::Vec2, Ty::Float) => Some(Ty::Vec2),
250                (Ty::Vec2, Ty::Vec2) => Some(Ty::Vec2),
251                (Ty::Vec2, Ty::Mat2) => Some(Ty::Vec2),
252                (Ty::Vec3, Ty::Float) => Some(Ty::Vec3),
253                (Ty::Vec3, Ty::Vec3) => Some(Ty::Vec3),
254                (Ty::Vec3, Ty::Mat3) => Some(Ty::Vec3),
255                (Ty::Vec4, Ty::Float) => Some(Ty::Vec4),
256                (Ty::Vec4, Ty::Vec4) => Some(Ty::Vec4),
257                (Ty::Vec4, Ty::Mat4) => Some(Ty::Vec4),
258                (Ty::Mat2, Ty::Float) => Some(Ty::Mat2),
259                (Ty::Mat2, Ty::Mat2) => Some(Ty::Mat2),
260                (Ty::Mat3, Ty::Float) => Some(Ty::Mat3),
261                (Ty::Mat3, Ty::Mat3) => Some(Ty::Mat3),
262                (Ty::Mat4, Ty::Float) => Some(Ty::Mat4),
263                (Ty::Mat4, Ty::Mat4) => Some(Ty::Mat4),
264                _ => None,
265            },
266            BinOp::Or | BinOp::And => match (&left_ty, &right_ty) {
267                (Ty::Bool, Ty::Bool) => Some(Ty::Bool),
268                _ => None,
269            },
270            BinOp::Eq | BinOp::Ne => match (&left_ty, &right_ty) {
271                (Ty::Bool, Ty::Bool) => Some(Ty::Bool),
272                (Ty::Int, Ty::Int) => Some(Ty::Bool),
273                (Ty::Float, Ty::Float) => Some(Ty::Bool),
274                (Ty::Ivec2, Ty::Ivec2) => Some(Ty::Bool),
275                (Ty::Ivec3, Ty::Ivec3) => Some(Ty::Bool),
276                (Ty::Ivec4, Ty::Ivec4) => Some(Ty::Bool),
277                (Ty::Vec2, Ty::Vec2) => Some(Ty::Bool),
278                (Ty::Vec3, Ty::Vec3) => Some(Ty::Bool),
279                (Ty::Vec4, Ty::Vec4) => Some(Ty::Bool),
280                (Ty::Mat2, Ty::Mat2) => Some(Ty::Bool),
281                (Ty::Mat3, Ty::Mat3) => Some(Ty::Bool),
282                (Ty::Mat4, Ty::Mat4) => Some(Ty::Bool),
283                _ => None,
284            },
285            BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => match (&left_ty, &right_ty) {
286                (Ty::Int, Ty::Int) => Some(Ty::Bool),
287                (Ty::Float, Ty::Float) => Some(Ty::Bool),
288                _ => None,
289            },
290            BinOp::Add | BinOp::Sub | BinOp::Div => match (&left_ty, &right_ty) {
291                (Ty::Int, Ty::Int) => Some(Ty::Int),
292                (Ty::Float, Ty::Float) => Some(Ty::Float),
293                (Ty::Float, Ty::Vec2) => Some(Ty::Vec2),
294                (Ty::Float, Ty::Vec3) => Some(Ty::Vec3),
295                (Ty::Float, Ty::Vec4) => Some(Ty::Vec4),
296                (Ty::Float, Ty::Mat2) => Some(Ty::Mat2),
297                (Ty::Float, Ty::Mat3) => Some(Ty::Mat3),
298                (Ty::Float, Ty::Mat4) => Some(Ty::Mat4),
299                (Ty::Ivec2, Ty::Int) => Some(Ty::Ivec2),
300                (Ty::Ivec2, Ty::Ivec2) => Some(Ty::Ivec2),
301                (Ty::Ivec3, Ty::Int) => Some(Ty::Ivec3),
302                (Ty::Ivec3, Ty::Ivec3) => Some(Ty::Ivec3),
303                (Ty::Ivec4, Ty::Int) => Some(Ty::Ivec4),
304                (Ty::Ivec4, Ty::Ivec4) => Some(Ty::Ivec4),
305                (Ty::Vec2, Ty::Float) => Some(Ty::Vec2),
306                (Ty::Vec2, Ty::Vec2) => Some(Ty::Vec2),
307                (Ty::Vec3, Ty::Float) => Some(Ty::Vec3),
308                (Ty::Vec3, Ty::Vec3) => Some(Ty::Vec3),
309                (Ty::Vec4, Ty::Float) => Some(Ty::Vec4),
310                (Ty::Vec4, Ty::Vec4) => Some(Ty::Vec4),
311                (Ty::Mat2, Ty::Float) => Some(Ty::Mat2),
312                (Ty::Mat2, Ty::Mat2) => Some(Ty::Mat2),
313                (Ty::Mat3, Ty::Float) => Some(Ty::Mat3),
314                (Ty::Mat3, Ty::Mat3) => Some(Ty::Mat3),
315                (Ty::Mat4, Ty::Float) => Some(Ty::Mat4),
316                (Ty::Mat4, Ty::Mat4) => Some(Ty::Mat4),
317                _ => None,
318            },
319            BinOp::Mul => match (&left_ty, &right_ty) {
320                (Ty::Int, Ty::Int) => Some(Ty::Int),
321                (Ty::Float, Ty::Float) => Some(Ty::Float),
322                (Ty::Float, Ty::Vec2) => Some(Ty::Vec2),
323                (Ty::Float, Ty::Vec3) => Some(Ty::Vec3),
324                (Ty::Float, Ty::Vec4) => Some(Ty::Vec4),
325                (Ty::Float, Ty::Mat2) => Some(Ty::Mat2),
326                (Ty::Float, Ty::Mat3) => Some(Ty::Mat3),
327                (Ty::Float, Ty::Mat4) => Some(Ty::Mat4),
328                (Ty::Ivec2, Ty::Int) => Some(Ty::Ivec2),
329                (Ty::Ivec2, Ty::Ivec2) => Some(Ty::Ivec2),
330                (Ty::Ivec3, Ty::Int) => Some(Ty::Ivec3),
331                (Ty::Ivec3, Ty::Ivec3) => Some(Ty::Ivec3),
332                (Ty::Ivec4, Ty::Int) => Some(Ty::Ivec4),
333                (Ty::Ivec4, Ty::Ivec4) => Some(Ty::Ivec4),
334                (Ty::Vec2, Ty::Float) => Some(Ty::Vec2),
335                (Ty::Vec2, Ty::Vec2) => Some(Ty::Vec2),
336                (Ty::Vec2, Ty::Mat2) => Some(Ty::Vec2),
337                (Ty::Vec3, Ty::Float) => Some(Ty::Vec3),
338                (Ty::Vec3, Ty::Vec3) => Some(Ty::Vec3),
339                (Ty::Vec3, Ty::Mat3) => Some(Ty::Vec3),
340                (Ty::Vec4, Ty::Float) => Some(Ty::Vec4),
341                (Ty::Vec4, Ty::Vec4) => Some(Ty::Vec4),
342                (Ty::Vec4, Ty::Mat4) => Some(Ty::Vec4),
343                (Ty::Mat2, Ty::Float) => Some(Ty::Mat2),
344                (Ty::Mat2, Ty::Vec2) => Some(Ty::Vec2),
345                (Ty::Mat2, Ty::Mat2) => Some(Ty::Mat2),
346                (Ty::Mat3, Ty::Float) => Some(Ty::Mat3),
347                (Ty::Mat3, Ty::Vec3) => Some(Ty::Vec3),
348                (Ty::Mat3, Ty::Mat3) => Some(Ty::Mat3),
349                (Ty::Mat4, Ty::Float) => Some(Ty::Mat4),
350                (Ty::Mat4, Ty::Vec4) => Some(Ty::Vec4),
351                (Ty::Mat4, Ty::Mat4) => Some(Ty::Mat4),
352                _ => None,
353            },
354        }
355        .ok_or_else( || LiveError {
356            origin: live_error_origin!(),
357            span:span.into(),
358            message: format!(
359                "can't apply binary operator `{}` to operands of type `{}` and `{}",
360                op,
361                left_ty,
362                right_ty
363            )
364                .into(),
365        })
366    }
367    
368    fn ty_check_un_expr(&mut self, span: TokenSpan, op: UnOp, expr: &Expr) -> Result<Ty, LiveError> {
369        let ty = self.ty_check_expr(expr) ?;
370        match op {
371            UnOp::Not => match ty {
372                Ty::Bool => Some(Ty::Bool),
373                _ => None,
374            },
375            UnOp::Neg => match ty {
376                Ty::Int => Some(Ty::Int),
377                Ty::Float => Some(Ty::Float),
378                Ty::Vec2 => Some(Ty::Vec2),
379                Ty::Vec3 => Some(Ty::Vec3),
380                Ty::Vec4 => Some(Ty::Vec4),
381                _ => None,
382            },
383        }
384        .ok_or_else( || LiveError {
385            origin: live_error_origin!(),
386            span:span.into(),
387            message: format!(
388                "can't apply unary operator `{}` to operand of type `{}`",
389                op,
390                ty
391            )
392                .into(),
393        })
394    }
395    
396    /*
397    fn ty_check_closure_call_expr(
398        &mut self,
399        span: Span,
400        ident: Ident,
401        arg_exprs: &[Expr],
402        outer_param_index: &Cell<Option<usize>>,
403    ) -> Result<Ty, LiveError> {
404        
405        for arg_expr in arg_exprs {
406            self.ty_check_expr(arg_expr) ?;
407        }
408        match self.scopes.find_sym_on_scopes(ident, span) {
409            Some(scopesym)=> match &scopesym.kind{
410                ScopeSymKind::Closure{return_ty, params, param_index} => {
411                    let closure_args = self.check_params_against_args(span, &params, arg_exprs) ?;
412                    // error out
413                    if closure_args.len() > 0{
414                        return Err(LiveError {
415                            origin: live_error_origin!(),
416                            span,
417                            message: format!("Cannot pass closures to closures, please implement"),
418                        })
419                    }
420                    outer_param_index.set(Some(*param_index));
421                    return Ok(return_ty.clone())
422                }
423                _=>()
424            }
425            _ => ()
426        }
427        Err(LiveError {
428            origin: live_error_origin!(),
429            span,
430            message: format!("Closure call `{}` is not defined on", ident),
431        })
432    }
433    */
434    
435    fn ty_check_plain_call_expr(
436        &mut self,
437        span: TokenSpan,
438        ident: Option<Ident>,
439        arg_exprs: &[Expr],
440        fn_ptr: Option<FnPtr>,
441        closure_site_index: &Cell<Option<usize>>,
442        outer_param_index: &Cell<Option<usize>>,
443    ) -> Result<Ty, LiveError> {
444        
445        for arg_expr in arg_exprs {
446            self.ty_check_expr(arg_expr) ?;
447        }
448        
449        if let Some(ident) = ident{
450            match self.scopes.find_sym_on_scopes(ident, span) {
451                Some(scopesym)=> match &scopesym.kind{
452                    ScopeSymKind::Closure{return_ty, params, param_index} => {
453                        let closure_args = self.check_params_against_args(span, &params, arg_exprs) ?;
454                        // error out
455                        if closure_args.len() > 0{
456                            return Err(LiveError {
457                                origin: live_error_origin!(),
458                                span:span.into(),
459                                message: format!("Cannot pass closures to closures, please implement"),
460                            })
461                        }
462                        outer_param_index.set(Some(*param_index));
463                        return Ok(return_ty.clone())
464                    }
465                    _=>()
466                }
467                _ => ()
468            }
469        }
470        
471        // alright so.it must be a plain call
472        if let Some(fn_ptr) = fn_ptr{
473            let fn_def = self.shader_registry.all_fns.get(&fn_ptr).expect("fn ptr invalid");
474            
475            self.check_call_args(span, fn_ptr, arg_exprs, &fn_def, Some(closure_site_index)) ?;
476            
477            // lets return the right ty
478            return Ok(fn_def.return_ty.borrow().clone().unwrap())
479        }
480        return Err(LiveError {
481            origin: live_error_origin!(),
482            span:span.into(),
483            message: format!("Function not found {}", ident.unwrap()),
484        }) 
485    }
486    
487    fn ty_check_method_call_expr(
488        &mut self,
489        span: TokenSpan,
490        ident: Ident,
491        arg_exprs: &[Expr],
492        closure_site_index: &Cell<Option<usize>>,
493    ) -> Result<Ty, LiveError> {
494        
495        let ty = self.ty_check_expr(&arg_exprs[0]) ?;
496        match ty {
497            Ty::DrawShader(shader_ptr) => { // a shader method call
498                
499                if let Some(fn_decl) = self.shader_registry.draw_shader_method_decl_from_ident(
500                    self.shader_registry.draw_shader_defs.get(&shader_ptr).unwrap(),
501                    ident
502                ) {
503
504                    for arg_expr in arg_exprs {
505                        self.ty_check_expr(arg_expr) ?;
506                    }
507
508                    self.check_call_args(span, fn_decl.fn_ptr, arg_exprs, fn_decl, Some(closure_site_index)) ?;
509                    
510                    if let Some(return_ty) = fn_decl.return_ty.borrow().clone() {
511                        return Ok(return_ty);
512                    }
513                    return Err(LiveError {
514                        origin: live_error_origin!(),
515                        span:span.into(),
516                        message: format!("shader method `{}` is not type checked `{}`", ident, ty),
517                    });
518                }
519            },
520            Ty::Struct(struct_ptr) => {
521                //println!("GOT STRUCT {:?}", struct_ptr);
522                // ok lets find 'ident' on struct_ptr
523                if let Some(fn_decl) = self.shader_registry.struct_method_decl_from_ident(
524                    self.shader_registry.structs.get(&struct_ptr).unwrap(),
525                    ident
526                ) {
527                    for arg_expr in arg_exprs {
528                        self.ty_check_expr(arg_expr) ?;
529                    }
530
531                    self.check_call_args(span, fn_decl.fn_ptr, arg_exprs, fn_decl, Some(closure_site_index)) ?;
532                    
533                    if let Some(return_ty) = fn_decl.return_ty.borrow().clone() {
534                        return Ok(return_ty);
535                    }
536                    return Err(LiveError {
537                        origin: live_error_origin!(),
538                        span:span.into(),
539                        message: format!("struct method `{}` is not type checked `{}`", ident, ty),
540                    });
541                }
542            },
543            _ => ()
544        }
545        Err(LiveError {
546            origin: live_error_origin!(),
547            span:span.into(),
548            message: format!("method `{}` is not defined on type `{}`", ident, ty),
549        })
550    }
551    
552    
553    fn ty_check_builtin_call_expr(
554        &mut self,
555        span: TokenSpan,
556        ident: Ident,
557        arg_exprs: &[Expr],
558    ) -> Result<Ty, LiveError> {
559        for arg_expr in arg_exprs {
560            self.ty_check_expr(arg_expr) ?;
561        }
562        
563        let builtin = self.shader_registry.builtins.get(&ident).unwrap();
564        let arg_tys = arg_exprs
565            .iter()
566            .map( | arg_expr | arg_expr.ty.borrow().as_ref().unwrap().clone())
567            .collect::<Vec<_ >> ();
568        Ok(builtin .return_tys .get(&arg_tys) .ok_or_else(||{
569            let mut message = String::new();
570            
571            //if id == live_id!(color_file){
572             //   println!("CONST {:#?}", arg_exprs);
573            //}
574            
575            write!(
576                message,
577                "can't apply builtin `{}` to arguments of types ",
578                ident
579            )
580                .unwrap();
581            let mut sep = "";
582            for arg_ty in arg_tys {
583                write!(message, "{}{}", sep, arg_ty).unwrap();
584                sep = ", ";
585            }
586            LiveError {origin: live_error_origin!(), span:span.into(), message}
587        }) ? .clone())
588    }
589    
590    fn check_call_args(
591        &mut self,
592        span: TokenSpan,
593        fn_ptr: FnPtr,
594        arg_exprs: &[Expr],
595        fn_def: &FnDef,
596        closure_site_index: Option<&Cell<Option<usize>>>
597    ) -> Result<(), LiveError> {
598        match self.check_params_against_args(span, &fn_def.params, arg_exprs) {
599           Err(err)=> Err(LiveError {
600                origin: live_error_origin!(),
601                span:span.into(),
602                message: format!("function: `{}`: {}", self.shader_registry.fn_ident_from_ptr(self.live_registry, fn_ptr), err.message)
603            }),
604            Ok(closure_args)=>{
605                if closure_args.len()>0{
606                    let mut ci = self.scopes.closure_sites.borrow_mut();
607                    if closure_site_index.is_none(){
608                        return Err(LiveError {
609                            origin: live_error_origin!(),
610                            span:span.into(),
611                            message: format!("Closures not supported here {}", self.shader_registry.fn_ident_from_ptr(self.live_registry, fn_ptr))
612                        });
613                    }
614                    closure_site_index.unwrap().set(Some(ci.len()));
615                    ci.push(ClosureSite{
616                        call_to: fn_ptr,
617                        all_closed_over: BTreeSet::new(),
618                        closure_args
619                    })
620                }
621                Ok(())
622            }
623        }
624    }
625    
626    fn check_params_against_args(
627        &mut self,
628        span: TokenSpan,
629        params: &[Param],
630        arg_exprs: &[Expr],
631    ) -> Result<Vec<ClosureSiteArg>, LiveError> {
632        if arg_exprs.len() < params.len() {
633            return Err(LiveError {
634                origin: live_error_origin!(),
635                span:span.into(),
636                message: format!(
637                    "not enough arguments expected {}, got {}",
638                    params.len(),
639                    arg_exprs.len(),
640                )
641                    .into(),
642            });
643        }
644        if arg_exprs.len() > params.len() {
645            return Err(LiveError {
646                origin: live_error_origin!(),
647                span:span.into(),
648                message: format!(
649                    "too many arguments for call expected {}, got {}",
650                    params.len(),
651                    arg_exprs.len()
652                )
653                    .into(),
654            });
655        }
656        let mut closure_args= Vec::new();
657        for (param_index, (arg_expr, param)) in arg_exprs.iter().zip(params.iter()).enumerate()
658        {
659            let arg_ty = arg_expr.ty.borrow();
660            let arg_ty = arg_ty.as_ref().unwrap();
661            let param_ty = param.ty_expr.ty.borrow();
662            let param_ty = param_ty.as_ref().unwrap();
663            
664            // if the thing is a closure def / decl we have to do a deep compare
665            // we should have the closure def on our scopes
666            // and the closure decl should be on our param.ty_expr
667            if let Ty::ClosureDef(closure_def_index) = arg_ty{
668                if let Ty::ClosureDecl = param_ty{
669                    closure_args.push(ClosureSiteArg{
670                        param_index,
671                        closure_def_index:*closure_def_index,
672                    });
673                    continue
674                }
675            }
676            if arg_ty != param_ty {
677                return Err(LiveError {
678                    origin: live_error_origin!(),
679                    span:span.into(),
680                    message: format!(
681                        "wrong type for argument {} expected `{}`, got `{}`",
682                        param_index + 1,
683                        param_ty,
684                        arg_ty,
685                    ).into()
686                });
687            }
688            if param.is_inout {
689                self.lhs_checker().lhs_check_expr(arg_expr) ?;
690            }
691        }
692        if closure_args.len()>0{
693            
694        }
695        Ok(closure_args)
696    }
697    
698    fn ty_check_field_expr(
699        &mut self,
700        span: TokenSpan,
701        expr: &Expr,
702        field_ident: Ident,
703    ) -> Result<Ty, LiveError> {
704        let ty = self.ty_check_expr(expr) ?;
705        match ty {
706            ref ty if ty.is_vector() => {
707                let swizzle = Swizzle::parse(field_ident)
708                    .filter( | swizzle | {
709                    if swizzle.len() > 4 {
710                        return false;
711                    }
712                    let slots = ty.slots();
713                    for &index in swizzle {
714                        if index > slots {
715                            return false;
716                        }
717                    }
718                    true
719                })
720                    .ok_or_else( || LiveError {
721                    origin: live_error_origin!(),
722                    span:span.into(),
723                    message: format!("field `{}` is not defined on type `{}`", field_ident, ty),
724                }) ?;
725                Ok(match ty {
726                    Ty::Bvec2 | Ty::Bvec3 | Ty::Bvec4 => match swizzle.len() {
727                        1 => Ty::Bool,
728                        2 => Ty::Bvec2,
729                        3 => Ty::Bvec3,
730                        4 => Ty::Bvec4,
731                        _ => panic!(),
732                    },
733                    Ty::Ivec2 | Ty::Ivec3 | Ty::Ivec4 => match swizzle.len() {
734                        1 => Ty::Int,
735                        2 => Ty::Ivec2,
736                        3 => Ty::Ivec3,
737                        4 => Ty::Ivec4,
738                        _ => panic!(),
739                    },
740                    Ty::Vec2 | Ty::Vec3 | Ty::Vec4 => match swizzle.len() {
741                        1 => Ty::Float,
742                        2 => Ty::Vec2,
743                        3 => Ty::Vec3,
744                        4 => Ty::Vec4,
745                        _ => panic!(),
746                    },
747                    _ => panic!(),
748                })
749            }
750            Ty::Struct(struct_ptr) => {
751                Ok(self.shader_registry.structs.get(&struct_ptr) .unwrap() .find_field(field_ident) .ok_or(LiveError {
752                    origin: live_error_origin!(),
753                    span:span.into(),
754                    message: format!("field `{}` is not defined on type `{:?}`", field_ident, struct_ptr),
755                }) ? .ty_expr .ty .borrow() .as_ref() .unwrap() .clone())
756            },
757            Ty::DrawShader(shader_ptr) => {
758                Ok(self.shader_registry.draw_shader_defs.get(&shader_ptr).unwrap().find_field(field_ident) .ok_or(LiveError {
759                    origin: live_error_origin!(),
760                    span:span.into(),
761                    message: format!("field `{}` is not defined on shader `{:?}`", field_ident, shader_ptr),
762                }) ? .ty_expr .ty .borrow() .as_ref() .unwrap() .clone())
763            }
764            _ => Err(LiveError {
765                origin: live_error_origin!(),
766                span:span.into(),
767                message: format!("can't access field on value of type `{}`", ty).into(),
768            }),
769        }
770    }
771    
772    fn ty_check_index_expr(
773        &mut self,
774        span: TokenSpan,
775        expr: &Expr,
776        index_expr: &Expr,
777    ) -> Result<Ty, LiveError> {
778        let ty = self.ty_check_expr(expr) ?;
779        let index_ty = self.ty_check_expr(index_expr) ?;
780        let elem_ty = match ty {
781            Ty::Bvec2 | Ty::Bvec3 | Ty::Bvec4 => Ty::Bool,
782            Ty::Ivec2 | Ty::Ivec3 | Ty::Ivec4 => Ty::Int,
783            Ty::Vec2 | Ty::Vec3 | Ty::Vec4 => Ty::Float,
784            Ty::Mat2 => Ty::Vec2,
785            Ty::Mat3 => Ty::Vec3,
786            Ty::Mat4 => Ty::Vec4,
787            _ => {
788                return Err(LiveError {
789                    origin: live_error_origin!(),
790                    span:span.into(),
791                    message: format!("can't index into value of type `{}`", ty).into(),
792                })
793            }
794        };
795        if index_ty != Ty::Int {
796            return Err(LiveError {
797                origin: live_error_origin!(),
798                span:span.into(),
799                message: "index is not an integer".into(),
800            });
801        }
802        Ok(elem_ty)
803    }
804    
805    #[allow(clippy::redundant_closure_call)]
806    fn ty_check_cons_call_expr(
807        &mut self,
808        span: TokenSpan,
809        ty_lit: TyLit,
810        arg_exprs: &[Expr],
811    ) -> Result<Ty, LiveError> {
812        let ty = ty_lit.to_ty();
813        let arg_tys = arg_exprs
814            .iter()
815            .map( | arg_expr | self.ty_check_expr(arg_expr))
816            .collect::<Result<Vec<_>, _ >> () ?;
817        match (&ty, arg_tys.as_slice()) {
818            (ty, [arg_ty]) if ty.is_scalar() && arg_ty.is_scalar() => Ok(ty.clone()),
819            (ty, [arg_ty]) if ty.is_vector() && arg_ty.is_scalar() => Ok(ty.clone()),
820            (ty, [arg_ty]) if ty.is_matrix() && arg_ty.is_scalar() || arg_ty.is_matrix() => {
821                Ok(ty.clone())
822            }
823            (ty, arg_tys)
824            if ty.is_vector()
825                && ( || {
826                arg_tys.iter().all( | arg_ty | {
827                    arg_ty.is_scalar() || arg_ty.is_vector() || arg_ty.is_matrix()
828                })
829            })()
830                || ty.is_matrix()
831                && ( || {
832                arg_tys.iter().all( | arg_ty | {
833                    arg_ty.is_scalar() || arg_ty.is_vector() || arg_ty.is_matrix()
834                })
835            })() =>
836            {
837                let expected_slots = ty.slots();
838                let actual_slots = arg_tys.iter().map( | arg_ty | arg_ty.slots()).sum::<usize>();
839                if actual_slots < expected_slots {
840                    return Err(LiveError {
841                        origin: live_error_origin!(),
842                        span:span.into(),
843                        message: format!(
844                            "not enough components for call to constructor `{}`: expected {}, got {}",
845                            ty_lit,
846                            actual_slots,
847                            expected_slots,
848                        )
849                            .into()
850                    });
851                }
852                if actual_slots > expected_slots {
853                    return Err(LiveError {
854                        origin: live_error_origin!(),
855                        span:span.into(),
856                        message: format!(
857                            "too many components for call to constructor `{}`: expected {}, got {}",
858                            ty_lit,
859                            expected_slots,
860                            actual_slots,
861                        )
862                            .into(),
863                    });
864                }
865                Ok(ty.clone())
866            }
867            _ => Err(LiveError {
868                origin: live_error_origin!(),
869                span:span.into(),
870                message: format!(
871                    "can't construct value of type `{}` with arguments of types `{}`",
872                    ty,
873                    CommaSep(&arg_tys)
874                )
875                    .into(),
876            }),
877        }
878    }
879    
880    fn ty_check_var_expr(
881        &mut self,
882        span: TokenSpan,
883        kind: &Cell<Option<VarKind >>,
884        var_resolve: VarResolve,
885        ident: Option<Ident>,
886    ) -> Result<Ty, LiveError> {
887        
888        if let Some(ident) = ident{
889            match self.scopes.find_sym_on_scopes(ident, span) {
890                Some(scopesym)=> {
891                    scopesym.referenced.set(true);
892                    match &scopesym.kind{
893                        ScopeSymKind::MutLocal => {
894                            kind.set(Some(VarKind::MutLocal{ident, shadow:scopesym.sym.shadow}));
895                            return Ok(scopesym.sym.ty.clone())
896                        }
897                        ScopeSymKind::Local => {
898                            kind.set(Some(VarKind::Local{ident, shadow:scopesym.sym.shadow}));
899                            return Ok(scopesym.sym.ty.clone())
900                        }
901                        ScopeSymKind::Closure{..}=>{
902                            // ok the thing is a closure..
903                            // except we dont know what kind of closure
904                            
905                            return Err(LiveError {
906                                origin: live_error_origin!(),
907                                span:span.into(),
908                                message: format!("`{}` is a closure and cannot be used as a variable", ident),
909                            })
910                        }
911                    }
912                }
913                _=>()
914            }
915        }
916        // use the suggestion
917        match var_resolve {
918            VarResolve::LiveValue(value_ptr, ty_lit) => {
919                kind.set(Some(VarKind::LiveValue(value_ptr)));
920                return Ok(ty_lit.to_ty());
921            }
922            VarResolve::Function(fn_ptr) => {
923                return Err(LiveError {
924                    origin: live_error_origin!(),
925                    span:span.into(),
926                    message: format!("`{}` implement using functions as closure args", ident.unwrap()),
927                })
928            }
929            VarResolve::NotFound => {
930                 
931                return Err(LiveError {
932                    origin: live_error_origin!(),
933                    span:span.into(),
934                    message: format!("`{}` is not defined in this scope", ident.unwrap()),
935                })
936            }
937        }
938    }
939    
940    fn ty_check_struct_cons(
941        &mut self,
942        struct_ptr: StructPtr,
943        span: TokenSpan,
944        args: &Vec<(Ident, Expr)>,
945    ) -> Result<Ty, LiveError> {
946
947        let struct_decl = self.shader_registry.structs.get(&struct_ptr).unwrap();
948        for (ident, expr) in args {
949            self.ty_check_expr(expr) ?;
950            // ok so now we find ident, then check the type
951            if let Some(field) = struct_decl.fields.iter().find( | field | field.ident == *ident) {
952                // ok so the field has a TyExpr
953                let field_ty = field.ty_expr.ty.borrow();
954                let my_ty = expr.ty.borrow();
955                if field_ty.as_ref() != my_ty.as_ref() {
956                    return Err(LiveError {
957                        origin: live_error_origin!(),
958                        span:span.into(),
959                        message: format!("field `{}` is the wrong type {} instead of {}", ident, my_ty.as_ref().unwrap(), field_ty.as_ref().unwrap()),
960                    })
961                }
962            }
963            else {
964                return Err(LiveError {
965                    origin: live_error_origin!(),
966                    span:span.into(),
967                    message: format!("`{}` is not a valid struct field", ident),
968                })
969            }
970        }
971        // if we are missing idents or have doubles, error
972        for field in &struct_decl.fields {
973            if args.iter().position( | (ident, expr) | ident == &field.ident).is_none() {
974                return Err(LiveError {
975                    origin: live_error_origin!(),
976                    span:span.into(),
977                    message: format!("`{}` field is missing", field.ident),
978                })
979            }
980        }
981        for i in 0..args.len() {
982            for j in (i + 1)..args.len() {
983                if args[i].0 == args[j].0 { // duplicate
984                    return Err(LiveError {
985                        origin: live_error_origin!(),
986                        span:span.into(),
987                        message: format!("`{}` field is duplicated", args[i].0),
988                    })
989                }
990            }
991        }
992        // its all ok.
993        Ok(Ty::Struct(struct_ptr))
994    }
995    
996    fn ty_check_lit_expr(&mut self, _span: TokenSpan, lit: Lit) -> Result<Ty, LiveError> {
997        Ok(lit.to_ty())
998    }
999}