src/bookofnim/deepdives/pragmasEffects

Source   Edit  

pragmas, effects and experimental features

TLDR

  • pragmas
    • syntax: {.pragma1, pragma2:val, etc.}
    • many pragmas require familiarity of C/C++/objc
    • FYI:
      • a futile attempt was taken at categorizing pragmas
      • template annotation & macro pragmas are in templateMacros.nim
      • thread/async pragmas are in asyncPar.nim
  • effect system consists of
    • proc exception tracking
    • user defined effect tag tracking
    • functional side effect tracking
    • memory/gc safety tracking

links

TODOs

pragmas

  • enable new functionality without adding new keywords to the language
  • are processed on the fly durings emantic checking
  • push & prop pragmas should spark your imagination
  • user defined pragmas are in a module wide scope distinct from all other symbol types
    • cannot be improted from a module
  • union & packed pragma should not use inheritance/GCed memory
var x {.pragmaX.} = thingsome
var y {.intdefine.} = 20 # see intdefine, 20 will be replaced if --define:y=blah
proc y(): auto {.pragmaX:value.} =

{.experimental: "pragmaZ".} # can be module scoped too

{.pragma:myPragma, pragmaX, pragmaY.} # create new pragma named myPragma
proc Z(): auto {.myPragma.} # <- now receives pragmaX and pragmaY

custom pragmas

  • compile tiem pragmas: pass to the compiler via --define:X=Y
    • intdefine replaces all assignments to X with value extracted from --define:X=42
    • strdefine same as intdefine but for strings
    • booldefine same as intdefine but for bools
  • user defined pragmas: WOOP is a new pragma,
    • pragma:WOOP, pragmaX, pragmaY
  • see templateMacros.nim for template pragmas

universal pragmas

  • compileTime marks proc as compile time only; vars init during compile and const at runtime
  • deprecated: "optional msg" flag, prints warning in compiler logs if symbol is used
  • effects will output all inferred effects (e.g. exceptions) up to this point
  • error: "msg" annotate a symbol with an error msg; when the symbol is used a static error is thrown
  • fatal: "msg" same as error but compilation is guaranteed to be aborted when symbol is used
  • linearScanEnd signify the end of expected case branches for optimization
  • pop: x,y,z remove pragma/all pushed pragmas, e.g. {.pop.} removes all
  • push: x,y,z add pragmas until popped, e.g. {.push hints:off, warningblah: on.}
  • used: inform the compiler this symbol/module is used, and not to print warning about it
  • warning: "msg" same as error but for warnings

var pragmas

  • global converts a proc scoped var into a global
  • threadvar informs the compiler this var should be local to a thread

routine pragmas

  • async requires import asyncdispatch; proc can now use await keyword
  • base method used on a base type for inheritable objects
  • closure
  • effectsOf: paramX inform the compiler this proc has the effects of paramX
  • noReturn proc that never returns
  • noSideEffect proc is interpreted as a func (see routines.nim)
  • raises: x,y,z list permitted exceptions; non listed force compiler errs
  • tags: x,y,z list of user defined effects to enforce
  • thread informs the compiler this proc is meant for execution on a new thread
  • varags this proc can take a variable number of params after the last one

type pragmas

  • acyclic mark object as non recursive incase GC infers otherwise; for GC optimization
  • bycopy pass this obj/tuple by value into procs
  • byref pass this obj/tuple by ref into procs
  • final mark an object as non inheritable
  • inheritable create alternative RootObj
  • overloadableEnums allows two Enums to have same fieldnames, to be resolved at runtime
  • packed sets an objects field back to back in memory; e.g. for network/hardware drivers
  • pure requires enums to be fully qualified; x fails, but y.x doesnt
  • shallow objects can be shallow copied; use w/ caution; speeds up assignments considerably
  • union sets an objects fields overlaid in memory producing a union instead of struct in C/++

JS pragmas

  • importJs fns/symbols that can be called via obj.fn(args)

experimental pragmas

  • enable experimental features
    • parallel

compilation pragmas

  • assertions:on/off
  • boundChecks:on/off
  • callconv:on/off
  • checks:on/off
  • hintwoop:on/off
  • hints:on/off
  • nilChecks:on/off
  • optimization:none/speed/size
  • overflowChecks: on/off
  • patterns:on/off
  • warningwoop:on/off
  • warnings:on/off

niche pragmas

  • asmNoStackFrame should only be used by procs consisting only of assembler statements
  • line modify line information as seen in stacktraces
  • regiser a var for placement in hardware registry for faster access

unknown/skipped/C pragmas

  • align
  • bitsize
  • codegenDecl
  • compile
  • computedGoTo dunno; something to do with case statements in a while loop and interpreters
  • cpopNonPod
  • dirty something to do with templates
  • discardable
  • dynlib: "exactName" import a proc/var from a dynamic .{dll,so} library
  • dynlib export this symbol to a dynamic library, must be used with exportc
  • emit
  • exportc: "optionalName" use the symbols/provided name when exporting this to c
  • extern: "x$1" affects symbol name mangling when exported
  • header
  • importc import a proc/var from C
  • importCpp
  • importObjC
  • incompleteStruct
  • inject something to do with symbol visibility
  • inline a proc; dunno what that means
  • link
  • localPassc
  • nodecl
  • passc
  • passl
  • registerProc dunno; included in the compileTime example
  • size dunno
  • volatile

effects

  • informing the compiler about a routine's side effects
  • impacts type compatibility and compilation

exception tracking effects

  • implemented through the raises pragma and indirectly through try statements
    • only tracks Exceptions, not Defects
  • can be attach to any type of routine (except func?)
    • in a type def, e.g. type x = proc {.raises [...].} are part of type checks on assignment
  • general rules for determining which exceptions a routine throws
    • all routines potentially raise System.Exception
      • if routine X is invoked and its body cant be inferred
      • unless
        • routine contains a try/except statement, then those are included
        • routine X indirectly invoked via Y(...), then X has effectsOf: Y
        • routine X imported via importc, then no exceptions expected
        • raise and tryh
        • an explicit raises is defined, then can raise only those declared
          • this trumps all others except:
            • expression Y can raise A,B,C and is invoked within Xs scope, then X raises + Y raises

user defined effects

  • tag routines with custom effects via named types
  • routines tagged must be invoked with the named type in scope

functional side effect tracking

gc safety memory effects

effect types

  • IOEffect
    • ExecIOEffect executing IO operation
    • ReadIOEffect describes a read IO operation
    • RootEffect custom effects should inherit from this
    • TimeEffect
    • WriteIOEffect

Types

Oops = object of CatchableError
Source   Edit  

Procs

proc canOnlyRaiseOops(): bool {....raises: [Oops], tags: [], forbids: [].}
Source   Edit  
proc couldRaise(thisParam: proc (): bool): bool {....raises: [],
    effectsOf: thisParam, ...tags: [], forbids: [].}
Source   Edit  
proc neverRaises(a: string): bool {....raises: [], tags: [], forbids: [].}
any inferred exceptions/defects cause compilation errors Source   Edit  
proc passCallback(): bool {....raises: [Oops], tags: [], forbids: [].}
Source   Edit