Reworked to allow derived classes to call base class methods which have been overridden via explicit qualification
[SVN r13588]
This commit is contained in:
parent
5d20da9769
commit
abb0398b5a
@ -7,15 +7,54 @@ import numbers ;
|
||||
import errors : * ;
|
||||
import set ;
|
||||
import modules ;
|
||||
import assert ;
|
||||
|
||||
classes = ;
|
||||
|
||||
# Declare a class with the given name. The caller should have defined
|
||||
# a (local) rule called 'name' which acts as the new class'
|
||||
# constructor. Module-local variables declared in the constructor will
|
||||
# act like instance variables, and rules defined in the constructor
|
||||
# will act like methods.
|
||||
rule class ( name : bases * )
|
||||
# Construct a class in the module of the caller, which should be a
|
||||
# class instance. This rule is imported into each class and instance
|
||||
# under the name <class-name>.__init__ for the most-derived class and
|
||||
# all of its bases. It extracts <class-name> by inspecting the
|
||||
# backtrace and uses that to call the user-defined intitialization
|
||||
# function.
|
||||
local rule __init__ (
|
||||
* # all arguments are forwarded directly to the user-defined
|
||||
# initialization function.
|
||||
)
|
||||
{
|
||||
# pull the name of the class being initialized from the backtrace
|
||||
local bt = [ BACKTRACE ] ;
|
||||
local class = [ MATCH ^(.*)[.]__init__$ : $(bt[4]) ] ;
|
||||
|
||||
assert.nonempty-variable class ;
|
||||
|
||||
# The calling module is the instance names
|
||||
local instance = [ CALLER_MODULE ] ;
|
||||
|
||||
# call the class rule that was defined by the user, from within the instance module
|
||||
module $(instance)
|
||||
{
|
||||
# This invocation defines all of the class' member rules within the instance
|
||||
$(class).$(class) $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
|
||||
}
|
||||
|
||||
# Make all the class' member rules available as qualified names
|
||||
# within the instance
|
||||
local rules = [ RULENAMES $(instance) ] ;
|
||||
IMPORT $(instance) : $(rules) : $(instance) : $(class).$(rules) ;
|
||||
}
|
||||
|
||||
# Declare a class. The caller should have defined a (local) rule
|
||||
# called 'name' which acts as the new class' constructor. Module-local
|
||||
# variables declared in the constructor will act like instance
|
||||
# variables, and rules defined in the constructor will act like
|
||||
# methods.
|
||||
rule class (
|
||||
name # The name of the class and of its initialization rule in
|
||||
# the caller's module
|
||||
|
||||
: bases * # list of base classes
|
||||
)
|
||||
{
|
||||
if $(name) in $(classes)
|
||||
{
|
||||
@ -29,7 +68,6 @@ rule class ( name : bases * )
|
||||
|
||||
# This is a record of the class' base classes
|
||||
modules.poke class@$(name) : __bases__ : $(bases) ;
|
||||
#modules.poke class@$(name) : __derived__ : ;
|
||||
modules.poke class@$(name) : __name__ : $(name) ;
|
||||
|
||||
module class@$(name)
|
||||
@ -38,29 +76,34 @@ rule class ( name : bases * )
|
||||
# users can easily call "inherit", for example.
|
||||
import class : * ;
|
||||
|
||||
# The constructor will be known as "__init__" in the class'
|
||||
# namespace.
|
||||
IMPORT [ CALLER_MODULE ] : $(__name__) : class@$(__name__) : __init__ ;
|
||||
|
||||
# Cause the __init__ function and all of the class modules
|
||||
# rules to be visible to the builtin RULENAMES rule. We'll
|
||||
# need them in order to implement subclasses and instances of
|
||||
# the class.
|
||||
EXPORT class@$(__name__) : __init__ # [ RULENAMES class ]
|
||||
;
|
||||
# The constructor will be called through the __init__ rule
|
||||
# above. We import both rules into the class' module here,
|
||||
# then export them. Although rules are actually only called in
|
||||
# instances' modules, collecting them here saves us a
|
||||
# recursive traversal of all bases to import names into the
|
||||
# instance.
|
||||
IMPORT [ CALLER_MODULE ] : $(__name__) : class@$(__name__) : $(__name__).$(__name__) ;
|
||||
IMPORT class : __init__ : class@$(__name__) : $(__name__).__init__ ;
|
||||
EXPORT class@$(__name__) : $(__name__).$(__name__) $(__name__).__init__ ;
|
||||
|
||||
# Bring the __init__ functions in from the base classes, using
|
||||
# the optional localize parameter so that it will execute in
|
||||
# the instance's module
|
||||
# Bring the __init__ functions in from the base classes, and
|
||||
# check for inheritance cycles.
|
||||
for local base in $(__bases__)
|
||||
{
|
||||
# ECHO import __init__ from module class@$(base) into class@$(__name__) as $(base).__init__ ;
|
||||
IMPORT class@$(base) : __init__ : class@$(__name__) : $(base).__init__ ;
|
||||
EXPORT class@$(__name__) : $(base).__init__ ;
|
||||
local base-rules = [ RULENAMES class@$(base) ] ;
|
||||
|
||||
if ( $(__name__).$(__name__) in $(base-rules) )
|
||||
|| ( $(__name__).__init__ in $(base-rules) )
|
||||
{
|
||||
error base class cycle in class $(__name__) ;
|
||||
}
|
||||
|
||||
IMPORT class@$(base) : $(base-rules) : class@$(__name__) : $(base-rules) ;
|
||||
EXPORT class@$(__name__) : $(base-rules) ;
|
||||
|
||||
# Also make note of bidirectional inheritance links.
|
||||
module class@$(base)
|
||||
{
|
||||
# not using symbolic name "name" here because it might
|
||||
# be a module-local variable
|
||||
__derived__ += $(1) ;
|
||||
}
|
||||
}
|
||||
@ -86,7 +129,7 @@ rule instance ( name : class args * : * )
|
||||
IMPORT $(<) : $(rules) : : $(<).$(rules) ;
|
||||
|
||||
# Now initialize the instance
|
||||
__init__ $(>[2-]) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
|
||||
$(>[1]).__init__ $(>[2-]) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
|
||||
|
||||
# Make a record of the instance's class. We need to do this
|
||||
# last because it will be set to each of the class' base
|
||||
@ -209,7 +252,6 @@ rule __test__ ( )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class myclass ;
|
||||
|
||||
local rule derived1 ( z_ )
|
||||
@ -245,6 +287,12 @@ rule __test__ ( )
|
||||
{
|
||||
return derived2.g ;
|
||||
}
|
||||
|
||||
rule get-x ( )
|
||||
{
|
||||
# Test the ability to call base class functions with qualification.
|
||||
return [ myclass.get-x ] ;
|
||||
}
|
||||
}
|
||||
|
||||
class derived2 : myclass ;
|
||||
|
Loading…
Reference in New Issue
Block a user