1 // maybe we want to call "value" "reduce" and only use one class.
5 classvar <callers, <current, <>callFunc;
6 classvar <>defaultValue;
7 classvar <>protected = false, <>verbose = false;
8 classvar <>defaultValue=1;
11 source_ { arg obj; this.value = obj }
16 ^this.reduceFuncProxy(args)
18 valueArray { arg args;
19 ^this.reduceFuncProxy(args)
21 valueEnvir { arg ... args;
22 ^this.notYetImplemented(thisMethod)
23 //^value.valueEnvir(*args) ? defaultValue
25 valueArrayEnvir { arg ... args;
26 ^this.notYetImplemented(thisMethod)
27 //^value.valueArrayEnvir(args) ? defaultValue
29 functionPerformList { arg selector, arglist;
30 ^this.performList(selector, arglist)
33 // this allows recursion
35 ^this.reduceFuncProxy(args, false)
37 // function composition
39 ^NAryValueProxy(this, args)
45 // use in list comprehension
50 this.source.do(function) // problem: on the fly change is not picked up in this case.
53 doesNotUnderstand { arg selector ... args;
54 ^this.composeNAryOp(selector, args)
57 // streams and patterns
59 embedInStream { arg inval;
64 if(curVal !== value) { str = value.asStream; curVal = value };
65 outval = str.next(inval);
70 }.embedInStream(inval)
74 composeUnaryOp { arg aSelector;
75 ^UnaryOpFunctionProxy.new(aSelector, this)
77 composeBinaryOp { arg aSelector, something, adverb;
78 ^BinaryOpFunctionProxy.new(aSelector, this, something, adverb);
80 reverseComposeBinaryOp { arg aSelector, something, adverb;
81 ^BinaryOpFunctionProxy.new(aSelector, something, this, adverb);
83 composeNAryOp { arg aSelector, anArgList;
84 ^NAryOpFunctionProxy.new(aSelector, this, anArgList)
88 // used by AbstractFunction:reduceFuncProxy
89 // to prevent reduction of enclosed functions
90 valueFuncProxy { arg args;
91 ^this.catchRecursion {
92 value.valueFuncProxy(args)
93 } ?? { this.valueEmpty(args) };
96 valueEmpty { arg args;
98 ("* ? incomplete definition: %\n").postf(this.infoString(args))
103 reduceFuncProxy { arg args, protect=true;
106 value.reduceFuncProxy(args)
108 this.catchRecursion {
109 value.reduceFuncProxy(args)
111 } ?? { this.valueEmpty(args) };
114 catchRecursion { arg func;
121 if(this.includedInCallers) {
123 ("* ! Couldn't solve a recursive definition in %\n")
124 .postf(this.infoString)
126 callFunc.value(this, callers, \recursion);
129 // add this to the list of current callers
130 callers = callers.add(this);
134 callFunc.value(this, callers, val);
137 if(verbose and: { exception.isKindOf(Exception)} ) {
138 ("Error or incomplete specification" + exception.errorString).postln;
140 /* if(exception.isKindOf(this.class).not) {
152 ^callers.notNil and: { callers.includes(this) }
156 var res = this.findKey;
157 ^if(res.notNil) { "~" ++ res } { this.asString }
160 infoString { arg args;
161 var who, str="", src;
163 if(who.isNil) { ^this.asString };
165 src = this.source.postString;
166 if(args.notNil and: {args.notEmpty}) {
167 args = args.collect(_.postString);
168 str = "\nArguments passed: %".format(args)
170 ^"% <- %".format(who, src.asString) ++ str
174 ^currentEnvironment.findKeyForValue(this)
177 storeOn { arg stream;
178 // maybe should try to catch a recursion here:
179 stream << this.class.name << "(" <<< value << ")" }
187 all = IdentityDictionary.new
194 res = super.new.source_(val);
197 if(val.notNil) { res.source = val };