Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117package errors
import ( "bytes" "fmt" "os" "path/filepath"
"git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/token")
// FileError is an error inside a file at a given line and column.type FileError struct { err error file *fs.File stack string source Source}
// Error implements the error interface.func (e *FileError) Error() string { return e.err.Error()}
// File returns the file the error came from.func (e *FileError) File() *fs.File { return e.file}
// Line returns the line contents and the offset from the position.func (e *FileError) Line() (string, int) { contents := e.file.Bytes start := bytes.LastIndexByte(contents[:e.source.Start()], '\n')
if start == -1 { start = 0 } else { start++ }
end := bytes.IndexByte(contents[e.source.Start():], '\n')
if end == -1 { end = len(contents) } else { end += int(e.source.Start()) }
asciiSpace := [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1}
for asciiSpace[contents[start]] == 1 { start++ }
return string(contents[start:end]), int(e.source.Start()) - start}
// LineColumn returns the line and column of the error.func (e *FileError) LineColumn() (int, int) { line := 1 column := 1 lineStart := -1
for _, t := range e.file.Tokens { if t.Position >= e.source.Start() { column = int(e.source.Start()) - lineStart break }
if t.Kind == token.NewLine { lineStart = int(t.Position) line++ } }
return line, column}
// Link returns a clickable link containing the path, line and column.func (e *FileError) Link() string { path := e.Path() line, column := e.LineColumn() return fmt.Sprintf("%s:%d:%d", path, line, column)}
// Path returns the relative path of the file to shorten the error message.func (e *FileError) Path() string { workDir, err := os.Getwd()
if err != nil { return e.file.Path }
relative, err := filepath.Rel(workDir, e.file.Path)
if err != nil { return e.file.Path }
return filepath.ToSlash(relative)}
// Source returns the byte offsets inside the file.func (e *FileError) Source() Source { return e.source}
// Stack returns the call stack at the time the error was created.func (e *FileError) Stack() string { return e.stack}
// Unwrap returns the wrapped error.func (e *FileError) Unwrap() error { return e.err}