options.nim 41 KB

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