⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 feature.jam

📁 C++的一个好库。。。现在很流行
💻 JAM
📖 第 1 页 / 共 3 页
字号:
#  (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
#  distribute this software is granted provided this copyright notice appears in
#  all copies. This software is provided "as is" without express or implied
#  warranty, and with no claim as to its suitability for any purpose.

import "class" : * ;

import errors : error lol->list ;
import sequence ;
import regex ;
import set ;
import utility ;
import modules indirect ;
import assert : * ;

local rule setup ( )
{
    .all-attributes =

      implicit 
      executed 
      composite
      optional 
      symmetric
      free      
      incidental  
      path  
      dependency  
      propagated 
      link-incompatible
      subfeature
      order-sensitive
      ;

    .all-features = ;
    .all-subfeatures = ; # non-subfeatures
    .all-top-features = ; # non-subfeatures
    .all-implicit-values = ;
}
setup ;

# prepare a fresh space to test in by moving all global variable
# settings into the given temporary module and erasing them here.
rule prepare-test ( temp-module )
{
    DELETE_MODULE $(temp-module) ;
    
    # transfer globals to temp-module
    for local v in [ VARNAMES feature ]
    {
        if [ MATCH (\\.) : $(v) ]
        {
            modules.poke $(temp-module) : $(v) : $($(v)) ;
            $(v) = ;
        }
    }
    setup ;
}

# clear out all global variables and recover all variables from the
# given temporary module
rule finish-test ( temp-module )
{
    # clear globals
    for local v in [ VARNAMES feature ]
    {
        if [ MATCH (\\.) : $(v) ]
        {
            $(v) = ;
        }
    }
    
    for local v in [ VARNAMES $(temp-module) ]
    {
        $(v) = [ modules.peek $(temp-module) : $(v) ] ;
    }
    DELETE_MODULE $(temp-module) ;
}


# Transform features by bracketing any elements which aren't already
# bracketed by "<>"
local rule grist ( features * )
{
    local empty = "" ;
    local r = $(empty:G=$(features)) ;
    return $(r) ;
}

empty = "" ;

# declare a new feature with the given name, values, and attributes.
rule feature ( 
    name         # feature name
  : values *     # the allowable values - may be extended later with feature.extend
  : attributes * # The feature's attributes (e.g. implicit, free, propagated...)
)
{
    name = [ grist $(name) ] ;

    local error ;

    # if there are any unknown attributes...
    if ! ( $(attributes) in $(.all-attributes) )
    {
        error = unknown attributes:
          [ set.difference $(attributes) : $(.all-attributes) ] ;
    }
    else if $(name) in $(.all-features)
    {
        error = feature already defined: ;
    }
    else if implicit in $(attributes) && free in $(attributes)
    {
        error = free features cannot also be implicit ;
    }
    else if free in $(attributes) && propagated in $(attributes)
    {            
        error = free features cannot be propagated ;
    }           
    

    if $(error)
    {
        error $(error)
          : "in" feature declaration:
          : feature [ lol->list $(1) : $(2) : $(3) ] ;
    }

    $(name).values ?= ;
    $(name).attributes = $(attributes) ;
    $(name).subfeatures ?= ;
    $(attributes).features += $(name) ;

    .all-features += $(name) ;
    if subfeature in $(attributes)
    {
        .all-subfeatures += $(name) ;
    }
    else
    {
        .all-top-features += $(name) ;
    }
    extend $(name) : $(values) ;    
}

# set default value of the given feature, overriding any previous
# default.
rule set-default ( feature : value )
{
    local f = [ grist $(feature) ] ;
    if ! $(value) in $($(f).values) 
    {
        errors.error "The specified default value, '$(value)' is invalid" 
          : "allowed values are: " $($(f).values) ;
    }    
    $(f).default = $(value) ;
}


# return the default property values for the given features.
rule defaults ( features * )
{
    local result ;
    for local f in $(features)
    {
        local a = $($(f).attributes) ;
        if ( free in $(a) ) || ( optional in $(a) )
        {
        }
        else
        {
            result += $(f)$($(f).default) ;
        }
    }
    return $(result) ;
}

# returns true iff all elements of names are valid features.
rule valid ( names + )
{
    if $(names) in $(.all-features)
    {
        return true ;
    }
}

# return the attibutes of the given feature
rule attributes ( feature )
{
    if ! [ valid $(feature) ]
    {
        error \"$(feature)\" is not a valid feature name ;
    }
    return $($(feature).attributes) ;
}

# return the values of the given feature
rule values ( feature )
{
    return $($(feature).values) ;
}

# returns true iff 'value-string' is a value-string of an implicit feature
rule is-implicit-value ( value-string )
{
    local v = [ regex.split $(value-string) - ] ;
    local failed ;
    if ! $(v[1]) in $(.all-implicit-values) 
    {
        failed = true ;
    }
    else 
    {
        local feature = $($(v[1]).implicit-feature) ;
        
        for local subvalue in $(v[2-])
        {
            if ! [ find-implied-subfeature $(feature) $(subvalue) : $(v[1]) ]
            {
                failed = true ;
            }
        }
    }
    
    if ! $(failed)       
    {
        return true ;
    }
}

