Skip to content

Commit

Permalink
Try #206:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Jan 26, 2022
2 parents b9ea9a1 + 431c4ea commit bec41a2
Show file tree
Hide file tree
Showing 21 changed files with 2,498 additions and 232 deletions.
2 changes: 1 addition & 1 deletion compiler/ast/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ proc addTypeDeclVerboseMaybe*(result: var string, conf: ConfigRef; typ: PType) =
else:
result.add typeToString(typ)

template `$`*(typ: PType): string = typeToString(typ)
proc `$`*(typ: PType): string = typeToString(typ)

proc base*(t: PType): PType =
result = t[0]
Expand Down
12 changes: 9 additions & 3 deletions compiler/front/cli_reporter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ import
],
vm/[
vm_enums
]
],
./reporter_common

import front/options as compiler_options

Expand Down Expand Up @@ -122,7 +123,7 @@ proc toStr(conf: ConfigRef, loc: TLineInfo, dropExt: bool = false): string =
## Convert location to printable string
conf.wrap(
"$1($2, $3)" % [
toFilenameOption(conf, loc.fileIndex, conf.filenameOption).dropExt(dropExt),
conf.formatPath(loc.fileIndex).dropExt(dropExt),
$loc.line,
$(loc.col + ColOffset)
],
Expand Down Expand Up @@ -3021,7 +3022,12 @@ proc reportBody*(conf: ConfigRef, r: ExternalReport): string =
result = "$1 is not a valid number" % r.cmdlineProvided

of rextInvalidValue:
result = r.cmdlineError
result = ("Unexpected value for " &
"the $1. Expected one of $2, but got '$3'") % [
r.cmdlineSwitch,
r.cmdlineAllowed.mapIt("'" & it & "'").join(", "),
r.cmdlineProvided
]

of rextUnexpectedValue:
result = "Unexpected value for $1. Expected one of $2" % [
Expand Down
16 changes: 15 additions & 1 deletion compiler/front/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ import
front/[
condsyms,
options,
msgs
msgs,
cli_reporter,
sexp_reporter
],
backend/[
extccomp
Expand Down Expand Up @@ -1121,6 +1123,17 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
else:
conf.localReport(info, invalidSwitchValue @["abs", "canonical", "legacyRelProj"])

of "msgformat":
case arg.normalize:
of "text":
conf.setReportHook cli_reporter.reportHook

of "sexp":
conf.setReportHook sexp_reporter.reportHook

else:
conf.localReport(info, invalidSwitchValue @["text", "sexp"])

of "processing":
incl(conf, cnCurrent, rsemProcessing)
incl(conf, cnMainPackage, rsemProcessing)
Expand Down Expand Up @@ -1269,6 +1282,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "nilseqs", "nilchecks", "mainmodule", "m", "symbol", "taintmode",
"cs", "deadcodeelim":
warningOptionNoop(switch)

else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
else: invalidCmdLineOption(conf, pass, switch, info)
Expand Down
1 change: 0 additions & 1 deletion compiler/front/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,6 @@ type
) {.closure.} ## All
## textual output from the compiler goes through this callback.
writeHook*: proc(conf: ConfigRef, output: string, flags: MsgFlags) {.closure.}

structuredReportHook*: ReportHook
cppCustomNamespace*: string
vmProfileData*: ProfileData
Expand Down
41 changes: 41 additions & 0 deletions compiler/front/reporter_common.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import
front/[
options,
msgs
],
ast/[
lineinfos,
],
std/[
os,
tables,
strutils
]

proc formatPath*(conf: ConfigRef, path: string): string =
## Format absolute path for reporting
if path in conf.m.filenameToIndexTbl:
# Check if path is registered in filename table index - in that case
# formatting is done using `FileInfo` data from the config.
let id = conf.m.filenameToIndexTbl[path]
result = toFilenameOption(conf, id, conf.filenameOption)

else:
# Path not registered in the filename table - most likely an
# instantiation info report location
when compileOption"excessiveStackTrace":
# instLoc(), when `--excessiveStackTrace` is used, generates full
# paths that /might/ need to be filtered if `--filenames:canonical`.
const compilerRoot = currentSourcePath().parentDir().parentDir()
if conf.filenameOption == foCanonical and
path.startsWith(compilerRoot):
result = path[(compilerRoot.len + 1) .. ^1]

else:
result = path

else:
result = path

proc formatPath*(conf: ConfigRef, idx: FileIndex): string =
conf.toFilenameOption(idx, conf.filenameOption)
189 changes: 189 additions & 0 deletions compiler/front/sexp_reporter.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
## Implementation of the CLI message generator

import
experimental/[
sexp,
diff,
colortext
],
ast/[
lineinfos,
ast,
reports
],
front/[
options,
msgs
],
std/[
strutils
],
./reporter_common.nim


var writeConf: ConfigRef

import std/options as std_options

proc addFields[T](s: var SexpNode, r: T, ignore: seq[string] = @[])

proc sexp[T: object | tuple](obj: T): SexpNode =
result = newSList()
addFields(result, obj)

proc sexp[T: object | tuple](obj: ref T): SexpNode =
result = newSList()
addFields(result, obj[])

proc sexp*[E: enum](e: E): SexpNode = newSSymbol($e)

proc sexpItems*[T](s: T): SexpNode =
result = newSList()
for item in items(s):
result.add sexp(item)


proc sexp*[T](s: seq[T]): SexpNode = sexpItems(s)
proc sexp*[R, T](s: array[R, T]): SexpNode = sexpItems(s)
proc sexp*[I](s: set[I]): SexpNode = sexpItems(s)
proc sexp*(s: cstring): SexpNode = sexp($s)

proc sexp*(v: SomeInteger): SexpNode = newSInt(BiggestInt(v))
proc sexp*(id: FileIndex): SexpNode =
sexp(writeConf.formatPath(id))


# proc sexp*(id: ReportLineInfo): SexpNode =
# sexp([
# line = sexp(id.line),
# filename =
# ])

iterator sexpFields[T](obj: T, ignore: seq[string] = @[]): SexpNode =
for name, value in fieldPairs(obj):
var pass = true
when value is ref or value is ptr:
if isNil(value):
pass = false

when value is seq or value is string:
if len(value) == 0:
pass = false

when value is TLineInfo:
if pass and value == unknownLineInfo:
pass = false

when value is ReportLineInfo:
if pass and value.isValid():
pass = false

if pass and name in ignore:
pass = false

if pass:
yield newSKeyword(name, sexp(value))


func add*(other: var SexpNode, str: string, expr: SexpNode) =
other.add newSSymbol(":" & str)
other.add expr

proc sexp*[T](o: Option[T]): SexpNode =
if o.isNone: newSNil() else: sexp(o.get())

proc addFields[T](s: var SexpNode, r: T, ignore: seq[string] = @[]) =
for item in sexpFields(r, ignore):
s.add item

proc sexp*(i: ReportLineInfo): SexpNode =
convertSexp([
writeConf.formatPath(i.file).sexp(),
sexp(i.line),
sexp(i.col)
])

proc sexp*(i: TLineInfo): SexpNode =
convertSexp([sexp(i.fileIndex), sexp(i.line), sexp(i.col)])

proc sexp*(e: StackTraceEntry): SexpNode =
result = newSList()
result.addFields(e, @["filename"])
result.add newSKeyword(
"filename", writeConf.formatPath($e.filename).sexp())


proc sexp*(typ: PType): SexpNode =
if typ.isNil: return newSNil()
result = newSList()
result.add newSSymbol(($typ.kind)[2 ..^ 1])
if typ.sons.len > 0:
result.add("sons", sexp(typ.sons))

proc sexp*(node: PNode): SexpNode =
if node.isNil: return newSNil()

result = newSList()
result.add newSSymbol(($node.kind)[2 ..^ 1])
case node.kind:
of nkCharLit..nkUInt64Lit: result.add sexp(node.intVal)
of nkFloatLit..nkFloat128Lit: result.add sexp(node.floatVal)
of nkStrLit..nkTripleStrLit: result.add sexp(node.strVal)
of nkSym: result.add newSSymbol(node.sym.name.s)
of nkIdent: result.add newSSymbol(node.ident.s)
else:
for node in node.sons:
result.add sexp(node)

proc sexp*(t: PSym): SexpNode =
convertSexp([
substr($t.kind, 2).newSSymbol(),
name = sexp(t.name.s),
info = sexp(t.info)
])


proc reportHook*(conf: ConfigRef, r: Report): TErrorHandling =
writeConf = conf
let wkind = conf.writabilityKind(r)

if wkind == writeDisabled:
return

else:
var s = newSList()
s.add newSSymbol(multiReplace($r.kind, {
"rsem": "Sem",
"rpar": "Par",
"rlex": "Lex",
"rint": "Int",
"rext": "Ext",
"rdbg": "Dbg",
"rback": "Bck",
}))
s.add newSSymbol(":severity")
s.add sexp(conf.severity(r))

let f = @["kind"]

case r.category:
of repLexer: s.addFields(r.lexReport, f)
of repParser: s.addFields(r.parserReport, f)
of repCmd: s.addFields(r.cmdReport, f)
of repSem:
if r.kind == rsemProcessingStmt:
s.addFields(r.semReport, f & "node")

else:
s.addFields(r.semReport, f)

of repDebug: s.addFields(r.debugReport)
of repInternal: s.addFields(r.internalReport)
of repBackend: s.addFields(r.backendReport)
of repExternal: s.addFields(r.externalReport)

if wkind == writeForceEnabled:
echo s.toLine()

else:
conf.writeln(s.toLine())
2 changes: 1 addition & 1 deletion compiler/sem/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
firstMismatch: z.firstMismatch,
diagnostics: z.diagnostics,
isDiagnostic: z.diagnosticsEnabled or efExplain in flags
))
))

else:
# Symbol table has been modified. Restart and pre-calculate all syms
Expand Down
Loading

0 comments on commit bec41a2

Please sign in to comment.