Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools: added a port of dust #979

Draft
wants to merge 13 commits into
base: devel
Choose a base branch
from
2 changes: 0 additions & 2 deletions compiler/front/cli_reporter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1209,7 +1209,6 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string =

of rsemUseOrDiscardExpr:
let n = r.wrongNode

result.add(
"expression '",
n.render,
Expand All @@ -1220,7 +1219,6 @@ proc reportBody*(conf: ConfigRef, r: SemReport): string =

if r.ast.info.line != n.info.line or
r.ast.info.fileIndex != n.info.fileIndex:

result.add "; start of expression here: " & conf$r.ast.info

if r.ast.typ.kind == tyProc:
Expand Down
8 changes: 5 additions & 3 deletions compiler/front/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,11 @@ proc getReportHook*(conf: ConfigRef): ReportHook =
proc report*(conf: ConfigRef, inReport: Report): TErrorHandling =
## Write `inReport`
assert inReport.kind != repNone, "Cannot write out empty report"
assert(conf.structuredReportHook != nil,
"Cannot write report with empty report hook")
return conf.structuredReportHook(conf, inReport)
# TODO: use a no-op structuredHook in dust instead of nil
# assert(conf.structuredReportHook != nil,
# "Cannot write report with empty report hook")
if conf.structuredReportHook != nil:
return conf.structuredReportHook(conf, inReport)

proc canReport*(conf: ConfigRef, id: NodeId): bool =
## Check whether report with given ID can actually be written out, or it
Expand Down
16 changes: 9 additions & 7 deletions compiler/sem/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -316,15 +316,15 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
if n[0].isError:
return wrapError(c.config, n)
for i in 1 ..< n.len:
n[i][^1] = discardCheck(c, n[i][^1], flags)
if n[i][^1].isError:
n[i] = discardCheck(c, n[i], flags)
if n[i].isError:
return wrapError(c.config, n)
if typ == c.enforceVoidContext:
result.typ = c.enforceVoidContext
else:
if n.lastSon.kind == nkFinally:
n[^1][^1] = discardCheck(c, n[^1][^1], flags)
if n[^1][^1].isError:
n[^1] = discardCheck(c, n[^1], flags)
if n[^1].isError:
return wrapError(c.config, n)
n[0] = fitNode(c, typ, n[0], n[0].info)
for i in 1..last:
Expand Down Expand Up @@ -1424,20 +1424,22 @@ proc symForVar(c: PContext, n: PNode): PSym =
let
hasPragma = n.kind == nkPragmaExpr
resultNode = newSymGNode(skForVar, (if hasPragma: n[0] else: n), c)
semmedNode = if hasPragma: copyNodeWithKids(n) else: resultNode

result = getDefNameSymOrRecover(resultNode)
styleCheckDef(c.config, result)

if hasPragma:
let pragma = pragmaDecl(c, result, n[1], forVarPragmas)
if pragma.kind == nkError:
n[1] = pragma
semmedNode[0] = resultNode
semmedNode[1] = pragma

if resultNode.kind == nkError or hasPragma and n[1].kind == nkError:
result = newSym(skError, result.name, nextSymId(c.idgen), result.owner,
n.info)
result.typ = c.errorType
result.ast = c.config.wrapError(n)
result.ast = c.config.wrapError(semmedNode)

proc semSingleForVar(c: PContext, formal: PType, view: ViewTypeKind, n: PNode): PNode =
## Semantically analyses a single definition of a variable in the context of
Expand All @@ -1446,7 +1448,7 @@ proc semSingleForVar(c: PContext, formal: PType, view: ViewTypeKind, n: PNode):

let v = symForVar(c, n)
if v.kind == skError:
return c.config.wrapError(n)
return v.ast

if getCurrOwner(c).kind == skModule:
incl(v.flags, sfGlobal)
Expand Down
2 changes: 1 addition & 1 deletion compiler/utils/astrepr.nim
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ proc treeRepr*(
else:
addi indent, rconf.formatKind(typ.kind) + style.kind
if trfShowTypeSym notin rconf and typ.sym != nil:
# If the name is not show in verbose manner as a field, print it
# If the name is not shown in verbose manner as a field, print it
# beforehand as a regular string.
add " \""
add typ.sym.name.s + style.identLit
Expand Down
186 changes: 186 additions & 0 deletions tools/dust/boring.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
##[

the boring bits that really aren't very relevant to dust.

]##

import std/times
import std/os
import std/parseopt

from std/strutils import endsWith

import
compiler / ast / [
idents,
lineinfos,
],
compiler / front / [
cmdlinehelper,
# commands,
condsyms,
msgs,
options,
optionsprocessor,
],
compiler / modules / [
modules,
modulegraphs,
],
compiler / utils / pathutils

from compiler / front / commands import procSwitchResultToEvents,
cliEventLogger,
showMsg

const
NimCfg* {.strdefine.} = "nim".addFileExt "cfg"

template excludeAllNotes(config: ConfigRef; n: typed) =
config.notes.excl n
when compiles(config.mainPackageNotes):
config.mainPackageNotes.excl n
when compiles(config.foreignPackageNotes):
config.foreignPackageNotes.excl n

proc processArgument(pass: TCmdLinePass; p: OptParser;
argsCount: var int; config: ConfigRef): bool =
if argsCount == 0:
if p.key.endsWith(".nim"):
config.setCmd cmdCompileToC
config.projectName = unixToNativePath(p.key)
config.arguments = cmdLineRest(p)
result = true
elif pass != passCmd2: setCommandEarly(config, p.key)
else:
if pass == passCmd1: config.commandArgs.add p.key
if argsCount == 1:
# support UNIX style filenames everywhere for portable build scripts:
if config.projectName.len == 0 and config.inputMode == pimFile:
config.projectName = unixToNativePath(p.key)
config.arguments = cmdLineRest(p)
result = true
inc argsCount

proc cmdLine(pass: TCmdLinePass, cmd: openArray[string]; config: ConfigRef) =
## parse the command-line into the config
var p = initOptParser(cmd)
var argsCount = 0

config.commandLine.setLen 0 # some bug
while true:
next(p)
case p.kind
of cmdEnd:
break
of cmdLongOption, cmdShortOption:
config.commandLine.add " "
config.commandLine.add:
if p.kind == cmdLongOption: "--" else: "-"
config.commandLine.add p.key.quoteShell
if p.val.len > 0:
config.commandLine.add ':'
config.commandLine.add p.val.quoteShell
if p.key == " ":
p.key = "-"
if processArgument(pass, p, argsCount, config):
break
else:
# Main part of the configuration processing -
# `optionsprocessor.processSwitch` processes input switches a second
# time and puts them in necessary configuration fields.
let res = processSwitch(pass, p, config)
for e in procSwitchResultToEvents(config, pass, p.key, p.val, res):
config.cliEventLogger(e)
of cmdArgument:
config.commandLine.add " "
config.commandLine.add p.key.quoteShell
if processArgument(pass, p, argsCount, config):
break

when false:
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and
config.arguments.len > 0 and
config.command.normalize notin ["run", "e"]:
rawMessage(config, errGenerated, errArgsNeedRunOption)

proc helpOnError(config: ConfigRef) =
const
Usage = """
dust [options] [projectfile]

Options: Same options that the Nimskull compiler supports.
"""
showMsg(config, Usage)
msgQuit 0

proc reset*(graph: ModuleGraph) =
## reset the module graph so it is ready for recompilation
# we're not dirty if we don't have a fileindex
if graph.config.projectMainIdx != InvalidFileIdx:
# mark the program as dirty
graph.markDirty graph.config.projectMainIdx
# mark dependencies as dirty
graph.markClientsDirty graph.config.projectMainIdx
# reset the error counter
graph.config.errorCounter = 0

proc compile*(graph: ModuleGraph) =
## compile a module graph
reset graph
let config = graph.config
config.lastCmdTime = epochTime()
if config.libpath notin config.searchPaths:
config.searchPaths.add config.libpath # make sure we can import

config.setErrorMaxHighMaybe # for now, we honor errorMax
defineSymbol(config, "nimcheck") # useful for static: reasons

graph.suggestMode = true # needed for dirty flags
compileProject graph # process the graph

proc setup*(cache: IdentCache; config: ConfigRef; graph: ModuleGraph): bool =
proc noop(graph: ModuleGraph) {.used.} = discard
let prog = NimProg(supportsStdinFile: true,
processCmdLine: cmdLine) #, mainCommand: mainCommand)
initDefinesProg(prog, config, "dust")
if paramCount() == 0:
helpOnError(config)
else:
let argv = getExecArgs()
processCmdLineAndProjectPath(prog, config, argv)
result = loadConfigsAndProcessCmdLine(prog, cache, config, graph, argv)

proc parentDir(file: AbsoluteFile): AbsoluteDir =
result = AbsoluteDir(file) / RelativeDir".."

proc loadConfig*(graph: ModuleGraph; fn: AbsoluteFile) =
## use the ident cache to load the project config for the given filename
var result = graph.config

#excludeAllNotes(result, hintConf)
#excludeAllNotes(result, hintLineTooLong)

initDefines(result.symbols)

let compilerPath = AbsoluteFile findExe"nim"
result.prefixDir = parentDir(compilerPath) / RelativeDir".."
result.projectPath = parentDir(fn)

when false:
let cfg = fn.string & ExtSep & "cfg"
if fileExists(cfg):
if not readConfigFile(cfg.AbsoluteFile, graph.cache, result):
raise newException(ValueError, "couldn't parse " & cfg)
else:
let cwd = getCurrentDir()
setCurrentDir $result.projectPath
try:
discard loadConfigs(NimCfg.RelativeFile, graph.cache, result)
finally:
setCurrentDir cwd

incl result, optStaticBoundsCheck
excl result, optWarns
excl result, optHints
Loading