1#![allow(dead_code)]
13use crate::SourceRead;
14
15use super::super::lookup::{self, LookupResult, MethodSet};
16use super::super::obj::EntityType;
17use super::super::objects::TypeKey;
18use super::super::operand::{Operand, OperandMode};
19use super::super::selection::{Selection, SelectionKind};
20use super::super::typ;
21use super::super::universe::ExprKind;
22use super::check::{Checker, FilesContext};
23use super::util::{UnpackResult, UnpackedResultLeftovers};
24use go_parser::ast::{CallExpr, Expr, Node, SelectorExpr};
25use go_parser::Pos;
26use std::rc::Rc;
27
28impl<'a, S: SourceRead> Checker<'a, S> {
29 pub fn call(
30 &mut self,
31 x: &mut Operand,
32 e: &Rc<CallExpr>,
33 fctx: &mut FilesContext<S>,
34 ) -> ExprKind {
35 self.expr_or_type(x, &e.func, fctx);
36
37 let expr = Some(Expr::Call(e.clone()));
38 match x.mode {
39 OperandMode::Invalid => {
40 self.use_exprs(&e.args, fctx);
41 x.expr = expr;
42 ExprKind::Statement
43 }
44 OperandMode::TypeExpr => {
45 let t = x.typ.unwrap();
47 x.mode = OperandMode::Invalid;
48 match e.args.len() {
49 0 => self.error(
50 e.r_paren,
51 format!("missing argument in conversion to {}", self.new_dis(&t)),
52 ),
53 1 => {
54 self.expr(x, &e.args[0], fctx);
55 if !x.invalid() {
56 self.conversion(x, t, fctx);
57 }
58 }
59 _ => {
60 self.use_exprs(&e.args, fctx);
61 self.error(
62 e.args[e.args.len() - 1].pos(self.ast_objs),
63 format!("too many arguments in conversion to {}", self.new_dis(&t)),
64 )
65 }
66 }
67 x.expr = expr;
68 ExprKind::Conversion
69 }
70 OperandMode::Builtin(id) => {
71 if !self.builtin(x, e, id, fctx) {
72 x.mode = OperandMode::Invalid;
73 }
74 x.expr = expr;
75 self.octx.has_call_or_recv = match x.mode {
77 OperandMode::Invalid | OperandMode::Constant(_) => false,
78 _ => true,
79 };
80 self.tc_objs.universe().builtins()[&id].kind
81 }
82 _ => {
83 let sig_key = typ::underlying_type(x.typ.unwrap(), self.tc_objs);
85 if let Some(sig) = self.otype(sig_key).try_as_signature() {
86 let sig_results = sig.results();
87 let variadic = sig.variadic();
88 let pcount = sig.params_count(self.tc_objs);
89 let result = self.unpack(&e.args, pcount, false, variadic, fctx);
90 match result {
91 UnpackResult::Error => x.mode = OperandMode::Invalid,
92 _ => {
93 let (count, _) = result.rhs_count();
94 let re = UnpackedResultLeftovers::new(&result, None);
95 self.arguments(x, e, sig_key, &re, count, fctx);
96 }
97 }
98
99 let sigre = self.tc_objs.types[sig_results].try_as_tuple().unwrap();
101 match sigre.vars().len() {
102 0 => x.mode = OperandMode::NoValue,
103 1 => {
104 x.mode = OperandMode::Value;
105 x.typ = self.lobj(sigre.vars()[0]).typ(); }
107 _ => {
108 x.mode = OperandMode::Value;
109 x.typ = Some(sig_results);
110 }
111 }
112 self.octx.has_call_or_recv = true;
113 } else {
114 let dis = self.new_dis(x);
115 self.invalid_op(dis.pos(), &format!("cannot call non-function {}", dis));
116 x.mode = OperandMode::Invalid;
117 }
118 x.expr = expr;
119 ExprKind::Statement
120 }
121 }
122 }
123
124 pub fn arguments(
126 &mut self,
127 x: &mut Operand,
128 call: &CallExpr,
129 sig: TypeKey,
130 re: &UnpackedResultLeftovers,
131 n: usize,
132 fctx: &mut FilesContext<S>,
133 ) {
134 let sig_val = self.otype(sig).try_as_signature().unwrap();
135 let variadic = sig_val.variadic();
136 let params = self.otype(sig_val.params()).try_as_tuple().unwrap();
137 let params_len = params.vars().len();
138 if let Some(ell) = call.ellipsis {
139 if !variadic {
140 let dis = self.new_dis(&call.func);
141 self.error(
142 ell,
143 format!("cannot use ... in call to non-variadic {}", dis),
144 );
145 re.use_all(self, fctx);
146 return;
147 }
148 if call.args.len() == 1 && n > 1 {
149 let dis = self.new_dis(&call.args[0]);
150 self.error(ell, format!("cannot use ... with {}-valued {}", n, dis));
151 re.use_all(self, fctx);
152 return;
153 }
154 }
155
156 let note = &format!("argument to {}", self.new_dis(&call.func));
158 for i in 0..n {
159 re.get(self, x, i, fctx);
160 if !x.invalid() {
161 let ellipsis = if i == n - 1 { call.ellipsis } else { None };
162 self.argument(sig, i, x, ellipsis, note, fctx);
163 }
164 }
165
166 let count = if variadic { n + 1 } else { n };
170 if count < params_len {
171 let dis = self.new_dis(&call.func);
172 self.error(
173 call.r_paren,
174 format!("too few arguments in call to {}", dis),
175 );
176 }
177 }
178
179 fn argument(
182 &mut self,
183 sig: TypeKey,
184 i: usize,
185 x: &mut Operand,
186 ellipsis: Option<Pos>,
187 note: &str,
188 fctx: &mut FilesContext<S>,
189 ) {
190 self.single_value(x);
191 if x.invalid() {
192 return;
193 }
194
195 let sig_val = self.otype(sig).try_as_signature().unwrap();
196 let params = self.otype(sig_val.params()).try_as_tuple().unwrap();
197 let n = params.vars().len();
198
199 let mut ty = if i < n {
200 self.lobj(params.vars()[i]).typ().unwrap()
201 } else if sig_val.variadic() {
202 let t = self.lobj(params.vars()[n - 1]).typ().unwrap();
203 if cfg!(debug_assertions) {
204 if self.otype(t).try_as_slice().is_none() {
205 let pos = self.lobj(params.vars()[n - 1]).pos();
206 let td = self.new_dis(&t);
207 self.dump(
208 Some(pos),
209 &format!("expected unnamed slice type, got {}", td),
210 );
211 }
212 }
213 t
214 } else {
215 self.error_str(x.pos(self.ast_objs), "too many arguments");
216 return;
217 };
218
219 if let Some(pos) = ellipsis {
220 if i != n - 1 {
222 self.error_str(pos, "can only use ... with matching parameter");
223 return;
224 }
225 let xtype = x.typ.unwrap();
226 if self
227 .otype(xtype)
228 .underlying_val(self.tc_objs)
229 .try_as_slice()
230 .is_none()
231 && xtype != self.basic_type(typ::BasicType::UntypedNil)
232 {
233 let xd = self.new_dis(x);
234 let td = self.new_dis(&ty);
235 self.error(
236 xd.pos(),
237 format!("cannot use {} as parameter of type {}", xd, td),
238 );
239 return;
240 }
241 } else if sig_val.variadic() && i >= n - 1 {
242 ty = self.otype(ty).try_as_slice().unwrap().elem();
243 }
244
245 self.assignment(x, Some(ty), note, fctx);
246 }
247
248 pub fn selector(&mut self, x: &mut Operand, e: &Rc<SelectorExpr>, fctx: &mut FilesContext<S>) {
249 let err_exit = |x: &mut Operand| {
250 x.mode = OperandMode::Invalid;
251 x.expr = Some(Expr::Selector(e.clone()));
252 };
253
254 match &e.expr {
259 Expr::Ident(ikey) => {
260 let ident = self.ast_ident(*ikey);
261 if let Some(okey) = self.lookup(&ident.name) {
262 let lobj = &mut self.tc_objs.lobjs[okey];
263 let lobj_pkg = lobj.pkg();
264 match lobj.entity_type_mut() {
265 EntityType::PkgName(imported, used) => {
266 debug_assert_eq!(self.pkg, lobj_pkg.unwrap());
267 self.result.record_use(*ikey, okey);
268 *used = true;
269 let pkg = &self.tc_objs.pkgs[*imported];
270 let sel_name = &self.ast_objs.idents[e.sel].name;
271 let exp_op = self.tc_objs.scopes[*pkg.scope()].lookup(sel_name);
272 if exp_op.is_none() {
273 if !pkg.fake() {
274 let pos = self.ast_ident(e.sel).pos;
275 let msg = format!(
276 "{} not declared by package {}",
277 sel_name,
278 pkg.name().as_ref().unwrap()
279 );
280 self.error(pos, msg);
281 }
282 return err_exit(x);
283 }
284 let exp = self.lobj(*exp_op.unwrap());
285 if !exp.exported() {
286 let pos = self.ast_ident(e.sel).pos;
287 let msg = format!(
288 "{} not declared by package {}",
289 sel_name,
290 pkg.name().as_ref().unwrap()
291 );
292 self.error(pos, msg);
293 }
294 self.result.record_use(e.sel, *exp_op.unwrap());
295
296 let exp = self.lobj(*exp_op.unwrap());
299 x.mode = match exp.entity_type() {
300 EntityType::Const(v) => OperandMode::Constant(v.clone()),
301 EntityType::TypeName => OperandMode::TypeExpr,
302 EntityType::Var(_) => OperandMode::Variable,
303 EntityType::Func(_) => OperandMode::Value,
304 EntityType::Builtin(id) => OperandMode::Builtin(*id),
305 _ => unreachable!(),
306 };
307 x.typ = exp.typ();
308 x.expr = Some(Expr::Selector(e.clone()));
309 return;
310 }
311 _ => {}
312 }
313 }
314 }
315 _ => {}
316 }
317
318 self.expr_or_type(x, &e.expr, fctx);
319 if x.invalid() {
320 return err_exit(x);
321 }
322
323 let sel_name = &self.ast_objs.idents[e.sel].name;
324 let result = lookup::lookup_field_or_method(
325 x.typ.unwrap(),
326 x.mode == OperandMode::Variable,
327 Some(self.pkg),
328 sel_name,
329 self.tc_objs,
330 );
331
332 let (okey, indices, indirect) = match result {
333 LookupResult::Entry(okey, indices, indirect) => (okey, indices, indirect),
334 _ => {
335 let pos = self.ast_ident(e.sel).pos;
336 let msg = match &result {
337 LookupResult::Ambiguous(_) => format!("ambiguous selector {}", sel_name),
338 LookupResult::NotFound => {
339 let ed = self.new_dis(x.expr.as_ref().unwrap());
340 let td = self.new_td_o(&x.typ);
341 format!(
342 "{}.{} undefined (type {} has no field or method {})",
343 ed, sel_name, td, sel_name
344 )
345 }
346 LookupResult::BadMethodReceiver => {
347 let td = self.new_td_o(&x.typ);
348 format!("{} is not in method set of {}", sel_name, td)
349 }
350 LookupResult::Entry(_, _, _) => unreachable!(),
351 };
352 self.error(pos, msg);
353 return err_exit(x);
354 }
355 };
356
357 if self.lobj(okey).entity_type().is_func() {
359 self.obj_decl(okey, None, fctx);
360 }
361
362 let sel_name = &self.ast_objs.idents[e.sel].name;
363 if x.mode == OperandMode::TypeExpr {
364 match self.lobj(okey).entity_type() {
366 EntityType::Func(_) => {
367 let selection = Selection::new(
368 SelectionKind::MethodExpr,
369 x.typ,
370 okey,
371 indices,
372 indirect,
373 self.tc_objs,
374 );
375 self.result.record_selection(e, selection);
376
377 let var = self
380 .tc_objs
381 .new_var(0, Some(self.pkg), "".to_owned(), x.typ);
382 let lobj = self.lobj(okey);
383 let sig = self.otype(lobj.typ().unwrap()).try_as_signature().unwrap();
384 let (p, r, v) = (sig.params(), sig.results(), sig.variadic());
385 let params_val = self.otype(p).try_as_tuple().unwrap();
386 let mut vars = vec![var];
387 vars.append(&mut params_val.vars().clone());
388 let params = self.tc_objs.new_t_tuple(vars);
389 let new_sig = self.tc_objs.new_t_signature(None, None, params, r, v);
390 x.mode = OperandMode::Value;
391 x.typ = Some(new_sig);
392
393 self.add_decl_dep(okey);
394 }
395 _ => {
396 let ed = self.new_dis(x.expr.as_ref().unwrap());
397 let td = self.new_td_o(&x.typ);
398 let msg = format!(
399 "{}.{} undefined (type {} has no method {})",
400 ed, sel_name, td, sel_name
401 );
402 self.error(self.ast_ident(e.sel).pos, msg);
403 return err_exit(x);
404 }
405 }
406 } else {
407 let lobj = &self.tc_objs.lobjs[okey];
409 match lobj.entity_type() {
410 EntityType::Var(_) => {
411 let selection = Selection::new(
412 SelectionKind::FieldVal,
413 x.typ,
414 okey,
415 indices,
416 indirect,
417 self.tc_objs,
418 );
419 self.result.record_selection(e, selection);
420 x.mode = if x.mode == OperandMode::Variable || indirect {
421 OperandMode::Variable
422 } else {
423 OperandMode::Value
424 };
425 x.typ = lobj.typ();
426 }
427 EntityType::Func(_) => {
428 let selection = Selection::new(
429 SelectionKind::MethodVal,
430 x.typ,
431 okey,
432 indices,
433 indirect,
434 self.tc_objs,
435 );
436 self.result.record_selection(e, selection);
437
438 if cfg!(debug_assertions) {
439 let mut typ = x.typ.unwrap();
441 if x.mode == OperandMode::Variable {
442 if self.otype(typ).try_as_pointer().is_none()
448 && !typ::is_interface(typ, self.tc_objs)
449 {
450 typ = self.tc_objs.new_t_pointer(typ);
451 }
452 }
453 let mset = MethodSet::new(&typ, self.tc_objs);
454 let re = mset.lookup(&self.pkg, sel_name, self.tc_objs);
455 if re.is_none() || re.unwrap().obj() != okey {
456 let obj_name = self.lobj(okey).name();
457 let expr = Expr::Selector(e.clone());
458 let ed = self.new_dis(&expr);
459 let td = self.new_dis(&typ);
460 let md = self.new_dis(re.unwrap());
461 self.dump(
462 None,
463 &format!("{}: ({}).{} -> {}", ed.pos(), td, obj_name, md),
464 );
465 self.dump(None, &format!("{}\n", self.new_dis(&mset)));
466 panic!("method sets and lookup don't agree");
467 }
468 }
469
470 x.mode = OperandMode::Value;
471
472 let lobj = &self.tc_objs.lobjs[okey];
474 let sig = self.otype(lobj.typ().unwrap()).try_as_signature().unwrap();
475 let (p, r, v) = (sig.params(), sig.results(), sig.variadic());
476 let new_sig = self.tc_objs.new_t_signature(None, None, p, r, v);
477 x.typ = Some(new_sig);
478
479 self.add_decl_dep(okey);
480 }
481 _ => unreachable!(),
482 }
483 }
484 x.expr = Some(Expr::Selector(e.clone()));
485 }
486}