diff options
Diffstat (limited to 'compiler/options.nim')
-rw-r--r-- | compiler/options.nim | 188 |
1 files changed, 115 insertions, 73 deletions
diff --git a/compiler/options.nim b/compiler/options.nim index a94405e05..b77bdd2a3 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -8,11 +8,12 @@ # import - os, strutils, strtabs, sets, lineinfos, platform, - prefixmatches, pathutils, nimpaths, tables + lineinfos, platform, + prefixmatches, pathutils, nimpaths -from terminal import isatty -from times import utc, fromUnix, local, getTime, format, DateTime +import std/[tables, os, strutils, strtabs, sets] +from std/terminal import isatty +from std/times import utc, fromUnix, local, getTime, format, DateTime from std/private/globs import nativeToUnixPath when defined(nimPreviewSlimSystem): @@ -24,7 +25,7 @@ const useEffectSystem* = true useWriteTracking* = false hasFFI* = defined(nimHasLibFFI) - copyrightYear* = "2022" + copyrightYear* = "2024" nimEnableCovariance* = defined(nimEnableCovariance) @@ -49,6 +50,7 @@ type # please make sure we have under 32 options optSinkInference # 'sink T' inference optCursorInference optImportHidden + optQuirky TOptions* = set[TOption] TGlobalOption* = enum @@ -78,10 +80,13 @@ type # please make sure we have under 32 options optThreadAnalysis, # thread analysis pass optTlsEmulation, # thread var emulation turned on optGenIndex # generate index file for documentation; + optGenIndexOnly # generate only index file for documentation + optNoImportdoc # disable loading external documentation files optEmbedOrigSrc # embed the original source in the generated code # also: generate header file optIdeDebug # idetools: debug mode optIdeTerse # idetools: use terse descriptions + optIdeExceptionInlayHints optExcessiveStackTrace # fully qualified module filenames optShowAllMismatches # show all overloading resolution candidates optWholeProject # for 'doc': output any dependency @@ -100,12 +105,11 @@ type # please make sure we have under 32 options optBenchmarkVM # Enables cpuTime() in the VM optProduceAsm # produce assembler code optPanics # turn panics (sysFatal) into a process termination - optNimV1Emulation # emulate Nim v1.0 - optNimV12Emulation # emulate Nim v1.2 - optNimV16Emulation # emulate Nim v1.6 optSourcemap optProfileVM # enable VM profiler optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types. + optShowNonExportedFields # for documentation: show fields that are not exported + optJsBigInt64 # use bigints for 64-bit integers in JS TGlobalOptions* = set[TGlobalOption] @@ -141,10 +145,11 @@ type Command* = enum ## Nim's commands cmdNone # not yet processed command cmdUnknown # command unmapped - cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS + cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun # compile and run in nimache cmdTcc # run the project via TCC backend cmdCheck # semantic checking for whole project + cmdM # only compile a single cmdParse # parse a single file (for debugging) cmdRod # .rod to some text representation (for debugging) cmdIdeTools # ide tools (e.g. nimsuggest) @@ -165,16 +170,15 @@ type cmdInteractive # start interactive session cmdNop cmdJsonscript # compile a .json build file - cmdNimfix # old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs) const - cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun} + cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, + cmdCompileToJS, cmdCrun} cmdDocLike* = {cmdDoc0, cmdDoc, cmdDoc2tex, cmdJsondoc0, cmdJsondoc, cmdCtags, cmdBuildindex} type - NimVer* = tuple[major: int, minor: int, patch: int] TStringSeq* = seq[string] TGCMode* = enum # the selected GC gcUnselected = "unselected" @@ -183,6 +187,7 @@ type gcRegions = "regions" gcArc = "arc" gcOrc = "orc" + gcAtomicArc = "atomicArc" gcMarkAndSweep = "markAndSweep" gcHooks = "hooks" gcRefc = "refc" @@ -193,10 +198,9 @@ type IdeCmd* = enum ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod, ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols, - ideRecompile, ideChanged, ideType, ideDeclaration + ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints Feature* = enum ## experimental features; DO NOT RENAME THESE! - implicitDeref, # deadcode; remains here for backwards compatibility dotOperators, callOperator, parallel, @@ -208,7 +212,7 @@ type codeReordering, compiletimeFFI, ## This requires building nim with `-d:nimHasLibFFI` - ## which itself requires `nimble install libffi`, see #10150 + ## which itself requires `koch installdeps libffi`, see #10150 ## Note: this feature can't be localized with {.push.} vmopsDanger, strictFuncs, @@ -219,7 +223,12 @@ type unicodeOperators, # deadcode flexibleOptionalParams, strictDefs, - strictCaseObjects + strictCaseObjects, + inferGenericTypes, + openSym, # remove nfDisabledOpenSym when this is default + # alternative to above: + genericsOpenSym + vtables LegacyFeature* = enum allowSemcheckedAstModification, @@ -232,13 +241,19 @@ type ## are not anymore. laxEffects ## Lax effects system prior to Nim 2.0. + verboseTypeMismatch + emitGenerics + ## generics are emitted in the module that contains them. + ## Useful for libraries that rely on local passC + jsNoLambdaLifting + ## Old transformation for closures in JS backend SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest TSystemCC* = enum ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc, - ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl + ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl, ccHipcc, ccNvcc ExceptionSystem* = enum excNone, # no exception system selected yet @@ -276,8 +291,27 @@ type scope*, localUsages*, globalUsages*: int # more usages is better tokenLen*: int version*: int + endLine*: uint16 + endCol*: int + inlayHintInfo*: SuggestInlayHint + Suggestions* = seq[Suggest] + SuggestInlayHintKind* = enum + sihkType = "Type", + sihkParameter = "Parameter" + sihkException = "Exception" + + SuggestInlayHint* = ref object + kind*: SuggestInlayHintKind + line*: int # Starts at 1 + column*: int # Starts at 0 + label*: string + paddingLeft*: bool + paddingRight*: bool + allowInsert*: bool + tooltip*: string + ProfileInfo* = object time*: float count*: int @@ -329,12 +363,12 @@ type cppDefines*: HashSet[string] # (*) headerFile*: string + nimbasePattern*: string # pattern to find nimbase.h features*: set[Feature] legacyFeatures*: set[LegacyFeature] arguments*: string ## the arguments to be passed to the program that ## should be run ideCmd*: IdeCmd - oldNewlines*: bool cCompiler*: TSystemCC # the used compiler modifiedyNotes*: TNoteKinds # notes that have been set/unset from either cmdline/configs cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline @@ -361,8 +395,7 @@ type outDir*: AbsoluteDir jsonBuildFile*: AbsoluteFile prefixDir*, libpath*, nimcacheDir*: AbsoluteDir - nimStdlibVersion*: NimVer - dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef + dllOverrides*, moduleOverrides*, cfileSpecificOptions*: StringTableRef projectName*: string # holds a name like 'nim' projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/ projectFull*: AbsoluteFile # projectPath/projectName @@ -374,7 +407,6 @@ type commandArgs*: seq[string] # any arguments after the main command commandLine*: string extraCmds*: seq[string] # for writeJsonBuildInstructions - keepComments*: bool # whether the parser needs to keep comments implicitImports*: seq[string] # modules that are to be implicitly imported implicitIncludes*: seq[string] # modules that are to be implicitly included docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \ @@ -406,15 +438,15 @@ type nimMainPrefix*: string vmProfileData*: ProfileData -proc parseNimVersion*(a: string): NimVer = - # could be moved somewhere reusable - if a.len > 0: - let b = a.split(".") - assert b.len == 3, a - template fn(i) = result[i] = b[i].parseInt # could be optimized if needed - fn(0) - fn(1) - fn(2) + expandProgress*: bool + expandLevels*: int + expandNodeResult*: string + expandPosition*: TLineInfo + + currentConfigDir*: string # used for passPP only; absolute dir + clientProcessId*: int + + proc assignIfDefault*[T](result: var T, val: T, def = default(T)) = ## if `result` was already assigned to a value (that wasn't `def`), this is a noop. @@ -457,7 +489,7 @@ when false: fn(globalOptions) fn(selectedGC) -const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel} +const oldExperimentalFeatures* = {dotOperators, callOperator, parallel} const ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, @@ -468,7 +500,8 @@ const optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck, optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs` optTrMacros, optStyleCheck, optCursorInference} - DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace} + DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace, + optJsBigInt64} proc getSrcTimestamp(): DateTime = try: @@ -547,7 +580,6 @@ proc newConfigRef*(): ConfigRef = command: "", # the main command (e.g. cc, check, scan, etc) commandArgs: @[], # any arguments after the main command commandLine: "", - keepComments: true, # whether the parser needs to keep comments implicitImports: @[], # modules that are to be implicitly imported implicitIncludes: @[], # modules that are to be implicitly included docSeeSrcUrl: "", @@ -567,6 +599,7 @@ proc newConfigRef*(): ConfigRef = maxLoopIterationsVM: 10_000_000, vmProfileData: newProfileData(), spellSuggestMax: spellSuggestSecretSauce, + currentConfigDir: "" ) initConfigRefCommon(result) setTargetFromSystem(result.target) @@ -587,12 +620,6 @@ proc newPartialConfigRef*(): ConfigRef = proc cppDefine*(c: ConfigRef; define: string) = c.cppDefines.incl define -proc getStdlibVersion*(conf: ConfigRef): NimVer = - if conf.nimStdlibVersion == (0,0,0): - let s = conf.symbols.getOrDefault("nimVersion", "") - conf.nimStdlibVersion = s.parseNimVersion - result = conf.nimStdlibVersion - proc isDefined*(conf: ConfigRef; symbol: string): bool = if conf.symbols.hasKey(symbol): result = true @@ -610,7 +637,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = osQnx, osAtari, osAix, osHaiku, osVxWorks, osSolaris, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos, - osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr} + osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr, osNuttX} of "linux": result = conf.target.targetOS in {osLinux, osAndroid} of "bsd": @@ -632,6 +659,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = result = conf.target.targetOS == osFreeRTOS of "zephyr": result = conf.target.targetOS == osZephyr + of "nuttx": + result = conf.target.targetOS == osNuttX of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian of "cpu8": result = CPU[conf.target.targetCPU].bit == 8 @@ -641,12 +670,12 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool = of "nimrawsetjmp": result = conf.target.targetOS in {osSolaris, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osMacosx} - else: discard + else: result = false template quitOrRaise*(conf: ConfigRef, msg = "") = # xxx in future work, consider whether to also intercept `msgQuit` calls if conf.isDefined("nimDebug"): - doAssert false, msg + raiseAssert msg else: quit(msg) # quits with QuitFailure @@ -706,22 +735,24 @@ proc getPrefixDir*(conf: ConfigRef): AbsoluteDir = ## clone or using installed nim, so that these exist: `result/doc/advopt.txt` ## and `result/lib/system.nim` if not conf.prefixDir.isEmpty: result = conf.prefixDir - else: result = AbsoluteDir splitPath(getAppDir()).head + else: + let binParent = AbsoluteDir splitPath(getAppDir()).head + when defined(posix): + if binParent == AbsoluteDir"/usr": + result = AbsoluteDir"/usr/lib/nim" + elif binParent == AbsoluteDir"/usr/local": + result = AbsoluteDir"/usr/local/lib/nim" + else: + result = binParent + else: + result = binParent proc setDefaultLibpath*(conf: ConfigRef) = # set default value (can be overwritten): if conf.libpath.isEmpty: # choose default libpath: var prefix = getPrefixDir(conf) - when defined(posix): - if prefix == AbsoluteDir"/usr": - conf.libpath = AbsoluteDir"/usr/lib/nim" - elif prefix == AbsoluteDir"/usr/local": - conf.libpath = AbsoluteDir"/usr/local/lib/nim" - else: - conf.libpath = prefix / RelativeDir"lib" - else: - conf.libpath = prefix / RelativeDir"lib" + conf.libpath = prefix / RelativeDir"lib" # Special rule to support other tools (nimble) which import the compiler # modules and make use of them. @@ -742,7 +773,10 @@ proc setFromProjectName*(conf: ConfigRef; projectName: string) = conf.projectFull = AbsoluteFile projectName let p = splitFile(conf.projectFull) let dir = if p.dir.isEmpty: AbsoluteDir getCurrentDir() else: p.dir - conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile dir) + try: + conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile dir) + except OSError: + conf.projectPath = dir conf.projectName = p.name proc removeTrailingDirSep*(path: string): string = @@ -775,16 +809,17 @@ proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir = else: "_d" # XXX projectName should always be without a file extension! - result = if not conf.nimcacheDir.isEmpty: - conf.nimcacheDir - elif conf.backend == backendJs: - if conf.outDir.isEmpty: - conf.projectPath / genSubDir - else: - conf.outDir / genSubDir - else: - AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name & - nimcacheSuffix(conf)) + result = + if not conf.nimcacheDir.isEmpty: + conf.nimcacheDir + elif conf.backend == backendJs: + if conf.outDir.isEmpty: + conf.projectPath / genSubDir + else: + conf.outDir / genSubDir + else: + AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name & + nimcacheSuffix(conf)) proc pathSubs*(conf: ConfigRef; p, config: string): string = let home = removeTrailingDirSep(os.getHomeDir()) @@ -851,14 +886,6 @@ template patchModule(conf: ConfigRef) {.dirty.} = let ov = conf.moduleOverrides[key] if ov.len > 0: result = AbsoluteFile(ov) -when (NimMajor, NimMinor) < (1, 1) or not declared(isRelativeTo): - proc isRelativeTo(path, base: string): bool = - # pending #13212 use os.isRelativeTo - let path = path.normalizedPath - let base = base.normalizedPath - let ret = relativePath(path, base) - result = path.len > 0 and not ret.startsWith ".." - const stdlibDirs* = [ "pure", "core", "arch", "pure/collections", @@ -870,9 +897,10 @@ const stdlibDirs* = [ const pkgPrefix = "pkg/" - stdPrefix = "std/" + stdPrefix* = "std/" proc getRelativePathFromConfigPath*(conf: ConfigRef; f: AbsoluteFile, isTitle = false): RelativeFile = + result = RelativeFile("") let f = $f if isTitle: for dir in stdlibDirs: @@ -903,10 +931,12 @@ proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFile = # returns path to module var m = addFileExt(modulename, NimExt) + var hasRelativeDot = false if m.startsWith(pkgPrefix): result = findFile(conf, m.substr(pkgPrefix.len), suppressStdlib = true) else: if m.startsWith(stdPrefix): + result = AbsoluteFile("") let stripped = m.substr(stdPrefix.len) for candidate in stdlibDirs: let path = (conf.libpath.string / candidate / stripped) @@ -916,7 +946,11 @@ proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFi else: # If prefixed with std/ why would we add the current module path! let currentPath = currentModule.splitFile.dir result = AbsoluteFile currentPath / m - if not fileExists(result): + if m.startsWith('.') and not fileExists(result): + result = AbsoluteFile "" + hasRelativeDot = true + + if not fileExists(result) and not hasRelativeDot: result = findFile(conf, m) patchModule(conf) @@ -994,6 +1028,12 @@ proc isDynlibOverride*(conf: ConfigRef; lib: string): bool = result = optDynlibOverrideAll in conf.globalOptions or conf.dllOverrides.hasKey(lib.canonDynlibName) +proc showNonExportedFields*(conf: ConfigRef) = + incl(conf.globalOptions, optShowNonExportedFields) + +proc expandDone*(conf: ConfigRef): bool = + result = conf.ideCmd == ideExpand and conf.expandLevels == 0 and conf.expandProgress + proc parseIdeCmd*(s: string): IdeCmd = case s: of "sug": ideSug @@ -1033,9 +1073,11 @@ proc `$`*(c: IdeCmd): string = of ideProject: "project" of ideGlobalSymbols: "globalSymbols" of ideDeclaration: "declaration" + of ideExpand: "expand" of ideRecompile: "recompile" of ideChanged: "changed" of ideType: "type" + of ideInlayHints: "inlayHints" proc floatInt64Align*(conf: ConfigRef): int16 = ## Returns either 4 or 8 depending on reasons. |