summary refs log tree commit diff stats
path: root/compiler/transf.nim
Commit message (Collapse)AuthorAgeFilesLines
* Refactor injectdestructors (#12295)Clyybber2019-10-011-1/+0
| | | One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.
* Fix spellings (#12277) [backport]Federico Ceratto2019-09-271-2/+2
|
* Small ast.nim cleanup (#12156)Clyybber2019-09-091-22/+22
| | | | | * Remove sonsLen * Use Indexable
* Merge branch 'devel' into uint-range-checksAraq2019-09-021-2/+1
|\
| * Support iterators returning lent T (#11938)cooldome2019-08-311-2/+1
| | | | | | | | | | | | | | * lent iterators * rebase tests * update changelog * fix comments, more tests
* | minor stuffArne Döring2019-08-271-1/+1
|/
* removed unused imports [refactoring]Andreas Rumpf2019-08-081-1/+1
|
* int128 on firstOrd, lastOrd and lengthOrd (#11701)Arne Döring2019-08-071-2/+2
| | | | * fixes #11847
* [refactoring] remove unused imports in the compiler and in some stdlib modulesAraq2019-07-181-2/+2
|
* fixes #11683Araq2019-07-101-5/+6
|
* fixes #8316 (#11673)Andreas Rumpf2019-07-061-7/+15
|
* fix complex typdesc iteratorsJasper Jenkins2019-05-081-0/+1
|
* Replace countup(x, y) with x .. yClyybber2019-05-071-3/+3
|
* Replace countup(x, y-1) with x ..< yClyybber2019-05-071-9/+9
|
* fixes #11050Araq2019-04-171-0/+2
|
* dfa.nim: track object/tuple field accesses more precisely; sink(o.x); ↵Araq2019-04-161-2/+2
| | | | sink(o.y) needs to compile; activate the tuple unpacking transf.nim bugfix
* make strscans module work with --newruntimeAndreas Rumpf2019-04-141-1/+1
| pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#
#
#           The Nim Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# This module handles the reading of the config file.

import
  llstream, commands, os, strutils, msgs, lexer, ast,
  options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig

when defined(nimPreviewSlimSystem):
  import std/syncio

# ---------------- configuration file parser -----------------------------
# we use Nim's lexer here to save space and work

proc ppGetTok(L: var Lexer, tok: var Token) =
  # simple filter
  rawGetTok(L, tok)
  while tok.tokType in {tkComment}: rawGetTok(L, tok)

proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool
proc parseAtom(L: var Lexer, tok: var Token; config: ConfigRef): bool =
  if tok.tokType == tkParLe:
    ppGetTok(L, tok)
    result = parseExpr(L, tok, config)
    if tok.tokType == tkParRi: ppGetTok(L, tok)
    else: lexMessage(L, errGenerated, "expected closing ')'")
  elif tok.tokType == tkNot:
    ppGetTok(L, tok)
    result = not parseAtom(L, tok, config)
  else:
    result = isDefined(config, tok.ident.s)
    ppGetTok(L, tok)

proc parseAndExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
  result = parseAtom(L, tok, config)
  while tok.tokType == tkAnd:
    ppGetTok(L, tok)          # skip "and"
    var b = parseAtom(L, tok, config)
    result = result and b

proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
  result = parseAndExpr(L, tok, config)
  while tok.tokType == tkOr:
    ppGetTok(L, tok)          # skip "or"
    var b = parseAndExpr(L, tok, config)
    result = result or b

proc evalppIf(L: var Lexer, tok: var Token; config: ConfigRef)olspan='5' class='logmsg'>
Fixes #9177

* fixes some bugAndreas Rumpf2019-02-061-0/+1
|
* Show lineinfo of for in yield (#9779)Alexander Ivanov2018-12-131-0/+5
|
* VM: don't inject destructor calls, refs #7041Andreas Rumpf2018-11-061-13/+16
|
* Transf minor code optimization (#9433)cooldome2018-10-191-37/+12
|
* Change the order of compilation passes, transformation is made lazy at code ↵cooldome2018-10-181-22/+42
| | | | | | | | | | | | | | | gen (#8489) * Ast no transformation * Add getImplNoTransform to the macros module * progress on delaying transf * Fix methods tranformation * Fix lazy lambdalifting * fix create thread wrapper * transform for lambda lifting * improve getImplTransformed * Fix destructor tests * try to fix nimprof for linux
* fixes #5519Araq2018-10-181-3/+6
|
* fixes #7972Araq2018-10-181-10/+13
|
* Field checks for everybody (#8957)LemonBoy2018-10-091-1/+1
| | | | | | | | | | | | | | | | | | | | | * Field checks for JS backend * Clean nkCall nodes with no arguments Generating a nkEmpty in place of no arguments makes no sense form the AST point of view and also trips up the VM codegen. * Field checks for VM backend * Test case for #6612 This patchset fixes #6612 * Add test case for LHS double evaluation * Prevent LHS double-eval for JS backend * Prevent double evaluation in VM backend
* Fix transformation of yield in inline context (#9135)LemonBoy2018-10-091-15/+28
| | | | | | When the loop variables are part of the envP block it is not safe to use a nkFastAsgn. Fixes #2656
* Make the registered passes local to the ModuleGraph (#9259)LemonBoy2018-10-091-1/+1
| | | Closes #9068
* enable destructors for top level statements; needs to be documentedAndreas Rumpf2018-09-241-4/+4
|
* Revert #7964LemonBoy2018-09-211-6/+5
| | | | | | | Somehow the test case doesn't crash anymore and the regression in the doc generation is fixed. Fixes #9019
* fixes #1616; fixes 'nim doc' regressionsAndreas Rumpf2018-09-171-1/+2
|
* Fix AST generation for case statements (#8908)LemonBoy2018-09-071-1/+5
| | | Fixes #7534
* fixes merge conflictAndreas Rumpf2018-08-191-5/+6
|\
| * Fix unsound transform pass (#8633)LemonBoy2018-08-141-0/+4
| | | | | | | | | | When a `var openArray[T]` function parameter goes trough the `transformAddrDeref` pass we may lose the `var` specifier, leading to nasty crashes at runtime.
| * Mysterious fix for #8550 (#8561)LemonBoy2018-08-121-5/+2
| | | | | | | | Replacing the `for` body with a nkEmpty node is not the right thing to do.
* | more progress on destructor based stringsAndreas Rumpf2018-07-131-4/+4
|/
* make tests green againAndreas Rumpf2018-07-051-0/+2
|
* allow referencing other parameters in default parameter valuesZahary Karadjov2018-06-161-0/+46
| | | | | | | | fix #7756 fix #1201 fix #7000 fix #3002 fix #1046
* fixes yet another merge conflictAraq2018-06-111-1/+1
|\
| * Removed oldIterTranf featureYuriy Glukhov2018-06-101-1/+1
| |
* | fixex merge conflictsAraq2018-06-081-2/+6
|\|
| * Merge branch 'devel' into yield-in-tryYuriy Glukhov2018-05-151-52/+57
| |\
="w"> ppGetTok(L, tok) elif tok.tokType == tkEof: lexMessage(L, errGenerated, "expected @end") else: ppGetTok(L, tok) proc parseDirective(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) = ppGetTok(L, tok) # skip @ case whichKeyword(tok.ident) of wIf: setLen(condStack, condStack.len + 1) let res = evalppIf(L, tok, config) condStack[high(condStack)] = res if not res: jumpToDirective(L, tok, jdElseEndif, config, condStack) of wElif: doElif(L, tok, config, condStack) of wElse: doElse(L, tok, config, condStack) of wEnd: doEnd(L, tok, condStack) of wWrite: ppGetTok(L, tok) msgs.msgWriteln(config, strtabs.`%`($tok, config.configVars, {useEnvironment, useKey})) ppGetTok(L, tok) else: case tok.ident.s.normalize of "putenv": ppGetTok(L, tok) var key = $tok ppGetTok(L, tok) os.putEnv(key, $tok) ppGetTok(L, tok) of "prependenv": ppGetTok(L, tok) var key = $tok ppGetTok(L, tok) os.putEnv(key, $tok & os.getEnv(key)) ppGetTok(L, tok) of "appendenv": ppGetTok(L, tok) var key = $tok ppGetTok(L, tok) os.putEnv(key, os.getEnv(key) & $tok) ppGetTok(L, tok) else: lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok) proc confTok(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) = ppGetTok(L, tok) while tok.ident != nil and tok.ident.s == "@": parseDirective(L, tok, config, condStack) # else: give the token to the parser proc checkSymbol(L: Lexer, tok: Token) = if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}: lexMessage(L, errGenerated, "expected identifier, but got: " & $tok) proc parseAssignment(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) = if tok.ident != nil: if tok.ident.s == "-" or tok.ident.s == "--": confTok(L, tok, config, condStack) # skip unnecessary prefix var info = getLineInfo(L, tok) # save for later in case of an error checkSymbol(L, tok) var s = $tok confTok(L, tok, config, condStack) # skip symbol var val = "" while tok.tokType == tkDot: s.add('.') confTok(L, tok, config, condStack) checkSymbol(L, tok) s.add($tok) confTok(L, tok, config, condStack) if tok.tokType == tkBracketLe: # BUGFIX: val, not s! confTok(L, tok, config, condStack) checkSymbol(L, tok) val.add('[') val.add($tok) confTok(L, tok, config, condStack) if tok.tokType == tkBracketRi: confTok(L, tok, config, condStack) else: lexMessage(L, errGenerated, "expected closing ']'") val.add(']') let percent = tok.ident != nil and tok.ident.s == "%=" if tok.tokType in {tkColon, tkEquals} or percent: if val.len > 0: val.add(':') confTok(L, tok, config, condStack) # skip ':' or '=' or '%' checkSymbol(L, tok) val.add($tok) confTok(L, tok, config, condStack) # skip symbol if tok.tokType in {tkColon, tkEquals}: val.add($tok) # add the : confTok(L, tok, config, condStack) # skip symbol checkSymbol(L, tok) val.add($tok) # add the token after it confTok(L, tok, config, condStack) # skip symbol while tok.ident != nil and tok.ident.s == "&": confTok(L, tok, config, condStack) checkSymbol(L, tok) val.add($tok) confTok(L, tok, config, condStack) if percent: processSwitch(s, strtabs.`%`(val, config.configVars, {useEnvironment, useEmpty}), passPP, info, config) else: processSwitch(s, val, passPP, info, config) proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache; config: ConfigRef): bool = var L: Lexer tok: Token stream: PLLStream stream = llStreamOpen(filename, fmRead) if stream != nil: initToken(tok) openLexer(L, filename, stream, cache, config) tok.tokType = tkEof # to avoid a pointless warning var condStack: seq[bool] = @[] confTok(L, tok, config, condStack) # read in the first token while tok.tokType != tkEof: parseAssignment(L, tok, config, condStack) if condStack.len > 0: lexMessage(L, errGenerated, "expected @end") closeLexer(L) return true proc getUserConfigPath*(filename: RelativeFile): AbsoluteFile = result = getConfigDir().AbsoluteDir / RelativeDir"nim" / filename proc getSystemConfigPath*(conf: ConfigRef; filename: RelativeFile): AbsoluteFile = # try standard configuration file (installation did not distribute files # the UNIX way) let p = getPrefixDir(conf) result = p / RelativeDir"config" / filename when defined(unix): if not fileExists(result): result = p / RelativeDir"etc/nim" / filename if not fileExists(result): result = AbsoluteDir"/etc/nim" / filename proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator) = setDefaultLibpath(conf) template readConfigFile(path) = let configPath = path if readConfigFile(configPath, cache, conf): conf.configFiles.add(configPath) template runNimScriptIfExists(path: AbsoluteFile, isMain = false) = let p = path # eval once var s: PLLStream if isMain and optWasNimscript in conf.globalOptions: if conf.projectIsStdin: s = stdin.llStreamOpen elif conf.projectIsCmd: s = llStreamOpen(conf.cmdInput) if s == nil and fileExists(p): s = llStreamOpen(p, fmRead) if s != nil: conf.configFiles.add(p) runNimScript(cache, p, idgen, freshDefines = false, conf, s) if optSkipSystemConfigFile notin conf.globalOptions: readConfigFile(getSystemConfigPath(conf, cfg)) if cfg == DefaultConfig: runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims)) if optSkipUserConfigFile notin conf.globalOptions: readConfigFile(getUserConfigPath(cfg)) if cfg == DefaultConfig: runNimScriptIfExists(getUserConfigPath(DefaultConfigNims)) let pd = if not conf.projectPath.isEmpty: conf.projectPath else: AbsoluteDir(getCurrentDir()) if optSkipParentConfigFiles notin conf.globalOptions: for dir in parentDirs(pd.string, fromRoot=true, inclusive=false): readConfigFile(AbsoluteDir(dir) / cfg) if cfg == DefaultConfig: runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims) if optSkipProjConfigFile notin conf.globalOptions: readConfigFile(pd / cfg) if cfg == DefaultConfig: runNimScriptIfExists(pd / DefaultConfigNims) if conf.projectName.len != 0: # new project wide config file: var projectConfig = changeFileExt(conf.projectFull, "nimcfg") if not fileExists(projectConfig): projectConfig = changeFileExt(conf.projectFull, "nim.cfg") readConfigFile(projectConfig) let scriptFile = conf.projectFull.changeFileExt("nims") let scriptIsProj = scriptFile == conf.projectFull template showHintConf = for filename in conf.configFiles: # delayed to here so that `hintConf` is honored rawMessage(conf, hintConf, filename.string) if conf.cmd == cmdNimscript: showHintConf() conf.configFiles.setLen 0 if conf.cmd notin {cmdIdeTools, cmdCheck, cmdDump}: if conf.cmd == cmdNimscript: runNimScriptIfExists(conf.projectFull, isMain = true) else: runNimScriptIfExists(scriptFile, isMain = true) else: if not scriptIsProj: runNimScriptIfExists(scriptFile, isMain = true) else: # 'nimsuggest foo.nims' means to just auto-complete the NimScript file # `nim check foo.nims' means to check the syntax of the NimScript file discard showHintConf()