# Copyright 2022 Mattia Giambirtone & All Contributors # # 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. ## Utilities to print formatted error messages to stderr import frontend/compiler/compiler import frontend/parsing/parser import frontend/parsing/lexer import errors import std/os import std/terminal import std/strutils import std/strformat proc printError(file, line: string, lineNo: int, pos: tuple[start, stop: int], fn: Declaration, msg: string) = ## Internal helper to print a formatted error message ## to stderr stderr.styledWrite(fgRed, styleBright, "Error in ", fgYellow, &"{file}:{lineNo}:{pos.start}") if not fn.isNil() and fn.kind == funDecl: stderr.styledWrite(fgRed, styleBright, " in function ", fgYellow, FunDecl(fn).name.token.lexeme) stderr.styledWriteLine(styleBright, fgDefault, ": ", msg) if line.len() > 0: stderr.styledWrite(fgRed, styleBright, "Source line: ", resetStyle, fgDefault, line[0..", "", "stdin"]: file = relativePath(exc.file, getCurrentDir()) contents = readFile(file).strip(chars={'\n'}).splitLines()[exc.line - 1] else: contents = exc.compiler.getSource().strip(chars={'\n'}).splitLines()[exc.line - 1] printError(file, contents, exc.line, exc.node.getRelativeBoundaries(), exc.function, exc.msg) proc print*(exc: ParseError) = ## Prints a formatted error message ## for parsing errors to stderr var file = exc.file if file notin ["", ""]: file = relativePath(exc.file, getCurrentDir()) printError(file, exc.parser.getSource().strip(chars={'\n'}).splitLines()[exc.line - 1], exc.line, exc.token.relPos, exc.parser.getCurrentFunction(), exc.msg) proc print*(exc: LexingError) = ## Prints a formatted error message ## for lexing errors to stderr var file = exc.file if file notin ["", ""]: file = relativePath(exc.file, getCurrentDir()) printError(file, exc.lexer.getSource().strip(chars={'\n'}).splitLines()[exc.line - 1], exc.line, exc.pos, nil, exc.msg)