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 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(¶m.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 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 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, ¶ms, arg_exprs) ?;
454 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 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 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) => { 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 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 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 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 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 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 if let Some(field) = struct_decl.fields.iter().find( | field | field.ident == *ident) {
952 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 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 { 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 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}