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