# return the implicit feature associated with the given implicit value.
rule implied-feature ( implicit-value )
{
    local components = [ regex.split $(implicit-value) "-" ] ;
    
    local feature = $($(components[1]).implicit-feature) ;
    if ! $(feature)
    {
        error \"$(implicit-value)\" is not a value of an implicit feature ;
        feature = "" ; # keep testing happy; it expects a result.
    }
    return $(feature) ;
}

local rule find-implied-subfeature ( feature subvalue : value-string ? )
{
    # feature should be of the form <feature-name>
    if $(feature) != $(feature:G)
    {
        error invalid feature $(feature) ;
    }

    return $($(feature)$(value-string:E="")<>$(subvalue).subfeature) ;
}

# Given a feature and a value of one of its subfeatures, find the name
# of the subfeature. If value-string is supplied, looks for implied
# subfeatures that are specific to that value of feature
rule implied-subfeature ( 
  feature               # The main feature name
    subvalue            # The value of one of its subfeatures
    : value-string ?    # The value of the main feature
)
{
    local subfeature = [ find-implied-subfeature $(feature) $(subvalue)
      : $(value-string) ] ;

    if ! $(subfeature)
    {
        value-string ?= "" ;
        error \"$(subvalue)\" is not a known subfeature value of
          $(feature)$(value-string) ;
    }

    return $(subfeature) ;
}

# generate an error if the feature is unknown
local rule validate-feature ( feature )
{
    if ! $(feature) in $(.all-features)
    {
        error unknown feature \"$(feature)\" ;
    }
}

# Given a feature and value, or just a value corresponding to an
# implicit feature, returns a property set consisting of all component
# subfeatures and their values. For example:
#
#   expand-subfeatures <toolset>gcc-2.95.2-linux-x86
#       -> <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
#
#   equivalent to:
#       expand-subfeatures gcc-2.95.2-linux-x86
local rule expand-subfeatures-aux ( 
    feature ? # The name of the feature, or empty if value corresponds to an implicit property
  : value     # The value of the feature.
  : dont-validate ? # If set, no validation of value string will be done  
)
{
    if $(feature)
    {
        feature = $(feature) ;
    }

    if ! $(feature)
    {
        feature = [ implied-feature $(value) ] ;
    }
    else
    {
        validate-feature $(feature) ;
    }
    if ! $(dont-validate)
    {        
        validate-value-string $(feature) $(value) ;
    }
    
    local components = [ regex.split $(value) "-" ] ;
    
    # get the top-level feature's value
    local value = $(components[1]:G=) ;

    local result = $(components[1]:G=$(feature)) ;
    
    local subvalues = $(components[2-]) ;
    while $(subvalues)
    {
        local subvalue = $(subvalues[1]) ; # pop the head off of subvalues
        subvalues = $(subvalues[2-]) ;
        
        local subfeature = [ find-implied-subfeature $(feature) $(subvalue) : $(value) ] ;
        
        # If no subfeature was found, reconstitute the value string and use that
        if ! $(subfeature)
        {
            result = $(components:J=-) ;
            result = $(result:G=$(feature)) ;
            subvalues = ; # stop looping
        }
        else
        {
            local f = [ MATCH ^<(.*)>$ : $(feature) ] ;
            result += $(subvalue:G=$(f)-$(subfeature)) ;
        }
    }
    
    return $(result) ;
}

# Make all elements of properties corresponding to implicit features
# explicit, and express all subfeature values as separate properties
# in their own right. For example, the property
#
#    gcc-2.95.2-linux-x86
#
# might expand to
#
#   <toolset>gcc <toolset-version>2.95.2 <toolset-os>linux <toolset-cpu>x86
#
rule expand-subfeatures ( 
  properties * # property set with elements of the form
           # <feature>value-string or just value-string in the
           # case of implicit features.
  : dont-validate ?
)
{
    local result ;
    for local p in $(properties)
    {
        # Don't expand subfeatures in subfeatures
        if ! [ MATCH "(:)" : $(p:G) ]
        {            
            result += [ expand-subfeatures-aux $(p:G) : $(p:G=) : $(dont-validate) ] ;
        }
        else
        {
            result += $(p) ;
        }        
    }
    return $(result) ;
}

# Helper for extend, below. Handles the feature case.
local rule extend-feature ( feature : values * )
{
    feature = [ grist $(feature) ] ;
    validate-feature $(feature) ;
    if implicit in $($(feature).attributes)
    {
        for local v in $(values)
        {
            if $($(v).implicit-feature)
            {
                error $(v) is already associated with the \"$($(v).implicit-feature)\" feature ;
            }
            $(v).implicit-feature = $(feature) ;
        }

        .all-implicit-values += $(values) ;
    }
    if ! $($(feature).values)
    {
        # This is the first value specified for this feature,
        # take it as default value

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -