/* * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package runtime import ( "unsafe" "github.com/goplus/llgo/c/bitcast" "github.com/goplus/llgo/internal/abi" ) type errorString string func (e errorString) RuntimeError() {} func (e errorString) Error() string { return "runtime error: " + string(e) } type plainError string func (e plainError) Error() string { return string(e) } func AssertRuntimeError(b bool, msg string) { if b { panic(errorString(msg).Error()) } } func AssertNegativeShift(b bool) { if b { panic(errorString("negative shift amount").Error()) } } func AssertIndexRange(b bool) { if b { panic(errorString("index out of range").Error()) } } // printany prints an argument passed to panic. // If panic is called with a value that has a String or Error method, // it has already been converted into a string by preprintpanics. func printany(i any) { switch v := i.(type) { case nil: print("nil") case bool: print(v) case int: print(v) case int8: print(v) case int16: print(v) case int32: print(v) case int64: print(v) case uint: print(v) case uint8: print(v) case uint16: print(v) case uint32: print(v) case uint64: print(v) case uintptr: print(v) case float32: print(v) case float64: print(v) case complex64: print(v) case complex128: print(v) case string: print(v) case error: print(v.Error()) case interface{ String() string }: print(v.String()) default: printanycustomtype(i) } } func efaceOf(ep *any) *eface { return (*eface)(unsafe.Pointer(ep)) } func printanycustomtype(i any) { e := efaceOf(&i) typestring := e._type.String() switch e._type.Kind() { case abi.String: print(typestring, `("`, *(*string)(e.data), `")`) case abi.Bool: if isDirectIface(e._type) { print(typestring, "(", uintptr(e.data) != 0, ")") } else { print(typestring, "(", *(*bool)(e.data), ")") } case abi.Int, abi.Int8, abi.Int16, abi.Int32, abi.Int64: if isDirectIface(e._type) { print(typestring, "(", int64(uintptr(e.data)), ")") } else { print(typestring, "(", *(*int64)(e.data), ")") } case abi.Uint, abi.Uint8, abi.Uint16, abi.Uint32, abi.Uint64, abi.Uintptr: if isDirectIface(e._type) { print(typestring, "(", uint64(uintptr(e.data)), ")") } else { print(typestring, "(", *(*uint64)(e.data), ")") } case abi.Float32: if isDirectIface(e._type) { print(typestring, "(", bitcast.ToFloat32((uintptr(e.data))), ")") } else { print(typestring, "(", *(*float32)(e.data), ")") } case abi.Float64: if isDirectIface(e._type) { print(typestring, "(", bitcast.ToFloat64(uintptr(e.data)), ")") } else { print(typestring, "(", *(*float64)(e.data), ")") } case abi.Complex64: println(typestring, *(*complex64)(e.data)) case abi.Complex128: println(typestring, *(*complex128)(e.data)) default: print("(", typestring, ") ", e.data) } }