1#![allow(dead_code)]
2use super::constant;
3use super::lookup::missing_method;
4use super::objects::{TCObjects, TypeKey};
5use super::typ;
6use super::typ::{fmt_type, BasicType, Type};
7use super::universe::{Builtin, Universe};
8use goscript_parser::ast;
9use goscript_parser::ast::*;
10use goscript_parser::objects::{FuncTypeKey, IdentKey, Objects as AstObjects};
11use goscript_parser::position;
12use goscript_parser::token::Token;
13use goscript_parser::visitor::{walk_expr, ExprVisitor};
14use std::fmt;
15use std::fmt::Display;
16use std::fmt::Write;
17
18#[derive(Clone, Debug, PartialEq)]
20pub enum OperandMode {
21 Invalid, NoValue, Builtin(Builtin), TypeExpr, Constant(constant::Value), Variable, MapIndex, Value, CommaOk, }
31
32impl OperandMode {
33 pub fn constant_val(&self) -> Option<&constant::Value> {
34 match self {
35 OperandMode::Constant(v) => Some(v),
36 _ => None,
37 }
38 }
39
40 pub fn builtin_id(&self) -> Option<Builtin> {
41 match self {
42 OperandMode::Builtin(id) => Some(*id),
43 _ => None,
44 }
45 }
46}
47
48impl fmt::Display for OperandMode {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 f.write_str(match self {
51 OperandMode::Invalid => "invalid operand",
52 OperandMode::NoValue => "no value",
53 OperandMode::Builtin(_) => "built-in",
54 OperandMode::TypeExpr => "type",
55 OperandMode::Constant(_) => "constant",
56 OperandMode::Variable => "variable",
57 OperandMode::MapIndex => "map index expression",
58 OperandMode::Value => "value",
59 OperandMode::CommaOk => "comma, ok expression",
60 })
61 }
62}
63
64#[derive(Clone, Debug)]
69pub struct Operand {
70 pub mode: OperandMode,
71 pub expr: Option<ast::Expr>,
72 pub typ: Option<TypeKey>,
73}
74
75impl Operand {
76 pub fn new() -> Operand {
77 Operand::with(OperandMode::Invalid, None, None)
78 }
79
80 pub fn with(mode: OperandMode, expr: Option<ast::Expr>, typ: Option<TypeKey>) -> Operand {
81 Operand {
82 mode: mode,
83 expr: expr,
84 typ: typ,
85 }
86 }
87
88 pub fn invalid(&self) -> bool {
89 self.mode == OperandMode::Invalid
90 }
91
92 pub fn pos(&self, ast_objs: &AstObjects) -> position::Pos {
93 if let Some(e) = &self.expr {
94 e.pos(ast_objs)
95 } else {
96 0
97 }
98 }
99
100 pub fn set_const(&mut self, t: &Token, u: &Universe) {
101 let bt = match t {
102 Token::INT(_) => BasicType::UntypedInt,
103 Token::FLOAT(_) => BasicType::UntypedFloat,
104 Token::IMAG(_) => BasicType::UntypedComplex,
105 Token::CHAR(_) => BasicType::UntypedRune,
106 Token::STRING(_) => BasicType::UntypedString,
107 _ => unreachable!(),
108 };
109 self.mode = OperandMode::Constant(constant::Value::with_literal(t));
110 self.typ = Some(u.types()[&bt]);
111 }
112
113 pub fn is_nil(&self, u: &Universe) -> bool {
114 match self.mode {
115 OperandMode::Value => self.typ == Some(u.types()[&BasicType::UntypedNil]),
116 _ => false,
117 }
118 }
119
120 pub fn assignable_to(&self, t: TypeKey, reason: Option<&mut String>, objs: &TCObjects) -> bool {
124 let u = objs.universe();
125 if self.invalid() || t == u.types()[&BasicType::Invalid] {
126 return true; }
128
129 if typ::identical(self.typ.unwrap(), t, objs) {
130 return true;
131 }
132
133 let (k_left, k_right) = (t, self.typ.unwrap());
134 let t_left = &objs.types[k_left];
135 let t_right = &objs.types[k_right];
136 let ut_key_left = typ::underlying_type(k_left, objs);
137 let ut_key_right = typ::underlying_type(k_right, objs);
138 let ut_left = &objs.types[ut_key_left];
139 let ut_right = &objs.types[ut_key_right];
140
141 if ut_right.is_untyped(objs) {
142 match ut_left {
143 Type::Basic(detail) => {
144 if self.is_nil(u) && detail.typ() == BasicType::UnsafePointer {
145 return true;
146 }
147 if let OperandMode::Constant(val) = &self.mode {
148 return val.representable(detail, None);
149 }
150 if detail.typ() == BasicType::Bool {
153 return ut_right.try_as_basic().unwrap().typ() == BasicType::UntypedBool;
154 }
155 }
156 Type::Interface(detail) => return self.is_nil(u) || detail.is_empty(),
157 Type::Pointer(_)
158 | Type::Signature(_)
159 | Type::Slice(_)
160 | Type::Map(_)
161 | Type::Chan(_) => return self.is_nil(u),
162 _ => {}
163 }
164 }
165
166 if typ::identical(ut_key_right, ut_key_left, objs)
170 && (!t_right.is_named() || !t_left.is_named())
171 {
172 return true;
173 }
174
175 if let Some(_) = ut_left.try_as_interface() {
177 if let Some((m, wrong_type)) = missing_method(k_right, ut_key_left, true, objs) {
178 if let Some(re) = reason {
179 let msg = if wrong_type {
180 "wrong type for method"
181 } else {
182 "missing method"
183 };
184 *re = format!("{} {}", msg, objs.lobjs[m].name());
185 }
186 return false;
187 }
188 return true;
189 }
190
191 if let Some(cr) = ut_right.try_as_chan() {
195 if cr.dir() == typ::ChanDir::SendRecv {
196 if let Some(cl) = ut_left.try_as_chan() {
197 if typ::identical(cr.elem(), cl.elem(), objs) {
198 return !t_right.is_named() || !t_left.is_named();
199 }
200 }
201 }
202 }
203
204 false
205 }
206
207 pub fn fmt(
234 &self,
235 f: &mut fmt::Formatter<'_>,
236 tc_objs: &TCObjects,
237 ast_objs: &AstObjects,
238 ) -> fmt::Result {
239 let universe = tc_objs.universe();
240 let mut has_expr = true;
241
242 if let Some(expr) = &self.expr {
244 fmt_expr(&expr, f, ast_objs)?;
245 } else {
246 match &self.mode {
247 OperandMode::Builtin(bi) => {
248 f.write_str(universe.builtins()[bi].name)?;
249 }
250 OperandMode::TypeExpr => {
251 fmt_type(self.typ, f, tc_objs)?;
252 }
253 OperandMode::Constant(val) => {
254 f.write_str(&val.to_string())?;
255 }
256 _ => has_expr = false,
257 }
258 }
259 if has_expr {
260 f.write_str(" (")?;
261 }
262
263 let has_type = match self.mode {
265 OperandMode::Invalid
266 | OperandMode::NoValue
267 | OperandMode::Builtin(_)
268 | OperandMode::TypeExpr => false,
269 _ => {
270 let tval = &tc_objs.types[self.typ.unwrap()];
271 if tval.is_untyped(tc_objs) {
272 f.write_str(tval.try_as_basic().unwrap().name())?;
273 f.write_char(' ')?;
274 false
275 } else {
276 true
277 }
278 }
279 };
280
281 self.mode.fmt(f)?;
283
284 if let OperandMode::Constant(val) = &self.mode {
286 if self.expr.is_some() {
287 f.write_char(' ')?;
288 f.write_str(&val.to_string())?;
289 }
290 }
291
292 if has_type {
294 if self.typ != Some(universe.types()[&BasicType::Invalid]) {
295 f.write_str(" of type ")?;
296 fmt_type(self.typ, f, tc_objs)?;
297 } else {
298 f.write_str(" with invalid type")?;
299 }
300 }
301
302 if has_expr {
304 f.write_char(')')?;
305 }
306 Ok(())
307 }
308}
309
310pub fn fmt_expr(expr: &Expr, f: &mut fmt::Formatter<'_>, ast_objs: &AstObjects) -> fmt::Result {
314 ExprFormater {
319 f: f,
320 ast_objs: ast_objs,
321 }
322 .visit_expr(expr)
323}
324
325struct ExprFormater<'a, 'b> {
326 f: &'a mut fmt::Formatter<'b>,
327 ast_objs: &'a AstObjects,
328}
329
330impl<'a, 'b> ExprVisitor for ExprFormater<'a, 'b> {
331 type Result = fmt::Result;
332
333 fn visit_expr(&mut self, expr: &Expr) -> Self::Result {
334 walk_expr(self, expr)
335 }
336
337 fn visit_expr_ident(&mut self, _: &Expr, ident: &IdentKey) -> Self::Result {
338 self.fmt_ident(ident)
339 }
340
341 fn visit_expr_ellipsis(&mut self, _: &Expr, els: &Option<Expr>) -> Self::Result {
342 self.f.write_str("...")?;
343 if let Some(e) = els {
344 self.visit_expr(e)?;
345 }
346 Ok(())
347 }
348
349 fn visit_expr_basic_lit(&mut self, _: &Expr, blit: &BasicLit) -> Self::Result {
350 blit.token.fmt(self.f)
351 }
352
353 fn visit_expr_func_lit(&mut self, this: &Expr, flit: &FuncLit) -> Self::Result {
354 self.f.write_char('(')?;
355 self.visit_expr_func_type(this, &flit.typ)?;
356 self.f.write_str(" literal)")
357 }
358
359 fn visit_expr_composit_lit(&mut self, _: &Expr, clit: &CompositeLit) -> Self::Result {
360 self.f.write_char('(')?;
361 match &clit.typ {
362 Some(t) => {
363 self.visit_expr(t)?;
364 }
365 None => {
366 self.f.write_str("(bad expr)")?;
367 }
368 }
369 self.f.write_str(" literal)")
370 }
371
372 fn visit_expr_paren(&mut self, _: &Expr, expr: &Expr) -> Self::Result {
373 self.f.write_char('(')?;
374 self.visit_expr(expr)?;
375 self.f.write_char(')')
376 }
377
378 fn visit_expr_selector(&mut self, this: &Expr, expr: &Expr, ident: &IdentKey) -> Self::Result {
379 self.visit_expr(expr)?;
380 self.f.write_char('.')?;
381 self.visit_expr_ident(this, ident)
382 }
383
384 fn visit_expr_index(&mut self, _: &Expr, expr: &Expr, index: &Expr) -> Self::Result {
385 self.visit_expr(expr)?;
386 self.f.write_char('[')?;
387 self.visit_expr(index)?;
388 self.f.write_char(']')
389 }
390
391 fn visit_expr_slice(
392 &mut self,
393 _: &Expr,
394 expr: &Expr,
395 low: &Option<Expr>,
396 high: &Option<Expr>,
397 max: &Option<Expr>,
398 ) -> Self::Result {
399 self.visit_expr(expr)?;
400 self.f.write_char('[')?;
401 if let Some(l) = low {
402 self.visit_expr(l)?;
403 }
404 self.f.write_char(':')?;
405 if let Some(h) = high {
406 self.visit_expr(h)?;
407 }
408 if let Some(m) = max {
409 self.f.write_char(':')?;
410 self.visit_expr(m)?;
411 }
412 self.f.write_char(']')
413 }
414
415 fn visit_expr_type_assert(
416 &mut self,
417 _: &Expr,
418 expr: &Expr,
419 typ: &Option<Expr>,
420 ) -> Self::Result {
421 self.visit_expr(expr)?;
422 self.f.write_str(".(")?;
423 match &typ {
424 Some(t) => {
425 self.visit_expr(t)?;
426 }
427 None => {
428 self.f.write_str("(bad expr)")?;
429 }
430 }
431 self.f.write_char(')')
432 }
433
434 fn visit_expr_call(
435 &mut self,
436 _: &Expr,
437 func: &Expr,
438 args: &Vec<Expr>,
439 ellipsis: bool,
440 ) -> Self::Result {
441 self.visit_expr(func)?;
442 self.f.write_char('(')?;
443 for (i, arg) in args.iter().enumerate() {
444 if i > 0 {
445 self.f.write_str(", ")?;
446 }
447 self.visit_expr(arg)?;
448 }
449 if ellipsis {
450 self.f.write_str("...")?;
451 }
452 self.f.write_char(')')
453 }
454
455 fn visit_expr_star(&mut self, _: &Expr, expr: &Expr) -> Self::Result {
456 self.f.write_char('*')?;
457 self.visit_expr(expr)
458 }
459
460 fn visit_expr_unary(&mut self, _: &Expr, expr: &Expr, op: &Token) -> Self::Result {
461 op.fmt(self.f)?;
462 self.visit_expr(expr)
463 }
464
465 fn visit_expr_binary(
466 &mut self,
467 _: &Expr,
468 left: &Expr,
469 op: &Token,
470 right: &Expr,
471 ) -> Self::Result {
472 self.visit_expr(left)?;
473 self.f.write_fmt(format_args!(" {} ", op))?;
474 self.visit_expr(right)
475 }
476
477 fn visit_expr_key_value(&mut self, _: &Expr, _: &Expr, _: &Expr) -> Self::Result {
478 self.f.write_str("(bad expr)")
479 }
480
481 fn visit_expr_array_type(&mut self, _: &Expr, len: &Option<Expr>, elm: &Expr) -> Self::Result {
482 self.f.write_char('[')?;
483 if let Some(l) = len {
484 self.visit_expr(l)?;
485 }
486 self.f.write_char(']')?;
487 self.visit_expr(elm)
488 }
489
490 fn visit_expr_struct_type(&mut self, _: &Expr, s: &StructType) -> Self::Result {
491 self.f.write_str("struct{")?;
492 self.fmt_fields(&s.fields, "; ", false)?;
493 self.f.write_char('}')
494 }
495
496 fn visit_expr_func_type(&mut self, _: &Expr, s: &FuncTypeKey) -> Self::Result {
497 self.f.write_str("func")?;
498 self.fmt_sig(&self.ast_objs.ftypes[*s])
499 }
500
501 fn visit_expr_interface_type(&mut self, _: &Expr, s: &InterfaceType) -> Self::Result {
502 self.f.write_str("interface{")?;
503 self.fmt_fields(&s.methods, "; ", true)?;
504 self.f.write_char('}')
505 }
506
507 fn visit_map_type(&mut self, _: &Expr, key: &Expr, val: &Expr, _: &Expr) -> Self::Result {
508 self.f.write_str("map[")?;
509 self.visit_expr(key)?;
510 self.f.write_char(']')?;
511 self.visit_expr(val)
512 }
513
514 fn visit_chan_type(&mut self, _: &Expr, chan: &Expr, dir: &ChanDir) -> Self::Result {
515 let s = match dir {
516 ChanDir::Send => "chan<- ",
517 ChanDir::Recv => "<-chan ",
518 ChanDir::SendRecv => "chan ",
519 };
520 self.f.write_str(s)?;
521 self.visit_expr(chan)
522 }
523
524 fn visit_bad_expr(&mut self, _: &Expr, _: &BadExpr) -> Self::Result {
525 self.f.write_str("(bad expr)")
526 }
527}
528
529impl<'a, 'b> ExprFormater<'a, 'b> {
530 fn fmt_sig(&mut self, sig: &FuncType) -> fmt::Result {
531 self.f.write_char('(')?;
532 self.fmt_fields(&sig.params, ", ", false)?;
533 self.f.write_char(')')?;
534 if let Some(re) = &sig.results {
535 self.f.write_char(' ')?;
536 if re.list.len() == 1 {
537 let field = &self.ast_objs.fields[re.list[0]];
538 if field.names.len() == 0 {
539 self.visit_expr(&field.typ)?;
540 }
541 } else {
542 self.f.write_char('(')?;
543 self.fmt_fields(&re, ", ", false)?;
544 self.f.write_char(')')?;
545 }
546 }
547 Ok(())
548 }
549
550 fn fmt_fields(&mut self, fields: &FieldList, sep: &str, iface: bool) -> fmt::Result {
551 for (i, fkey) in fields.list.iter().enumerate() {
552 if i > 0 {
553 self.f.write_str(sep)?;
554 }
555 let field = &self.ast_objs.fields[*fkey];
556 for (i, name) in field.names.iter().enumerate() {
557 if i > 0 {
558 self.f.write_str(", ")?;
559 self.fmt_ident(name)?;
560 }
561 }
562 if iface {
564 match &field.typ {
565 Expr::Func(sig) => {
566 self.fmt_sig(&self.ast_objs.ftypes[*sig])?;
567 }
568 _ => {}
569 }
570 } else {
571 if field.names.len() > 0 {
573 self.f.write_char(' ')?;
574 }
575 self.visit_expr(&field.typ)?;
576 }
577 }
578 Ok(())
579 }
580
581 fn fmt_ident(&mut self, ident: &IdentKey) -> fmt::Result {
582 self.f.write_str(&self.ast_objs.idents[*ident].name)
583 }
584}