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, int64(i))
17 }
18 }
19
20 func (c *Checker) checkConstDeclAt(d *ConstDecl, typExpr Expr, valExpr Expr, iotaVal int64) {
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 int64) []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 int64) 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{int64(len(cs.s))}
108 }
109 }
110 }
111 if sel, ok := e.Fun.(*SelectorExpr); ok {
112 if pkg, ok := sel.X.(*Name); ok && pkg.Value == "unsafe" {
113 switch sel.Sel.Value {
114 case "Sizeof", "Alignof", "Offsetof":
115 return constInt{8}
116 }
117 }
118 }
119 if len(e.ArgList) != 1 {
120 return nil
121 }
122 inner := c.evalConst(e.ArgList[0], iotaVal)
123 if inner == nil {
124 return nil
125 }
126 targetType := c.resolveTypeExpr(e.Fun)
127 if targetType == nil {
128 funName := "?"
129 if id, ok2 := e.Fun.(*Name); ok2 {
130 funName = id.Value
131 }
132 writeStr(2, " CONST-CONV-FAIL fun=" | funName | " pkg=" | c.pkg.path | "\n")
133 return nil
134 }
135 return convertConstLocal(inner, targetType)
136 }
137 return nil
138 }
139
140 func evalBasicLitLocal(e *BasicLit) ConstVal {
141 switch e.Kind {
142 case IntLit:
143 n := parseIntLocal(e.Value)
144 return constInt{n}
145 case FloatLit:
146 f := parseFloatLocal(e.Value)
147 return constFloat{v: f, lit: e.Value}
148 case StringLit:
149 s := interpStringLocal(e.Value)
150 return constStr{s}
151 case RuneLit:
152 s := interpStringLocal(e.Value)
153 if len(s) > 0 {
154 return constInt{int64(decodeFirstRune(s))}
155 }
156 return constInt{0}
157 }
158 return nil
159 }
160
161 func parseIntLocal(s string) int64 {
162 if len(s) == 0 {
163 return 0
164 }
165 neg := false
166 i := 0
167 if s[0] == '-' {
168 neg = true
169 i = 1
170 } else if s[0] == '+' {
171 i = 1
172 }
173 base := int64(10)
174 if i < len(s)-1 && s[i] == '0' {
175 c := s[i+1]
176 if c == 'x' || c == 'X' {
177 base = 16
178 i += 2
179 } else if c == 'o' || c == 'O' {
180 base = 8
181 i += 2
182 } else if c == 'b' || c == 'B' {
183 base = 2
184 i += 2
185 } else if c >= '0' && c <= '7' {
186 base = 8
187 i += 1
188 }
189 }
190 var n int64
191 for ; i < len(s); i++ {
192 ch := s[i]
193 if ch == '_' {
194 continue
195 }
196 var d int64
197 if ch >= '0' && ch <= '9' {
198 d = int64(ch - '0')
199 } else if ch >= 'a' && ch <= 'f' {
200 d = int64(ch-'a') + 10
201 } else if ch >= 'A' && ch <= 'F' {
202 d = int64(ch-'A') + 10
203 } else {
204 break
205 }
206 n = n*base + d
207 }
208 if neg {
209 return -n
210 }
211 return n
212 }
213
214 func parseFloatLocal(s string) float64 {
215 if len(s) == 0 {
216 return 0.0
217 }
218 neg := false
219 i := 0
220 if s[0] == '-' {
221 neg = true
222 i = 1
223 } else if s[0] == '+' {
224 i = 1
225 }
226 var intPart float64
227 for ; i < len(s); i++ {
228 ch := s[i]
229 if ch == '_' {
230 continue
231 }
232 if ch < '0' || ch > '9' {
233 break
234 }
235 intPart = intPart*10.0 + float64(ch-'0')
236 }
237 var fracPart float64
238 if i < len(s) && s[i] == '.' {
239 i++
240 divisor := 10.0
241 for ; i < len(s); i++ {
242 ch := s[i]
243 if ch == '_' {
244 continue
245 }
246 if ch < '0' || ch > '9' {
247 break
248 }
249 fracPart = fracPart + float64(ch-'0')/divisor
250 divisor = divisor * 10.0
251 }
252 }
253 result := intPart + fracPart
254 if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
255 i++
256 expNeg := false
257 if i < len(s) && s[i] == '-' {
258 expNeg = true
259 i++
260 } else if i < len(s) && s[i] == '+' {
261 i++
262 }
263 var exp int
264 for ; i < len(s); i++ {
265 ch := s[i]
266 if ch < '0' || ch > '9' {
267 break
268 }
269 exp = exp*10 + int(ch-'0')
270 }
271 mul := 1.0
272 for j := 0; j < exp; j++ {
273 mul = mul * 10.0
274 }
275 if expNeg {
276 result = result / mul
277 } else {
278 result = result * mul
279 }
280 }
281 if neg {
282 return -result
283 }
284 return result
285 }
286
287 func interpStringLocal(s string) string {
288 if len(s) < 2 {
289 return s
290 }
291 if s[0] == '`' {
292 return s[1 : len(s)-1]
293 }
294 quote := s[0]
295 if quote != '"' && quote != '\'' {
296 return s
297 }
298 s = s[1 : len(s)-1]
299 hasEsc := false
300 for i := 0; i < len(s); i++ {
301 if s[i] == '\\' {
302 hasEsc = true
303 break
304 }
305 }
306 if !hasEsc {
307 return s
308 }
309 var buf []byte
310 for i := 0; i < len(s); i++ {
311 if s[i] != '\\' {
312 buf = append(buf, s[i])
313 continue
314 }
315 i++
316 if i >= len(s) {
317 break
318 }
319 switch s[i] {
320 case 'n':
321 buf = append(buf, '\n')
322 case 't':
323 buf = append(buf, '\t')
324 case 'r':
325 buf = append(buf, '\r')
326 case '\\':
327 buf = append(buf, '\\')
328 case '\'':
329 buf = append(buf, '\'')
330 case '"':
331 buf = append(buf, '"')
332 case '0':
333 buf = append(buf, 0)
334 case 'a':
335 buf = append(buf, '\a')
336 case 'b':
337 buf = append(buf, '\b')
338 case 'f':
339 buf = append(buf, '\f')
340 case 'v':
341 buf = append(buf, '\v')
342 case 'x':
343 if i+2 < len(s) {
344 h := hexDigit(s[i+1])*16 + hexDigit(s[i+2])
345 buf = append(buf, byte(h))
346 i += 2
347 }
348 case 'u':
349 if i+4 < len(s) {
350 r := rune(hexDigit(s[i+1]))*4096 + rune(hexDigit(s[i+2]))*256 + rune(hexDigit(s[i+3]))*16 + rune(hexDigit(s[i+4]))
351 buf = appendRuneUTF8(buf, r)
352 i += 4
353 }
354 case 'U':
355 if i+8 < len(s) {
356 var r rune
357 for j := 1; j <= 8; j++ {
358 r = r*16 + rune(hexDigit(s[i+j]))
359 }
360 buf = appendRuneUTF8(buf, r)
361 i += 8
362 }
363 default:
364 if s[i] >= '0' && s[i] <= '7' {
365 v := int(s[i] - '0')
366 if i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' {
367 v = v*8 + int(s[i+1]-'0')
368 i++
369 if i+1 < len(s) && s[i+1] >= '0' && s[i+1] <= '7' {
370 v = v*8 + int(s[i+1]-'0')
371 i++
372 }
373 }
374 buf = append(buf, byte(v))
375 } else {
376 buf = append(buf, s[i])
377 }
378 }
379 }
380 return string(buf)
381 }
382
383 func hexDigit(c byte) int {
384 if c >= '0' && c <= '9' {
385 return int(c - '0')
386 }
387 if c >= 'a' && c <= 'f' {
388 return int(c-'a') + 10
389 }
390 if c >= 'A' && c <= 'F' {
391 return int(c-'A') + 10
392 }
393 return 0
394 }
395
396 func appendRuneUTF8(buf []byte, r rune) []byte {
397 if r < 0x80 {
398 return append(buf, byte(r))
399 }
400 if r < 0x800 {
401 buf = append(buf, byte(0xC0|(r>>6)))
402 return append(buf, byte(0x80|(r&0x3F)))
403 }
404 if r < 0x10000 {
405 buf = append(buf, byte(0xE0|(r>>12)))
406 buf = append(buf, byte(0x80|((r>>6)&0x3F)))
407 return append(buf, byte(0x80|(r&0x3F)))
408 }
409 buf = append(buf, byte(0xF0|(r>>18)))
410 buf = append(buf, byte(0x80|((r>>12)&0x3F)))
411 buf = append(buf, byte(0x80|((r>>6)&0x3F)))
412 return append(buf, byte(0x80|(r&0x3F)))
413 }
414
415 func (c *Checker) evalConstOp(e *Operation, iotaVal int64) ConstVal {
416 if e.Y == nil {
417 x := c.evalConst(e.X, iotaVal)
418 if x == nil {
419 writeStr(2, " CONSTOP-UNARY-NIL-X pkg=" | c.pkg.path | "\n")
420 return nil
421 }
422 r := evalUnaryLocal(e.Op, x)
423 if r == nil {
424 writeStr(2, " CONSTOP-UNARY-NIL-R pkg=" | c.pkg.path | " x=" | x.String() | "\n")
425 }
426 return r
427 }
428 x := c.evalConst(e.X, iotaVal)
429 y := c.evalConst(e.Y, iotaVal)
430 if x == nil || y == nil {
431 return nil
432 }
433 return evalBinaryLocal(e.Op, x, y)
434 }
435
436 func evalUnaryLocal(op Operator, x ConstVal) ConstVal {
437 switch op {
438 case Add:
439 return x
440 case Sub:
441 if ci, ok := x.(constInt); ok {
442 return constInt{-ci.v}
443 }
444 if cf, ok := x.(constFloat); ok {
445 neg := ""
446 if cf.lit != "" {
447 neg = "-" + cf.lit
448 }
449 return constFloat{v: -cf.v, lit: neg}
450 }
451 case Xor:
452 if ci, ok := x.(constInt); ok {
453 return constInt{^ci.v}
454 }
455 case Not:
456 if cb, ok := x.(constBool); ok {
457 return constBool{!cb.v}
458 }
459 }
460 return nil
461 }
462
463 func evalBinaryLocal(op Operator, x ConstVal, y ConstVal) ConstVal {
464 switch op {
465 case Add:
466 if xi, ok := x.(constInt); ok {
467 return constInt{xi.v + cvInt(y)}
468 }
469 if xf, ok := x.(constFloat); ok {
470 return constFloat{v: xf.v + cvFloat(y)}
471 }
472 if xs, ok := x.(constStr); ok {
473 return constStr{xs.s + cvStr(y)}
474 }
475 case Sub:
476 if xi, ok := x.(constInt); ok {
477 return constInt{xi.v - cvInt(y)}
478 }
479 if xf, ok := x.(constFloat); ok {
480 return constFloat{v: xf.v - cvFloat(y)}
481 }
482 case Mul:
483 if xi, ok := x.(constInt); ok {
484 return constInt{xi.v * cvInt(y)}
485 }
486 if xf, ok := x.(constFloat); ok {
487 return constFloat{v: xf.v * cvFloat(y)}
488 }
489 case Div:
490 if xi, ok := x.(constInt); ok {
491 d := cvInt(y)
492 if d == 0 {
493 return constInt{0}
494 }
495 return constInt{xi.v / d}
496 }
497 if xf, ok := x.(constFloat); ok {
498 d := cvFloat(y)
499 if d == 0.0 {
500 return constFloat{v: 0.0}
501 }
502 return constFloat{v: xf.v / d}
503 }
504 case Rem:
505 if xi, ok := x.(constInt); ok {
506 d := cvInt(y)
507 if d == 0 {
508 return constInt{0}
509 }
510 return constInt{xi.v % d}
511 }
512 case And:
513 if xi, ok := x.(constInt); ok {
514 return constInt{xi.v & cvInt(y)}
515 }
516 case Or:
517 if xi, ok := x.(constInt); ok {
518 return constInt{xi.v | cvInt(y)}
519 }
520 if xs, ok := x.(constStr); ok {
521 return constStr{xs.s + cvStr(y)}
522 }
523 case Xor:
524 if xi, ok := x.(constInt); ok {
525 return constInt{xi.v ^ cvInt(y)}
526 }
527 case Shl:
528 if xi, ok := x.(constInt); ok {
529 shift := uint(cvInt(y))
530 return constInt{xi.v << shift}
531 }
532 case Shr:
533 if xi, ok := x.(constInt); ok {
534 shift := uint(cvInt(y))
535 return constInt{xi.v >> shift}
536 }
537 case AndNot:
538 if xi, ok := x.(constInt); ok {
539 return constInt{xi.v &^ cvInt(y)}
540 }
541 case Eql:
542 return constBool{constEqual(x, y)}
543 case Neq:
544 return constBool{!constEqual(x, y)}
545 case Lss:
546 return constBool{constLess(x, y)}
547 case Leq:
548 return constBool{constLess(x, y) || constEqual(x, y)}
549 case Gtr:
550 return constBool{constLess(y, x)}
551 case Geq:
552 return constBool{constLess(y, x) || constEqual(x, y)}
553 }
554 return nil
555 }
556
557 func constEqual(x ConstVal, y ConstVal) bool {
558 if xi, ok := x.(constInt); ok {
559 return xi.v == cvInt(y)
560 }
561 if xf, ok := x.(constFloat); ok {
562 return xf.v == cvFloat(y)
563 }
564 if xs, ok := x.(constStr); ok {
565 return xs.s == cvStr(y)
566 }
567 if xb, ok := x.(constBool); ok {
568 if yb, ok := y.(constBool); ok {
569 return xb.v == yb.v
570 }
571 }
572 return false
573 }
574
575 func constLess(x ConstVal, y ConstVal) bool {
576 if xi, ok := x.(constInt); ok {
577 return xi.v < cvInt(y)
578 }
579 if xf, ok := x.(constFloat); ok {
580 return xf.v < cvFloat(y)
581 }
582 if xs, ok := x.(constStr); ok {
583 return xs.s < cvStr(y)
584 }
585 return false
586 }
587
588 func convertConstLocal(v ConstVal, target Type) ConstVal {
589 b, ok := safeUnderlying(target).(*Basic)
590 if !ok {
591 return v
592 }
593 switch {
594 case b.info&IsInteger != 0:
595 iv := cvInt(v)
596 return constInt{iv}
597 case b.info&IsFloat != 0:
598 fv := cvFloat(v)
599 return constFloat{v: fv}
600 case b.info&IsString != 0:
601 if cvKind(v) == 3 {
602 n := cvInt(v)
603 return constStr{runeToStr(rune(n))}
604 }
605 return v
606 }
607 return v
608 }
609
610 func untypedTypeOfCV(v ConstVal) Type {
611 switch cvKind(v) {
612 case 1:
613 return Typ[UntypedBool]
614 case 3:
615 return Typ[UntypedInt]
616 case 4:
617 return Typ[UntypedFloat]
618 case 2:
619 return Typ[UntypedString]
620 }
621 return nil
622 }
623
624 func cvKind(val ConstVal) int {
625 switch val.(type) {
626 case constBool:
627 return 1
628 case constStr:
629 return 2
630 case constInt:
631 return 3
632 case constFloat:
633 return 4
634 case constNil:
635 return 0
636 }
637 return 0
638 }
639
640 func constInt64CV(v ConstVal) (int64, bool) {
641 if v == nil || cvKind(v) != 3 {
642 return 0, false
643 }
644 if ci, ok := v.(constInt); ok {
645 return ci.v, true
646 }
647 return 0, false
648 }
649
650 func (c *Checker) IsConstExpr(e Expr) bool {
651 return c.evalConst(e, 0) != nil
652 }
653
654 func (c *Checker) evalArrayLen(e Expr) int64 {
655 v := c.evalConst(e, 0)
656 if v == nil {
657 return 0
658 }
659 n, _ := constInt64CV(v)
660 return n
661 }
662
663 func cvInt(v ConstVal) int64 {
664 if ci, ok := v.(constInt); ok {
665 return ci.v
666 }
667 if cf, ok := v.(constFloat); ok {
668 return int64(cf.v)
669 }
670 return 0
671 }
672
673 func cvFloat(v ConstVal) float64 {
674 if cf, ok := v.(constFloat); ok {
675 return cf.v
676 }
677 if ci, ok := v.(constInt); ok {
678 return float64(ci.v)
679 }
680 return 0
681 }
682
683 func cvStr(v ConstVal) string {
684 if cs, ok := v.(constStr); ok {
685 return cs.s
686 }
687 return ""
688 }
689
690 func decodeFirstRune(s string) int32 {
691 b := s[0]
692 if b < 0x80 {
693 return int32(b)
694 }
695 if b < 0xC0 {
696 return int32(b)
697 }
698 if b < 0xE0 && len(s) >= 2 {
699 return int32(b&0x1F)<<6 | int32(s[1]&0x3F)
700 }
701 if b < 0xF0 && len(s) >= 3 {
702 return int32(b&0x0F)<<12 | int32(s[1]&0x3F)<<6 | int32(s[2]&0x3F)
703 }
704 if len(s) >= 4 {
705 return int32(b&0x07)<<18 | int32(s[1]&0x3F)<<12 | int32(s[2]&0x3F)<<6 | int32(s[3]&0x3F)
706 }
707 return int32(b)
708 }
709
710 func runeToStr(r rune) string {
711 if r < 0 || r > 0x10FFFF {
712 r = 0xFFFD
713 }
714 var buf [4]byte
715 if r <= 0x7F {
716 buf[0] = byte(r)
717 return string(buf[:1])
718 }
719 if r <= 0x7FF {
720 buf[0] = byte(0xC0 | (r >> 6))
721 buf[1] = byte(0x80 | (r & 0x3F))
722 return string(buf[:2])
723 }
724 if r <= 0xFFFF {
725 buf[0] = byte(0xE0 | (r >> 12))
726 buf[1] = byte(0x80 | ((r >> 6) & 0x3F))
727 buf[2] = byte(0x80 | (r & 0x3F))
728 return string(buf[:3])
729 }
730 buf[0] = byte(0xF0 | (r >> 18))
731 buf[1] = byte(0x80 | ((r >> 12) & 0x3F))
732 buf[2] = byte(0x80 | ((r >> 6) & 0x3F))
733 buf[3] = byte(0x80 | (r & 0x3F))
734 return string(buf[:4])
735 }
736