tc_const.mx raw
1 package main
2
3 func (c *Checker) checkConstGroup(decls []*ConstDecl) {
4 var prevType Expr
5 var prevValues Expr
6 for i, d := range decls {
7 typ := d.Type
8 vals := d.Values
9 if vals == nil {
10 typ = prevType
11 vals = prevValues
12 } else {
13 prevType = typ
14 prevValues = vals
15 }
16 c.checkConstDeclAt(d, typ, vals, int32(i))
17 }
18 }
19
20 func (c *Checker) checkConstDeclAt(d *ConstDecl, typExpr Expr, valExpr Expr, iotaVal int32) {
21 var typ Type
22 if typExpr != nil {
23 typ = c.resolveTypeExpr(typExpr)
24 }
25
26 var vals []ConstVal
27 if valExpr != nil {
28 vals = c.evalConstExprList(valExpr, iotaVal)
29 }
30
31 for i, name := range d.NameList {
32 if name.Value == "_" {
33 continue
34 }
35 obj, ok := c.pkg.scope.Lookup(name.Value).(*TCConst)
36 if !ok {
37 continue
38 }
39 var cv ConstVal
40 if i < len(vals) {
41 cv = vals[i]
42 }
43 obj.val = cv
44 if c.pkg.path == "strconv" {
45 cvStr := "nil"
46 if cv != nil {
47 cvStr = cv.String()
48 }
49 writeStr(2, " TC-CONST-SET name=" | name.Value | " val=" | cvStr | " pkg=" | c.pkg.path | "\n")
50 }
51 if typ != nil {
52 obj.typ = typ
53 } else if cv != nil {
54 obj.typ = untypedTypeOfCV(cv)
55 }
56 if c.info != nil {
57 c.info.Defs[name] = obj
58 }
59 }
60 }
61
62 func (c *Checker) evalConstExprList(e Expr, iotaVal int32) []ConstVal {
63 if l, ok := e.(*ListExpr); ok {
64 var out []ConstVal
65 for _, el := range l.ElemList {
66 v := c.evalConst(el, iotaVal)
67 out = append(out, v)
68 }
69 return out
70 }
71 v := c.evalConst(e, iotaVal)
72 return []ConstVal{v}
73 }
74
75 func (c *Checker) evalConst(e Expr, iotaVal int32) ConstVal {
76 if e == nil {
77 return nil
78 }
79 switch e := e.(type) {
80 case *BasicLit:
81 return evalBasicLitLocal(e)
82 case *Name:
83 if e.Value == "iota" {
84 return constInt{iotaVal}
85 }
86 _, obj := c.lookup(e.Value, c.pkg.scope)
87 if obj == nil {
88 writeStr(2, " CONST-LOOKUP-FAIL name=" | e.Value | " pkg=" | c.pkg.path | "\n")
89 return nil
90 }
91 if k, ok := obj.(*TCConst); ok {
92 if k.val == nil {
93 writeStr(2, " CONST-REF-NIL name=" | e.Value | " pkg=" | c.pkg.path | "\n")
94 }
95 return k.val
96 }
97 return nil
98 case *Operation:
99 return c.evalConstOp(e, iotaVal)
100 case *ParenExpr:
101 return c.evalConst(e.X, iotaVal)
102 case *CallExpr:
103 if id, ok := e.Fun.(*Name); ok && id.Value == "len" && len(e.ArgList) == 1 {
104 if lit, ok := e.ArgList[0].(*BasicLit); ok && lit.Kind == StringLit {
105 lv := evalBasicLitLocal(lit)
106 if cs, ok := lv.(constStr); ok {
107 return constInt{int32(len(cs.s))}
108 }
109 }
110 av := c.evalConst(e.ArgList[0], iotaVal)
111 if cs, ok := av.(constStr); ok {
112 return constInt{int32(len(cs.s))}
113 }
114 }
115 if sel, ok := e.Fun.(*SelectorExpr); ok {
116 if pkg, ok := sel.X.(*Name); ok && pkg.Value == "unsafe" {
117 switch sel.Sel.Value {
118 case "Sizeof", "Alignof", "Offsetof":
119 return constInt{8}
120 }
121 }
122 }
123 if len(e.ArgList) != 1 {
124 return nil
125 }
126 inner := c.evalConst(e.ArgList[0], iotaVal)
127 if inner == nil {
128 return nil
129 }
130 targetType := c.resolveTypeExpr(e.Fun)
131 if targetType == nil {
132 funName := "?"
133 if id, ok2 := e.Fun.(*Name); ok2 {
134 funName = id.Value
135 }
136 writeStr(2, " CONST-CONV-FAIL fun=" | funName | " pkg=" | c.pkg.path | "\n")
137 return nil
138 }
139 return convertConstLocal(inner, targetType)
140 }
141 return nil
142 }
143
144 func evalBasicLitLocal(e *BasicLit) ConstVal {
145 switch e.Kind {
146 case IntLit:
147 n := parseIntLocal(e.Value)
148 return constInt{n}
149 case FloatLit:
150 f := parseFloatLocal(e.Value)
151 return constFloat{v: f, lit: e.Value}
152 case StringLit:
153 s := interpStringLocal(e.Value)
154 return constStr{s}
155 case RuneLit:
156 s := interpStringLocal(e.Value)
157 if len(s) > 0 {
158 return constInt{int32(decodeFirstRune(s))}
159 }
160 return constInt{0}
161 }
162 return nil
163 }
164
165 func parseIntLocal(s string) int32 {
166 if len(s) == 0 {
167 return 0
168 }
169 neg := false
170 i := 0
171 if s[0] == '-' {
172 neg = true
173 i = 1
174 } else if s[0] == '+' {
175 i = 1
176 }
177 base := int32(10)
178 if i < len(s)-1 && s[i] == '0' {
179 c := s[i+1]
180 if c == 'x' || c == 'X' {
181 base = 16
182 i += 2
183 } else if c == 'o' || c == 'O' {
184 base = 8
185 i += 2
186 } else if c == 'b' || c == 'B' {
187 base = 2
188 i += 2
189 } else if c >= '0' && c <= '7' {
190 base = 8
191 i += 1
192 }
193 }
194 var n int32
195 for ; i < len(s); i++ {
196 ch := s[i]
197 if ch == '_' {
198 continue
199 }
200 var d int32
201 if ch >= '0' && ch <= '9' {
202 d = int32(ch - '0')
203 } else if ch >= 'a' && ch <= 'f' {
204 d = int32(ch-'a') + 10
205 } else if ch >= 'A' && ch <= 'F' {
206 d = int32(ch-'A') + 10
207 } else {
208 break
209 }
210 n = n*base + d
211 }
212 if neg {
213 return -n
214 }
215 return n
216 }
217
218 func parseFloatLocal(s string) float64 {
219 if len(s) == 0 {
220 return 0.0
221 }
222 neg := false
223 i := 0
224 if s[0] == '-' {
225 neg = true
226 i = 1
227 } else if s[0] == '+' {
228 i = 1
229 }
230 if i+2 < len(s) && s[i] == '0' && (s[i+1] == 'x' || s[i+1] == 'X') {
231 result := parseHexFloat(s[i:])
232 if neg {
233 return -result
234 }
235 return result
236 }
237 var intPart float64
238 for ; i < len(s); i++ {
239 ch := s[i]
240 if ch == '_' {
241 continue
242 }
243 if ch < '0' || ch > '9' {
244 break
245 }
246 intPart = intPart*10.0 + float64(ch-'0')
247 }
248 var fracPart float64
249 if i < len(s) && s[i] == '.' {
250 i++
251 divisor := 10.0
252 for ; i < len(s); i++ {
253 ch := s[i]
254 if ch == '_' {
255 continue
256 }
257 if ch < '0' || ch > '9' {
258 break
259 }
260 fracPart = fracPart + float64(ch-'0')/divisor
261 divisor = divisor * 10.0
262 }
263 }
264 result := intPart + fracPart
265 if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
266 i++
267 expNeg := false
268 if i < len(s) && s[i] == '-' {
269 expNeg = true
270 i++
271 } else if i < len(s) && s[i] == '+' {
272 i++
273 }
274 var exp int32
275 for ; i < len(s); i++ {
276 ch := s[i]
277 if ch < '0' || ch > '9' {
278 break
279 }
280 exp = exp*10 + int32(ch-'0')
281 }
282 mul := 1.0
283 for j := 0; j < exp; j++ {
284 mul = mul * 10.0
285 }
286 if expNeg {
287 result = result / mul
288 } else {
289 result = result * mul
290 }
291 }
292 if neg {
293 return -result
294 }
295 return result
296 }
297
298 func parseHexFloat(s string) float64 {
299 i := 2
300 var mantissa float64
301 for ; i < len(s); i++ {
302 ch := s[i]
303 if ch == '_' {
304 continue
305 }
306 d := hexDigitVal(ch)
307 if d < 0 {
308 break
309 }
310 mantissa = mantissa*16.0 + float64(d)
311 }
312 if i < len(s) && s[i] == '.' {
313 i++
314 divisor := 16.0
315 for ; i < len(s); i++ {
316 ch := s[i]
317 if ch == '_' {
318 continue
319 }
320 d := hexDigitVal(ch)
321 if d < 0 {
322 break
323 }
324 mantissa = mantissa + float64(d)/divisor
325 divisor = divisor * 16.0
326 }
327 }
328 if i < len(s) && (s[i] == 'p' || s[i] == 'P') {
329 i++
330 expNeg := false
331 if i < len(s) && s[i] == '-' {
332 expNeg = true
333 i++
334 } else if i < len(s) && s[i] == '+' {
335 i++
336 }
337 var exp int32
338 for ; i < len(s); i++ {
339 ch := s[i]
340 if ch < '0' || ch > '9' {
341 break
342 }
343 exp = exp*10 + int32(ch-'0')
344 }
345 if expNeg {
346 for j := 0; j < exp; j++ {
347 mantissa = mantissa / 2.0
348 }
349 } else {
350 for j := 0; j < exp; j++ {
351 mantissa = mantissa * 2.0
352 }
353 }
354 }
355 return mantissa
356 }
357
358 func hexDigitVal(ch byte) int32 {
359 if ch >= '0' && ch <= '9' {
360 return int32(ch - '0')
361 }
362 if ch >= 'a' && ch <= 'f' {
363 return int32(ch-'a') + 10
364 }
365 if ch >= 'A' && ch <= 'F' {
366 return int32(ch-'A') + 10
367 }
368 return -1
369 }
370
371 func interpStringLocal(s string) string {
372 if len(s) < 2 {
373 return s
374 }
375 if s[0] == '`' {
376 return s[1 : len(s)-1]
377 }
378 quote := s[0]
379 if quote != '"' && quote != '\'' {
380 return s
381 }
382 s = s[1 : len(s)-1]
383 hasEsc := false
384 for i := 0; i < len(s); i++ {
385 if s[i] == '\\' {
386 hasEsc = true
387 break
388 }
389 }
390 if !hasEsc {
391 return s
392 }
393 var buf []byte
394 for i := 0; i < len(s); i++ {
395 if s[i] != '\\' {
396 buf = append(buf, s[i])
397 continue
398 }
399 i++
400 if i >= len(s) {
401 break
402 }
403 switch s[i] {
404 case 'n':
405 buf = append(buf, '\n')
406 case 't':
407 buf = append(buf, '\t')
408 case 'r':
409 buf = append(buf, '\r')
410 case '\\':
411 buf = append(buf, '\\')
412 case '\'':
413 buf = append(buf, '\'')
414 case '"':
415 buf = append(buf, '"')
416 case '0':
417 buf = append(buf, 0)
418 case 'a':
419 buf = append(buf, '\a')
420 case 'b':
421 buf = append(buf, '\b')
422 case 'f':
423 buf = append(buf, '\f')
424 case 'v':
425 buf = append(buf, '\v')
426 case 'x':
427 if i+2 < len(s) {
428 h := hexDigit(s[i+1])*16 + hexDigit(s[i+2])
429 buf = append(buf, byte(h))
430 i += 2
431 }
432 case 'u':
433 if i+4 < len(s) {
434 r := rune(hexDigit(s[i+1]))*4096 + rune(hexDigit(s[i+2]))*256 + rune(hexDigit(s[i+3]))*16 + rune(hexDigit(s[i+4]))
435 buf = appendRuneUTF8(buf, r)
436 i += 4
437 }
438 case 'U':
439 if i+8 < len(s) {
440 var r rune
441 for j := 1; j <= 8; j++ {
442 r = r*16 + rune(hexDigit(s[i+j]))
443 }
444 buf = appendRuneUTF8(buf, r)
445 i += 8
446 }
447 default:
448 if s[i] >= '0' && s[i] <= '7' {
449 v := int32(s[i] - '0')
450 if i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' {
451 v = v*8 + int32(s[i+1]-'0')
452 i++
453 if i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' {
454 v = v*8 + int32(s[i+1]-'0')
455 i++
456 }
457 }
458 buf = append(buf, byte(v))
459 } else {
460 buf = append(buf, s[i])
461 }
462 }
463 }
464 return string(buf)
465 }
466
467 func hexDigit(c byte) int32 {
468 if c >= '0' && c <= '9' {
469 return int32(c - '0')
470 }
471 if c >= 'a' && c <= 'f' {
472 return int32(c-'a') + 10
473 }
474 if c >= 'A' && c <= 'F' {
475 return int32(c-'A') + 10
476 }
477 return 0
478 }
479
480 func appendRuneUTF8(buf []byte, r rune) []byte {
481 if r < 0x80 {
482 return append(buf, byte(r))
483 }
484 if r < 0x800 {
485 buf = append(buf, byte(0xC0|(r>>6)))
486 return append(buf, byte(0x80|(r&0x3F)))
487 }
488 if r < 0x10000 {
489 buf = append(buf, byte(0xE0|(r>>12)))
490 buf = append(buf, byte(0x80|((r>>6)&0x3F)))
491 return append(buf, byte(0x80|(r&0x3F)))
492 }
493 buf = append(buf, byte(0xF0|(r>>18)))
494 buf = append(buf, byte(0x80|((r>>12)&0x3F)))
495 buf = append(buf, byte(0x80|((r>>6)&0x3F)))
496 return append(buf, byte(0x80|(r&0x3F)))
497 }
498
499 func (c *Checker) evalConstOp(e *Operation, iotaVal int32) ConstVal {
500 if e.Y == nil {
501 x := c.evalConst(e.X, iotaVal)
502 if x == nil {
503 writeStr(2, " CONSTOP-UNARY-NIL-X pkg=" | c.pkg.path | "\n")
504 return nil
505 }
506 r := evalUnaryLocal(e.Op, x)
507 if r == nil {
508 writeStr(2, " CONSTOP-UNARY-NIL-R pkg=" | c.pkg.path | " x=" | x.String() | "\n")
509 }
510 return r
511 }
512 x := c.evalConst(e.X, iotaVal)
513 y := c.evalConst(e.Y, iotaVal)
514 if x == nil || y == nil {
515 return nil
516 }
517 return evalBinaryLocal(e.Op, x, y)
518 }
519
520 func evalUnaryLocal(op Operator, x ConstVal) ConstVal {
521 switch op {
522 case Add:
523 return x
524 case Sub:
525 if ci, ok := x.(constInt); ok {
526 return constInt{-ci.v}
527 }
528 if cf, ok := x.(constFloat); ok {
529 neg := ""
530 if cf.lit != "" {
531 neg = "-" + cf.lit
532 }
533 return constFloat{v: -cf.v, lit: neg}
534 }
535 case Xor:
536 if ci, ok := x.(constInt); ok {
537 return constInt{^ci.v}
538 }
539 case Not:
540 if cb, ok := x.(constBool); ok {
541 return constBool{!cb.v}
542 }
543 }
544 return nil
545 }
546
547 func evalBinaryLocal(op Operator, x ConstVal, y ConstVal) ConstVal {
548 switch op {
549 case Add:
550 if xi, ok := x.(constInt); ok {
551 return constInt{xi.v + cvInt(y)}
552 }
553 if xf, ok := x.(constFloat); ok {
554 return constFloat{v: xf.v + cvFloat(y)}
555 }
556 if xs, ok := x.(constStr); ok {
557 return constStr{xs.s + cvStr(y)}
558 }
559 case Sub:
560 if xi, ok := x.(constInt); ok {
561 return constInt{xi.v - cvInt(y)}
562 }
563 if xf, ok := x.(constFloat); ok {
564 return constFloat{v: xf.v - cvFloat(y)}
565 }
566 case Mul:
567 if xi, ok := x.(constInt); ok {
568 return constInt{xi.v * cvInt(y)}
569 }
570 if xf, ok := x.(constFloat); ok {
571 return constFloat{v: xf.v * cvFloat(y)}
572 }
573 case Div:
574 if xi, ok := x.(constInt); ok {
575 d := cvInt(y)
576 if d == 0 {
577 return constInt{0}
578 }
579 return constInt{xi.v / d}
580 }
581 if xf, ok := x.(constFloat); ok {
582 d := cvFloat(y)
583 if d == 0.0 {
584 return constFloat{v: 0.0}
585 }
586 return constFloat{v: xf.v / d}
587 }
588 case Rem:
589 if xi, ok := x.(constInt); ok {
590 d := cvInt(y)
591 if d == 0 {
592 return constInt{0}
593 }
594 return constInt{xi.v % d}
595 }
596 case And:
597 if xi, ok := x.(constInt); ok {
598 return constInt{xi.v & cvInt(y)}
599 }
600 case Or:
601 if xi, ok := x.(constInt); ok {
602 return constInt{xi.v | cvInt(y)}
603 }
604 if xs, ok := x.(constStr); ok {
605 return constStr{xs.s + cvStr(y)}
606 }
607 case Xor:
608 if xi, ok := x.(constInt); ok {
609 return constInt{xi.v ^ cvInt(y)}
610 }
611 case Shl:
612 if xi, ok := x.(constInt); ok {
613 shift := uint32(cvInt(y))
614 return constInt{xi.v << shift}
615 }
616 case Shr:
617 if xi, ok := x.(constInt); ok {
618 shift := uint32(cvInt(y))
619 return constInt{xi.v >> shift}
620 }
621 case AndNot:
622 if xi, ok := x.(constInt); ok {
623 return constInt{xi.v &^ cvInt(y)}
624 }
625 case Eql:
626 return constBool{constEqual(x, y)}
627 case Neq:
628 return constBool{!constEqual(x, y)}
629 case Lss:
630 return constBool{constLess(x, y)}
631 case Leq:
632 return constBool{constLess(x, y) || constEqual(x, y)}
633 case Gtr:
634 return constBool{constLess(y, x)}
635 case Geq:
636 return constBool{constLess(y, x) || constEqual(x, y)}
637 }
638 return nil
639 }
640
641 func constEqual(x ConstVal, y ConstVal) bool {
642 if xi, ok := x.(constInt); ok {
643 return xi.v == cvInt(y)
644 }
645 if xf, ok := x.(constFloat); ok {
646 return xf.v == cvFloat(y)
647 }
648 if xs, ok := x.(constStr); ok {
649 return xs.s == cvStr(y)
650 }
651 if xb, ok := x.(constBool); ok {
652 if yb, ok := y.(constBool); ok {
653 return xb.v == yb.v
654 }
655 }
656 return false
657 }
658
659 func constLess(x ConstVal, y ConstVal) bool {
660 if xi, ok := x.(constInt); ok {
661 return xi.v < cvInt(y)
662 }
663 if xf, ok := x.(constFloat); ok {
664 return xf.v < cvFloat(y)
665 }
666 if xs, ok := x.(constStr); ok {
667 return xs.s < cvStr(y)
668 }
669 return false
670 }
671
672 func convertConstLocal(v ConstVal, target Type) ConstVal {
673 b, ok := safeUnderlying(target).(*Basic)
674 if !ok {
675 return v
676 }
677 switch {
678 case b.info&IsInteger != 0:
679 iv := cvInt(v)
680 return constInt{iv}
681 case b.info&IsFloat != 0:
682 fv := cvFloat(v)
683 return constFloat{v: fv}
684 case b.info&IsString != 0:
685 if cvKind(v) == 3 {
686 n := cvInt(v)
687 return constStr{runeToStr(rune(n))}
688 }
689 return v
690 }
691 return v
692 }
693
694 func untypedTypeOfCV(v ConstVal) Type {
695 switch cvKind(v) {
696 case 1:
697 return Typ[UntypedBool]
698 case 3:
699 return Typ[UntypedInt]
700 case 4:
701 return Typ[UntypedFloat]
702 case 2:
703 return Typ[UntypedString]
704 }
705 return nil
706 }
707
708 func cvKind(val ConstVal) int32 {
709 switch val.(type) {
710 case constBool:
711 return 1
712 case constStr:
713 return 2
714 case constInt:
715 return 3
716 case constFloat:
717 return 4
718 case constNil:
719 return 0
720 }
721 return 0
722 }
723
724 func constInt64CV(v ConstVal) (int32, bool) {
725 if v == nil || cvKind(v) != 3 {
726 return 0, false
727 }
728 if ci, ok := v.(constInt); ok {
729 return ci.v, true
730 }
731 return 0, false
732 }
733
734 func (c *Checker) IsConstExpr(e Expr) bool {
735 return c.evalConst(e, 0) != nil
736 }
737
738 func (c *Checker) evalArrayLen(e Expr) int32 {
739 v := c.evalConst(e, 0)
740 if v == nil {
741 return 0
742 }
743 n, _ := constInt64CV(v)
744 return n
745 }
746
747 func cvInt(v ConstVal) int32 {
748 if ci, ok := v.(constInt); ok {
749 return ci.v
750 }
751 if cf, ok := v.(constFloat); ok {
752 return int32(cf.v)
753 }
754 return 0
755 }
756
757 func cvFloat(v ConstVal) float64 {
758 if cf, ok := v.(constFloat); ok {
759 return cf.v
760 }
761 if ci, ok := v.(constInt); ok {
762 return float64(ci.v)
763 }
764 return 0
765 }
766
767 func cvStr(v ConstVal) string {
768 if cs, ok := v.(constStr); ok {
769 return cs.s
770 }
771 return ""
772 }
773
774 func decodeFirstRune(s string) int32 {
775 b := s[0]
776 if b < 0x80 {
777 return int32(b)
778 }
779 if b < 0xC0 {
780 return int32(b)
781 }
782 if b < 0xE0 && len(s) >= 2 {
783 return int32(b&0x1F)<<6 | int32(s[1]&0x3F)
784 }
785 if b < 0xF0 && len(s) >= 3 {
786 return int32(b&0x0F)<<12 | int32(s[1]&0x3F)<<6 | int32(s[2]&0x3F)
787 }
788 if len(s) >= 4 {
789 return int32(b&0x07)<<18 | int32(s[1]&0x3F)<<12 | int32(s[2]&0x3F)<<6 | int32(s[3]&0x3F)
790 }
791 return int32(b)
792 }
793
794 func runeToStr(r rune) string {
795 if r < 0 || r > 0x10FFFF {
796 r = 0xFFFD
797 }
798 var buf [4]byte
799 if r <= 0x7F {
800 buf[0] = byte(r)
801 return string(buf[:1])
802 }
803 if r <= 0x7FF {
804 buf[0] = byte(0xC0 | (r >> 6))
805 buf[1] = byte(0x80 | (r & 0x3F))
806 return string(buf[:2])
807 }
808 if r <= 0xFFFF {
809 buf[0] = byte(0xE0 | (r >> 12))
810 buf[1] = byte(0x80 | ((r >> 6) & 0x3F))
811 buf[2] = byte(0x80 | (r & 0x3F))
812 return string(buf[:3])
813 }
814 buf[0] = byte(0xF0 | (r >> 18))
815 buf[1] = byte(0x80 | ((r >> 12) & 0x3F))
816 buf[2] = byte(0x80 | ((r >> 6) & 0x3F))
817 buf[3] = byte(0x80 | (r & 0x3F))
818 return string(buf[:4])
819 }
820