2) seems the most flexible/powerful one. Constants can be regarded as special attributes that can be accessed in the class object and in each of its instances. Currently their value is a symbol.
As you are envisioning some sort of a method execution to determine the constant value, how about allowing a method body (like an attribute setter method without an argument) to define the constant value? Something like: ::constant aconstant foo -- like now ::constant fullsize -- new: no value supplied, just the name expose fullsize fullsize=2**12 ::constant halfsize -- new: no value supplied, just the name expose halfsize fullsize halfsize=fullsize/2 ::constant x_halfsize_x -- new: no value supplied, just the name expose x_halfsize_x x_halfsize_x= self~x_fullsize_x/2 -- employ "self" ::constant x_fullsize_x 4096 -- like now ::constant abc -- new: no method body use name as value, hence will use "abc" as its constant value ---rony On 17.12.2018 23:41, Rick McGuire wrote: > I admit this is a feature I've wanted for some time but was not sure how to > actually do it. Since > Erich opened the feature request, I thought I should give it a closer look. > I've gotten far enough > into this that I believe it can be done, with some restrictions. There are a > few items where > decisions need to be made on which direction to proceed. > > So, basically this will work by building a special method that runs on the > class object during the > package install process. Each class directive will have its own special > method and the > instructions executed will be any ::constant directive that has a > non-constant expression value. > There should be no restrictions on the expressions and the variables SELF and > SUPER will have the > expected values for a method run on a class object. The expressions when run > will be traceable if > ::options trace is used, even interactive trace. I've got most of the > mechanisms on how to do all > of this worked out and it looks pretty clean. > > My first thought was to apply the current rules for parsing ::CONSTANT and > anything that fell > outside of the current rules would be a constant. This works, but there is a > gotcha. The current > rules allow constants to be defined using > > ::constant aconstant foo > > where foo is a symbol treated as a constant. Going this route means > > ::constant aconstant self > ::constant anotherConstant (self) > > would produce different results. The parsing code could consider non-constant > symbols to be > expressions, which would cause these to have the same values, and most > ::constant declarations > would be unaffected because the variable would be uninitialized, and thus > have the same > values...with the exception of the variables SELF and SUPER, which will have > a value. There's also > the issue of ::options novalue error, which will suddenly start getting > tripped by instructions > that were fine before. > > Right now, I'm leaning toward an explicit syntax to indicate the value needs > to be computed at > class creation time. We already have a precedent of using parens to indicate > a general expression, > so I believe we should use that. No parens, old rule, in parens, an > expression to be evaluated. > > Part of the processing I envision is the constant methods are created > initially, but are > "incomplete" and if they are invoked before they are "completed", they will > raise a new subcode of > error 97 to indicate the constant had not been initialized. Initialization > occurs in declaration > order, so constants can refer to other constants of the same class, as long > as they were declared > prior to the usage. That is > > ::constant fullsize (2**12) > ::constant halfsize (self~fullsize/2) > > Would work, but > > ::constant halfsize (self~fullsize/2) > ::constant fullsize (2**12) > > would give an error evaluating self~fullsize. Directives with true constant > values will be > available always, so > > ::constant halfsize (self~fullsize/2) > ::constant fullsize 4096 > > would work because fullsize method was complete at parse time. > > The next issue I'm wrestling with is when to perform the calculation. The > current package > installation code does things in two passes. During parsing, the classes are > analyzed for > inheritance dependencies and the classes are created so that classes that are > required by other > classes are created first, so these are not done in top-down declaration > order. > > Once all of the class objects have been created, a second pass is done to > call the activate() > methods on the new class objects. > > The dynamic constants (looking for a better name for these...) introduce a > third stage to this > processing. I see three approaches that can be used: > > 1) Completing the constants is part of the class creation, so it is done for > each class in turn. > This will limit somewhat the ability to refer classes defined within the same > package. > 2) Perform a complete pass through the class objects initializing the > constants. This allows some > capability to reference other classes and all of the constants are completed > before any of the > activate() methods are invoked. > 3) Perform the constant initialization at the same time activate() is called > on the class. Again, > this limits the ability of class activate() methods to use the constants > defined by another class. > > Right now, I'm leaning toward 2), because it means the classes are all fully > initialized as class > objects before any of the activate() methods are calls. > > Those are the biggest issues I see here. I've got enough code roughed out to > believe this can > work, but I have quite a bit more to go. > > Rick > 2) Completing
_______________________________________________ Oorexx-devel mailing list Oorexx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/oorexx-devel