1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149 |
- #
- #
- # The Nim Compiler
- # (c) Copyright 2015 Andreas Rumpf
- #
- # See the file "copying.txt", included in this
- # distribution, for details about the copyright.
- #
- # abstract syntax tree + symbol table
- import
- lineinfos, options, ropes, idents, int128, wordrecg
- import std/[tables, hashes]
- from std/strutils import toLowerAscii
- when defined(nimPreviewSlimSystem):
- import std/assertions
- export int128
- import nodekinds
- export nodekinds
- type
- TCallingConvention* = enum
- ccNimCall = "nimcall" # nimcall, also the default
- ccStdCall = "stdcall" # procedure is stdcall
- ccCDecl = "cdecl" # cdecl
- ccSafeCall = "safecall" # safecall
- ccSysCall = "syscall" # system call
- ccInline = "inline" # proc should be inlined
- ccNoInline = "noinline" # proc should not be inlined
- ccFastCall = "fastcall" # fastcall (pass parameters in registers)
- ccThisCall = "thiscall" # thiscall (parameters are pushed right-to-left)
- ccClosure = "closure" # proc has a closure
- ccNoConvention = "noconv" # needed for generating proper C procs sometimes
- ccMember = "member" # proc is a (cpp) member
- TNodeKinds* = set[TNodeKind]
- type
- TSymFlag* = enum # 63 flags!
- sfUsed, # read access of sym (for warnings) or simply used
- sfExported, # symbol is exported from module
- sfFromGeneric, # symbol is instantiation of a generic; this is needed
- # for symbol file generation; such symbols should always
- # be written into the ROD file
- sfGlobal, # symbol is at global scope
- sfForward, # symbol is forward declared
- sfWasForwarded, # symbol had a forward declaration
- # (implies it's too dangerous to patch its type signature)
- sfImportc, # symbol is external; imported
- sfExportc, # symbol is exported (under a specified name)
- sfMangleCpp, # mangle as cpp (combines with `sfExportc`)
- sfVolatile, # variable is volatile
- sfRegister, # variable should be placed in a register
- sfPure, # object is "pure" that means it has no type-information
- # enum is "pure", its values need qualified access
- # variable is "pure"; it's an explicit "global"
- sfNoSideEffect, # proc has no side effects
- sfSideEffect, # proc may have side effects; cannot prove it has none
- sfMainModule, # module is the main module
- sfSystemModule, # module is the system module
- sfNoReturn, # proc never returns (an exit proc)
- sfAddrTaken, # the variable's address is taken (ex- or implicitly);
- # *OR*: a proc is indirectly called (used as first class)
- sfCompilerProc, # proc is a compiler proc, that is a C proc that is
- # needed for the code generator
- sfEscapes # param escapes
- # currently unimplemented
- sfDiscriminant, # field is a discriminant in a record/object
- sfRequiresInit, # field must be initialized during construction
- sfDeprecated, # symbol is deprecated
- sfExplain, # provide more diagnostics when this symbol is used
- sfError, # usage of symbol should trigger a compile-time error
- sfShadowed, # a symbol that was shadowed in some inner scope
- sfThread, # proc will run as a thread
- # variable is a thread variable
- sfCppNonPod, # tells compiler to treat such types as non-pod's, so that
- # `thread_local` is used instead of `__thread` for
- # {.threadvar.} + `--threads`. Only makes sense for importcpp types.
- # This has a performance impact so isn't set by default.
- sfCompileTime, # proc can be evaluated at compile time
- sfConstructor, # proc is a C++ constructor
- sfDispatcher, # copied method symbol is the dispatcher
- # deprecated and unused, except for the con
- sfBorrow, # proc is borrowed
- sfInfixCall, # symbol needs infix call syntax in target language;
- # for interfacing with C++, JS
- sfNamedParamCall, # symbol needs named parameter call syntax in target
- # language; for interfacing with Objective C
- sfDiscardable, # returned value may be discarded implicitly
- sfOverridden, # proc is overridden
- sfCallsite # A flag for template symbols to tell the
- # compiler it should use line information from
- # the calling side of the macro, not from the
- # implementation.
- sfGenSym # symbol is 'gensym'ed; do not add to symbol table
- sfNonReloadable # symbol will be left as-is when hot code reloading is on -
- # meaning that it won't be renamed and/or changed in any way
- sfGeneratedOp # proc is a generated '='; do not inject destructors in it
- # variable is generated closure environment; requires early
- # destruction for --newruntime.
- sfTemplateParam # symbol is a template parameter
- sfCursor # variable/field is a cursor, see RFC 177 for details
- sfInjectDestructors # whether the proc needs the 'injectdestructors' transformation
- sfNeverRaises # proc can never raise an exception, not even OverflowDefect
- # or out-of-memory
- sfSystemRaisesDefect # proc in the system can raise defects
- sfUsedInFinallyOrExcept # symbol is used inside an 'except' or 'finally'
- sfSingleUsedTemp # For temporaries that we know will only be used once
- sfNoalias # 'noalias' annotation, means C's 'restrict'
- # for templates and macros, means cannot be called
- # as a lone symbol (cannot use alias syntax)
- sfEffectsDelayed # an 'effectsDelayed' parameter
- sfGeneratedType # A anonymous generic type that is generated by the compiler for
- # objects that do not have generic parameters in case one of the
- # object fields has one.
- #
- # This is disallowed but can cause the typechecking to go into
- # an infinite loop, this flag is used as a sentinel to stop it.
- sfVirtual # proc is a C++ virtual function
- sfByCopy # param is marked as pass bycopy
- sfMember # proc is a C++ member of a type
- sfCodegenDecl # type, proc, global or proc param is marked as codegenDecl
- sfWasGenSym # symbol was 'gensym'ed
- sfForceLift # variable has to be lifted into closure environment
- sfDirty # template is not hygienic (old styled template) module,
- # compiled from a dirty-buffer
- sfCustomPragma # symbol is custom pragma template
- sfBase, # a base method
- sfGoto # var is used for 'goto' code generation
- sfAnon, # symbol name that was generated by the compiler
- # the compiler will avoid printing such names
- # in user messages.
- sfAllUntyped # macro or template is immediately expanded in a generic context
- sfTemplateRedefinition # symbol is a redefinition of an earlier template
- TSymFlags* = set[TSymFlag]
- const
- sfNoInit* = sfMainModule # don't generate code to init the variable
- sfNoForward* = sfRegister
- # forward declarations are not required (per module)
- sfReorder* = sfForward
- # reordering pass is enabled
- sfCompileToCpp* = sfInfixCall # compile the module as C++ code
- sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
- sfExperimental* = sfOverridden # module uses the .experimental switch
- sfWrittenTo* = sfBorrow # param is assigned to
- # currently unimplemented
- sfCppMember* = { sfVirtual, sfMember, sfConstructor } # proc is a C++ member, meaning it will be attached to the type definition
- const
- # getting ready for the future expr/stmt merge
- nkWhen* = nkWhenStmt
- nkWhenExpr* = nkWhenStmt
- nkEffectList* = nkArgList
- # hacks ahead: an nkEffectList is a node with 4 children:
- exceptionEffects* = 0 # exceptions at position 0
- requiresEffects* = 1 # 'requires' annotation
- ensuresEffects* = 2 # 'ensures' annotation
- tagEffects* = 3 # user defined tag ('gc', 'time' etc.)
- pragmasEffects* = 4 # not an effect, but a slot for pragmas in proc type
- forbiddenEffects* = 5 # list of illegal effects
- effectListLen* = 6 # list of effects list
- nkLastBlockStmts* = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
- # these must be last statements in a block
- type
- TTypeKind* = enum # order is important!
- # Don't forget to change hti.nim if you make a change here
- # XXX put this into an include file to avoid this issue!
- # several types are no longer used (guess which), but a
- # spot in the sequence is kept for backwards compatibility
- # (apparently something with bootstrapping)
- # if you need to add a type, they can apparently be reused
- tyNone, tyBool, tyChar,
- tyEmpty, tyAlias, tyNil, tyUntyped, tyTyped, tyTypeDesc,
- tyGenericInvocation, # ``T[a, b]`` for types to invoke
- tyGenericBody, # ``T[a, b, body]`` last parameter is the body
- tyGenericInst, # ``T[a, b, realInstance]`` instantiated generic type
- # realInstance will be a concrete type like tyObject
- # unless this is an instance of a generic alias type.
- # then realInstance will be the tyGenericInst of the
- # completely (recursively) resolved alias.
- tyGenericParam, # ``a`` in the above patterns
- tyDistinct,
- tyEnum,
- tyOrdinal, # integer types (including enums and boolean)
- tyArray,
- tyObject,
- tyTuple,
- tySet,
- tyRange,
- tyPtr, tyRef,
- tyVar,
- tySequence,
- tyProc,
- tyPointer, tyOpenArray,
- tyString, tyCstring, tyForward,
- tyInt, tyInt8, tyInt16, tyInt32, tyInt64, # signed integers
- tyFloat, tyFloat32, tyFloat64, tyFloat128,
- tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
- tyOwned, tySink, tyLent,
- tyVarargs,
- tyUncheckedArray
- # An array with boundaries [0,+∞]
- tyError # used as erroneous type (for idetools)
- # as an erroneous node should match everything
- tyBuiltInTypeClass
- # Type such as the catch-all object, tuple, seq, etc
- tyUserTypeClass
- # the body of a user-defined type class
- tyUserTypeClassInst
- # Instance of a parametric user-defined type class.
- # Structured similarly to tyGenericInst.
- # tyGenericInst represents concrete types, while
- # this is still a "generic param" that will bind types
- # and resolves them during sigmatch and instantiation.
- tyCompositeTypeClass
- # Type such as seq[Number]
- # The notes for tyUserTypeClassInst apply here as well
- # sons[0]: the original expression used by the user.
- # sons[1]: fully expanded and instantiated meta type
- # (potentially following aliases)
- tyInferred
- # In the initial state `base` stores a type class constraining
- # the types that can be inferred. After a candidate type is
- # selected, it's stored in `last`. Between `base` and `last`
- # there may be 0, 2 or more types that were also considered as
- # possible candidates in the inference process (i.e. last will
- # be updated to store a type best conforming to all candidates)
- tyAnd, tyOr, tyNot
- # boolean type classes such as `string|int`,`not seq`,
- # `Sortable and Enumable`, etc
- tyAnything
- # a type class matching any type
- tyStatic
- # a value known at compile type (the underlying type is .base)
- tyFromExpr
- # This is a type representing an expression that depends
- # on generic parameters (the expression is stored in t.n)
- # It will be converted to a real type only during generic
- # instantiation and prior to this it has the potential to
- # be any type.
- tyConcept
- # new style concept.
- tyVoid
- # now different from tyEmpty, hurray!
- tyIterable
- static:
- # remind us when TTypeKind stops to fit in a single 64-bit word
- # assert TTypeKind.high.ord <= 63
- discard
- const
- tyPureObject* = tyTuple
- GcTypeKinds* = {tyRef, tySequence, tyString}
- tyTypeClasses* = {tyBuiltInTypeClass, tyCompositeTypeClass,
- tyUserTypeClass, tyUserTypeClassInst,
- tyAnd, tyOr, tyNot, tyAnything}
- tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyUntyped} + tyTypeClasses
- tyUserTypeClasses* = {tyUserTypeClass, tyUserTypeClassInst}
- # consider renaming as `tyAbstractVarRange`
- abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
- tyTypeDesc, tyAlias, tyInferred, tySink, tyOwned}
- abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias,
- tyInferred, tySink, tyOwned} # xxx what about tyStatic?
- type
- TTypeKinds* = set[TTypeKind]
- TNodeFlag* = enum
- nfNone,
- nfBase2, # nfBase10 is default, so not needed
- nfBase8,
- nfBase16,
- nfAllConst, # used to mark complex expressions constant; easy to get rid of
- # but unfortunately it has measurable impact for compilation
- # efficiency
- nfTransf, # node has been transformed
- nfNoRewrite # node should not be transformed anymore
- nfSem # node has been checked for semantics
- nfLL # node has gone through lambda lifting
- nfDotField # the call can use a dot operator
- nfDotSetter # the call can use a setter dot operarator
- nfExplicitCall # x.y() was used instead of x.y
- nfExprCall # this is an attempt to call a regular expression
- nfIsRef # this node is a 'ref' node; used for the VM
- nfIsPtr # this node is a 'ptr' node; used for the VM
- nfPreventCg # this node should be ignored by the codegen
- nfBlockArg # this a stmtlist appearing in a call (e.g. a do block)
- nfFromTemplate # a top-level node returned from a template
- nfDefaultParam # an automatically inserter default parameter
- nfDefaultRefsParam # a default param value references another parameter
- # the flag is applied to proc default values and to calls
- nfExecuteOnReload # A top-level statement that will be executed during reloads
- nfLastRead # this node is a last read
- nfFirstWrite # this node is a first write
- nfHasComment # node has a comment
- nfSkipFieldChecking # node skips field visable checking
- nfDisabledOpenSym # temporary: node should be nkOpenSym but cannot
- # because openSym experimental switch is disabled
- # gives warning instead
- TNodeFlags* = set[TNodeFlag]
- TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 47)
- tfVarargs, # procedure has C styled varargs
- # tyArray type represeting a varargs list
- tfNoSideEffect, # procedure type does not allow side effects
- tfFinal, # is the object final?
- tfInheritable, # is the object inheritable?
- tfHasOwned, # type contains an 'owned' type and must be moved
- tfEnumHasHoles, # enum cannot be mapped into a range
- tfShallow, # type can be shallow copied on assignment
- tfThread, # proc type is marked as ``thread``; alias for ``gcsafe``
- tfFromGeneric, # type is an instantiation of a generic; this is needed
- # because for instantiations of objects, structural
- # type equality has to be used
- tfUnresolved, # marks unresolved typedesc/static params: e.g.
- # proc foo(T: typedesc, list: seq[T]): var T
- # proc foo(L: static[int]): array[L, int]
- # can be attached to ranges to indicate that the range
- # can be attached to generic procs with free standing
- # type parameters: e.g. proc foo[T]()
- # depends on unresolved static params.
- tfResolved # marks a user type class, after it has been bound to a
- # concrete type (lastSon becomes the concrete type)
- tfRetType, # marks return types in proc (used to detect type classes
- # used as return types for return type inference)
- tfCapturesEnv, # whether proc really captures some environment
- tfByCopy, # pass object/tuple by copy (C backend)
- tfByRef, # pass object/tuple by reference (C backend)
- tfIterator, # type is really an iterator, not a tyProc
- tfPartial, # type is declared as 'partial'
- tfNotNil, # type cannot be 'nil'
- tfRequiresInit, # type contains a "not nil" constraint somewhere or
- # a `requiresInit` field, so the default zero init
- # is not appropriate
- tfNeedsFullInit, # object type marked with {.requiresInit.}
- # all fields must be initialized
- tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode
- tfHasMeta, # type contains "wildcard" sub-types such as generic params
- # or other type classes
- tfHasGCedMem, # type contains GC'ed memory
- tfPacked
- tfHasStatic
- tfGenericTypeParam
- tfImplicitTypeParam
- tfInferrableStatic
- tfConceptMatchedTypeSym
- tfExplicit # for typedescs, marks types explicitly prefixed with the
- # `type` operator (e.g. type int)
- tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
- # T and I here can bind to both typedesc and static types
- # before this is determined, we'll consider them to be a
- # wildcard type.
- tfHasAsgn # type has overloaded assignment operator
- tfBorrowDot # distinct type borrows '.'
- tfTriggersCompileTime # uses the NimNode type which make the proc
- # implicitly '.compiletime'
- tfRefsAnonObj # used for 'ref object' and 'ptr object'
- tfCovariant # covariant generic param mimicking a ptr type
- tfWeakCovariant # covariant generic param mimicking a seq/array type
- tfContravariant # contravariant generic param
- tfCheckedForDestructor # type was checked for having a destructor.
- # If it has one, t.destructor is not nil.
- tfAcyclic # object type was annotated as .acyclic
- tfIncompleteStruct # treat this type as if it had sizeof(pointer)
- tfCompleteStruct
- # (for importc types); type is fully specified, allowing to compute
- # sizeof, alignof, offsetof at CT
- tfExplicitCallConv
- tfIsConstructor
- tfEffectSystemWorkaround
- tfIsOutParam
- tfSendable
- tfImplicitStatic
- TTypeFlags* = set[TTypeFlag]
- TSymKind* = enum # the different symbols (start with the prefix sk);
- # order is important for the documentation generator!
- skUnknown, # unknown symbol: used for parsing assembler blocks
- # and first phase symbol lookup in generics
- skConditional, # symbol for the preprocessor (may become obsolete)
- skDynLib, # symbol represents a dynamic library; this is used
- # internally; it does not exist in Nim code
- skParam, # a parameter
- skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()``
- skTemp, # a temporary variable (introduced by compiler)
- skModule, # module identifier
- skType, # a type
- skVar, # a variable
- skLet, # a 'let' symbol
- skConst, # a constant
- skResult, # special 'result' variable
- skProc, # a proc
- skFunc, # a func
- skMethod, # a method
- skIterator, # an iterator
- skConverter, # a type converter
- skMacro, # a macro
- skTemplate, # a template; currently also misused for user-defined
- # pragmas
- skField, # a field in a record or object
- skEnumField, # an identifier in an enum
- skForVar, # a for loop variable
- skLabel, # a label (for block statement)
- skStub, # symbol is a stub and not yet loaded from the ROD
- # file (it is loaded on demand, which may
- # mean: never)
- skPackage, # symbol is a package (used for canonicalization)
- TSymKinds* = set[TSymKind]
- const
- routineKinds* = {skProc, skFunc, skMethod, skIterator,
- skConverter, skMacro, skTemplate}
- ExportableSymKinds* = {skVar, skLet, skConst, skType, skEnumField, skStub} + routineKinds
- tfUnion* = tfNoSideEffect
- tfGcSafe* = tfThread
- tfObjHasKids* = tfEnumHasHoles
- tfReturnsNew* = tfInheritable
- tfNonConstExpr* = tfExplicitCallConv
- ## tyFromExpr where the expression shouldn't be evaluated as a static value
- skError* = skUnknown
- var
- eqTypeFlags* = {tfIterator, tfNotNil, tfVarIsPtr, tfGcSafe, tfNoSideEffect, tfIsOutParam}
- ## type flags that are essential for type equality.
- ## This is now a variable because for emulation of version:1.0 we
- ## might exclude {tfGcSafe, tfNoSideEffect}.
- type
- TMagic* = enum # symbols that require compiler magic:
- mNone,
- mDefined, mDeclared, mDeclaredInScope, mCompiles, mArrGet, mArrPut, mAsgn,
- mLow, mHigh, mSizeOf, mAlignOf, mOffsetOf, mTypeTrait,
- mIs, mOf, mAddr, mType, mTypeOf,
- mPlugin, mEcho, mShallowCopy, mSlurp, mStaticExec, mStatic,
- mParseExprToAst, mParseStmtToAst, mExpandToAst, mQuoteAst,
- mInc, mDec, mOrd,
- mNew, mNewFinalize, mNewSeq, mNewSeqOfCap,
- mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
- mIncl, mExcl, mCard, mChr,
- mGCref, mGCunref,
- mAddI, mSubI, mMulI, mDivI, mModI,
- mSucc, mPred,
- mAddF64, mSubF64, mMulF64, mDivF64,
- mShrI, mShlI, mAshrI, mBitandI, mBitorI, mBitxorI,
- mMinI, mMaxI,
- mAddU, mSubU, mMulU, mDivU, mModU,
- mEqI, mLeI, mLtI,
- mEqF64, mLeF64, mLtF64,
- mLeU, mLtU,
- mEqEnum, mLeEnum, mLtEnum,
- mEqCh, mLeCh, mLtCh,
- mEqB, mLeB, mLtB,
- mEqRef, mLePtr, mLtPtr,
- mXor, mEqCString, mEqProc,
- mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
- mUnaryPlusI, mBitnotI,
- mUnaryPlusF64, mUnaryMinusF64,
- mCharToStr, mBoolToStr,
- mCStrToStr,
- mStrToStr, mEnumToStr,
- mAnd, mOr,
- mImplies, mIff, mExists, mForall, mOld,
- mEqStr, mLeStr, mLtStr,
- mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
- mConStrStr, mSlice,
- mDotDot, # this one is only necessary to give nice compile time warnings
- mFields, mFieldPairs, mOmpParFor,
- mAppendStrCh, mAppendStrStr, mAppendSeqElem,
- mInSet, mRepr, mExit,
- mSetLengthStr, mSetLengthSeq,
- mIsPartOf, mAstToStr, mParallel,
- mSwap, mIsNil, mArrToSeq, mOpenArrayToSeq,
- mNewString, mNewStringOfCap, mParseBiggestFloat,
- mMove, mEnsureMove, mWasMoved, mDup, mDestroy, mTrace,
- mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mAccessTypeField,
- mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
- mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
- mOrdinal, mIterableType,
- mInt, mInt8, mInt16, mInt32, mInt64,
- mUInt, mUInt8, mUInt16, mUInt32, mUInt64,
- mFloat, mFloat32, mFloat64, mFloat128,
- mBool, mChar, mString, mCstring,
- mPointer, mNil, mExpr, mStmt, mTypeDesc,
- mVoidType, mPNimrodNode, mSpawn, mDeepCopy,
- mIsMainModule, mCompileDate, mCompileTime, mProcCall,
- mCpuEndian, mHostOS, mHostCPU, mBuildOS, mBuildCPU, mAppType,
- mCompileOption, mCompileOptionArg,
- mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel,
- mNKind, mNSymKind,
- mNccValue, mNccInc, mNcsAdd, mNcsIncl, mNcsLen, mNcsAt,
- mNctPut, mNctLen, mNctGet, mNctHasNext, mNctNext,
- mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
- mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetStrVal, mNLineInfo,
- mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mNSigHash, mNSizeOf,
- mNBindSym, mNCallSite,
- mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
- mNHint, mNWarning, mNError,
- mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
- mNimvm, mIntDefine, mStrDefine, mBoolDefine, mGenericDefine, mRunnableExamples,
- mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
- mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault
- const
- # things that we can evaluate safely at compile time, even if not asked for it:
- ctfeWhitelist* = {mNone, mSucc,
- mPred, mInc, mDec, mOrd, mLengthOpenArray,
- mLengthStr, mLengthArray, mLengthSeq,
- mArrGet, mArrPut, mAsgn, mDestroy,
- mIncl, mExcl, mCard, mChr,
- mAddI, mSubI, mMulI, mDivI, mModI,
- mAddF64, mSubF64, mMulF64, mDivF64,
- mShrI, mShlI, mBitandI, mBitorI, mBitxorI,
- mMinI, mMaxI,
- mAddU, mSubU, mMulU, mDivU, mModU,
- mEqI, mLeI, mLtI,
- mEqF64, mLeF64, mLtF64,
- mLeU, mLtU,
- mEqEnum, mLeEnum, mLtEnum,
- mEqCh, mLeCh, mLtCh,
- mEqB, mLeB, mLtB,
- mEqRef, mEqProc, mLePtr, mLtPtr, mEqCString, mXor,
- mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
- mUnaryPlusF64, mUnaryMinusF64,
- mCharToStr, mBoolToStr,
- mCStrToStr,
- mStrToStr, mEnumToStr,
- mAnd, mOr,
- mEqStr, mLeStr, mLtStr,
- mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
- mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
- mInSet, mRepr, mOpenArrayToSeq}
- generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
- ## magics that are generated as normal procs in the backend
- type
- ItemId* = object
- module*: int32
- item*: int32
- proc `$`*(x: ItemId): string =
- "(module: " & $x.module & ", item: " & $x.item & ")"
- proc `==`*(a, b: ItemId): bool {.inline.} =
- a.item == b.item and a.module == b.module
- proc hash*(x: ItemId): Hash =
- var h: Hash = hash(x.module)
- h = h !& hash(x.item)
- result = !$h
- type
- PNode* = ref TNode
- TNodeSeq* = seq[PNode]
- PType* = ref TType
- PSym* = ref TSym
- TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes
- when defined(useNodeIds):
- id*: int
- typField: PType
- info*: TLineInfo
- flags*: TNodeFlags
- case kind*: TNodeKind
- of nkCharLit..nkUInt64Lit:
- intVal*: BiggestInt
- of nkFloatLit..nkFloat128Lit:
- floatVal*: BiggestFloat
- of nkStrLit..nkTripleStrLit:
- strVal*: string
- of nkSym:
- sym*: PSym
- of nkIdent:
- ident*: PIdent
- else:
- sons*: TNodeSeq
- when defined(nimsuggest):
- endInfo*: TLineInfo
- TStrTable* = object # a table[PIdent] of PSym
- counter*: int
- data*: seq[PSym]
- # -------------- backend information -------------------------------
- TLocKind* = enum
- locNone, # no location
- locTemp, # temporary location
- locLocalVar, # location is a local variable
- locGlobalVar, # location is a global variable
- locParam, # location is a parameter
- locField, # location is a record field
- locExpr, # "location" is really an expression
- locProc, # location is a proc (an address of a procedure)
- locData, # location is a constant
- locCall, # location is a call expression
- locOther # location is something other
- TLocFlag* = enum
- lfIndirect, # backend introduced a pointer
- lfNoDeepCopy, # no need for a deep copy
- lfNoDecl, # do not declare it in C
- lfDynamicLib, # link symbol to dynamic library
- lfExportLib, # export symbol for dynamic library generation
- lfHeader, # include header file for symbol
- lfImportCompilerProc, # ``importc`` of a compilerproc
- lfSingleUse # no location yet and will only be used once
- lfEnforceDeref # a copyMem is required to dereference if this a
- # ptr array due to C array limitations.
- # See #1181, #6422, #11171
- lfPrepareForMutation # string location is about to be mutated (V2)
- TStorageLoc* = enum
- OnUnknown, # location is unknown (stack, heap or static)
- OnStatic, # in a static section
- OnStack, # location is on hardware stack
- OnHeap # location is on heap or global
- # (reference counting needed)
- TLocFlags* = set[TLocFlag]
- TLoc* = object
- k*: TLocKind # kind of location
- storage*: TStorageLoc
- flags*: TLocFlags # location's flags
- lode*: PNode # Node where the location came from; can be faked
- snippet*: Rope # C code snippet of location (code generators)
- # ---------------- end of backend information ------------------------------
- TLibKind* = enum
- libHeader, libDynamic
- TLib* = object # also misused for headers!
- # keep in sync with PackedLib
- kind*: TLibKind
- generated*: bool # needed for the backends:
- isOverridden*: bool
- name*: Rope
- path*: PNode # can be a string literal!
- CompilesId* = int ## id that is used for the caching logic within
- ## ``system.compiles``. See the seminst module.
- TInstantiation* = object
- sym*: PSym
- concreteTypes*: seq[PType]
- compilesId*: CompilesId
- PInstantiation* = ref TInstantiation
- TScope* {.acyclic.} = object
- depthLevel*: int
- symbols*: TStrTable
- parent*: PScope
- allowPrivateAccess*: seq[PSym] # # enable access to private fields
- PScope* = ref TScope
- PLib* = ref TLib
- TSym* {.acyclic.} = object # Keep in sync with PackedSym
- itemId*: ItemId
- # proc and type instantiations are cached in the generic symbol
- case kind*: TSymKind
- of routineKinds:
- #procInstCache*: seq[PInstantiation]
- gcUnsafetyReason*: PSym # for better error messages regarding gcsafe
- transformedBody*: PNode # cached body after transf pass
- of skLet, skVar, skField, skForVar:
- guard*: PSym
- bitsize*: int
- alignment*: int # for alignment
- else: nil
- magic*: TMagic
- typ*: PType
- name*: PIdent
- info*: TLineInfo
- when defined(nimGear2):
- loadFrom*: pointer
- when defined(nimsuggest):
- endInfo*: TLineInfo
- hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
- ownerField: PSym
- flags*: TSymFlags
- ast*: PNode # syntax tree of proc, iterator, etc.:
- # the whole proc including header; this is used
- # for easy generation of proper error messages
- # for variant record fields the discriminant
- # expression
- # for modules, it's a placeholder for compiler
- # generated code that will be appended to the
- # module after the sem pass (see appendToModule)
- options*: TOptions
- position*: int # used for many different things:
- # for enum fields its position;
- # for fields its offset
- # for parameters its position (starting with 0)
- # for a conditional:
- # 1 iff the symbol is defined, else 0
- # (or not in symbol table)
- # for modules, an unique index corresponding
- # to the module's fileIdx
- # for variables a slot index for the evaluator
- offset*: int32 # offset of record field
- disamb*: int32 # disambiguation number; the basic idea is that
- # `<procname>__<module>_<disamb>` is unique
- loc*: TLoc
- annex*: PLib # additional fields (seldom used, so we use a
- # reference to another object to save space)
- when hasFFI:
- cname*: string # resolved C declaration name in importc decl, e.g.:
- # proc fun() {.importc: "$1aux".} => cname = funaux
- constraint*: PNode # additional constraints like 'lit|result'; also
- # misused for the codegenDecl and virtual pragmas in the hope
- # it won't cause problems
- # for skModule the string literal to output for
- # deprecated modules.
- instantiatedFrom*: PSym # for instances, the generic symbol where it came from.
- when defined(nimsuggest):
- allUsages*: seq[TLineInfo]
- TTypeSeq* = seq[PType]
- TTypeAttachedOp* = enum ## as usual, order is important here
- attachedWasMoved,
- attachedDestructor,
- attachedAsgn,
- attachedDup,
- attachedSink,
- attachedTrace,
- attachedDeepCopy
- TType* {.acyclic.} = object # \
- # types are identical iff they have the
- # same id; there may be multiple copies of a type
- # in memory!
- # Keep in sync with PackedType
- itemId*: ItemId
- kind*: TTypeKind # kind of type
- callConv*: TCallingConvention # for procs
- flags*: TTypeFlags # flags of the type
- sons: TTypeSeq # base types, etc.
- when defined(nimGear2):
- loadFrom*: pointer
- n*: PNode # node for types:
- # for range types a nkRange node
- # for record types a nkRecord node
- # for enum types a list of symbols
- # if kind == tyInt: it is an 'int literal(x)' type
- # for procs and tyGenericBody, it's the
- # formal param list
- # for concepts, the concept body
- # else: unused
- ownerField: PSym # the 'owner' of the type
- sym*: PSym # types have the sym associated with them
- # it is used for converting types to strings
- size*: BiggestInt # the size of the type in bytes
- # -1 means that the size is unkwown
- align*: int16 # the type's alignment requirements
- paddingAtEnd*: int16 #
- loc*: TLoc
- typeInst*: PType # for generic instantiations the tyGenericInst that led to this
- # type.
- uniqueId*: ItemId # due to a design mistake, we need to keep the real ID here as it
- # is required by the --incremental:on mode.
- TPair* = object
- key*, val*: RootRef
- TPairSeq* = seq[TPair]
- TNodePair* = object
- h*: Hash # because it is expensive to compute!
- key*: PNode
- val*: int
- TNodePairSeq* = seq[TNodePair]
- TNodeTable* = object # the same as table[PNode] of int;
- # nodes are compared by structure!
- counter*: int
- data*: TNodePairSeq
- TObjectSeq* = seq[RootRef]
- TObjectSet* = object
- counter*: int
- data*: TObjectSeq
- TImplication* = enum
- impUnknown, impNo, impYes
- template nodeId(n: PNode): int = cast[int](n)
- template typ*(n: PNode): PType =
- n.typField
- proc owner*(s: PSym|PType): PSym {.inline.} =
- result = s.ownerField
- proc setOwner*(s: PSym|PType, owner: PSym) {.inline.} =
- s.ownerField = owner
- type Gconfig = object
- # we put comments in a side channel to avoid increasing `sizeof(TNode)`, which
- # reduces memory usage given that `PNode` is the most allocated type by far.
- comments: Table[int, string] # nodeId => comment
- useIc*: bool
- var gconfig {.threadvar.}: Gconfig
- proc setUseIc*(useIc: bool) = gconfig.useIc = useIc
- proc comment*(n: PNode): string =
- if nfHasComment in n.flags and not gconfig.useIc:
- # IC doesn't track comments, see `packed_ast`, so this could fail
- result = gconfig.comments[n.nodeId]
- else:
- result = ""
- proc `comment=`*(n: PNode, a: string) =
- let id = n.nodeId
- if a.len > 0:
- # if needed, we could periodically cleanup gconfig.comments when its size increases,
- # to ensure only live nodes (and with nfHasComment) have an entry in gconfig.comments;
- # for compiling compiler, the waste is very small:
- # num calls to newNodeImpl: 14984160 (num of PNode allocations)
- # size of gconfig.comments: 33585
- # num of nodes with comments that were deleted and hence wasted: 3081
- n.flags.incl nfHasComment
- gconfig.comments[id] = a
- elif nfHasComment in n.flags:
- n.flags.excl nfHasComment
- gconfig.comments.del(id)
- # BUGFIX: a module is overloadable so that a proc can have the
- # same name as an imported module. This is necessary because of
- # the poor naming choices in the standard library.
- const
- OverloadableSyms* = {skProc, skFunc, skMethod, skIterator,
- skConverter, skModule, skTemplate, skMacro, skEnumField}
- GenericTypes*: TTypeKinds = {tyGenericInvocation, tyGenericBody,
- tyGenericParam}
- StructuralEquivTypes*: TTypeKinds = {tyNil, tyTuple, tyArray,
- tySet, tyRange, tyPtr, tyRef, tyVar, tyLent, tySequence, tyProc, tyOpenArray,
- tyVarargs}
- ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
- # var x = expr
- tyBool, tyChar, tyEnum, tyArray, tyObject,
- tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tyLent, tySequence, tyProc,
- tyPointer,
- tyOpenArray, tyString, tyCstring, tyInt..tyInt64, tyFloat..tyFloat128,
- tyUInt..tyUInt64}
- IntegralTypes* = {tyBool, tyChar, tyEnum, tyInt..tyInt64,
- tyFloat..tyFloat128, tyUInt..tyUInt64} # weird name because it contains tyFloat
- ConstantDataTypes*: TTypeKinds = {tyArray, tySet,
- tyTuple, tySequence}
- NilableTypes*: TTypeKinds = {tyPointer, tyCstring, tyRef, tyPtr,
- tyProc, tyError} # TODO
- PtrLikeKinds*: TTypeKinds = {tyPointer, tyPtr} # for VM
- PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
- nfDotSetter, nfDotField,
- nfIsRef, nfIsPtr, nfPreventCg, nfLL,
- nfFromTemplate, nfDefaultRefsParam,
- nfExecuteOnReload, nfLastRead,
- nfFirstWrite, nfSkipFieldChecking,
- nfDisabledOpenSym}
- namePos* = 0
- patternPos* = 1 # empty except for term rewriting macros
- genericParamsPos* = 2
- paramsPos* = 3
- pragmasPos* = 4
- miscPos* = 5 # used for undocumented and hacky stuff
- bodyPos* = 6 # position of body; use rodread.getBody() instead!
- resultPos* = 7
- dispatcherPos* = 8
- nfAllFieldsSet* = nfBase2
- nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice,
- nkClosedSymChoice, nkOpenSym}
- nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit}
- nkLiterals* = {nkCharLit..nkTripleStrLit}
- nkFloatLiterals* = {nkFloatLit..nkFloat128Lit}
- nkLambdaKinds* = {nkLambda, nkDo}
- declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef}
- routineDefs* = declarativeDefs + {nkMacroDef, nkTemplateDef}
- procDefs* = nkLambdaKinds + declarativeDefs
- callableDefs* = nkLambdaKinds + routineDefs
- nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
- nkStrKinds* = {nkStrLit..nkTripleStrLit}
- skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
- skProcKinds* = {skProc, skFunc, skTemplate, skMacro, skIterator,
- skMethod, skConverter}
- defaultSize = -1
- defaultAlignment = -1
- defaultOffset* = -1
- proc getPIdent*(a: PNode): PIdent {.inline.} =
- ## Returns underlying `PIdent` for `{nkSym, nkIdent}`, or `nil`.
- case a.kind
- of nkSym: a.sym.name
- of nkIdent: a.ident
- of nkOpenSymChoice, nkClosedSymChoice: a.sons[0].sym.name
- of nkOpenSym: getPIdent(a.sons[0])
- else: nil
- const
- moduleShift = when defined(cpu32): 20 else: 24
- template id*(a: PType | PSym): int =
- let x = a
- (x.itemId.module.int shl moduleShift) + x.itemId.item.int
- type
- IdGenerator* = ref object # unfortunately, we really need the 'shared mutable' aspect here.
- module*: int32
- symId*: int32
- typeId*: int32
- sealed*: bool
- disambTable*: CountTable[PIdent]
- const
- PackageModuleId* = -3'i32
- proc idGeneratorFromModule*(m: PSym): IdGenerator =
- assert m.kind == skModule
- result = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0, disambTable: initCountTable[PIdent]())
- proc idGeneratorForPackage*(nextIdWillBe: int32): IdGenerator =
- result = IdGenerator(module: PackageModuleId, symId: nextIdWillBe - 1'i32, typeId: 0, disambTable: initCountTable[PIdent]())
- proc nextSymId(x: IdGenerator): ItemId {.inline.} =
- assert(not x.sealed)
- inc x.symId
- result = ItemId(module: x.module, item: x.symId)
- proc nextTypeId*(x: IdGenerator): ItemId {.inline.} =
- assert(not x.sealed)
- inc x.typeId
- result = ItemId(module: x.module, item: x.typeId)
- when false:
- proc nextId*(x: IdGenerator): ItemId {.inline.} =
- inc x.item
- result = x[]
- when false:
- proc storeBack*(dest: var IdGenerator; src: IdGenerator) {.inline.} =
- assert dest.ItemId.module == src.ItemId.module
- if dest.ItemId.item > src.ItemId.item:
- echo dest.ItemId.item, " ", src.ItemId.item, " ", src.ItemId.module
- assert dest.ItemId.item <= src.ItemId.item
- dest = src
- var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
- proc isCallExpr*(n: PNode): bool =
- result = n.kind in nkCallKinds
- proc discardSons*(father: PNode)
- proc len*(n: PNode): int {.inline.} =
- result = n.sons.len
- proc safeLen*(n: PNode): int {.inline.} =
- ## works even for leaves.
- if n.kind in {nkNone..nkNilLit}: result = 0
- else: result = n.len
- proc safeArrLen*(n: PNode): int {.inline.} =
- ## works for array-like objects (strings passed as openArray in VM).
- if n.kind in {nkStrLit..nkTripleStrLit}: result = n.strVal.len
- elif n.kind in {nkNone..nkFloat128Lit}: result = 0
- else: result = n.len
- proc add*(father, son: PNode) =
- assert son != nil
- father.sons.add(son)
- proc addAllowNil*(father, son: PNode) {.inline.} =
- father.sons.add(son)
- template `[]`*(n: PNode, i: int): PNode = n.sons[i]
- template `[]=`*(n: PNode, i: int; x: PNode) = n.sons[i] = x
- template `[]`*(n: PNode, i: BackwardsIndex): PNode = n[n.len - i.int]
- template `[]=`*(n: PNode, i: BackwardsIndex; x: PNode) = n[n.len - i.int] = x
- proc add*(father, son: PType) =
- assert son != nil
- father.sons.add(son)
- proc addAllowNil*(father, son: PType) {.inline.} =
- father.sons.add(son)
- template `[]`*(n: PType, i: int): PType = n.sons[i]
- template `[]=`*(n: PType, i: int; x: PType) = n.sons[i] = x
- template `[]`*(n: PType, i: BackwardsIndex): PType = n[n.len - i.int]
- template `[]=`*(n: PType, i: BackwardsIndex; x: PType) = n[n.len - i.int] = x
- proc getDeclPragma*(n: PNode): PNode =
- ## return the `nkPragma` node for declaration `n`, or `nil` if no pragma was found.
- ## Currently only supports routineDefs + {nkTypeDef}.
- case n.kind
- of routineDefs:
- if n[pragmasPos].kind != nkEmpty: result = n[pragmasPos]
- else: result = nil
- of nkTypeDef:
- #[
- type F3*{.deprecated: "x3".} = int
- TypeSection
- TypeDef
- PragmaExpr
- Postfix
- Ident "*"
- Ident "F3"
- Pragma
- ExprColonExpr
- Ident "deprecated"
- StrLit "x3"
- Empty
- Ident "int"
- ]#
- if n[0].kind == nkPragmaExpr:
- result = n[0][1]
- else:
- result = nil
- else:
- # support as needed for `nkIdentDefs` etc.
- result = nil
- if result != nil:
- assert result.kind == nkPragma, $(result.kind, n.kind)
- proc extractPragma*(s: PSym): PNode =
- ## gets the pragma node of routine/type/var/let/const symbol `s`
- if s.kind in routineKinds: # bug #24167
- if s.ast[pragmasPos] != nil and s.ast[pragmasPos].kind != nkEmpty:
- result = s.ast[pragmasPos]
- else:
- result = nil
- elif s.kind in {skType, skVar, skLet, skConst}:
- if s.ast != nil and s.ast.len > 0:
- if s.ast[0].kind == nkPragmaExpr and s.ast[0].len > 1:
- # s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
- result = s.ast[0][1]
- else:
- result = nil
- else:
- result = nil
- else:
- result = nil
- assert result == nil or result.kind == nkPragma
- proc skipPragmaExpr*(n: PNode): PNode =
- ## if pragma expr, give the node the pragmas are applied to,
- ## otherwise give node itself
- if n.kind == nkPragmaExpr:
- result = n[0]
- else:
- result = n
- proc setInfoRecursive*(n: PNode, info: TLineInfo) =
- ## set line info recursively
- if n != nil:
- for i in 0..<n.safeLen: setInfoRecursive(n[i], info)
- n.info = info
- when defined(useNodeIds):
- const nodeIdToDebug* = -1 # 2322968
- var gNodeId: int
- template newNodeImpl(info2) =
- result = PNode(kind: kind, info: info2)
- when false:
- # this would add overhead, so we skip it; it results in a small amount of leaked entries
- # for old PNode that gets re-allocated at the same address as a PNode that
- # has `nfHasComment` set (and an entry in that table). Only `nfHasComment`
- # should be used to test whether a PNode has a comment; gconfig.comments
- # can contain extra entries for deleted PNode's with comments.
- gconfig.comments.del(cast[int](result))
- template setIdMaybe() =
- when defined(useNodeIds):
- result.id = gNodeId
- if result.id == nodeIdToDebug:
- echo "KIND ", result.kind
- writeStackTrace()
- inc gNodeId
- proc newNode*(kind: TNodeKind): PNode =
- ## new node with unknown line info, no type, and no children
- newNodeImpl(unknownLineInfo)
- setIdMaybe()
- proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode =
- ## new node with line info, no type, and no children
- newNodeImpl(info)
- setIdMaybe()
- proc newNodeI*(kind: TNodeKind, info: TLineInfo, children: int): PNode =
- ## new node with line info, type, and children
- newNodeImpl(info)
- if children > 0:
- newSeq(result.sons, children)
- setIdMaybe()
- proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
- ## new node with line info, type, and no children
- result = newNode(kind)
- result.info = info
- result.typ() = typ
- proc newNode*(kind: TNodeKind, info: TLineInfo): PNode =
- ## new node with line info, no type, and no children
- newNodeImpl(info)
- setIdMaybe()
- proc newAtom*(ident: PIdent, info: TLineInfo): PNode =
- result = newNode(nkIdent, info)
- result.ident = ident
- proc newAtom*(kind: TNodeKind, intVal: BiggestInt, info: TLineInfo): PNode =
- result = newNode(kind, info)
- result.intVal = intVal
- proc newAtom*(kind: TNodeKind, floatVal: BiggestFloat, info: TLineInfo): PNode =
- result = newNode(kind, info)
- result.floatVal = floatVal
- proc newAtom*(kind: TNodeKind; strVal: sink string; info: TLineInfo): PNode =
- result = newNode(kind, info)
- result.strVal = strVal
- proc newTree*(kind: TNodeKind; info: TLineInfo; children: varargs[PNode]): PNode =
- result = newNodeI(kind, info)
- if children.len > 0:
- result.info = children[0].info
- result.sons = @children
- proc newTree*(kind: TNodeKind; children: varargs[PNode]): PNode =
- result = newNode(kind)
- if children.len > 0:
- result.info = children[0].info
- result.sons = @children
- proc newTreeI*(kind: TNodeKind; info: TLineInfo; children: varargs[PNode]): PNode =
- result = newNodeI(kind, info)
- if children.len > 0:
- result.info = children[0].info
- result.sons = @children
- proc newTreeIT*(kind: TNodeKind; info: TLineInfo; typ: PType; children: varargs[PNode]): PNode =
- result = newNodeIT(kind, info, typ)
- if children.len > 0:
- result.info = children[0].info
- result.sons = @children
- template previouslyInferred*(t: PType): PType =
- if t.sons.len > 1: t.last else: nil
- when false:
- import tables, strutils
- var x: CountTable[string]
- addQuitProc proc () {.noconv.} =
- for k, v in pairs(x):
- echo k
- echo v
- proc newSym*(symKind: TSymKind, name: PIdent, idgen: IdGenerator; owner: PSym,
- info: TLineInfo; options: TOptions = {}): PSym =
- # generates a symbol and initializes the hash field too
- assert not name.isNil
- let id = nextSymId idgen
- result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id,
- options: options, ownerField: owner, offset: defaultOffset,
- disamb: getOrDefault(idgen.disambTable, name).int32)
- idgen.disambTable.inc name
- when false:
- if id.module == 48 and id.item == 39:
- writeStackTrace()
- echo "kind ", symKind, " ", name.s
- if owner != nil: echo owner.name.s
- proc astdef*(s: PSym): PNode =
- # get only the definition (initializer) portion of the ast
- if s.ast != nil and s.ast.kind in {nkIdentDefs, nkConstDef}:
- s.ast[2]
- else:
- s.ast
- proc isMetaType*(t: PType): bool =
- return t.kind in tyMetaTypes or
- (t.kind == tyStatic and t.n == nil) or
- tfHasMeta in t.flags
- proc isUnresolvedStatic*(t: PType): bool =
- return t.kind == tyStatic and t.n == nil
- proc linkTo*(t: PType, s: PSym): PType {.discardable.} =
- t.sym = s
- s.typ = t
- result = t
- proc linkTo*(s: PSym, t: PType): PSym {.discardable.} =
- t.sym = s
- s.typ = t
- result = s
- template fileIdx*(c: PSym): FileIndex =
- # XXX: this should be used only on module symbols
- c.position.FileIndex
- template filename*(c: PSym): string =
- # XXX: this should be used only on module symbols
- c.position.FileIndex.toFilename
- proc appendToModule*(m: PSym, n: PNode) =
- ## The compiler will use this internally to add nodes that will be
- ## appended to the module after the sem pass
- if m.ast == nil:
- m.ast = newNode(nkStmtList)
- m.ast.sons = @[n]
- else:
- assert m.ast.kind == nkStmtList
- m.ast.sons.add(n)
- const # for all kind of hash tables:
- GrowthFactor* = 2 # must be power of 2, > 0
- StartSize* = 8 # must be power of 2, > 0
- proc copyStrTable*(dest: var TStrTable, src: TStrTable) =
- dest.counter = src.counter
- setLen(dest.data, src.data.len)
- for i in 0..high(src.data): dest.data[i] = src.data[i]
- proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) =
- dest.counter = src.counter
- setLen(dest.data, src.data.len)
- for i in 0..high(src.data): dest.data[i] = src.data[i]
- proc discardSons*(father: PNode) =
- father.sons = @[]
- proc withInfo*(n: PNode, info: TLineInfo): PNode =
- n.info = info
- return n
- proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode =
- result = newNode(nkIdent)
- result.ident = ident
- result.info = info
- proc newSymNode*(sym: PSym): PNode =
- result = newNode(nkSym)
- result.sym = sym
- result.typ() = sym.typ
- result.info = sym.info
- proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
- result = newNode(nkSym)
- result.sym = sym
- result.typ() = sym.typ
- result.info = info
- proc newOpenSym*(n: PNode): PNode {.inline.} =
- result = newTreeI(nkOpenSym, n.info, n)
- proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
- result = newNode(kind)
- result.intVal = intVal
- proc newIntNode*(kind: TNodeKind, intVal: Int128): PNode =
- result = newNode(kind)
- result.intVal = castToInt64(intVal)
- proc lastSon*(n: PNode): PNode {.inline.} = n.sons[^1]
- template setLastSon*(n: PNode, s: PNode) = n.sons[^1] = s
- template firstSon*(n: PNode): PNode = n.sons[0]
- template secondSon*(n: PNode): PNode = n.sons[1]
- template hasSon*(n: PNode): bool = n.len > 0
- template has2Sons*(n: PNode): bool = n.len > 1
- proc replaceFirstSon*(n, newson: PNode) {.inline.} =
- n.sons[0] = newson
- proc replaceSon*(n: PNode; i: int; newson: PNode) {.inline.} =
- n.sons[i] = newson
- proc last*(n: PType): PType {.inline.} = n.sons[^1]
- proc elementType*(n: PType): PType {.inline.} = n.sons[^1]
- proc skipModifier*(n: PType): PType {.inline.} = n.sons[^1]
- proc indexType*(n: PType): PType {.inline.} = n.sons[0]
- proc baseClass*(n: PType): PType {.inline.} = n.sons[0]
- proc base*(t: PType): PType {.inline.} =
- result = t.sons[0]
- proc returnType*(n: PType): PType {.inline.} = n.sons[0]
- proc setReturnType*(n, r: PType) {.inline.} = n.sons[0] = r
- proc setIndexType*(n, idx: PType) {.inline.} = n.sons[0] = idx
- proc firstParamType*(n: PType): PType {.inline.} = n.sons[1]
- proc firstGenericParam*(n: PType): PType {.inline.} = n.sons[1]
- proc typeBodyImpl*(n: PType): PType {.inline.} = n.sons[^1]
- proc genericHead*(n: PType): PType {.inline.} = n.sons[0]
- proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
- ## Used throughout the compiler code to test whether a type tree contains or
- ## doesn't contain a specific type/types - it is often the case that only the
- ## last child nodes of a type tree need to be searched. This is a really hot
- ## path within the compiler!
- result = t
- while result.kind in kinds: result = last(result)
- proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
- let kind = skipTypes(typ, abstractVarRange).kind
- case kind
- of tyInt: result = newNode(nkIntLit)
- of tyInt8: result = newNode(nkInt8Lit)
- of tyInt16: result = newNode(nkInt16Lit)
- of tyInt32: result = newNode(nkInt32Lit)
- of tyInt64: result = newNode(nkInt64Lit)
- of tyChar: result = newNode(nkCharLit)
- of tyUInt: result = newNode(nkUIntLit)
- of tyUInt8: result = newNode(nkUInt8Lit)
- of tyUInt16: result = newNode(nkUInt16Lit)
- of tyUInt32: result = newNode(nkUInt32Lit)
- of tyUInt64: result = newNode(nkUInt64Lit)
- of tyBool, tyEnum:
- # XXX: does this really need to be the kind nkIntLit?
- result = newNode(nkIntLit)
- of tyStatic: # that's a pre-existing bug, will fix in another PR
- result = newNode(nkIntLit)
- else: raiseAssert $kind
- result.intVal = intVal
- result.typ() = typ
- proc newIntTypeNode*(intVal: Int128, typ: PType): PNode =
- # XXX: introduce range check
- newIntTypeNode(castToInt64(intVal), typ)
- proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
- result = newNode(kind)
- result.floatVal = floatVal
- proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
- result = newNode(kind)
- result.strVal = strVal
- proc newStrNode*(strVal: string; info: TLineInfo): PNode =
- result = newNodeI(nkStrLit, info)
- result.strVal = strVal
- proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
- params,
- name, pattern, genericParams,
- pragmas, exceptions: PNode): PNode =
- result = newNodeI(kind, info)
- result.sons = @[name, pattern, genericParams, params,
- pragmas, exceptions, body]
- const
- AttachedOpToStr*: array[TTypeAttachedOp, string] = [
- "=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"]
- proc `$`*(s: PSym): string =
- if s != nil:
- result = s.name.s & "@" & $s.id
- else:
- result = "<nil>"
- when false:
- iterator items*(t: PType): PType =
- for i in 0..<t.sons.len: yield t.sons[i]
- iterator pairs*(n: PType): tuple[i: int, n: PType] =
- for i in 0..<n.sons.len: yield (i, n.sons[i])
- when true:
- proc len*(n: PType): int {.inline.} =
- result = n.sons.len
- proc sameTupleLengths*(a, b: PType): bool {.inline.} =
- result = a.sons.len == b.sons.len
- iterator tupleTypePairs*(a, b: PType): (int, PType, PType) =
- for i in 0 ..< a.sons.len:
- yield (i, a.sons[i], b.sons[i])
- iterator underspecifiedPairs*(a, b: PType; start = 0; without = 0): (PType, PType) =
- # XXX Figure out with what typekinds this is called.
- for i in start ..< min(a.sons.len, b.sons.len) + without:
- yield (a.sons[i], b.sons[i])
- proc signatureLen*(t: PType): int {.inline.} =
- result = t.sons.len
- proc paramsLen*(t: PType): int {.inline.} =
- result = t.sons.len - 1
- proc genericParamsLen*(t: PType): int {.inline.} =
- assert t.kind == tyGenericInst
- result = t.sons.len - 2 # without 'head' and 'body'
- proc genericInvocationParamsLen*(t: PType): int {.inline.} =
- assert t.kind == tyGenericInvocation
- result = t.sons.len - 1 # without 'head'
- proc kidsLen*(t: PType): int {.inline.} =
- result = t.sons.len
- proc genericParamHasConstraints*(t: PType): bool {.inline.} = t.sons.len > 0
- proc hasElementType*(t: PType): bool {.inline.} = t.sons.len > 0
- proc isEmptyTupleType*(t: PType): bool {.inline.} = t.sons.len == 0
- proc isSingletonTupleType*(t: PType): bool {.inline.} = t.sons.len == 1
- proc genericConstraint*(t: PType): PType {.inline.} = t.sons[0]
- iterator genericInstParams*(t: PType): (bool, PType) =
- for i in 1..<t.sons.len-1:
- yield (i!=1, t.sons[i])
- iterator genericInstParamPairs*(a, b: PType): (int, PType, PType) =
- for i in 1..<min(a.sons.len, b.sons.len)-1:
- yield (i-1, a.sons[i], b.sons[i])
- iterator genericInvocationParams*(t: PType): (bool, PType) =
- for i in 1..<t.sons.len:
- yield (i!=1, t.sons[i])
- iterator genericInvocationAndBodyElements*(a, b: PType): (PType, PType) =
- for i in 1..<a.sons.len:
- yield (a.sons[i], b.sons[i-1])
- iterator genericInvocationParamPairs*(a, b: PType): (bool, PType, PType) =
- for i in 1..<a.sons.len:
- if i >= b.sons.len:
- yield (false, nil, nil)
- else:
- yield (true, a.sons[i], b.sons[i])
- iterator genericBodyParams*(t: PType): (int, PType) =
- for i in 0..<t.sons.len-1:
- yield (i, t.sons[i])
- iterator userTypeClassInstParams*(t: PType): (bool, PType) =
- for i in 1..<t.sons.len-1:
- yield (i!=1, t.sons[i])
- iterator ikids*(t: PType): (int, PType) =
- for i in 0..<t.sons.len: yield (i, t.sons[i])
- const
- FirstParamAt* = 1
- FirstGenericParamAt* = 1
- iterator paramTypes*(t: PType): (int, PType) =
- for i in FirstParamAt..<t.sons.len: yield (i, t.sons[i])
- iterator paramTypePairs*(a, b: PType): (PType, PType) =
- for i in FirstParamAt..<a.sons.len: yield (a.sons[i], b.sons[i])
- template paramTypeToNodeIndex*(x: int): int = x
- iterator kids*(t: PType): PType =
- for i in 0..<t.sons.len: yield t.sons[i]
- iterator signature*(t: PType): PType =
- # yields return type + parameter types
- for i in 0..<t.sons.len: yield t.sons[i]
- proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType = nil): PType =
- let id = nextTypeId idgen
- result = PType(kind: kind, ownerField: owner, size: defaultSize,
- align: defaultAlignment, itemId: id,
- uniqueId: id, sons: @[])
- if son != nil: result.sons.add son
- when false:
- if result.itemId.module == 55 and result.itemId.item == 2:
- echo "KNID ", kind
- writeStackTrace()
- proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} = dest.sons = sons
- proc setSon*(dest: PType; son: sink PType) {.inline.} = dest.sons = @[son]
- proc setSonsLen*(dest: PType; len: int) {.inline.} = setLen(dest.sons, len)
- proc mergeLoc(a: var TLoc, b: TLoc) =
- if a.k == low(typeof(a.k)): a.k = b.k
- if a.storage == low(typeof(a.storage)): a.storage = b.storage
- a.flags.incl b.flags
- if a.lode == nil: a.lode = b.lode
- if a.snippet == "": a.snippet = b.snippet
- proc newSons*(father: PNode, length: int) =
- setLen(father.sons, length)
- proc newSons*(father: PType, length: int) =
- setLen(father.sons, length)
- proc truncateInferredTypeCandidates*(t: PType) {.inline.} =
- assert t.kind == tyInferred
- if t.sons.len > 1:
- setLen(t.sons, 1)
- proc assignType*(dest, src: PType) =
- dest.kind = src.kind
- dest.flags = src.flags
- dest.callConv = src.callConv
- dest.n = src.n
- dest.size = src.size
- dest.align = src.align
- # this fixes 'type TLock = TSysLock':
- if src.sym != nil:
- if dest.sym != nil:
- dest.sym.flags.incl src.sym.flags-{sfUsed, sfExported}
- if dest.sym.annex == nil: dest.sym.annex = src.sym.annex
- mergeLoc(dest.sym.loc, src.sym.loc)
- else:
- dest.sym = src.sym
- newSons(dest, src.sons.len)
- for i in 0..<src.sons.len: dest[i] = src[i]
- proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType =
- result = newType(t.kind, idgen, owner)
- assignType(result, t)
- result.sym = t.sym # backend-info should not be copied
- proc exactReplica*(t: PType): PType =
- result = PType(kind: t.kind, ownerField: t.owner, size: defaultSize,
- align: defaultAlignment, itemId: t.itemId,
- uniqueId: t.uniqueId)
- assignType(result, t)
- result.sym = t.sym # backend-info should not be copied
- proc copySym*(s: PSym; idgen: IdGenerator): PSym =
- result = newSym(s.kind, s.name, idgen, s.owner, s.info, s.options)
- #result.ast = nil # BUGFIX; was: s.ast which made problems
- result.typ = s.typ
- result.flags = s.flags
- result.magic = s.magic
- result.options = s.options
- result.position = s.position
- result.loc = s.loc
- result.annex = s.annex # BUGFIX
- result.constraint = s.constraint
- if result.kind in {skVar, skLet, skField}:
- result.guard = s.guard
- result.bitsize = s.bitsize
- result.alignment = s.alignment
- proc createModuleAlias*(s: PSym, idgen: IdGenerator, newIdent: PIdent, info: TLineInfo;
- options: TOptions): PSym =
- result = newSym(s.kind, newIdent, idgen, s.owner, info, options)
- # keep ID!
- result.ast = s.ast
- #result.id = s.id # XXX figure out what to do with the ID.
- result.flags = s.flags
- result.options = s.options
- result.position = s.position
- result.loc = s.loc
- result.annex = s.annex
- proc initStrTable*(): TStrTable =
- result = TStrTable(counter: 0)
- newSeq(result.data, StartSize)
- proc initObjectSet*(): TObjectSet =
- result = TObjectSet(counter: 0)
- newSeq(result.data, StartSize)
- proc initNodeTable*(): TNodeTable =
- result = TNodeTable(counter: 0)
- newSeq(result.data, StartSize)
- proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
- result = t
- var i = maxIters
- while result.kind in kinds:
- result = last(result)
- dec i
- if i == 0: return nil
- proc skipTypesOrNil*(t: PType, kinds: TTypeKinds): PType =
- ## same as skipTypes but handles 'nil'
- result = t
- while result != nil and result.kind in kinds:
- if result.sons.len == 0: return nil
- result = last(result)
- proc isGCedMem*(t: PType): bool {.inline.} =
- result = t.kind in {tyString, tyRef, tySequence} or
- t.kind == tyProc and t.callConv == ccClosure
- proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
- owner.flags.incl elem.flags * {tfHasMeta, tfTriggersCompileTime}
- if tfNotNil in elem.flags:
- if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
- owner.flags.incl tfNotNil
- if elem.isMetaType:
- owner.flags.incl tfHasMeta
- let mask = elem.flags * {tfHasAsgn, tfHasOwned}
- if mask != {} and propagateHasAsgn:
- let o2 = owner.skipTypes({tyGenericInst, tyAlias, tySink})
- if o2.kind in {tyTuple, tyObject, tyArray,
- tySequence, tySet, tyDistinct}:
- o2.flags.incl mask
- owner.flags.incl mask
- if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
- tyGenericInvocation, tyPtr}:
- let elemB = elem.skipTypes({tyGenericInst, tyAlias, tySink})
- if elemB.isGCedMem or tfHasGCedMem in elemB.flags:
- # for simplicity, we propagate this flag even to generics. We then
- # ensure this doesn't bite us in sempass2.
- owner.flags.incl tfHasGCedMem
- proc rawAddSon*(father, son: PType; propagateHasAsgn = true) =
- father.sons.add(son)
- if not son.isNil: propagateToOwner(father, son, propagateHasAsgn)
- proc addSonNilAllowed*(father, son: PNode) =
- father.sons.add(son)
- proc delSon*(father: PNode, idx: int) =
- if father.len == 0: return
- for i in idx..<father.len - 1: father[i] = father[i + 1]
- father.sons.setLen(father.len - 1)
- proc copyNode*(src: PNode): PNode =
- # does not copy its sons!
- if src == nil:
- return nil
- result = newNode(src.kind)
- result.info = src.info
- result.typ() = src.typ
- result.flags = src.flags * PersistentNodeFlags
- result.comment = src.comment
- when defined(useNodeIds):
- if result.id == nodeIdToDebug:
- echo "COMES FROM ", src.id
- case src.kind
- of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
- of nkFloatLiterals: result.floatVal = src.floatVal
- of nkSym: result.sym = src.sym
- of nkIdent: result.ident = src.ident
- of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
- else: discard
- when defined(nimsuggest):
- result.endInfo = src.endInfo
- template transitionNodeKindCommon(k: TNodeKind) =
- let obj {.inject.} = n[]
- n[] = TNode(kind: k, typField: n.typ, info: obj.info, flags: obj.flags)
- # n.comment = obj.comment # shouldn't be needed, the address doesnt' change
- when defined(useNodeIds):
- n.id = obj.id
- proc transitionSonsKind*(n: PNode, kind: range[nkComesFrom..nkTupleConstr]) =
- transitionNodeKindCommon(kind)
- n.sons = obj.sons
- proc transitionIntKind*(n: PNode, kind: range[nkCharLit..nkUInt64Lit]) =
- transitionNodeKindCommon(kind)
- n.intVal = obj.intVal
- proc transitionIntToFloatKind*(n: PNode, kind: range[nkFloatLit..nkFloat128Lit]) =
- transitionNodeKindCommon(kind)
- n.floatVal = BiggestFloat(obj.intVal)
- proc transitionNoneToSym*(n: PNode) =
- transitionNodeKindCommon(nkSym)
- template transitionSymKindCommon*(k: TSymKind) =
- let obj {.inject.} = s[]
- s[] = TSym(kind: k, itemId: obj.itemId, magic: obj.magic, typ: obj.typ, name: obj.name,
- info: obj.info, ownerField: obj.ownerField, flags: obj.flags, ast: obj.ast,
- options: obj.options, position: obj.position, offset: obj.offset,
- loc: obj.loc, annex: obj.annex, constraint: obj.constraint)
- when hasFFI:
- s.cname = obj.cname
- when defined(nimsuggest):
- s.allUsages = obj.allUsages
- proc transitionGenericParamToType*(s: PSym) =
- transitionSymKindCommon(skType)
- proc transitionRoutineSymKind*(s: PSym, kind: range[skProc..skTemplate]) =
- transitionSymKindCommon(kind)
- s.gcUnsafetyReason = obj.gcUnsafetyReason
- s.transformedBody = obj.transformedBody
- proc transitionToLet*(s: PSym) =
- transitionSymKindCommon(skLet)
- s.guard = obj.guard
- s.bitsize = obj.bitsize
- s.alignment = obj.alignment
- template copyNodeImpl(dst, src, processSonsStmt) =
- if src == nil: return
- dst = newNode(src.kind)
- dst.info = src.info
- when defined(nimsuggest):
- result.endInfo = src.endInfo
- dst.typ() = src.typ
- dst.flags = src.flags * PersistentNodeFlags
- dst.comment = src.comment
- when defined(useNodeIds):
- if dst.id == nodeIdToDebug:
- echo "COMES FROM ", src.id
- case src.kind
- of nkCharLit..nkUInt64Lit: dst.intVal = src.intVal
- of nkFloatLiterals: dst.floatVal = src.floatVal
- of nkSym: dst.sym = src.sym
- of nkIdent: dst.ident = src.ident
- of nkStrLit..nkTripleStrLit: dst.strVal = src.strVal
- else: processSonsStmt
- proc shallowCopy*(src: PNode): PNode =
- # does not copy its sons, but provides space for them:
- copyNodeImpl(result, src):
- newSeq(result.sons, src.len)
- proc copyTree*(src: PNode): PNode =
- # copy a whole syntax tree; performs deep copying
- copyNodeImpl(result, src):
- newSeq(result.sons, src.len)
- for i in 0..<src.len:
- result[i] = copyTree(src[i])
- proc copyTreeWithoutNode*(src, skippedNode: PNode): PNode =
- copyNodeImpl(result, src):
- result.sons = newSeqOfCap[PNode](src.len)
- for n in src.sons:
- if n != skippedNode:
- result.sons.add copyTreeWithoutNode(n, skippedNode)
- proc hasSonWith*(n: PNode, kind: TNodeKind): bool =
- for i in 0..<n.len:
- if n[i].kind == kind:
- return true
- result = false
- proc hasNilSon*(n: PNode): bool =
- for i in 0..<n.safeLen:
- if n[i] == nil:
- return true
- elif hasNilSon(n[i]):
- return true
- result = false
- proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
- result = false
- if n == nil: return
- case n.kind
- of nkEmpty..nkNilLit: result = n.kind in kinds
- else:
- for i in 0..<n.len:
- if n.kind in kinds or containsNode(n[i], kinds): return true
- proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
- case n.kind
- of nkEmpty..nkNilLit, nkFormalParams: result = n.kind == kind
- else:
- for i in 0..<n.len:
- if (n[i].kind == kind) or hasSubnodeWith(n[i], kind):
- return true
- result = false
- proc getInt*(a: PNode): Int128 =
- case a.kind
- of nkCharLit, nkUIntLit..nkUInt64Lit:
- result = toInt128(cast[uint64](a.intVal))
- of nkInt8Lit..nkInt64Lit:
- result = toInt128(a.intVal)
- of nkIntLit:
- # XXX: enable this assert
- # assert a.typ.kind notin {tyChar, tyUint..tyUInt64}
- result = toInt128(a.intVal)
- else:
- raiseRecoverableError("cannot extract number from invalid AST node")
- proc getInt64*(a: PNode): int64 {.deprecated: "use getInt".} =
- case a.kind
- of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
- result = a.intVal
- else:
- raiseRecoverableError("cannot extract number from invalid AST node")
- proc getFloat*(a: PNode): BiggestFloat =
- case a.kind
- of nkFloatLiterals: result = a.floatVal
- of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
- result = BiggestFloat a.intVal
- else:
- raiseRecoverableError("cannot extract number from invalid AST node")
- #doAssert false, "getFloat"
- #internalError(a.info, "getFloat")
- #result = 0.0
- proc getStr*(a: PNode): string =
- case a.kind
- of nkStrLit..nkTripleStrLit: result = a.strVal
- of nkNilLit:
- # let's hope this fixes more problems than it creates:
- result = ""
- else:
- raiseRecoverableError("cannot extract string from invalid AST node")
- #doAssert false, "getStr"
- #internalError(a.info, "getStr")
- #result = ""
- proc getStrOrChar*(a: PNode): string =
- case a.kind
- of nkStrLit..nkTripleStrLit: result = a.strVal
- of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
- else:
- raiseRecoverableError("cannot extract string from invalid AST node")
- #doAssert false, "getStrOrChar"
- #internalError(a.info, "getStrOrChar")
- #result = ""
- proc isGenericParams*(n: PNode): bool {.inline.} =
- ## used to judge whether a node is generic params.
- n != nil and n.kind == nkGenericParams
- proc isGenericRoutine*(n: PNode): bool {.inline.} =
- n != nil and n.kind in callableDefs and n[genericParamsPos].isGenericParams
- proc isGenericRoutineStrict*(s: PSym): bool {.inline.} =
- ## determines if this symbol represents a generic routine
- ## the unusual name is so it doesn't collide and eventually replaces
- ## `isGenericRoutine`
- s.kind in skProcKinds and s.ast.isGenericRoutine
- proc isGenericRoutine*(s: PSym): bool {.inline.} =
- ## determines if this symbol represents a generic routine or an instance of
- ## one. This should be renamed accordingly and `isGenericRoutineStrict`
- ## should take this name instead.
- ##
- ## Warning/XXX: Unfortunately, it considers a proc kind symbol flagged with
- ## sfFromGeneric as a generic routine. Instead this should likely not be the
- ## case and the concepts should be teased apart:
- ## - generic definition
- ## - generic instance
- ## - either generic definition or instance
- s.kind in skProcKinds and (sfFromGeneric in s.flags or
- s.ast.isGenericRoutine)
- proc skipGenericOwner*(s: PSym): PSym =
- ## Generic instantiations are owned by their originating generic
- ## symbol. This proc skips such owners and goes straight to the owner
- ## of the generic itself (the module or the enclosing proc).
- result = if s.kind == skModule:
- s
- elif s.kind in skProcKinds and sfFromGeneric in s.flags and s.owner.kind != skModule:
- s.owner.owner
- else:
- s.owner
- proc originatingModule*(s: PSym): PSym =
- result = s
- while result.kind != skModule: result = result.owner
- proc isRoutine*(s: PSym): bool {.inline.} =
- result = s.kind in skProcKinds
- proc isCompileTimeProc*(s: PSym): bool {.inline.} =
- result = s.kind == skMacro or
- s.kind in {skProc, skFunc} and sfCompileTime in s.flags
- proc hasPattern*(s: PSym): bool {.inline.} =
- result = isRoutine(s) and s.ast[patternPos].kind != nkEmpty
- iterator items*(n: PNode): PNode =
- for i in 0..<n.safeLen: yield n[i]
- iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
- for i in 0..<n.safeLen: yield (i, n[i])
- proc isAtom*(n: PNode): bool {.inline.} =
- result = n.kind >= nkNone and n.kind <= nkNilLit
- proc isEmptyType*(t: PType): bool {.inline.} =
- ## 'void' and 'typed' types are often equivalent to 'nil' these days:
- result = t == nil or t.kind in {tyVoid, tyTyped}
- proc makeStmtList*(n: PNode): PNode =
- if n.kind == nkStmtList:
- result = n
- else:
- result = newNodeI(nkStmtList, n.info)
- result.add n
- proc skipStmtList*(n: PNode): PNode =
- if n.kind in {nkStmtList, nkStmtListExpr}:
- for i in 0..<n.len-1:
- if n[i].kind notin {nkEmpty, nkCommentStmt}: return n
- result = n.lastSon
- else:
- result = n
- proc toVar*(typ: PType; kind: TTypeKind; idgen: IdGenerator): PType =
- ## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and
- ## returned. Otherwise ``typ`` is simply returned as-is.
- result = typ
- if typ.kind != kind:
- result = newType(kind, idgen, typ.owner, typ)
- proc toRef*(typ: PType; idgen: IdGenerator): PType =
- ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
- ## returned. Otherwise ``typ`` is simply returned as-is.
- result = typ
- if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
- result = newType(tyRef, idgen, typ.owner, typ)
- proc toObject*(typ: PType): PType =
- ## If ``typ`` is a tyRef then its immediate son is returned (which in many
- ## cases should be a ``tyObject``).
- ## Otherwise ``typ`` is simply returned as-is.
- let t = typ.skipTypes({tyAlias, tyGenericInst})
- if t.kind == tyRef: t.elementType
- else: typ
- proc toObjectFromRefPtrGeneric*(typ: PType): PType =
- #[
- See also `toObject`.
- Finds the underlying `object`, even in cases like these:
- type
- B[T] = object f0: int
- A1[T] = ref B[T]
- A2[T] = ref object f1: int
- A3 = ref object f2: int
- A4 = object f3: int
- ]#
- result = typ
- while true:
- case result.kind
- of tyGenericBody: result = result.last
- of tyRef, tyPtr, tyGenericInst, tyGenericInvocation, tyAlias: result = result[0]
- # automatic dereferencing is deep, refs #18298.
- else: break
- # result does not have to be object type
- proc isImportedException*(t: PType; conf: ConfigRef): bool =
- assert t != nil
- if conf.exc != excCpp:
- return false
- let base = t.skipTypes({tyAlias, tyPtr, tyDistinct, tyGenericInst})
- result = base.sym != nil and {sfCompileToCpp, sfImportc} * base.sym.flags != {}
- proc isInfixAs*(n: PNode): bool =
- return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.id == ord(wAs)
- proc skipColon*(n: PNode): PNode =
- result = n
- if n.kind == nkExprColonExpr:
- result = n[1]
- proc findUnresolvedStatic*(n: PNode): PNode =
- if n.kind == nkSym and n.typ != nil and n.typ.kind == tyStatic and n.typ.n == nil:
- return n
- if n.typ != nil and n.typ.kind == tyTypeDesc:
- let t = skipTypes(n.typ, {tyTypeDesc})
- if t.kind == tyGenericParam and not t.genericParamHasConstraints:
- return n
- for son in n:
- let n = son.findUnresolvedStatic
- if n != nil: return n
- return nil
- when false:
- proc containsNil*(n: PNode): bool =
- # only for debugging
- if n.isNil: return true
- for i in 0..<n.safeLen:
- if n[i].containsNil: return true
- template hasDestructor*(t: PType): bool = {tfHasAsgn, tfHasOwned} * t.flags != {}
- template incompleteType*(t: PType): bool =
- t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward}
- template typeCompleted*(s: PSym) =
- incl s.flags, sfNoForward
- template detailedInfo*(sym: PSym): string =
- sym.name.s
- proc isInlineIterator*(typ: PType): bool {.inline.} =
- typ.kind == tyProc and tfIterator in typ.flags and typ.callConv != ccClosure
- proc isIterator*(typ: PType): bool {.inline.} =
- typ.kind == tyProc and tfIterator in typ.flags
- proc isClosureIterator*(typ: PType): bool {.inline.} =
- typ.kind == tyProc and tfIterator in typ.flags and typ.callConv == ccClosure
- proc isClosure*(typ: PType): bool {.inline.} =
- typ.kind == tyProc and typ.callConv == ccClosure
- proc isNimcall*(s: PSym): bool {.inline.} =
- s.typ.callConv == ccNimCall
- proc isExplicitCallConv*(s: PSym): bool {.inline.} =
- tfExplicitCallConv in s.typ.flags
- proc isSinkParam*(s: PSym): bool {.inline.} =
- s.kind == skParam and (s.typ.kind == tySink or tfHasOwned in s.typ.flags)
- proc isSinkType*(t: PType): bool {.inline.} =
- t.kind == tySink or tfHasOwned in t.flags
- proc newProcType*(info: TLineInfo; idgen: IdGenerator; owner: PSym): PType =
- result = newType(tyProc, idgen, owner)
- result.n = newNodeI(nkFormalParams, info)
- rawAddSon(result, nil) # return type
- # result.n[0] used to be `nkType`, but now it's `nkEffectList` because
- # the effects are now stored in there too ... this is a bit hacky, but as
- # usual we desperately try to save memory:
- result.n.add newNodeI(nkEffectList, info)
- proc addParam*(procType: PType; param: PSym) =
- param.position = procType.sons.len-1
- procType.n.add newSymNode(param)
- rawAddSon(procType, param.typ)
- const magicsThatCanRaise = {
- mNone, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst, mEcho}
- proc canRaiseConservative*(fn: PNode): bool =
- if fn.kind == nkSym and fn.sym.magic notin magicsThatCanRaise:
- result = false
- else:
- result = true
- proc canRaise*(fn: PNode): bool =
- if fn.kind == nkSym and (fn.sym.magic notin magicsThatCanRaise or
- {sfImportc, sfInfixCall} * fn.sym.flags == {sfImportc} or
- sfGeneratedOp in fn.sym.flags):
- result = false
- elif fn.kind == nkSym and fn.sym.magic == mEcho:
- result = true
- else:
- # TODO check for n having sons? or just return false for now if not
- if fn.typ != nil and fn.typ.n != nil and fn.typ.n[0].kind == nkSym:
- result = false
- else:
- result = fn.typ != nil and fn.typ.n != nil and ((fn.typ.n[0].len < effectListLen) or
- (fn.typ.n[0][exceptionEffects] != nil and
- fn.typ.n[0][exceptionEffects].safeLen > 0))
- proc toHumanStrImpl[T](kind: T, num: static int): string =
- result = $kind
- result = result[num..^1]
- result[0] = result[0].toLowerAscii
- proc toHumanStr*(kind: TSymKind): string =
- ## strips leading `sk`
- result = toHumanStrImpl(kind, 2)
- proc toHumanStr*(kind: TTypeKind): string =
- ## strips leading `tk`
- result = toHumanStrImpl(kind, 2)
- proc skipHiddenAddr*(n: PNode): PNode {.inline.} =
- (if n.kind == nkHiddenAddr: n[0] else: n)
- proc isNewStyleConcept*(n: PNode): bool {.inline.} =
- assert n.kind == nkTypeClassTy
- result = n[0].kind == nkEmpty
- proc isOutParam*(t: PType): bool {.inline.} = tfIsOutParam in t.flags
- const
- nodesToIgnoreSet* = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
- nkTypeSection, nkProcDef, nkConverterDef,
- nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
- nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
- nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
- nkTypeOfExpr, nkMixinStmt, nkBindStmt}
- proc isTrue*(n: PNode): bool =
- n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or
- n.kind == nkIntLit and n.intVal != 0
- type
- TypeMapping* = Table[ItemId, PType]
- SymMapping* = Table[ItemId, PSym]
- template idTableGet*(tab: typed; key: PSym | PType): untyped = tab.getOrDefault(key.itemId)
- template idTablePut*(tab: typed; key, val: PSym | PType) = tab[key.itemId] = val
- template initSymMapping*(): Table[ItemId, PSym] = initTable[ItemId, PSym]()
- template initTypeMapping*(): Table[ItemId, PType] = initTable[ItemId, PType]()
- template resetIdTable*(tab: Table[ItemId, PSym]) = tab.clear()
- template resetIdTable*(tab: Table[ItemId, PType]) = tab.clear()
|