//go:build wasm package runtime import ( "unsafe" ) type stringer interface { String() string } //go:nobounds func printstring(s string) { for i := 0; i < len(s); i++ { putchar(s[i]) } } func printuint8(n uint8) { if TargetBits >= 32 { printuint32(uint32(n)) } else { prevdigits := n / 10 if prevdigits != 0 { printuint8(prevdigits) } putchar(byte((n % 10) + '0')) } } func printint8(n int8) { if TargetBits >= 32 { printint32(int32(n)) } else { if n < 0 { putchar('-') n = -n } printuint8(uint8(n)) } } func printuintptr(n uintptr) { switch unsafe.Sizeof(n) { case 2: printuint16(uint16(n)) case 4: printuint32(uint32(n)) case 8: printuint64(uint64(n)) } } func printuint16(n uint16) { printuint32(uint32(n)) } func printint16(n int16) { printint32(int32(n)) } func printuint32(n uint32) { printuint64(uint64(n)) } func printint32(n int32) { if n < 0 { putchar('-') n = -n } printuint32(uint32(n)) } //go:nobounds func printuint64(n uint64) { digits := [20]byte{} firstdigit := 19 for i := 19; i >= 0; i-- { digit := byte(n%10 + '0') digits[i] = digit if digit != '0' { firstdigit = i } n /= 10 } for i := firstdigit; i < 20; i++ { putchar(digits[i]) } } func printint64(n int64) { if n < 0 { putchar('-') n = -n } printuint64(uint64(n)) } func printfloat32(v float32) { switch { case v != v: printstring("NaN") return case v+v == v && v > 0: printstring("+Inf") return case v+v == v && v < 0: printstring("-Inf") return } const n = 7 var buf [n + 7]byte buf[0] = '+' e := 0 if v == 0 { if 1/v < 0 { buf[0] = '-' } } else { if v < 0 { v = -v buf[0] = '-' } for v >= 10 { e++ v /= 10 } for v < 1 { e-- v *= 10 } h := float32(5.0) for i := 0; i < n; i++ { h /= 10 } v += h if v >= 10 { e++ v /= 10 } } for i := 0; i < n; i++ { s := int32(v) buf[i+2] = byte(s + '0') v -= float32(s) v *= 10 } buf[1] = buf[2] buf[2] = '.' buf[n+2] = 'e' buf[n+3] = '+' if e < 0 { e = -e buf[n+3] = '-' } buf[n+4] = byte(e/100) + '0' buf[n+5] = byte(e/10)%10 + '0' buf[n+6] = byte(e%10) + '0' for _, c := range buf { putchar(c) } } func printfloat64(v float64) { switch { case v != v: printstring("NaN") return case v+v == v && v > 0: printstring("+Inf") return case v+v == v && v < 0: printstring("-Inf") return } const n = 7 var buf [n + 7]byte buf[0] = '+' e := 0 if v == 0 { if 1/v < 0 { buf[0] = '-' } } else { if v < 0 { v = -v buf[0] = '-' } for v >= 10 { e++ v /= 10 } for v < 1 { e-- v *= 10 } h := 5.0 for i := 0; i < n; i++ { h /= 10 } v += h if v >= 10 { e++ v /= 10 } } for i := 0; i < n; i++ { s := int32(v) buf[i+2] = byte(s + '0') v -= float64(s) v *= 10 } buf[1] = buf[2] buf[2] = '.' buf[n+2] = 'e' buf[n+3] = '+' if e < 0 { e = -e buf[n+3] = '-' } buf[n+4] = byte(e/100) + '0' buf[n+5] = byte(e/10)%10 + '0' buf[n+6] = byte(e%10) + '0' for _, c := range buf { putchar(c) } } func printcomplex64(c complex64) { putchar('(') printfloat32(real(c)) printfloat32(imag(c)) printstring("i)") } func printcomplex128(c complex128) { putchar('(') printfloat64(real(c)) printfloat64(imag(c)) printstring("i)") } func printspace() { putchar(' ') } func printnl() { if baremetal { putchar('\r') } putchar('\n') } // printitf for WASM: int≡int32 and uint≡uint32, so only int32/uint32 cases. func printitf(msg interface{}) { switch msg := msg.(type) { case bool: printbool(msg) case int8: printint8(msg) case int16: printint16(msg) case int32: printint32(msg) case int64: printint64(msg) case uint8: printuint8(msg) case uint16: printuint16(msg) case uint32: printuint32(msg) case uint64: printuint64(msg) case uintptr: printuintptr(msg) case float32: printfloat32(msg) case float64: printfloat64(msg) case complex64: printcomplex64(msg) case complex128: printcomplex128(msg) case string: printstring(msg) case error: printstring(msg.Error()) case stringer: printstring(msg.String()) default: itf := *(*_interface)(unsafe.Pointer(&msg)) putchar('(') printuintptr(uintptr(itf.typecode)) putchar(':') printptr(uintptr(itf.value)) putchar(')') } } func printmap(m *hashmap) { printstring("map[") if m == nil { printstring("nil") } else { switch unsafe.Sizeof(m.count) { case 8: printuint64(uint64(m.count)) case 4: printuint32(uint32(m.count)) case 2: printuint16(uint16(m.count)) } } putchar(']') } func printptr(ptr uintptr) { if ptr == 0 { printstring("nil") return } putchar('0') putchar('x') for i := 0; i < int32(unsafe.Sizeof(ptr))*2; i++ { nibble := byte(ptr >> (unsafe.Sizeof(ptr)*8 - 4)) if nibble < 10 { putchar(nibble + '0') } else { putchar(nibble - 10 + 'a') } ptr <<= 4 } } func printbool(b bool) { if b { printstring("true") } else { printstring("false") } } func printslice(ptr, len_, cap_ uintptr) { putchar('[') printuintptr(len_) putchar('/') printuintptr(cap_) putchar(']') printptr(ptr) }