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

📄 generators.jam

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 JAM
📖 第 1 页 / 共 3 页
字号:
# 'generator', has some change of being eventually used (probably after# conversion by other generators).## Returns '*' in case any type should be considered a viable source type for the# given generator.#rule viable-source-types-for-generator-real ( generator ){    local source-types = [ $(generator).source-types ] ;    if ! $(source-types)    {        # If generator does not specify any source types, it might be a special        # generator like builtin.lib-generator which just relays to other        # generators. Return '*' to indicate that any source type is possibly        # OK, since we do not know for sure.        return * ;    }    else    {        local result ;        for local s in $(source-types)        {            local viable-sources = [ generators.viable-source-types $(s) ] ;            if $(viable-sources) = *            {                result = * ;                source-types = ;  # Terminate the loop.            }            else            {                result += [ type.all-derived $(s) ] $(viable-sources) ;            }        }        return [ sequence.unique $(result) ] ;    }}# Helper rule, caches the result of 'viable-source-types-for-generator'.#local rule viable-source-types-for-generator ( generator ){    local key = .vstg.$(generator) ;    if ! $($(key))    {        .vstg-cached-generators += $(generator) ;        local v = [ viable-source-types-for-generator-real $(generator) ] ;        if ! $(v)        {            v = none ;        }        $(key) = $(v) ;    }    if $($(key)) != none    {        return $($(key)) ;    }}# Returns usage requirements + list of created targets.#local rule try-one-generator-really ( project name ? : generator : target-type    : property-set : sources * ){    local targets =        [ $(generator).run $(project) $(name) : $(property-set) : $(sources) ] ;    local usage-requirements ;    local success ;    generators.dout [ indent ] returned $(targets) ;    if $(targets)    {        success = true ;        if  [ class.is-a $(targets[1]) : property-set ]        {            usage-requirements = $(targets[1]) ;            targets = $(targets[2-]) ;        }        else        {            usage-requirements = [ property-set.empty ] ;        }    }    generators.dout [ indent ] "  generator" [ $(generator).id ] " spawned " ;    generators.dout [ indent ] " " $(targets) ;    if $(usage-requirements)    {        generators.dout [ indent ] "  with usage requirements:" $(x) ;    }    if $(success)    {        return $(usage-requirements) $(targets) ;    }}# Checks if generator invocation can be pruned, because it is guaranteed to# fail. If so, quickly returns an empty list. Otherwise, calls# try-one-generator-really.#local rule try-one-generator ( project name ? : generator : target-type    : property-set : sources * ){    local source-types ;    for local s in $(sources)    {        source-types += [ $(s).type ] ;    }    local viable-source-types = [ viable-source-types-for-generator $(generator)        ] ;    if  $(source-types) && $(viable-source-types) != * &&        ! [ set.intersection $(source-types) : $(viable-source-types) ]    {        local id = [ $(generator).id ] ;        generators.dout [ indent ] "  ** generator '$(id)' pruned" ;        #generators.dout [ indent ] "source-types" '$(source-types)' ;        #generators.dout [ indent ] "viable-source-types" '$(viable-source-types)' ;    }    else    {        return [ try-one-generator-really $(project) $(name) : $(generator) :            $(target-type) : $(property-set) : $(sources) ] ;    }}rule construct-types ( project name ? : target-types + : property-set    : sources + ){    local result ;    local matched-types ;    local usage-requirements = [ property-set.empty ] ;    for local t in $(target-types)    {        local r = [ construct $(project) $(name) : $(t) : $(property-set) :            $(sources) ] ;        if $(r)        {            usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;            result += $(r[2-]) ;            matched-types += $(t) ;        }    }    # TODO: have to introduce parameter controlling if several types can be    # matched and add appropriate checks.    # TODO: need to review the documentation for 'construct' to see if it should    # return $(source) even if nothing can be done with it. Currents docs seem    # to imply that, contrary to the behaviour.    if $(result)    {        return $(usage-requirements) $(result) ;    }    else    {        return $(usage-requirements) $(sources) ;    }}# Ensures all 'targets' have their type. If this is not so, exists with error.#local rule ensure-type ( targets * ){    for local t in $(targets)    {        if ! [ $(t).type ]        {            errors.error "target" [ $(t).str ] "has no type" ;        }    }}# Returns generators which can be used to construct target of specified type# with specified properties. Uses the following algorithm:# - iterates over requested target-type and all its bases (in the order returned#   by type.all-bases).# - for each type find all generators that generate that type and whose#   requirements are satisfied by properties.# - if the set of generators is not empty, returns that set.## Note: this algorithm explicitly ignores generators for base classes if there# is at least one generator for the requested target-type.#local rule find-viable-generators-aux ( target-type : property-set ){    # Select generators that can create the required target type.    local viable-generators = ;    local generator-rank = ;    import type ;    local t = [ type.all-bases $(target-type) ] ;    generators.dout [ indent ] find-viable-generators target-type= $(target-type)        property-set= [ $(property-set).as-path ] ;    # Get the list of generators for the requested type. If no generator is    # registered, try base type, and so on.    local generators ;    while $(t[1])    {        generators.dout [ indent ] "trying type" $(t[1]) ;        if $(.generators.$(t[1]))        {            generators.dout [ indent ] "there are generators for this type" ;            generators = $(.generators.$(t[1])) ;            if $(t[1]) != $(target-type)            {                # We are here because there were no generators found for                # target-type but there are some generators for its base type.                # We will try to use them, but they will produce targets of                # base type, not of 'target-type'. So, we clone the generators                # and modify the list of target types.                local generators2 ;                for local g in $(generators)                {                    # generators.register adds a generator to the list of                    # generators for toolsets, which is a bit strange, but                    # should work. That list is only used when inheriting a                    # toolset, which should have been done before running                    # generators.                    generators2 += [ $(g).clone-and-change-target-type $(t[1]) :                        $(target-type) ] ;                    generators.register $(generators2[-1]) ;                }                generators = $(generators2) ;            }            t = ;        }        t = $(t[2-]) ;    }    for local g in $(generators)    {        generators.dout [ indent ] "trying generator" [ $(g).id ] "(" [ $(g).source-types ] -> [ $(g).target-types ] ")" ;        local m = [ $(g).match-rank $(property-set) ] ;        if $(m)        {            generators.dout [ indent ] "  is viable" ;            viable-generators += $(g) ;        }    }    return $(viable-generators) ;}rule find-viable-generators ( target-type : property-set ){    local key = $(target-type).$(property-set) ;    local l = $(.fv.$(key)) ;    if ! $(l)    {        l = [ find-viable-generators-aux $(target-type) : $(property-set) ] ;        if ! $(l)        {            l = none ;        }        .fv.$(key) = $(l) ;    }    if $(l) = none    {        l = ;    }    local viable-generators ;    for local g in $(l)    {        # Avoid trying the same generator twice on different levels.        if ! $(g) in $(.active-generators)        {            viable-generators += $(g) ;        }    }    # Generators which override 'all'.    local all-overrides ;    # Generators which are overriden.    local overriden-ids ;    for local g in $(viable-generators)    {        local id = [ $(g).id ] ;        local this-overrides = $(.override.$(id)) ;        overriden-ids += $(this-overrides) ;        if all in $(this-overrides)        {            all-overrides += $(g) ;        }    }    if $(all-overrides)    {        viable-generators = $(all-overrides) ;    }    local result ;    for local g in $(viable-generators)    {        if ! [ $(g).id ] in $(overriden-ids)        {            result += $(g) ;        }    }    return $(result) ;}.construct-stack = ;# Attempts to construct a target by finding viable generators, running them and# selecting the dependency graph.#local rule construct-really ( project name ? : target-type : property-set :    sources * ){    viable-generators = [ find-viable-generators $(target-type) :        $(property-set) ] ;    generators.dout [ indent ] "*** " [ sequence.length $(viable-generators) ]        " viable generators" ;    local result ;    local generators-that-succeeded ;    for local g in $(viable-generators)    {        # This variable will be restored on exit from this scope.        local .active-generators = $(g) $(.active-generators) ;        local r = [ try-one-generator $(project) $(name) : $(g) : $(target-type)            : $(property-set) : $(sources) ] ;        if $(r)        {            generators-that-succeeded += $(g) ;            if $(result)            {                ECHO "Error: ambiguity found when searching for best transformation" ;                ECHO "Trying to produce type '$(target-type)' from: " ;                for local s in $(sources)                {                    ECHO " - " [ $(s).str ] ;                }                ECHO "Generators that succeeded:" ;                for local g in $(generators-that-succeeded)                {                    ECHO " - " [ $(g).id ] ;                }                ECHO "First generator produced: " ;                for local t in $(result[2-])                {                    ECHO " - " [ $(t).str ] ;                }                ECHO "Second generator produced: " ;                for local t in $(r[2-])                {                    ECHO " - " [ $(t).str ] ;                }                EXIT ;            }            else            {                result = $(r) ;            }        }    }    return $(result) ;}# Attempts to create a target of 'target-type' with 'properties' from 'sources'.# The 'sources' are treated as a collection of *possible* ingridients, i.e.# there is no obligation to consume them all.## Returns a list of targets. When this invocation is first instance of# 'construct' in stack, returns only targets of requested 'target-type',# otherwise, returns also unused sources and additionally generated targets.#rule construct ( project name ? : target-type : property-set * : sources * ){    if (.construct-stack)    {        ensure-type $(sources) ;    }    .construct-stack += 1 ;    increase-indent ;    if $(.debug)    {        generators.dout [ indent ] "*** construct" $(target-type) ;        for local s in $(sources)        {            generators.dout [ indent ] "    from" $(s) ;        }        generators.dout [ indent ] "    properties:" [ $(property-set).raw ] ;    }    local result = [ construct-really $(project) $(name) : $(target-type) :        $(property-set) : $(sources) ] ;    decrease-indent ;    .construct-stack = $(.construct-stack[2-]) ;    return $(result) ;}# Given 'result', obtained from some generator or generators.construct, adds# 'raw-properties' as usage requirements to it. If result already contains usage# requirements -- that is the first element of result of an instance of the# property-set class, the existing usage requirements and 'raw-properties' are# combined.#rule add-usage-requirements ( result * : raw-properties * ){    if $(result)    {        if [ class.is-a $(result[1]) : property-set ]        {            return [ $(result[1]).add-raw $(raw-properties) ] $(result[2-]) ;        }        else        {            return [ property-set.create $(raw-properties) ] $(result) ;        }    }}

⌨️ 快捷键说明

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