
This should make it much easier to figure out why and where an error happens at package initialization time.
83 строки
2,4 КиБ
Go
83 строки
2,4 КиБ
Go
package interp
|
|
|
|
// This file provides useful types for errors encountered during IR evaluation.
|
|
|
|
import (
|
|
"errors"
|
|
"go/scanner"
|
|
"go/token"
|
|
"path/filepath"
|
|
|
|
"tinygo.org/x/go-llvm"
|
|
)
|
|
|
|
// errUnreachable is returned when an unreachable instruction is executed. This
|
|
// error should not be visible outside of the interp package.
|
|
var errUnreachable = &Error{Err: errors.New("interp: unreachable executed")}
|
|
|
|
// unsupportedInstructionError returns a new "unsupported instruction" error for
|
|
// the given instruction. It includes source location information, when
|
|
// available.
|
|
func (e *evalPackage) unsupportedInstructionError(inst llvm.Value) *Error {
|
|
return e.errorAt(inst, errors.New("interp: unsupported instruction"))
|
|
}
|
|
|
|
// ErrorLine is one line in a traceback. The position may be missing.
|
|
type ErrorLine struct {
|
|
Pos token.Position
|
|
Inst llvm.Value
|
|
}
|
|
|
|
// Error encapsulates compile-time interpretation errors with an associated
|
|
// import path. The errors may not have a precise location attached.
|
|
type Error struct {
|
|
ImportPath string
|
|
Inst llvm.Value
|
|
Pos token.Position
|
|
Err error
|
|
Traceback []ErrorLine
|
|
}
|
|
|
|
// Error returns the string of the first error in the list of errors.
|
|
func (e *Error) Error() string {
|
|
return e.Pos.String() + ": " + e.Err.Error()
|
|
}
|
|
|
|
// errorAt returns an error value for the currently interpreted package at the
|
|
// location of the instruction. The location information may not be complete as
|
|
// it depends on debug information in the IR.
|
|
func (e *evalPackage) errorAt(inst llvm.Value, err error) *Error {
|
|
return &Error{
|
|
ImportPath: e.packagePath,
|
|
Pos: getPosition(inst),
|
|
Err: err,
|
|
}
|
|
}
|
|
|
|
// errorAt returns an error value at the location of the instruction.
|
|
// The location information may not be complete as it depends on debug
|
|
// information in the IR.
|
|
func errorAt(inst llvm.Value, msg string) scanner.Error {
|
|
return scanner.Error{
|
|
Pos: getPosition(inst),
|
|
Msg: msg,
|
|
}
|
|
}
|
|
|
|
// getPosition returns the position information for the given instruction, as
|
|
// far as it is available.
|
|
func getPosition(inst llvm.Value) token.Position {
|
|
if inst.IsAInstruction().IsNil() {
|
|
return token.Position{}
|
|
}
|
|
loc := inst.InstructionDebugLoc()
|
|
if loc.IsNil() {
|
|
return token.Position{}
|
|
}
|
|
file := loc.LocationScope().ScopeFile()
|
|
return token.Position{
|
|
Filename: filepath.Join(file.FileDirectory(), file.FileFilename()),
|
|
Line: int(loc.LocationLine()),
|
|
Column: int(loc.LocationColumn()),
|
|
}
|
|
}
|