| # Copyright 2003 Dave Abrahams |
| # Copyright 2003 Vladimir Prus |
| # Distributed under the Boost Software License, Version 1.0. |
| # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) |
| |
| import modules ; |
| import numbers ; |
| |
| |
| # The pattern that indirect rules must match: module%rule |
| .pattern = ^([^%]*)%([^%]+)$ ; |
| |
| |
| # |
| # Type checking rules. |
| # |
| local rule indirect-rule ( x ) |
| { |
| if ! [ MATCH $(.pattern) : $(x) ] |
| { |
| return "expected a string of the form module%rule, but got \""$(x)"\" for argument" ; |
| } |
| } |
| |
| |
| # Make an indirect rule which calls the given rule. If context is supplied it is |
| # expected to be the module in which to invoke the rule by the 'call' rule |
| # below. Otherwise, the rule will be invoked in the module of this rule's |
| # caller. |
| # |
| rule make ( rulename bound-args * : context ? ) |
| { |
| context ?= [ CALLER_MODULE ] ; |
| context ?= "" ; |
| return $(context)%$(rulename) $(bound-args) ; |
| } |
| |
| |
| # Make an indirect rule which calls the given rule. 'rulename' may be a |
| # qualified rule; if so it is returned unchanged. Otherwise, if frames is not |
| # supplied, the result will be invoked (by 'call', below) in the module of the |
| # caller. Otherwise, frames > 1 specifies additional call frames to back up in |
| # order to find the module context. |
| # |
| rule make-qualified ( rulename bound-args * : frames ? ) |
| { |
| if [ MATCH $(.pattern) : $(rulename) ] |
| { |
| return $(rulename) $(bound-args) ; |
| } |
| else |
| { |
| frames ?= 1 ; |
| # If the rule name includes a Jamfile module, grab it. |
| local module-context = [ MATCH ^(Jamfile<[^>]*>)\\..* : $(rulename) ] ; |
| |
| if ! $(module-context) |
| { |
| # Take the first dot-separated element as module name. This disallows |
| # module names with dots, but allows rule names with dots. |
| module-context = [ MATCH ^([^.]*)\\..* : $(rulename) ] ; |
| } |
| module-context ?= [ CALLER_MODULE $(frames) ] ; |
| return [ make $(rulename) $(bound-args) : $(module-context) ] ; |
| } |
| } |
| |
| |
| # Returns the module name in which the given indirect rule will be invoked. |
| # |
| rule get-module ( [indirect-rule] x ) |
| { |
| local m = [ MATCH $(.pattern) : $(x) ] ; |
| if ! $(m[1]) |
| { |
| m = ; |
| } |
| return $(m[1]) ; |
| } |
| |
| |
| # Returns the rulename that will be called when x is invoked. |
| # |
| rule get-rule ( [indirect-rule] x ) |
| { |
| local m = [ MATCH $(.pattern) : $(x) ] ; |
| return $(m[2]) ; |
| } |
| |
| |
| # Invoke the given indirect-rule. |
| # |
| rule call ( [indirect-rule] r args * : * ) |
| { |
| return [ modules.call-in [ get-module $(r) ] : [ get-rule $(r) ] $(args) |
| : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ] ; |
| } |
| |
| |
| rule __test__ |
| { |
| import assert ; |
| |
| rule foo-barr! ( x ) |
| { |
| assert.equal $(x) : x ; |
| } |
| |
| assert.equal [ get-rule [ make foo-barr! ] ] : foo-barr! ; |
| assert.equal [ get-module [ make foo-barr! ] ] : [ CALLER_MODULE ] ; |
| |
| call [ make foo-barr! ] x ; |
| call [ make foo-barr! x ] ; |
| call [ make foo-barr! : [ CALLER_MODULE ] ] x ; |
| } |