1#![allow(dead_code)]
13use super::constant;
14use super::objects::{ObjKey, PackageKey, ScopeKey, TCObjects, TypeKey};
15use super::package::Package;
16use super::typ;
17use super::universe;
18use super::universe::Universe;
19use go_parser::{ast, Map, Pos};
20use std::borrow::Cow;
21use std::fmt;
22use std::fmt::Write;
23
24#[derive(Clone, Debug, PartialEq)]
25pub struct VarProperty {
26 pub embedded: bool,
27 pub is_field: bool,
28 pub used: bool,
29}
30
31impl VarProperty {
32 pub fn new(embedded: bool, field: bool, used: bool) -> VarProperty {
33 VarProperty {
34 embedded: embedded,
35 is_field: field,
36 used: used,
37 }
38 }
39}
40
41#[derive(Clone, Debug, PartialEq)]
44pub enum EntityType {
45 PkgName(PackageKey, bool), Const(constant::Value),
49 TypeName,
51 Var(VarProperty),
54 Func(bool), Label(bool), Builtin(universe::Builtin),
64 Nil,
66}
67
68impl EntityType {
69 pub fn is_pkg_name(&self) -> bool {
70 match self {
71 EntityType::PkgName(_, _) => true,
72 _ => false,
73 }
74 }
75
76 pub fn is_const(&self) -> bool {
77 match self {
78 EntityType::Const(_) => true,
79 _ => false,
80 }
81 }
82
83 pub fn is_type_name(&self) -> bool {
84 match self {
85 EntityType::TypeName => true,
86 _ => false,
87 }
88 }
89
90 pub fn is_var(&self) -> bool {
91 match self {
92 EntityType::Var(_) => true,
93 _ => false,
94 }
95 }
96
97 pub fn is_func(&self) -> bool {
98 match self {
99 EntityType::Func(_) => true,
100 _ => false,
101 }
102 }
103
104 pub fn is_label(&self) -> bool {
105 match self {
106 EntityType::Label(_) => true,
107 _ => false,
108 }
109 }
110
111 pub fn is_builtin(&self) -> bool {
112 match self {
113 EntityType::Builtin(_) => true,
114 _ => false,
115 }
116 }
117
118 pub fn is_nil(&self) -> bool {
119 match self {
120 EntityType::Nil => true,
121 _ => false,
122 }
123 }
124
125 pub fn is_dependency(&self) -> bool {
126 match self {
127 EntityType::Const(_) | EntityType::Var(_) | EntityType::Func(_) => true,
128 _ => false,
129 }
130 }
131
132 pub fn func_has_ptr_recv(&self) -> bool {
133 match self {
134 EntityType::Func(h) => *h,
135 _ => unreachable!(),
136 }
137 }
138
139 pub fn func_set_has_ptr_recv(&mut self, has: bool) {
140 match self {
141 EntityType::Func(h) => {
142 *h = has;
143 }
144 _ => unreachable!(),
145 }
146 }
147
148 pub fn var_property(&self) -> &VarProperty {
149 match self {
150 EntityType::Var(prop) => prop,
151 _ => unreachable!(),
152 }
153 }
154
155 pub fn var_property_mut(&mut self) -> &mut VarProperty {
156 match self {
157 EntityType::Var(prop) => prop,
158 _ => unreachable!(),
159 }
160 }
161
162 pub fn label_used(&self) -> bool {
163 match self {
164 EntityType::Label(u) => *u,
165 _ => unreachable!(),
166 }
167 }
168
169 pub fn label_set_used(&mut self, used: bool) {
170 match self {
171 EntityType::Label(u) => {
172 *u = used;
173 }
174 _ => unreachable!(),
175 }
176 }
177}
178
179#[derive(Copy, Clone, Debug, PartialEq, Eq)]
180pub(crate) enum ObjColor {
181 White,
182 Black,
183 Gray(usize),
184}
185
186impl fmt::Display for ObjColor {
187 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188 match self {
189 ObjColor::White => f.write_str("white"),
190 ObjColor::Black => f.write_str("black"),
191 ObjColor::Gray(_) => f.write_str("gray"),
192 }
193 }
194}
195
196#[derive(Clone, Debug)]
203pub struct LangObj {
204 entity_type: EntityType,
205 parent: Option<ScopeKey>,
206 pos: Pos,
207 pkg: Option<PackageKey>,
208 name: String,
209 typ: Option<TypeKey>,
210 order: u32,
211 color: ObjColor,
212 scope_pos: Pos,
213}
214
215impl LangObj {
216 pub fn new_pkg_name(
217 pos: Pos,
218 pkg: Option<PackageKey>,
219 name: String,
220 imported: PackageKey,
221 univ: &Universe,
222 ) -> LangObj {
223 let t = univ.types()[&typ::BasicType::Invalid];
224 LangObj::new(
225 EntityType::PkgName(imported, false),
226 pos,
227 pkg,
228 name,
229 Some(t),
230 )
231 }
232
233 pub fn new_const(
234 pos: Pos,
235 pkg: Option<PackageKey>,
236 name: String,
237 typ: Option<TypeKey>,
238 val: constant::Value,
239 ) -> LangObj {
240 LangObj::new(EntityType::Const(val), pos, pkg, name, typ)
241 }
242
243 pub fn new_type_name(
244 pos: Pos,
245 pkg: Option<PackageKey>,
246 name: String,
247 typ: Option<TypeKey>,
248 ) -> LangObj {
249 LangObj::new(EntityType::TypeName, pos, pkg, name, typ)
250 }
251
252 pub fn new_var(
253 pos: Pos,
254 pkg: Option<PackageKey>,
255 name: String,
256 typ: Option<TypeKey>,
257 ) -> LangObj {
258 LangObj::new(
259 EntityType::Var(VarProperty::new(false, false, false)),
260 pos,
261 pkg,
262 name,
263 typ,
264 )
265 }
266
267 pub fn new_param_var(
268 pos: Pos,
269 pkg: Option<PackageKey>,
270 name: String,
271 typ: Option<TypeKey>,
272 ) -> LangObj {
273 LangObj::new(
274 EntityType::Var(VarProperty::new(false, false, true)),
275 pos,
276 pkg,
277 name,
278 typ,
279 )
280 }
281
282 pub fn new_field(
283 pos: Pos,
284 pkg: Option<PackageKey>,
285 name: String,
286 typ: Option<TypeKey>,
287 embedded: bool,
288 ) -> LangObj {
289 LangObj::new(
290 EntityType::Var(VarProperty::new(embedded, true, false)),
291 pos,
292 pkg,
293 name,
294 typ,
295 )
296 }
297
298 pub fn new_func(
299 pos: Pos,
300 pkg: Option<PackageKey>,
301 name: String,
302 typ: Option<TypeKey>,
303 ) -> LangObj {
304 LangObj::new(EntityType::Func(false), pos, pkg, name, typ)
305 }
306
307 pub fn new_label(pos: Pos, pkg: Option<PackageKey>, name: String, univ: &Universe) -> LangObj {
308 let t = univ.types()[&typ::BasicType::Invalid];
309 LangObj::new(EntityType::Label(false), pos, pkg, name, Some(t))
310 }
311
312 pub fn new_builtin(f: universe::Builtin, name: String, typ: TypeKey) -> LangObj {
313 LangObj::new(EntityType::Builtin(f), 0, None, name, Some(typ))
314 }
315
316 pub fn new_nil(typ: TypeKey) -> LangObj {
317 LangObj::new(EntityType::Nil, 0, None, "nil".to_owned(), Some(typ))
318 }
319
320 pub fn entity_type(&self) -> &EntityType {
321 &self.entity_type
322 }
323
324 pub fn entity_type_mut(&mut self) -> &mut EntityType {
325 &mut self.entity_type
326 }
327
328 pub fn parent(&self) -> Option<ScopeKey> {
329 self.parent
330 }
331
332 pub fn pos(&self) -> Pos {
333 self.pos
334 }
335
336 pub fn name(&self) -> &String {
337 &self.name
338 }
339
340 pub fn typ(&self) -> Option<TypeKey> {
341 self.typ
342 }
343
344 pub fn pkg(&self) -> Option<PackageKey> {
345 self.pkg
346 }
347
348 pub fn exported(&self) -> bool {
349 ast::is_exported(&self.name)
350 }
351
352 pub fn id(&self, objs: &TCObjects) -> Cow<str> {
353 let pkg = self.pkg.map(|x| &objs.pkgs[x]);
354 get_id(pkg, &self.name)
355 }
356
357 pub fn order(&self) -> u32 {
358 self.order
359 }
360
361 pub(crate) fn color(&self) -> ObjColor {
362 self.color
363 }
364
365 pub(crate) fn set_type(&mut self, typ: Option<TypeKey>) {
366 self.typ = typ
367 }
368
369 pub(crate) fn set_pkg(&mut self, pkg: Option<PackageKey>) {
370 self.pkg = pkg;
371 }
372
373 pub(crate) fn set_parent(&mut self, parent: Option<ScopeKey>) {
374 self.parent = parent
375 }
376
377 pub fn scope_pos(&self) -> &Pos {
378 &self.scope_pos
379 }
380
381 pub fn set_order(&mut self, order: u32) {
382 assert!(order > 0);
383 self.order = order;
384 }
385
386 pub(crate) fn set_color(&mut self, color: ObjColor) {
387 assert!(color != ObjColor::White);
388 self.color = color
389 }
390
391 pub(crate) fn set_scope_pos(&mut self, pos: Pos) {
392 self.scope_pos = pos
393 }
394
395 pub fn same_id(&self, pkg: Option<PackageKey>, name: &str, objs: &TCObjects) -> bool {
396 if name != self.name {
401 false
402 } else if self.exported() {
403 true
404 } else if pkg.is_none() || self.pkg.is_none() {
405 pkg == self.pkg
406 } else {
407 let a = &objs.pkgs[pkg.unwrap()];
408 let b = &objs.pkgs[self.pkg.unwrap()];
409 a.path() == b.path()
410 }
411 }
412
413 pub fn pkg_name_imported(&self) -> PackageKey {
414 match &self.entity_type {
415 EntityType::PkgName(imported, _) => *imported,
416 _ => unreachable!(),
417 }
418 }
419
420 pub fn const_val(&self) -> &constant::Value {
421 match &self.entity_type {
422 EntityType::Const(val) => val,
423 _ => unreachable!(),
424 }
425 }
426
427 pub(crate) fn set_const_val(&mut self, v: constant::Value) {
428 match &mut self.entity_type {
429 EntityType::Const(val) => *val = v,
430 _ => unreachable!(),
431 }
432 }
433
434 pub fn var_embedded(&self) -> bool {
435 match &self.entity_type {
436 EntityType::Var(prop) => prop.embedded,
437 _ => unreachable!(),
438 }
439 }
440
441 pub fn var_is_field(&self) -> bool {
442 match &self.entity_type {
443 EntityType::Var(prop) => prop.is_field,
444 _ => unreachable!(),
445 }
446 }
447
448 pub fn func_fmt_name(&self, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
449 match &self.entity_type {
450 EntityType::Func(_) => fmt_func_name(self, f, objs),
451 _ => unreachable!(),
452 }
453 }
454
455 pub fn func_scope(&self) -> &ScopeKey {
456 unimplemented!()
457 }
458
459 fn new(
460 entity_type: EntityType,
461 pos: Pos,
462 pkg: Option<PackageKey>,
463 name: String,
464 typ: Option<TypeKey>,
465 ) -> LangObj {
466 LangObj {
467 entity_type: entity_type,
468 parent: None,
469 pos: pos,
470 pkg: pkg,
471 name: name,
472 typ: typ,
473 order: 0,
474 color: color_for_typ(typ),
475 scope_pos: 0,
476 }
477 }
478}
479
480pub(crate) fn type_name_is_alias(okey: ObjKey, objs: &TCObjects) -> bool {
481 let lobj = &objs.lobjs[okey];
482 match lobj.entity_type {
483 EntityType::TypeName => match lobj.typ {
484 Some(t) => {
485 let ty = &objs.types[t];
486 match ty {
487 typ::Type::Basic(detail) => {
488 let universe = objs.universe();
489 if lobj.pkg() == Some(*universe.unsafe_pkg()) {
491 false
492 } else {
493 lobj.pkg().is_some()
500 || detail.name() != lobj.name()
501 || t == *universe.byte()
502 || t == *universe.rune()
503 }
504 }
505 typ::Type::Named(detail) => *detail.obj() != Some(okey),
506 _ => true,
507 }
508 }
509 None => false,
510 },
511 _ => unreachable!(),
512 }
513}
514
515pub(crate) struct ObjSet(Map<String, ObjKey>);
520
521impl ObjSet {
522 pub fn new() -> ObjSet {
523 ObjSet(Map::new())
524 }
525
526 pub fn insert(&self, okey: ObjKey, objs: &TCObjects) -> Option<&ObjKey> {
527 let obj = &objs.lobjs[okey];
528 let id = obj.id(objs);
529 self.0.get(id.as_ref())
530 }
531}
532
533pub(crate) fn get_id<'a>(pkg: Option<&Package>, name: &'a str) -> Cow<'a, str> {
537 if ast::is_exported(name) {
538 return Cow::Borrowed(name);
539 }
540 let path = if let Some(p) = pkg {
541 if !p.path().is_empty() {
542 p.path()
543 } else {
544 "_"
545 }
546 } else {
547 "_"
548 };
549 Cow::Owned(format!("{}.{}", path, name))
550}
551
552pub(crate) fn fmt_obj(okey: ObjKey, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
553 let obj = &objs.lobjs[okey];
554 match obj.entity_type() {
555 EntityType::PkgName(imported, _) => {
556 write!(f, "package {}", obj.name())?;
557 let path = objs.pkgs[*imported].path();
558 if path != obj.name() {
559 write!(f, " ('{}')", path)?;
560 }
561 }
562 EntityType::Const(_) => {
563 f.write_str("const")?;
564 fmt_obj_name(okey, f, objs)?;
565 fmt_obj_type(okey, f, objs)?;
566 }
567 EntityType::TypeName => {
568 f.write_str("type")?;
569 fmt_obj_name(okey, f, objs)?;
570 fmt_obj_type(okey, f, objs)?;
571 }
572 EntityType::Var(prop) => {
573 f.write_str(if prop.is_field { "field" } else { "var" })?;
574 fmt_obj_name(okey, f, objs)?;
575 fmt_obj_type(okey, f, objs)?;
576 }
577 EntityType::Func(_) => {
578 f.write_str("func ")?;
579 fmt_func_name(obj, f, objs)?;
580 if let Some(t) = obj.typ() {
581 typ::fmt_signature(t, f, objs)?;
582 }
583 }
584 EntityType::Label(_) => {
585 f.write_str("label")?;
586 fmt_obj_name(okey, f, objs)?;
587 }
588 EntityType::Builtin(_) => {
589 f.write_str("builtin")?;
590 fmt_obj_name(okey, f, objs)?;
591 }
592 EntityType::Nil => f.write_str("nil")?,
593 }
594 Ok(())
595}
596
597fn fmt_obj_name(okey: ObjKey, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
598 f.write_char(' ')?;
599 let obj = &objs.lobjs[okey];
600 if let Some(p) = obj.pkg {
601 let pkg_val = &objs.pkgs[p];
602 if let Some(k) = objs.scopes[*pkg_val.scope()].lookup(obj.name()) {
603 if *k == okey {
604 pkg_val.fmt_with_qualifier(f, objs.fmt_qualifier.as_ref())?;
605 }
606 }
607 }
608 f.write_str(obj.name())
609}
610
611fn fmt_obj_type(okey: ObjKey, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
612 let obj = &objs.lobjs[okey];
613 if obj.typ().is_none() {
614 return Ok(());
615 }
616 let mut obj_typ = obj.typ().unwrap();
617 if obj.entity_type().is_type_name() {
618 let typ_val = &objs.types[obj.typ().unwrap()];
619 if typ_val.try_as_basic().is_some() {
620 return Ok(());
621 }
622 if type_name_is_alias(okey, objs) {
623 f.write_str(" =")?;
624 } else {
625 obj_typ = typ::underlying_type(obj_typ, objs);
626 }
627 }
628 f.write_char(' ')?;
629 typ::fmt_type(Some(obj_typ), f, objs)
630}
631
632fn fmt_func_name(func: &LangObj, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
633 if let Some(t) = func.typ() {
634 let sig = objs.types[t].try_as_signature().unwrap();
635 if let Some(r) = sig.recv() {
636 f.write_char('(')?;
637 typ::fmt_type(objs.lobjs[*r].typ(), f, objs)?;
638 f.write_str(").")?;
639 } else {
640 if let Some(p) = func.pkg() {
641 objs.pkgs[p].fmt_with_qualifier(f, objs.fmt_qualifier.as_ref())?;
642 }
643 }
644 }
645 f.write_str(func.name())
646}
647
648fn color_for_typ(typ: Option<TypeKey>) -> ObjColor {
649 match typ {
650 Some(_) => ObjColor::Black,
651 None => ObjColor::White,
652 }
653}