Wiki
Version 1 (modified by hopscc, 11 years ago)

--

Ver Directive

This does not describe an existing feature.

A partial (and ongoing) implementation is available as a patch on ticket:312

Here is a a place to record notes and Doc for conditional compile directive and related features.

Motivation

Conditional inclusion of source code (aka "conditional compilation") is needed in many circumstances to accommodate different code versions for different hardware and OS platforms and (wrt cobra) different target backends/target Libraries and added coding for augmentation wrt different compiler options (tests, asserts on, contracts etc)

Other languages have various levels of support for conditional compilation. Progressing canonically from that implemented as a preprocessor by C, modified for Std C and C++. Adjusted in later languages C# (feature restricted (wrt C/C++) #if, #define), D (version and debug conditions, static-if ) and java (supported (or not) as a language false branching code removal optimisation)

This concept and syntax is based loosely on that of D (v2) without (currently) support for anything similar to static-if. see  D Conditional Compilation.

This directive describes and presents a setup for generating multiple versions of executable code from a single source code base
Hence the directive @ver is a shortened form indicating version or versioning.
(This is presented as a goal (versions) not a mechanism (utilising platform-chk, hardware, backend detection, ...)

Design Drivers

Problems with preprocessor like constructs for conditional compilation are well known and should be avoided.

Optionally compiled blocks in cobra should look like (tagged) code blocks not code in branch conditions in some overlay variant language to cobra.

We can, should and must do better than the solution provided circa 1970/1980 for C/C++

KISS. Favor clarity and simplicity for normal/common cases rather than providing capability for every possible conceivable case.

Concept

Code to be conditionally compiled should be presented in an inline separate indented block prefixed by a compiler directive tag used to match the situation that triggers the inclusion of the conditionally compiled code.

This tag is not a general purpose boolean condition.
Its a match to a 'situation' presented as a specifically named symbol possibly narrowed by additional specifications.

Each conditionally compiled clause stands alone, unrelated to condCompile constructs before or after.

Syntax

  @ver.<tag>[.<tagSpec>]  cobra-statement

  @ver.<tag>[.<tagSpec>]  
      <indented code-block>

Version directives are only recognised in select places:

i.e start of line in

  • a method
  • a Box declaration (class, struct, interface, etc)
  • a nameSpace declaration

A code block can be any of:

  • an indented block of statements
  • an indented block of Box member declarations
  • an indented block of Namespace members

Corresponding to the places a conditional compile (ver) directive is recognised.
(statements in a method, decls in a Box ( class-like declaration), decls in a NameSpace?)

e.g.

     @ver.never
         a = 1234
         # this code is never included

     @ver.jvm  l as List = java.util.ArrayList()
     @ver.clr  l = List()

     @ver.clr.35
         # do domething requiring CLR ver 3.5

            

Tags

These are predefined tags that the compiler provides to give matches for:.

  • clr - backend is CLR
  • jvm - backed is jvm
  • objc - backend is objc
  • windows - platform is Windows
  • mac - platform is Apple Mac
  • unix - platform is unix
  • dotnet - is running on .Net
  • mono - is running on mono
  • asserts - asserts are enabled
  • contracts - contracts are enabled
  • tests - tests are enabled
  • always - always true - always include code block
  • never - never included - suppress code block
  • cobra - match to cobra version number
  • otherThan - define to include code if the following tag/tags are NOT in effect

Arbitrary user defined tags can be set by passing a name (or name+value) to the compiler using the compiler -define option

    cobra -define:tagName ...
    cobra -define:tagName=value ... ( perhaps eventually)

e.g.
    cobra -define:color .....

Some tags may have additional specifications to narrow or better define the match. These follow the tag separated by a '.'

  • Version Numbers - where a version number or range is being checked for, the spec following the tag is an integer or an integer range ( two integers separated by '-') This matches if the version number is >= the version number given or version number is within the range specification given. (dotted version numbers (like '2.1.0') are converted to an integer by dropping internal dots ( so '2.1.0' becomes 210).

e.g.

       running on clr - @ver.clr
       clr > 2.0      - @ver.clr.20
       clr 2.0-3.1 inclusive    - @ver.clr.20-31
  • Where a specific value is being tested for - exact value to match follows tag separated by '.' the value may be quoted if need be.

e.g. chk for tag named 'color' - @ver.color

tag named color with value 'red' - @ver.color.red, @ver.color.'red'

Additionally (Different but the same)

@debug and @env below could conceivably be implemented using @ver (@ver.debug and @ver.env.<envVarName>) tags but its perhaps clearer, convenient and more concise to have separate directives.

1. @debug for code to be included when debug (-d) is on

   v = .doCalc
   @debug print v
   .postProcess(v) 


   val = .doBigCalc
   @debug
      vv = .prettyPrint(v)
      print 'BigCalc val [v.summary]'
      print '  -', vv
   v1 = .postProcess(v)

2. @env (optionally) for testing existence or value of on environment variable that can be used to include code.
Syntax is @env.<envVarName> or @env.<envVarName>.<value>

    @ver.env.IS_COBRA_DEV
        print 'running on cobra Development system'

    @ver.env.OSVer.'Windows_NT'  # or @ver.env.OSVer.Windows_NT
        print 'running on Windows NT'

3. Use of the 'cobra' tag can be elided for the following version-spec and the match will devolve to that cobra version spec( version Number or range). i.e

@ver.cobra.092
  # do something specific to cobra 0.92 or greater 

# is same as 
@ver.092
    # also code specific to cobra 0.92 or greater.

Notes re 'other' cases

Often you want to do something for a particular case (or cases) and something else for everything else not already mentioned even if its only to gen a diagnostic.

This is addressed for by the 'otherThan' tag.
It matches/succeeds when the test situation does not match to any of the appended tags (this is the only tag that may have a list of tags following).

Envisaged use is similar to the following

@ver.mono
    #something specific to mono
@ver.otherThan.mono
    # everything else not including mono


#perhaps more commonly for everything not explicitly already specified

@ver.clr
    #something specific to clr backend
@ver.jvm
    #something specific to jvm
    # many somethings 
@ver.mac
    #something specific to mac  
@ver.otherThan.clr.jvm.mac  # something for not clr,jvm or mac
    #Any other backend TBD
    @ct_trace 'otherThan clr, jvm, mac - Other backends not yet implemented'

Note here that this is the same form as all the others ( a matching tag + code, entirely standalone and complete in itself) but the sense of the match is reversed.

The syntax for matching the tags may yet change (@ver.otherThan.clr|mac|jvm, @ver.otherThan.clr.3.5|jvm.7, ...)

Questions

Is this set rich enough/sufficient for common uses ?

Is env var access necessary given -define on cobra commandLine ?

Any other predefined tags needed?

See Also

Discussion at  http://cobra-language.com/forums/viewtopic.php?f=4&t=966

IfDirective

CompilerDirectives

LanguageTopics