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

📄 class.jam

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 JAM
字号:
# Copyright 2001, 2002, 2003 Dave Abrahams# Copyright 2002, 2005 Rene Rivera# Copyright 2002, 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)# Polymorphic class system built on top of core Jam facilities.## Classes are defined by 'class' keywords::##     class myclass#     {#         rule __init__ ( arg1 )     # constructor#         {#             self.attribute = $(arg1) ;#         }##         rule method1 ( )           # method#         {#             return [ method2 ] ;#         }##         rule method2 ( )           # method#         {#             return $(self.attribute) ;#         }#     }## The __init__ rule is the constructor, and sets member variables.## New instances are created by invoking [ new <class> <args...> ]:##     local x = [ new myclass foo ] ;        # x is a new myclass object#     assert.result foo : [ $(x).method1 ] ; # $(x).method1 returns "foo"## Derived class are created by mentioning base classes in the declaration::##     class derived : myclass#     {#          rule __init__ ( arg )#          {#              myclass.__init__ $(arg) ;  # call base __init__##          }##          rule method2 ( )           # method override#          {#              return $(self.attribute)XXX ;#          }#     }## All methods operate virtually, replacing behavior in the base classes. For# example::##     local y = [ new derived foo ] ;            # y is a new derived object#     assert.result fooXXX : [ $(y).method1 ] ;  # $(y).method1 returns "foo"## Each class instance is its own core Jam module. All instance attributes and# methods are accessible without additional qualification from within the class# instance. All rules imported in class declaration, or visible in base classses# are also visible. Base methods are available in qualified form:# base-name.method-name. By convention, attribute names are prefixed with# "self.".import modules ;import numbers ;rule xinit ( instance : class ){    module $(instance)    {        __class__ = $(2) ;        __name__ = $(1) ;    }}rule new ( class args * : * ){    .next-instance ?= 1 ;    local id = object($(class))@$(.next-instance) ;    xinit $(id) : $(class) ;    INSTANCE $(id) : class@$(class) ;    IMPORT_MODULE $(id) ;    $(id).__init__ $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;    # Bump the next unique object name.    .next-instance = [ numbers.increment $(.next-instance) ] ;    # Return the name of the new instance.    return $(id) ;}rule bases ( class ){    module class@$(class)    {        return $(__bases__) ;    }}rule is-derived ( class : bases + ){    local stack = $(class) ;    local visited found ;    while ! $(found) && $(stack)    {        local top = $(stack[1]) ;        stack = $(stack[2-]) ;        if ! ( $(top) in $(visited) )        {            visited += $(top) ;            stack += [ bases $(top) ] ;            if $(bases) in $(visited)            {                found = true ;            }        }    }    return $(found) ;}# Returns true if the 'value' is a class instance.#rule is-instance ( value ){    return [ MATCH "^(object\\()[^@]+\\)@.*" : $(value) ] ;}# Check if the given value is of the given type.#rule is-a (    instance  # The value to check.    : type  # The type to test for.){    if [ is-instance $(instance) ]    {        return [ class.is-derived [ modules.peek $(instance) : __class__ ] : $(type) ] ;    }}local rule typecheck ( x ){    local class-name = [ MATCH "^\\[(.*)\\]$" : [ BACKTRACE 1 ] ] ;    if ! [ is-a $(x) : $(class-name) ]    {        return "Expected an instance of "$(class-name)" but got \""$(x)"\" for argument" ;    }}rule __test__ ( ){    import assert ;    import "class" : new ;    # This will be the construction function for a class called 'myclass'.    #    class myclass    {        import assert ;        rule __init__ ( x_ * : y_ * )        {            # Set some instance variables.            x = $(x_) ;            y = $(y_) ;            foo += 10 ;        }        rule set-x ( newx * )        {            x = $(newx) ;        }        rule get-x ( )        {            return $(x) ;        }        rule set-y ( newy * )        {            y = $(newy) ;        }        rule get-y ( )        {            return $(y) ;        }        rule f ( )        {            return [ g $(x) ] ;        }        rule g ( args * )        {            if $(x) in $(y)            {                return $(x) ;            }            else if $(y) in $(x)            {                return $(y) ;            }            else            {                return ;            }        }        rule get-class ( )        {            return $(__class__) ;        }        rule get-instance ( )        {            return $(__name__) ;        }        rule invariant ( )        {            assert.equal 1 : 1 ;        }        rule get-foo ( )        {            return $(foo) ;        }    }#    class myclass ;    class derived1 : myclass    {        rule __init__ ( z_ )        {            myclass.__init__ $(z_) : X ;            z = $(z_) ;        }        # Override g.        #        rule g ( args * )        {            return derived1.g ;        }        rule h ( )        {            return derived1.h ;        }        rule get-z ( )        {            return $(z) ;        }        # Check that 'assert.equal' visible in base class is visible here.        #        rule invariant2 ( )        {            assert.equal 2 : 2 ;        }        # Check that 'assert.variable-not-empty' visible in base class is        # visible here.        #        rule invariant3 ( )        {            local v = 10 ;            assert.variable-not-empty v ;        }    }#    class derived1 : myclass ;    class derived2 : myclass    {        rule __init__ ( )        {            myclass.__init__ 1 : 2 ;        }        # Override g.        #        rule g ( args * )        {            return derived2.g ;        }        # Test the ability to call base class functions with qualification.        #        rule get-x ( )        {            return [ myclass.get-x ] ;        }    }#    class derived2 : myclass ;    class derived2a : derived2    {        rule __init__        {            derived2.__init__ ;        }    }#    class derived2a : derived2 ;    local rule expect_derived2 ( [derived2] x ) { }    local a = [ new myclass 3 4 5 : 4 5 ] ;    local b = [ new derived1 4 ] ;    local b2 = [ new derived1 4 ] ;    local c = [ new derived2 ] ;    local d = [ new derived2 ] ;    local e = [ new derived2a ] ;    expect_derived2 $(d) ;    expect_derived2 $(e) ;    # Argument checking is set up to call exit(1) directly on failure, and we    # can not hijack that with try, so we should better not do this test by    # default. We could fix this by having errors look up and invoke the EXIT    # rule instead; EXIT can be hijacked (;-)    if --fail-typecheck in [ modules.peek : ARGV ]    {        try ;        {            expect_derived2 $(a) ;        }        catch            "Expected an instance of derived2 but got" instead            ;    }    #try ;    #{    #    new bad_subclass ;    #}    #catch    #  bad_subclass.bad_subclass failed to call base class constructor myclass.__init__    #  ;    #try ;    #{    #    class bad_subclass ;    #}    #catch bad_subclass has already been declared ;    assert.result 3 4 5 : $(a).get-x ;    assert.result 4 5 : $(a).get-y ;    assert.result 4 : $(b).get-x ;    assert.result X : $(b).get-y ;    assert.result 4 : $(b).get-z ;    assert.result 1 : $(c).get-x ;    assert.result 2 : $(c).get-y ;    assert.result 4 5 : $(a).f ;    assert.result derived1.g : $(b).f ;    assert.result derived2.g : $(c).f ;    assert.result derived2.g : $(d).f ;    assert.result 10 : $(b).get-foo ;    $(a).invariant ;    $(b).invariant2 ;    $(b).invariant3 ;    # Check that the __class__ attribute is getting properly set.    assert.result myclass : $(a).get-class ;    assert.result derived1 : $(b).get-class ;    assert.result $(a) : $(a).get-instance ;    $(a).set-x a.x ;    $(b).set-x b.x ;    $(c).set-x c.x ;    $(d).set-x d.x ;    assert.result a.x : $(a).get-x ;    assert.result b.x : $(b).get-x ;    assert.result c.x : $(c).get-x ;    assert.result d.x : $(d).get-x ;    class derived3 : derived1 derived2    {        rule __init__ ( )        {        }    }    assert.result : bases myclass ;    assert.result myclass : bases derived1 ;    assert.result myclass : bases derived2 ;    assert.result derived1 derived2 : bases derived3 ;    assert.true is-derived derived1 : myclass ;    assert.true is-derived derived2 : myclass ;    assert.true is-derived derived3 : derived1 ;    assert.true is-derived derived3 : derived2 ;    assert.true is-derived derived3 : derived1 derived2 myclass ;    assert.true is-derived derived3 : myclass ;    assert.false is-derived myclass : derived1 ;    assert.true is-instance $(a) ;    assert.false is-instance bar ;    assert.true is-a $(a) : myclass ;    assert.true is-a $(c) : derived2 ;    assert.true is-a $(d) : myclass ;    assert.false is-a literal : myclass ;}

⌨️ 快捷键说明

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