options.nim 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. import
  10. os, strutils, strtabs, sets, lineinfos, platform,
  11. prefixmatches, pathutils, nimpaths, tables
  12. from terminal import isatty
  13. from times import utc, fromUnix, local, getTime, format, DateTime
  14. from std/private/globs import nativeToUnixPath
  15. when defined(nimPreviewSlimSystem):
  16. import std/[syncio, assertions]
  17. const
  18. hasTinyCBackend* = defined(tinyc)
  19. useEffectSystem* = true
  20. useWriteTracking* = false
  21. hasFFI* = defined(nimHasLibFFI)
  22. copyrightYear* = "2023"
  23. nimEnableCovariance* = defined(nimEnableCovariance)
  24. type # please make sure we have under 32 options
  25. # (improves code efficiency a lot!)
  26. TOption* = enum # **keep binary compatible**
  27. optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
  28. optOverflowCheck, optRefCheck,
  29. optNaNCheck, optInfCheck, optStaticBoundsCheck, optStyleCheck,
  30. optAssert, optLineDir, optWarns, optHints,
  31. optOptimizeSpeed, optOptimizeSize,
  32. optStackTrace, # stack tracing support
  33. optStackTraceMsgs, # enable custom runtime msgs via `setFrameMsg`
  34. optLineTrace, # line tracing support (includes stack tracing)
  35. optByRef, # use pass by ref for objects
  36. # (for interfacing with C)
  37. optProfiler, # profiler turned on
  38. optImplicitStatic, # optimization: implicit at compile time
  39. # evaluation
  40. optTrMacros, # en/disable pattern matching
  41. optMemTracker,
  42. optSinkInference # 'sink T' inference
  43. optCursorInference
  44. optImportHidden
  45. optQuirky
  46. TOptions* = set[TOption]
  47. TGlobalOption* = enum
  48. gloptNone, optForceFullMake,
  49. optWasNimscript, # redundant with `cmdNimscript`, could be removed
  50. optListCmd, optCompileOnly, optNoLinking,
  51. optCDebug, # turn on debugging information
  52. optGenDynLib, # generate a dynamic library
  53. optGenStaticLib, # generate a static library
  54. optGenGuiApp, # generate a GUI application
  55. optGenScript, # generate a script file to compile the *.c files
  56. optGenCDeps, # generate a list of *.c files to be read by CMake
  57. optGenMapping, # generate a mapping file
  58. optRun, # run the compiled project
  59. optUseNimcache, # save artifacts (including binary) in $nimcache
  60. optStyleHint, # check that the names adhere to NEP-1
  61. optStyleError, # enforce that the names adhere to NEP-1
  62. optStyleUsages, # only enforce consistent **usages** of the symbol
  63. optSkipSystemConfigFile, # skip the system's cfg/nims config file
  64. optSkipProjConfigFile, # skip the project's cfg/nims config file
  65. optSkipUserConfigFile, # skip the users's cfg/nims config file
  66. optSkipParentConfigFiles, # skip parent dir's cfg/nims config files
  67. optNoMain, # do not generate a "main" proc
  68. optUseColors, # use colors for hints, warnings, and errors
  69. optThreads, # support for multi-threading
  70. optStdout, # output to stdout
  71. optThreadAnalysis, # thread analysis pass
  72. optTlsEmulation, # thread var emulation turned on
  73. optGenIndex # generate index file for documentation;
  74. optGenIndexOnly # generate only index file for documentation
  75. optNoImportdoc # disable loading external documentation files
  76. optEmbedOrigSrc # embed the original source in the generated code
  77. # also: generate header file
  78. optIdeDebug # idetools: debug mode
  79. optIdeTerse # idetools: use terse descriptions
  80. optExcessiveStackTrace # fully qualified module filenames
  81. optShowAllMismatches # show all overloading resolution candidates
  82. optWholeProject # for 'doc': output any dependency
  83. optDocInternal # generate documentation for non-exported symbols
  84. optMixedMode # true if some module triggered C++ codegen
  85. optDeclaredLocs # show declaration locations in messages
  86. optNoNimblePath
  87. optHotCodeReloading
  88. optDynlibOverrideAll
  89. optSeqDestructors # active if the implementation uses the new
  90. # string/seq implementation based on destructors
  91. optTinyRtti # active if we use the new "tiny RTTI"
  92. # implementation
  93. optOwnedRefs # active if the Nim compiler knows about 'owned'.
  94. optMultiMethods
  95. optBenchmarkVM # Enables cpuTime() in the VM
  96. optProduceAsm # produce assembler code
  97. optPanics # turn panics (sysFatal) into a process termination
  98. optSourcemap
  99. optProfileVM # enable VM profiler
  100. optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
  101. optShowNonExportedFields # for documentation: show fields that are not exported
  102. optJsBigInt64 # use bigints for 64-bit integers in JS
  103. TGlobalOptions* = set[TGlobalOption]
  104. const
  105. harmlessOptions* = {optForceFullMake, optNoLinking, optRun, optUseColors, optStdout}
  106. genSubDir* = RelativeDir"nimcache"
  107. NimExt* = "nim"
  108. RodExt* = "rod"
  109. HtmlExt* = "html"
  110. JsonExt* = "json"
  111. TagsExt* = "tags"
  112. TexExt* = "tex"
  113. IniExt* = "ini"
  114. DefaultConfig* = RelativeFile"nim.cfg"
  115. DefaultConfigNims* = RelativeFile"config.nims"
  116. DocConfig* = RelativeFile"nimdoc.cfg"
  117. DocTexConfig* = RelativeFile"nimdoc.tex.cfg"
  118. htmldocsDir* = htmldocsDirname.RelativeDir
  119. docRootDefault* = "@default" # using `@` instead of `$` to avoid shell quoting complications
  120. oKeepVariableNames* = true
  121. spellSuggestSecretSauce* = -1
  122. type
  123. TBackend* = enum
  124. backendInvalid = "" # for parseEnum
  125. backendC = "c"
  126. backendCpp = "cpp"
  127. backendJs = "js"
  128. backendObjc = "objc"
  129. # backendNimscript = "nimscript" # this could actually work
  130. # backendLlvm = "llvm" # probably not well supported; was cmdCompileToLLVM
  131. Command* = enum ## Nim's commands
  132. cmdNone # not yet processed command
  133. cmdUnknown # command unmapped
  134. cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS
  135. cmdCrun # compile and run in nimache
  136. cmdTcc # run the project via TCC backend
  137. cmdCheck # semantic checking for whole project
  138. cmdParse # parse a single file (for debugging)
  139. cmdRod # .rod to some text representation (for debugging)
  140. cmdIdeTools # ide tools (e.g. nimsuggest)
  141. cmdNimscript # evaluate nimscript
  142. cmdDoc0
  143. cmdDoc # convert .nim doc comments to HTML
  144. cmdDoc2tex # convert .nim doc comments to LaTeX
  145. cmdRst2html # convert a reStructuredText file to HTML
  146. cmdRst2tex # convert a reStructuredText file to TeX
  147. cmdMd2html # convert a Markdown file to HTML
  148. cmdMd2tex # convert a Markdown file to TeX
  149. cmdJsondoc0
  150. cmdJsondoc
  151. cmdCtags
  152. cmdBuildindex
  153. cmdGendepend
  154. cmdDump
  155. cmdInteractive # start interactive session
  156. cmdNop
  157. cmdJsonscript # compile a .json build file
  158. # old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs)
  159. const
  160. cmdBackends* = {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun}
  161. cmdDocLike* = {cmdDoc0, cmdDoc, cmdDoc2tex, cmdJsondoc0, cmdJsondoc,
  162. cmdCtags, cmdBuildindex}
  163. type
  164. NimVer* = tuple[major: int, minor: int, patch: int]
  165. TStringSeq* = seq[string]
  166. TGCMode* = enum # the selected GC
  167. gcUnselected = "unselected"
  168. gcNone = "none"
  169. gcBoehm = "boehm"
  170. gcRegions = "regions"
  171. gcArc = "arc"
  172. gcOrc = "orc"
  173. gcAtomicArc = "atomicArc"
  174. gcMarkAndSweep = "markAndSweep"
  175. gcHooks = "hooks"
  176. gcRefc = "refc"
  177. gcGo = "go"
  178. # gcRefc and the GCs that follow it use a write barrier,
  179. # as far as usesWriteBarrier() is concerned
  180. IdeCmd* = enum
  181. ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
  182. ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
  183. ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints
  184. Feature* = enum ## experimental features; DO NOT RENAME THESE!
  185. dotOperators,
  186. callOperator,
  187. parallel,
  188. destructor,
  189. notnil,
  190. dynamicBindSym,
  191. forLoopMacros, # not experimental anymore; remains here for backwards compatibility
  192. caseStmtMacros, # ditto
  193. codeReordering,
  194. compiletimeFFI,
  195. ## This requires building nim with `-d:nimHasLibFFI`
  196. ## which itself requires `nimble install libffi`, see #10150
  197. ## Note: this feature can't be localized with {.push.}
  198. vmopsDanger,
  199. strictFuncs,
  200. views,
  201. strictNotNil,
  202. overloadableEnums, # deadcode
  203. strictEffects,
  204. unicodeOperators, # deadcode
  205. flexibleOptionalParams,
  206. strictDefs,
  207. strictCaseObjects,
  208. openSym, # remove nfDisabledOpenSym when this is default
  209. # alternative to above:
  210. genericsOpenSym
  211. LegacyFeature* = enum
  212. allowSemcheckedAstModification,
  213. ## Allows to modify a NimNode where the type has already been
  214. ## flagged with nfSem. If you actually do this, it will cause
  215. ## bugs.
  216. checkUnsignedConversions
  217. ## Historically and especially in version 1.0.0 of the language
  218. ## conversions to unsigned numbers were checked. In 1.0.4 they
  219. ## are not anymore.
  220. laxEffects
  221. ## Lax effects system prior to Nim 2.0.
  222. verboseTypeMismatch
  223. SymbolFilesOption* = enum
  224. disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest
  225. TSystemCC* = enum
  226. ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc,
  227. ccTcc, ccEnv, ccIcl, ccIcc, ccClangCl
  228. ExceptionSystem* = enum
  229. excNone, # no exception system selected yet
  230. excSetjmp, # setjmp based exception handling
  231. excCpp, # use C++'s native exception handling
  232. excGoto, # exception handling based on goto (should become the new default for C)
  233. excQuirky # quirky exception handling
  234. CfileFlag* {.pure.} = enum
  235. Cached, ## no need to recompile this time
  236. External ## file was introduced via .compile pragma
  237. Cfile* = object
  238. nimname*: string
  239. cname*, obj*: AbsoluteFile
  240. flags*: set[CfileFlag]
  241. customArgs*: string
  242. CfileList* = seq[Cfile]
  243. Suggest* = ref object
  244. section*: IdeCmd
  245. qualifiedPath*: seq[string]
  246. name*: ptr string # not used beyond sorting purposes; name is also
  247. # part of 'qualifiedPath'
  248. filePath*: string
  249. line*: int # Starts at 1
  250. column*: int # Starts at 0
  251. doc*: string # Not escaped (yet)
  252. forth*: string # type
  253. quality*: range[0..100] # matching quality
  254. isGlobal*: bool # is a global variable
  255. contextFits*: bool # type/non-type context matches
  256. prefix*: PrefixMatch
  257. symkind*: byte
  258. scope*, localUsages*, globalUsages*: int # more usages is better
  259. tokenLen*: int
  260. version*: int
  261. endLine*: uint16
  262. endCol*: int
  263. inlayHintInfo*: SuggestInlayHint
  264. Suggestions* = seq[Suggest]
  265. SuggestInlayHintKind* = enum
  266. sihkType = "Type",
  267. sihkParameter = "Parameter"
  268. SuggestInlayHint* = ref object
  269. kind*: SuggestInlayHintKind
  270. line*: int # Starts at 1
  271. column*: int # Starts at 0
  272. label*: string
  273. paddingLeft*: bool
  274. paddingRight*: bool
  275. allowInsert*: bool
  276. tooltip*: string
  277. ProfileInfo* = object
  278. time*: float
  279. count*: int
  280. ProfileData* = ref object
  281. data*: TableRef[TLineInfo, ProfileInfo]
  282. StdOrrKind* = enum
  283. stdOrrStdout
  284. stdOrrStderr
  285. FilenameOption* = enum
  286. foAbs # absolute path, e.g.: /pathto/bar/foo.nim
  287. foRelProject # relative to project path, e.g.: ../foo.nim
  288. foCanonical # canonical module name
  289. foLegacyRelProj # legacy, shortest of (foAbs, foRelProject)
  290. foName # lastPathPart, e.g.: foo.nim
  291. foStacktrace # if optExcessiveStackTrace: foAbs else: foName
  292. ConfigRef* {.acyclic.} = ref object ## every global configuration
  293. ## fields marked with '*' are subject to
  294. ## the incremental compilation mechanisms
  295. ## (+) means "part of the dependency"
  296. backend*: TBackend # set via `nim x` or `nim --backend:x`
  297. target*: Target # (+)
  298. linesCompiled*: int # all lines that have been compiled
  299. options*: TOptions # (+)
  300. globalOptions*: TGlobalOptions # (+)
  301. macrosToExpand*: StringTableRef
  302. arcToExpand*: StringTableRef
  303. m*: MsgConfig
  304. filenameOption*: FilenameOption # how to render paths in compiler messages
  305. unitSep*: string
  306. evalTemplateCounter*: int
  307. evalMacroCounter*: int
  308. exitcode*: int8
  309. cmd*: Command # raw command parsed as enum
  310. cmdInput*: string # input command
  311. projectIsCmd*: bool # whether we're compiling from a command input
  312. implicitCmd*: bool # whether some flag triggered an implicit `command`
  313. selectedGC*: TGCMode # the selected GC (+)
  314. exc*: ExceptionSystem
  315. hintProcessingDots*: bool # true for dots, false for filenames
  316. verbosity*: int # how verbose the compiler is
  317. numberOfProcessors*: int # number of processors
  318. lastCmdTime*: float # when caas is enabled, we measure each command
  319. symbolFiles*: SymbolFilesOption
  320. spellSuggestMax*: int # max number of spelling suggestions for typos
  321. cppDefines*: HashSet[string] # (*)
  322. headerFile*: string
  323. nimbasePattern*: string # pattern to find nimbase.h
  324. features*: set[Feature]
  325. legacyFeatures*: set[LegacyFeature]
  326. arguments*: string ## the arguments to be passed to the program that
  327. ## should be run
  328. ideCmd*: IdeCmd
  329. oldNewlines*: bool
  330. cCompiler*: TSystemCC # the used compiler
  331. modifiedyNotes*: TNoteKinds # notes that have been set/unset from either cmdline/configs
  332. cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline
  333. foreignPackageNotes*: TNoteKinds
  334. notes*: TNoteKinds # notes after resolving all logic(defaults, verbosity)/cmdline/configs
  335. warningAsErrors*: TNoteKinds
  336. mainPackageNotes*: TNoteKinds
  337. mainPackageId*: int
  338. errorCounter*: int
  339. hintCounter*: int
  340. warnCounter*: int
  341. errorMax*: int
  342. maxLoopIterationsVM*: int ## VM: max iterations of all loops
  343. isVmTrace*: bool
  344. configVars*: StringTableRef
  345. symbols*: StringTableRef ## We need to use a StringTableRef here as defined
  346. ## symbols are always guaranteed to be style
  347. ## insensitive. Otherwise hell would break lose.
  348. packageCache*: StringTableRef
  349. nimblePaths*: seq[AbsoluteDir]
  350. searchPaths*: seq[AbsoluteDir]
  351. lazyPaths*: seq[AbsoluteDir]
  352. outFile*: RelativeFile
  353. outDir*: AbsoluteDir
  354. jsonBuildFile*: AbsoluteFile
  355. prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
  356. nimStdlibVersion*: NimVer
  357. dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef
  358. projectName*: string # holds a name like 'nim'
  359. projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
  360. projectFull*: AbsoluteFile # projectPath/projectName
  361. projectIsStdin*: bool # whether we're compiling from stdin
  362. lastMsgWasDot*: set[StdOrrKind] # the last compiler message was a single '.'
  363. projectMainIdx*: FileIndex # the canonical path id of the main module
  364. projectMainIdx2*: FileIndex # consider merging with projectMainIdx
  365. command*: string # the main command (e.g. cc, check, scan, etc)
  366. commandArgs*: seq[string] # any arguments after the main command
  367. commandLine*: string
  368. extraCmds*: seq[string] # for writeJsonBuildInstructions
  369. keepComments*: bool # whether the parser needs to keep comments
  370. implicitImports*: seq[string] # modules that are to be implicitly imported
  371. implicitIncludes*: seq[string] # modules that are to be implicitly included
  372. docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
  373. # The string uses the formatting variables `path` and `line`.
  374. docRoot*: string ## see nim --fullhelp for --docRoot
  375. docCmd*: string ## see nim --fullhelp for --docCmd
  376. configFiles*: seq[AbsoluteFile] # config files (cfg,nims)
  377. cIncludes*: seq[AbsoluteDir] # directories to search for included files
  378. cLibs*: seq[AbsoluteDir] # directories to search for lib files
  379. cLinkedLibs*: seq[string] # libraries to link
  380. externalToLink*: seq[string] # files to link in addition to the file
  381. # we compiled (*)
  382. linkOptionsCmd*: string
  383. compileOptionsCmd*: seq[string]
  384. linkOptions*: string # (*)
  385. compileOptions*: string # (*)
  386. cCompilerPath*: string
  387. toCompile*: CfileList # (*)
  388. suggestionResultHook*: proc (result: Suggest) {.closure.}
  389. suggestVersion*: int
  390. suggestMaxResults*: int
  391. lastLineInfo*: TLineInfo
  392. writelnHook*: proc (output: string) {.closure, gcsafe.}
  393. structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string;
  394. severity: Severity) {.closure, gcsafe.}
  395. cppCustomNamespace*: string
  396. nimMainPrefix*: string
  397. vmProfileData*: ProfileData
  398. expandProgress*: bool
  399. expandLevels*: int
  400. expandNodeResult*: string
  401. expandPosition*: TLineInfo
  402. clientProcessId*: int
  403. proc parseNimVersion*(a: string): NimVer =
  404. # could be moved somewhere reusable
  405. if a.len > 0:
  406. let b = a.split(".")
  407. assert b.len == 3, a
  408. template fn(i) = result[i] = b[i].parseInt # could be optimized if needed
  409. fn(0)
  410. fn(1)
  411. fn(2)
  412. proc assignIfDefault*[T](result: var T, val: T, def = default(T)) =
  413. ## if `result` was already assigned to a value (that wasn't `def`), this is a noop.
  414. if result == def: result = val
  415. template setErrorMaxHighMaybe*(conf: ConfigRef) =
  416. ## do not stop after first error (but honor --errorMax if provided)
  417. assignIfDefault(conf.errorMax, high(int))
  418. proc setNoteDefaults*(conf: ConfigRef, note: TNoteKind, enabled = true) =
  419. template fun(op) =
  420. conf.notes.op note
  421. conf.mainPackageNotes.op note
  422. conf.foreignPackageNotes.op note
  423. if enabled: fun(incl) else: fun(excl)
  424. proc setNote*(conf: ConfigRef, note: TNoteKind, enabled = true) =
  425. # see also `prepareConfigNotes` which sets notes
  426. if note notin conf.cmdlineNotes:
  427. if enabled: incl(conf.notes, note) else: excl(conf.notes, note)
  428. proc hasHint*(conf: ConfigRef, note: TNoteKind): bool =
  429. # ternary states instead of binary states would simplify logic
  430. if optHints notin conf.options: false
  431. elif note in {hintConf, hintProcessing}:
  432. # could add here other special notes like hintSource
  433. # these notes apply globally.
  434. note in conf.mainPackageNotes
  435. else: note in conf.notes
  436. proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool {.inline.} =
  437. optWarns in conf.options and note in conf.notes
  438. proc hcrOn*(conf: ConfigRef): bool = return optHotCodeReloading in conf.globalOptions
  439. when false:
  440. template depConfigFields*(fn) {.dirty.} = # deadcode
  441. fn(target)
  442. fn(options)
  443. fn(globalOptions)
  444. fn(selectedGC)
  445. const oldExperimentalFeatures* = {dotOperators, callOperator, parallel}
  446. const
  447. ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
  448. optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
  449. optStyleCheck}
  450. DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
  451. optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
  452. optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
  453. optTrMacros, optStyleCheck, optCursorInference}
  454. DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
  455. optJsBigInt64}
  456. proc getSrcTimestamp(): DateTime =
  457. try:
  458. result = utc(fromUnix(parseInt(getEnv("SOURCE_DATE_EPOCH",
  459. "not a number"))))
  460. except ValueError:
  461. # Environment variable malformed.
  462. # https://reproducible-builds.org/specs/source-date-epoch/: "If the
  463. # value is malformed, the build process SHOULD exit with a non-zero
  464. # error code", which this doesn't do. This uses local time, because
  465. # that maintains compatibility with existing usage.
  466. result = utc getTime()
  467. proc getDateStr*(): string =
  468. result = format(getSrcTimestamp(), "yyyy-MM-dd")
  469. proc getClockStr*(): string =
  470. result = format(getSrcTimestamp(), "HH:mm:ss")
  471. template newPackageCache*(): untyped =
  472. newStringTable(when FileSystemCaseSensitive:
  473. modeCaseInsensitive
  474. else:
  475. modeCaseSensitive)
  476. proc newProfileData(): ProfileData =
  477. ProfileData(data: newTable[TLineInfo, ProfileInfo]())
  478. const foreignPackageNotesDefault* = {
  479. hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting, hintUser, warnUser}
  480. proc isDefined*(conf: ConfigRef; symbol: string): bool
  481. when defined(nimDebugUtils):
  482. # this allows inserting debugging utilties in all modules that import `options`
  483. # with a single switch, which is useful when debugging compiler.
  484. import debugutils
  485. export debugutils
  486. proc initConfigRefCommon(conf: ConfigRef) =
  487. conf.selectedGC = gcUnselected
  488. conf.verbosity = 1
  489. conf.hintProcessingDots = true
  490. conf.options = DefaultOptions
  491. conf.globalOptions = DefaultGlobalOptions
  492. conf.filenameOption = foAbs
  493. conf.foreignPackageNotes = foreignPackageNotesDefault
  494. conf.notes = NotesVerbosity[1]
  495. conf.mainPackageNotes = NotesVerbosity[1]
  496. proc newConfigRef*(): ConfigRef =
  497. result = ConfigRef(
  498. cCompiler: ccGcc,
  499. macrosToExpand: newStringTable(modeStyleInsensitive),
  500. arcToExpand: newStringTable(modeStyleInsensitive),
  501. m: initMsgConfig(),
  502. cppDefines: initHashSet[string](),
  503. headerFile: "", features: {}, legacyFeatures: {},
  504. configVars: newStringTable(modeStyleInsensitive),
  505. symbols: newStringTable(modeStyleInsensitive),
  506. packageCache: newPackageCache(),
  507. searchPaths: @[],
  508. lazyPaths: @[],
  509. outFile: RelativeFile"",
  510. outDir: AbsoluteDir"",
  511. prefixDir: AbsoluteDir"",
  512. libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
  513. dllOverrides: newStringTable(modeCaseInsensitive),
  514. moduleOverrides: newStringTable(modeStyleInsensitive),
  515. cfileSpecificOptions: newStringTable(modeCaseSensitive),
  516. projectName: "", # holds a name like 'nim'
  517. projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
  518. projectFull: AbsoluteFile"", # projectPath/projectName
  519. projectIsStdin: false, # whether we're compiling from stdin
  520. projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
  521. command: "", # the main command (e.g. cc, check, scan, etc)
  522. commandArgs: @[], # any arguments after the main command
  523. commandLine: "",
  524. keepComments: true, # whether the parser needs to keep comments
  525. implicitImports: @[], # modules that are to be implicitly imported
  526. implicitIncludes: @[], # modules that are to be implicitly included
  527. docSeeSrcUrl: "",
  528. cIncludes: @[], # directories to search for included files
  529. cLibs: @[], # directories to search for lib files
  530. cLinkedLibs: @[], # libraries to link
  531. backend: backendInvalid,
  532. externalToLink: @[],
  533. linkOptionsCmd: "",
  534. compileOptionsCmd: @[],
  535. linkOptions: "",
  536. compileOptions: "",
  537. ccompilerpath: "",
  538. toCompile: @[],
  539. arguments: "",
  540. suggestMaxResults: 10_000,
  541. maxLoopIterationsVM: 10_000_000,
  542. vmProfileData: newProfileData(),
  543. spellSuggestMax: spellSuggestSecretSauce,
  544. )
  545. initConfigRefCommon(result)
  546. setTargetFromSystem(result.target)
  547. # enable colors by default on terminals
  548. if terminal.isatty(stderr):
  549. incl(result.globalOptions, optUseColors)
  550. when defined(nimDebugUtils):
  551. onNewConfigRef(result)
  552. proc newPartialConfigRef*(): ConfigRef =
  553. ## create a new ConfigRef that is only good enough for error reporting.
  554. when defined(nimDebugUtils):
  555. result = getConfigRef()
  556. else:
  557. result = ConfigRef()
  558. initConfigRefCommon(result)
  559. proc cppDefine*(c: ConfigRef; define: string) =
  560. c.cppDefines.incl define
  561. proc getStdlibVersion*(conf: ConfigRef): NimVer =
  562. if conf.nimStdlibVersion == (0,0,0):
  563. let s = conf.symbols.getOrDefault("nimVersion", "")
  564. conf.nimStdlibVersion = s.parseNimVersion
  565. result = conf.nimStdlibVersion
  566. proc isDefined*(conf: ConfigRef; symbol: string): bool =
  567. if conf.symbols.hasKey(symbol):
  568. result = true
  569. elif cmpIgnoreStyle(symbol, CPU[conf.target.targetCPU].name) == 0:
  570. result = true
  571. elif cmpIgnoreStyle(symbol, platform.OS[conf.target.targetOS].name) == 0:
  572. result = true
  573. else:
  574. case symbol.normalize
  575. of "x86": result = conf.target.targetCPU == cpuI386
  576. of "itanium": result = conf.target.targetCPU == cpuIa64
  577. of "x8664": result = conf.target.targetCPU == cpuAmd64
  578. of "posix", "unix":
  579. result = conf.target.targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
  580. osQnx, osAtari, osAix,
  581. osHaiku, osVxWorks, osSolaris, osNetbsd,
  582. osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
  583. osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr, osNuttX}
  584. of "linux":
  585. result = conf.target.targetOS in {osLinux, osAndroid}
  586. of "bsd":
  587. result = conf.target.targetOS in {osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos}
  588. of "freebsd":
  589. result = conf.target.targetOS in {osFreebsd, osCrossos}
  590. of "emulatedthreadvars":
  591. result = platform.OS[conf.target.targetOS].props.contains(ospLacksThreadVars)
  592. of "msdos": result = conf.target.targetOS == osDos
  593. of "mswindows", "win32": result = conf.target.targetOS == osWindows
  594. of "macintosh":
  595. result = conf.target.targetOS in {osMacos, osMacosx, osIos}
  596. of "osx", "macosx":
  597. result = conf.target.targetOS in {osMacosx, osIos}
  598. of "sunos": result = conf.target.targetOS == osSolaris
  599. of "nintendoswitch":
  600. result = conf.target.targetOS == osNintendoSwitch
  601. of "freertos", "lwip":
  602. result = conf.target.targetOS == osFreeRTOS
  603. of "zephyr":
  604. result = conf.target.targetOS == osZephyr
  605. of "nuttx":
  606. result = conf.target.targetOS == osNuttX
  607. of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
  608. of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
  609. of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
  610. of "cpu16": result = CPU[conf.target.targetCPU].bit == 16
  611. of "cpu32": result = CPU[conf.target.targetCPU].bit == 32
  612. of "cpu64": result = CPU[conf.target.targetCPU].bit == 64
  613. of "nimrawsetjmp":
  614. result = conf.target.targetOS in {osSolaris, osNetbsd, osFreebsd, osOpenbsd,
  615. osDragonfly, osMacosx}
  616. else: discard
  617. template quitOrRaise*(conf: ConfigRef, msg = "") =
  618. # xxx in future work, consider whether to also intercept `msgQuit` calls
  619. if conf.isDefined("nimDebug"):
  620. doAssert false, msg
  621. else:
  622. quit(msg) # quits with QuitFailure
  623. proc importantComments*(conf: ConfigRef): bool {.inline.} = conf.cmd in cmdDocLike + {cmdIdeTools}
  624. proc usesWriteBarrier*(conf: ConfigRef): bool {.inline.} = conf.selectedGC >= gcRefc
  625. template compilationCachePresent*(conf: ConfigRef): untyped =
  626. false
  627. # conf.symbolFiles in {v2Sf, writeOnlySf}
  628. template optPreserveOrigSource*(conf: ConfigRef): untyped =
  629. optEmbedOrigSrc in conf.globalOptions
  630. proc mainCommandArg*(conf: ConfigRef): string =
  631. ## This is intended for commands like check or parse
  632. ## which will work on the main project file unless
  633. ## explicitly given a specific file argument
  634. if conf.commandArgs.len > 0:
  635. result = conf.commandArgs[0]
  636. else:
  637. result = conf.projectName
  638. proc existsConfigVar*(conf: ConfigRef; key: string): bool =
  639. result = hasKey(conf.configVars, key)
  640. proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string =
  641. result = conf.configVars.getOrDefault(key, default)
  642. proc setConfigVar*(conf: ConfigRef; key, val: string) =
  643. conf.configVars[key] = val
  644. proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
  645. # explains regression https://github.com/nim-lang/Nim/issues/6583#issuecomment-625711125
  646. # Yet another reason why "" should not mean "."; `""/something` should raise
  647. # instead of implying "" == "." as it's bug prone.
  648. doAssert conf.outDir.string.len > 0
  649. result = conf.outDir / changeFileExt(filename, ext)
  650. proc absOutFile*(conf: ConfigRef): AbsoluteFile =
  651. doAssert not conf.outDir.isEmpty
  652. doAssert not conf.outFile.isEmpty
  653. result = conf.outDir / conf.outFile
  654. when defined(posix):
  655. if dirExists(result.string): result.string.add ".out"
  656. proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
  657. ## Create the output directory and returns a full path to the output file
  658. result = conf.absOutFile
  659. createDir result.string.parentDir
  660. proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
  661. ## Gets the prefix dir, usually the parent directory where the binary resides.
  662. ##
  663. ## This is overridden by some tools (namely nimsuggest) via the ``conf.prefixDir``
  664. ## field.
  665. ## This should resolve to root of nim sources, whether running nim from a local
  666. ## clone or using installed nim, so that these exist: `result/doc/advopt.txt`
  667. ## and `result/lib/system.nim`
  668. if not conf.prefixDir.isEmpty: result = conf.prefixDir
  669. else:
  670. let binParent = AbsoluteDir splitPath(getAppDir()).head
  671. when defined(posix):
  672. if binParent == AbsoluteDir"/usr":
  673. result = AbsoluteDir"/usr/lib/nim"
  674. elif binParent == AbsoluteDir"/usr/local":
  675. result = AbsoluteDir"/usr/local/lib/nim"
  676. else:
  677. result = binParent
  678. else:
  679. result = binParent
  680. proc setDefaultLibpath*(conf: ConfigRef) =
  681. # set default value (can be overwritten):
  682. if conf.libpath.isEmpty:
  683. # choose default libpath:
  684. var prefix = getPrefixDir(conf)
  685. conf.libpath = prefix / RelativeDir"lib"
  686. # Special rule to support other tools (nimble) which import the compiler
  687. # modules and make use of them.
  688. let realNimPath = findExe("nim")
  689. # Find out if $nim/../../lib/system.nim exists.
  690. let parentNimLibPath = realNimPath.parentDir.parentDir / "lib"
  691. if not fileExists(conf.libpath.string / "system.nim") and
  692. fileExists(parentNimLibPath / "system.nim"):
  693. conf.libpath = AbsoluteDir parentNimLibPath
  694. proc canonicalizePath*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
  695. result = AbsoluteFile path.string.expandFilename
  696. proc setFromProjectName*(conf: ConfigRef; projectName: string) =
  697. try:
  698. conf.projectFull = canonicalizePath(conf, AbsoluteFile projectName)
  699. except OSError:
  700. conf.projectFull = AbsoluteFile projectName
  701. let p = splitFile(conf.projectFull)
  702. let dir = if p.dir.isEmpty: AbsoluteDir getCurrentDir() else: p.dir
  703. conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile dir)
  704. conf.projectName = p.name
  705. proc removeTrailingDirSep*(path: string): string =
  706. if (path.len > 0) and (path[^1] == DirSep):
  707. result = substr(path, 0, path.len - 2)
  708. else:
  709. result = path
  710. proc disableNimblePath*(conf: ConfigRef) =
  711. incl conf.globalOptions, optNoNimblePath
  712. conf.lazyPaths.setLen(0)
  713. conf.nimblePaths.setLen(0)
  714. proc clearNimblePath*(conf: ConfigRef) =
  715. conf.lazyPaths.setLen(0)
  716. conf.nimblePaths.setLen(0)
  717. include packagehandling
  718. proc getOsCacheDir(): string =
  719. when defined(posix):
  720. result = getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") / "nim"
  721. else:
  722. result = getHomeDir() / genSubDir.string
  723. proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir =
  724. proc nimcacheSuffix(conf: ConfigRef): string =
  725. if conf.cmd == cmdCheck: "_check"
  726. elif isDefined(conf, "release") or isDefined(conf, "danger"): "_r"
  727. else: "_d"
  728. # XXX projectName should always be without a file extension!
  729. result = if not conf.nimcacheDir.isEmpty:
  730. conf.nimcacheDir
  731. elif conf.backend == backendJs:
  732. if conf.outDir.isEmpty:
  733. conf.projectPath / genSubDir
  734. else:
  735. conf.outDir / genSubDir
  736. else:
  737. AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
  738. nimcacheSuffix(conf))
  739. proc pathSubs*(conf: ConfigRef; p, config: string): string =
  740. let home = removeTrailingDirSep(os.getHomeDir())
  741. result = unixToNativePath(p % [
  742. "nim", getPrefixDir(conf).string,
  743. "lib", conf.libpath.string,
  744. "home", home,
  745. "config", config,
  746. "projectname", conf.projectName,
  747. "projectpath", conf.projectPath.string,
  748. "projectdir", conf.projectPath.string,
  749. "nimcache", getNimcacheDir(conf).string]).expandTilde
  750. iterator nimbleSubs*(conf: ConfigRef; p: string): string =
  751. let pl = p.toLowerAscii
  752. if "$nimblepath" in pl or "$nimbledir" in pl:
  753. for i in countdown(conf.nimblePaths.len-1, 0):
  754. let nimblePath = removeTrailingDirSep(conf.nimblePaths[i].string)
  755. yield p % ["nimblepath", nimblePath, "nimbledir", nimblePath]
  756. else:
  757. yield p
  758. proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
  759. ext: string): AbsoluteFile =
  760. ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
  761. result = getNimcacheDir(conf) / RelativeFile path.string.splitPath.tail.changeFileExt(ext)
  762. proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
  763. createSubDir: bool = true): AbsoluteFile =
  764. ## Return an absolute path of a generated intermediary file.
  765. ## Optionally creates the cache directory if `createSubDir` is `true`.
  766. let subdir = getNimcacheDir(conf)
  767. if createSubDir:
  768. try:
  769. createDir(subdir.string)
  770. except OSError:
  771. conf.quitOrRaise "cannot create directory: " & subdir.string
  772. result = subdir / RelativeFile f.string.splitPath.tail
  773. proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
  774. for it in conf.searchPaths:
  775. if suppressStdlib and it.string.startsWith(conf.libpath.string):
  776. continue
  777. result = it / f
  778. if fileExists(result):
  779. return canonicalizePath(conf, result)
  780. result = AbsoluteFile""
  781. proc rawFindFile2(conf: ConfigRef; f: RelativeFile): AbsoluteFile =
  782. for i, it in conf.lazyPaths:
  783. result = it / f
  784. if fileExists(result):
  785. # bring to front
  786. for j in countdown(i, 1):
  787. swap(conf.lazyPaths[j], conf.lazyPaths[j-1])
  788. return canonicalizePath(conf, result)
  789. result = AbsoluteFile""
  790. template patchModule(conf: ConfigRef) {.dirty.} =
  791. if not result.isEmpty and conf.moduleOverrides.len > 0:
  792. let key = getPackageName(conf, result.string) & "_" & splitFile(result).name
  793. if conf.moduleOverrides.hasKey(key):
  794. let ov = conf.moduleOverrides[key]
  795. if ov.len > 0: result = AbsoluteFile(ov)
  796. const stdlibDirs* = [
  797. "pure", "core", "arch",
  798. "pure/collections",
  799. "pure/concurrency",
  800. "pure/unidecode", "impure",
  801. "wrappers", "wrappers/linenoise",
  802. "windows", "posix", "js",
  803. "deprecated/pure"]
  804. const
  805. pkgPrefix = "pkg/"
  806. stdPrefix = "std/"
  807. proc getRelativePathFromConfigPath*(conf: ConfigRef; f: AbsoluteFile, isTitle = false): RelativeFile =
  808. let f = $f
  809. if isTitle:
  810. for dir in stdlibDirs:
  811. let path = conf.libpath.string / dir / f.lastPathPart
  812. if path.cmpPaths(f) == 0:
  813. return RelativeFile(stdPrefix & f.splitFile.name)
  814. template search(paths) =
  815. for it in paths:
  816. let it = $it
  817. if f.isRelativeTo(it):
  818. return relativePath(f, it).RelativeFile
  819. search(conf.searchPaths)
  820. search(conf.lazyPaths)
  821. proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile =
  822. if f.isAbsolute:
  823. result = if f.fileExists: AbsoluteFile(f) else: AbsoluteFile""
  824. else:
  825. result = rawFindFile(conf, RelativeFile f, suppressStdlib)
  826. if result.isEmpty:
  827. result = rawFindFile(conf, RelativeFile f.toLowerAscii, suppressStdlib)
  828. if result.isEmpty:
  829. result = rawFindFile2(conf, RelativeFile f)
  830. if result.isEmpty:
  831. result = rawFindFile2(conf, RelativeFile f.toLowerAscii)
  832. patchModule(conf)
  833. proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFile =
  834. # returns path to module
  835. var m = addFileExt(modulename, NimExt)
  836. var hasRelativeDot = false
  837. if m.startsWith(pkgPrefix):
  838. result = findFile(conf, m.substr(pkgPrefix.len), suppressStdlib = true)
  839. else:
  840. if m.startsWith(stdPrefix):
  841. let stripped = m.substr(stdPrefix.len)
  842. for candidate in stdlibDirs:
  843. let path = (conf.libpath.string / candidate / stripped)
  844. if fileExists(path):
  845. result = AbsoluteFile path
  846. break
  847. else: # If prefixed with std/ why would we add the current module path!
  848. let currentPath = currentModule.splitFile.dir
  849. result = AbsoluteFile currentPath / m
  850. if m.startsWith('.') and not fileExists(result):
  851. result = AbsoluteFile ""
  852. hasRelativeDot = true
  853. if not fileExists(result) and not hasRelativeDot:
  854. result = findFile(conf, m)
  855. patchModule(conf)
  856. proc findProjectNimFile*(conf: ConfigRef; pkg: string): string =
  857. const extensions = [".nims", ".cfg", ".nimcfg", ".nimble"]
  858. var
  859. candidates: seq[string] = @[]
  860. dir = pkg
  861. prev = dir
  862. nimblepkg = ""
  863. let pkgname = pkg.lastPathPart()
  864. while true:
  865. for k, f in os.walkDir(dir, relative = true):
  866. if k == pcFile and f != "config.nims":
  867. let (_, name, ext) = splitFile(f)
  868. if ext in extensions:
  869. let x = changeFileExt(dir / name, ".nim")
  870. if fileExists(x):
  871. candidates.add x
  872. if ext == ".nimble":
  873. if nimblepkg.len == 0:
  874. nimblepkg = name
  875. # Since nimble packages can have their source in a subfolder,
  876. # check the last folder we were in for a possible match.
  877. if dir != prev:
  878. let x = prev / x.extractFilename()
  879. if fileExists(x):
  880. candidates.add x
  881. else:
  882. # If we found more than one nimble file, chances are that we
  883. # missed the real project file, or this is an invalid nimble
  884. # package. Either way, bailing is the better choice.
  885. return ""
  886. let pkgname = if nimblepkg.len > 0: nimblepkg else: pkgname
  887. for c in candidates:
  888. if pkgname in c.extractFilename(): return c
  889. if candidates.len > 0:
  890. return candidates[0]
  891. prev = dir
  892. dir = parentDir(dir)
  893. if dir == "": break
  894. return ""
  895. proc canonicalImportAux*(conf: ConfigRef, file: AbsoluteFile): string =
  896. ##[
  897. Shows the canonical module import, e.g.:
  898. system, std/tables, fusion/pointers, system/assertions, std/private/asciitables
  899. ]##
  900. var ret = getRelativePathFromConfigPath(conf, file, isTitle = true)
  901. let dir = getNimbleFile(conf, $file).parentDir.AbsoluteDir
  902. if not dir.isEmpty:
  903. let relPath = relativeTo(file, dir)
  904. if not relPath.isEmpty and (ret.isEmpty or relPath.string.len < ret.string.len):
  905. ret = relPath
  906. if ret.isEmpty:
  907. ret = relativeTo(file, conf.projectPath)
  908. result = ret.string
  909. proc canonicalImport*(conf: ConfigRef, file: AbsoluteFile): string =
  910. let ret = canonicalImportAux(conf, file)
  911. result = ret.nativeToUnixPath.changeFileExt("")
  912. proc canonDynlibName(s: string): string =
  913. let start = if s.startsWith("lib"): 3 else: 0
  914. let ende = strutils.find(s, {'(', ')', '.'})
  915. if ende >= 0:
  916. result = s.substr(start, ende-1)
  917. else:
  918. result = s.substr(start)
  919. proc inclDynlibOverride*(conf: ConfigRef; lib: string) =
  920. conf.dllOverrides[lib.canonDynlibName] = "true"
  921. proc isDynlibOverride*(conf: ConfigRef; lib: string): bool =
  922. result = optDynlibOverrideAll in conf.globalOptions or
  923. conf.dllOverrides.hasKey(lib.canonDynlibName)
  924. proc showNonExportedFields*(conf: ConfigRef) =
  925. incl(conf.globalOptions, optShowNonExportedFields)
  926. proc expandDone*(conf: ConfigRef): bool =
  927. result = conf.ideCmd == ideExpand and conf.expandLevels == 0 and conf.expandProgress
  928. proc parseIdeCmd*(s: string): IdeCmd =
  929. case s:
  930. of "sug": ideSug
  931. of "con": ideCon
  932. of "def": ideDef
  933. of "use": ideUse
  934. of "dus": ideDus
  935. of "chk": ideChk
  936. of "chkFile": ideChkFile
  937. of "mod": ideMod
  938. of "highlight": ideHighlight
  939. of "outline": ideOutline
  940. of "known": ideKnown
  941. of "msg": ideMsg
  942. of "project": ideProject
  943. of "globalSymbols": ideGlobalSymbols
  944. of "recompile": ideRecompile
  945. of "changed": ideChanged
  946. of "type": ideType
  947. else: ideNone
  948. proc `$`*(c: IdeCmd): string =
  949. case c:
  950. of ideSug: "sug"
  951. of ideCon: "con"
  952. of ideDef: "def"
  953. of ideUse: "use"
  954. of ideDus: "dus"
  955. of ideChk: "chk"
  956. of ideChkFile: "chkFile"
  957. of ideMod: "mod"
  958. of ideNone: "none"
  959. of ideHighlight: "highlight"
  960. of ideOutline: "outline"
  961. of ideKnown: "known"
  962. of ideMsg: "msg"
  963. of ideProject: "project"
  964. of ideGlobalSymbols: "globalSymbols"
  965. of ideDeclaration: "declaration"
  966. of ideExpand: "expand"
  967. of ideRecompile: "recompile"
  968. of ideChanged: "changed"
  969. of ideType: "type"
  970. of ideInlayHints: "inlayHints"
  971. proc floatInt64Align*(conf: ConfigRef): int16 =
  972. ## Returns either 4 or 8 depending on reasons.
  973. if conf != nil and conf.target.targetCPU == cpuI386:
  974. #on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
  975. if conf.target.targetOS != osWindows:
  976. # on i386 for all known POSIX systems, 64bits ints are aligned
  977. # to 4bytes (except with -malign-double)
  978. return 4
  979. return 8