summaryrefslogtreecommitdiff
path: root/cad/src/exprs/Exprs.py
blob: f28e2d6210e1c278f507bcc853d8c2ed7fa9076f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
# Copyright 2006-2009 Nanorex, Inc.  See LICENSE file for details.
"""
Exprs.py -- class Expr, and related subclasses and utilities, other than those involving Instances

@author: Bruce
@version: $Id$
@copyright: 2006-2009 Nanorex, Inc.  See LICENSE file for details.

TODO:

this file is getting kind of long - maybe split it in some sensible way?
"""

# note: this module should not import ExprsMeta, though its InstanceOrExpr subclass needs to (in another module).
# instead, it is probably fully imported by ExprsMeta.

from utilities.debug import compact_stack
from utilities.debug import print_compact_stack
from utilities.debug import safe_repr

##from debug_prefs import debug_pref, Choice_boolean_False, Choice_boolean_True, Choice

from utilities.Comparison import same_vals

from exprs.py_utils import printnim, printfyi, printonce
from exprs.intern_ipath import intern_ipath

from foundation.state_constants import _UNSET_

# ==

EVAL_REFORM = True
    # False supposedly acts like old code, True like new code which has by now become standard;
    # this affects all class defs, so to be safe, print a warning if the value is not true.
    # [bruce 070115 & 071102]

if not EVAL_REFORM:
    print "EVAL_REFORM is %r" % EVAL_REFORM

# == utilities #e refile

def map_dictvals(func, dict1):
    """
    This does to a dict's values what map does to lists --
    i.e. it makes a new dict whose values v are replaced by func(v).
    [If you wish func also depended on k, see map_dictitems.]
    """
    return dict([(k,func(v)) for k,v in dict1.iteritems()])

def map_dictitems(func, dict1):
    """
    This does to a dict's items what map does to lists --
    i.e. it makes a new dict whose items are f(item) from the old dict's items.
    Func should take 1 argument, a pair (k,v), and return a new pair (k2, v2).
    Often k2 is k, but this is not required.
    If the new items have overlapping keys, the result is... I don't know what. #k
    """
    return dict(map(func, dict1.iteritems()))

# == serial numbers (along with code in Expr.__init__)

_next_e_serno = 1 # incremented after being used in each new Expr instance (whether or not _e_is_instance is true for it)
    ###e should we make it allocated in Expr subclasses too, by ExprsMeta, and unique in them?

_debug_e_serno = -1 ## normally -1 # set to the serno of an expr you want to watch #k untested since revised

def expr_serno(expr):
    """
    Return the unique serial number of any Expr (except that Expr python subclasses all return 0).
    Non-Exprs all return -1.
    """
    try:
        return expr._e_serno # what if expr is a class? is this 0 for all of those?? yes for now. ###k
    except:
        # for now, this case happens a lot, since ExprsMeta calls us on non-expr vals such as compute method functions,
        # and even sometimes on ordinary Python constants.
        assert not is_Expr(expr)
        return -1
    pass

# == predicates

def is_Expr(expr):
    """
    is expr an Expr -- meaning, a subclass or instance of class Expr?
    (Can be true even if it's also considered an Instance.)
    """
    return hasattr(expr, '_e_serno')

def is_expr_Instance(expr): ##e or just is_Instance?? or is_Expr_Instance?
    """
    #doc
    """
    return is_Expr(expr) and expr_is_Instance(expr)

def is_expr_Instance_or_None(expr): #070326, common enough to have its own predicate
    return expr is None or is_expr_Instance(expr)

def is_pure_expr(expr): ##e why not is_pure_Expr? is lowercase expr a generic term of some sort? [070207 terminology Q]
    """
    is expr an Expr (py class or py instance), but not an Instance?
    """
    return is_Expr(expr) and not expr_is_Instance(expr)

def expr_is_Instance(expr):
    """
    is an Expr an Instance?
    """
    res = expr._e_is_instance
    assert res is False or res is True ###e hmm, might fail for classes, need to fix
    return res

def is_Expr_pyinstance(expr): ##e make sure we check this before calling _e_eval / _e_compute_method / _e_make_in on an expr
    """
    Is expr an Expr, and also a python instance (not an Expr subclass)?
    (This is necessary to be sure you can safely call Expr methods on it.)
    (Note: If so, it might or might not be an Instance.)
    [Use this instead of isinstance(Expr) in case Expr module was reloaded.]
    """
    return is_Expr(expr) and is_Expr(expr.__class__)

def is_Expr_pyclass(expr):
    """
    Is expr an Expr and a python class (i.e. is it a subclass of Expr)?
    [This is easier to use than issubclass, since that has an exception on non-classes.]
    """
    return is_Expr(expr) and not is_Expr(expr.__class__)

def is_constant_expr(expr): # written for use in def If, not reviewed for more general use
    """
    #doc;
    WARNING: not reviewed for use after some code gets reloaded during debugging
    [but, it seems like it should be ok, since constant_Expr is defined in this module, and this module is not auto-reloaded.]
    """
    assert is_pure_expr(expr)
    return isinstance(expr, constant_Expr) ###k probably too limited; #e might need to delve in looking for sources of non-constancy;
        #e might prefer to return the simpified const value, or a non-constant indicator (eg an equiv constant_Expr or None)

def expr_constant_value(expr): # written for use in def If, not reviewed for more general use
    """
    #doc;
    WARNING: not fully reviewed for use after some code gets reloaded during debugging [see is_constant_expr doc for details].
    """
    if is_constant_expr(expr):
        return True, expr._e_constant_value #k will be wrong once is_constant_expr is improved -- a single func will need to do both things
    else:
        return False, "arb value"
    pass

def is_constant_for_instantiation(expr): #070131, moved here 070321 from instance_helpers.py
    """
    Is expr (which might be an arbitrary python object) a constant for instantiation?
    (If true, it's also a constant for eval, but not necessarily vice versa.)
    """
    #e refile? should be compatible with _e_make_in methods in kinds of exprs it's true for
    # anything except a pure expr is a constant, and so is an Expr subclass
    if not (is_pure_expr(expr) and is_Expr_pyinstance(expr)):
        return True
    # cover a constant Symbol too, e.g. Automatic
    #e (merge _e_sym_constant with _e_instance? see comment in Symbol._e_make_in for discussion)
    if getattr(expr, '_e_sym_constant', False):
        return True
    return False

# ==

class Expr(object): # notable subclasses: SymbolicExpr (OpExpr or Symbol), InstanceOrExpr
    """
    abstract class for symbolic expressions that python parser can build for us,
    from Symbols and operations including x.a and x(a);
    also used as superclass for WidgetExpr helper classes,
    though those don't yet usually require the operation-building facility,
    and I'm not positive that kluge can last forever.
       All Exprs have in common an ability to:
    - replace lexical variables in themselves with other exprs,
    in some cases retaining their link to the more general unreplaced form (so some memo data can be shared through it),
    tracking usage of lexical replacements so a caller can know whether or not the result is specific to a replacement
    or can be shared among all replaced versions of an unreplaced form;
    ###@@@ details?
    - be customized by being "called" on new arg/option lists; ###@@@
    - and (after enough replacement to be fully defined, and after being "placed" in a specific mutable environment)
    to evaluate themselves as formulas, in the current state of their environment,
    tracking usage of env attrs so an external system can know when the return value becomes invalid;
    -
    """
    ##e for debug it would be useful to record line/file of expr construction, and then for any instance or expr
    # printed in an error msg or traceback, print the chain of these (as it gets customized, gets args, gets instantiated) --
    # sort of like a stacktrace of where it was made. Not hard (see compact_stack for how). Enable using global flag. [070131]

    # default/initial values of instance variables
    _e_is_symbolic = False #061113
    _e_args = () # this is a tuple of the expr's args (processed by canon_expr), whenever those args are always all exprs.
    _e_kws = {} # this is a dict of the expr's kw args (processed by canon_expr), whenever all kwargs are exprs.
        # note: all expr subclasses which use this should reassign to it, so this shared version remains empty.
        # note: all Expr subclasses should store either all or none of their necessary data for copy in _e_args and _e_kws,
        # or they should override methods including copy(?) and replace(?) which make that assumption. ##k [061103]
    _e_is_instance = False # override in certain subclasses or instances ###IMPLEM
    _e_serno = 0 ###k guess; since Expr subclasses count as exprs, they all have a serno of 0 (I hope this is ok)
    _e_has_args = False # subclass __init__ or other methods must set this True when it's correct... ###nim, not sure well-defined
        # (though it might be definable as whether any __init__ or __call__ had nonempty args or empty kws)
        # (but bare symbols don't need args so they should have this True as well, similar for OpExpr -- all NIM)
        # see also InstanceOrExpr .has_args -- if this survives, that should be renamed so it's the same thing [done now, 061102]
        # (the original use for this, needs_wrap_by_ExprsMeta, doesn't need it -- the check for _self is enough) [061027]
    def __init__(self, *args, **kws):
        assert 0, "subclass %r of Expr must implement __init__" % self.__class__.__name__
    def __eq__(self, other):#070122
        """
        Default implem for many but not all subclasses of Expr.
        Note: we don't require _e_sernos to be equal!
        """
        # this and/or its overridings assume: same_vals works on Exprs [not tested or reviewed ###DOIT],
        # and widget_env is also given a correct __eq__ [###NIM, means lexenv_Exprs will rarely compare equal when they should].
        if self is other:
            return True
        if (not hasattr(other, '__class__')):
            return False # without this test, epydoc fails with: AttributeError: class SyntaxError has no attribute '__class__'
        if self.__class__.__name__ != other.__class__.__name__:
            return False #e this might change someday when comparing proxies -- see comment below
        if self.__class__ is not other.__class__:
            print "warning: exprs passed to __eq__, sernos %r and %r, have different classes with same name %s -- reload issue?" % \
                  (self._e_serno, other._e_serno, self.__class__.__name__)
            return False # this is safest (e.g. it lets us assume other is an Expr in the remaining code)
        if self._e_is_instance or other._e_is_instance: # this is not safe to ask unless we know other is an Expr
            return False # Instances are only equal if identical, for now (and an Instance can't equal a non-Instance);
                #e later two Instances might be equal if they know they're proxies for the same something else (not sure)
        # now we're comparing two pure exprs of the same class
        #e optim: if both are interned, return False; otherwise intern them and recompare
        # In case of Numeric array args, should we only use __ne__, use same_vals, or trust what we compare here to come out of
        # canon_expr? I think I'll trust canon_expr but use != anyway (redundant), but in constant_Expr use same_vals.
        if self._e_has_args != other._e_has_args:
            return False
        if self._e_args != other._e_args:
            return False
        if self._e_kws != other._e_kws:
            return False
        return True
    def __ne__(self, other):
        return not self.__eq__(other)
    def _e_init_e_serno(self): # renamed from _init_e_serno_, 061205
        """
        [private -- all subclasses must call this; the error of not doing so is not directly detected --
         but if they call canon_expr on their args, they should call this AFTER that, so self._e_serno
         will be higher than that of self's args! This may not be required for ExprsMeta sorting to work,
         but we want it to be true anyway, and I'm not 100% sure it's not required. (Tentative proof that it's not required:
         if you ignore serno of whatever canon_expr makes, prob only constant_Expr, then whole serno > part serno anyway.)]
        Assign a unique serial number, in order of construction of any Expr.
        FYI: This is used to sort exprs in ExprsMeta, and it's essential that the order
        matches that of the Expr constructors in the source code of the classes created by ExprsMeta
        (for reasons explained therein, near its expr_serno calls).
        """
        #e Probably this should be called by __init__ and our subclasses should call that,
        # but the above assert is useful in some form.
        # Note that this needn't be called by __call__ in InstanceOrExpr,
        # but only because that ends up calling __init__ on the new expr anyway.
        global _next_e_serno
        self._e_serno = _next_e_serno
        _next_e_serno += 1
        if self._e_serno == _debug_e_serno: #k hope not too early for %r to work
            print_compact_stack("just made expr %d, %r, at: " % (_debug_e_serno, self))
        return
    def _e_dir_added(self): # 061205
        """
        For a symbolic expr only, return the names in dir(self) which were stored by external assignments.
        """
        assert self._e_is_symbolic
        assert not self._e_is_instance #k probably implied by _e_is_symbolic
        return filter( lambda name: not (name.startswith('_e_') or name.startswith('__')) , dir(self) )
    def __call__(self, *args, **kws):
        assert 0, "subclass %r of Expr must implement __call__" % self.__class__.__name__
    # note: for __getattr__, see also the subclasses; for __getitem__ see below

    def __get__(self, obj, cls):
        """
        The presence of this method makes every Expr a Python descriptor. This is so an expr which is a formula in _self
        can be assigned to cls._C_attr for some attr (assuming cls inherits from InvalidatableAttrsMixin),
        and will be used as a "compute method" to evaluate obj.attr. The default implementation creates some sort of Lval object
        with its own inval flag and subscriptions, but sharing the _self-formula, which recomputes by evaluating the formula
        with _self representing obj.
        """
        # more on the implem:
        # It stores this Lval object in obj.__dict__[attr], finding attr by scanning cls.__dict__
        # the first time. (If it finds itself at more than one attr, this needs to work! Is that possible? Yes -- replace each
        # ref to the formula by a copy which knows attr... but maybe that has to be done when class is created?
        # Easiest way is first-use-of-class-detection in the default implem. (Metaclass is harder, for a mixin being who needs it.)
        #  Ah, easier way: just store descriptors on the real attrs that know what to do... as we're in the middle of doing
        # in the code that runs when we didn't, namely _C_rule or _CV_rule. ###)
        if obj is None:
            return self
        #e following error message text needs clarification -- when it comes out of the blue it's hard to understand
        print "__get__ is nim in the Expr", self, ", which is assigned to some attr in", obj ####@@@@ NIM; see above for how [061023 or 24]
        print "this formula needed wrapping by ExprsMeta to become a compute rule...:", self ####@@@@
        return
    def _e_compute_method(self, instance, index, _lvalue_flag = False):
        """
        Return a compute method version of this formula, which will use instance as the value of _self,
        at the given index relative to instance. [index is a required arg as of 070120.]

        Example index [#k guess 061110]: the attrname where self was found in instance (as an attrvalue),
        or if self was found inside some attrval (but not equal to the whole),
        a tuple containing the attrname and something encoding where self occurred in the attrval.
        Update 070120: that "found inside some attrval" part is now handled by lexenv_ipath_Expr,
        and index can be modified as suggested by kluge070119 (experimental, not yet debugged).
        """
        #####@@@@@ WRONG API in a few ways: name, scope of behavior, need for env in _e_eval, lack of replacement due to env w/in self.
        ##return lambda self = self: self._e_eval( _self = instance) #e assert no args received by this lambda?
        # TypeError: _e_eval() got an unexpected keyword argument '_self'
        ####@@@@ 061026 have to decide: are OpExprs mixed with ordinary exprs? even instances? do they need env, or just _self?
        # what about ipath? if embedded instances, does that force whole thing to be instantiated? (or no need?)
        # wait, embedded instances could not even be produced w/o whole thing instantiating... so i mean,
        # embedded things that *need to* instantiate. I guess we need to mark exprs re that...
        # (this might prevent need for ipath here, if pure opexprs can't need that path)
        # if so, who scans the expr to see if it's pure (no need for ipath or full env)? does expr track this as we build it?

        # try 2 061027 late: revised 070117
        assert instance._e_is_instance, "compute method for %r asked for on non-Instance %r (index %r, lvalflag %r)" % \
               (self, instance, index, _lvalue_flag) # happens if a kid is non-instantiated(?) # revised 070117

        env, ipath = instance._i_env_ipath_for_formula_at_index( index) # split out of here into IorE, 070117
            # does _self = instance binding [tho that might change -- 070120]

        if not _lvalue_flag:
            # usual case
            return lambda self=self, env=env, ipath=ipath: self._e_eval( env, ipath ) #e assert no args received by this lambda?
        else:
            # lvalue case, added 061204, experimental -- unclear if returned object is ever non-flyweight or has anything but .set_to
            # [note, this presumably never happens when EVAL_REFORM, at least as of late 070119]
            return lambda self=self, env=env, ipath=ipath: self._e_eval_lval( env, ipath )
        pass
    def __repr__(self): # class Expr
        """
        [often overridden by subclasses;
         __str__ can depend on __repr__ but not vice versa(?)
         (as python itself does by default(??))]
        """
        ## return str(self) #k can this cause infrecur?? yes, at least for testexpr_1 (a Rect_old) on 061016
        ## return "<%s at %#x: str = %r>" % (self.__class__.__name__, id(self), self.__str__())
        return "<%s#%d%s>" % (self.__class__.__name__, self._e_serno, self._e_repr_info())
    def _e_repr_info(self):#061114
        """
        [private helper for __repr__]
        """
        if self._e_has_args:
            if self._e_is_instance:
                return '(i)'
            else:
                return '(a)'
        else:
            if self._e_is_instance:
                return '(i w/o a)' # an error, i think, at least for now
            else:
                return ''
        pass
    # ==
    def __rmul__( self, lhs ):
        """operator b * a"""
        return mul_Expr(lhs, self)
    def __mul__( self, rhs ):
        """operator a * b"""
        return mul_Expr(self, rhs)
    def __rdiv__( self, lhs ):
        """operator b / a"""
        return div_Expr(lhs, self)
    def __div__( self, rhs ):
        """operator a / b"""
        return div_Expr(self, rhs)
    def __radd__( self, lhs ):
        """operator b + a"""
        return add_Expr(lhs, self)
    def __add__( self, rhs ):
        """operator a + b"""
        return add_Expr(self, rhs)
    def __rsub__( self, lhs ):
        """operator b - a"""
        return sub_Expr(lhs, self)
    def __sub__( self, rhs ):
        """operator a - b"""
        return sub_Expr(self, rhs)
    def __neg__( self):
        """operator -a"""
        return neg_Expr(self)
    def __pos__( self):
        """operator +a"""
        return pos_Expr(self)

    #e __mod__? (only ok if not used for print formatting -- otherwise we'd break debug prints like "%r" % expr)
    #e __len__? (might be ok, except lack of it catches bugs every so often, so I guess it's not a good idea)
    #e various type coercers...
    # but some special methodnames are impossible to support safely, like __str__, __eq__, etc...
    #e unless we have a special expr wrapper to give it the power to support all those too, but only if used right away. [061113]

    def __getitem__( self, index): #k not reviewed for slices, unlikely they'll work fully
        """ operator a[b] """
        #e will Instances extend this to return their kids??
        return getitem_Expr(self, index)

    # == not sure where these end up
    def __float__( self):
        """ operator float(a) """
        print_compact_stack( "kluge: float(expr) -> 17.0: " )####@@@@ need float_Expr
        return 17.0
    def _e_replace_using_subexpr_filter(self, func): #e rename, since more like map than filter; subexpr_mapper??
# zapped 061114 since common and so far always ok:
##        if not isinstance(self, (OpExpr, constant_Expr)):#k syntax
##            printfyi("_e_replace_using_subexpr_filter called on pyinstance of class %s" % self.__class__.__name__)
##                 ####k ever on an InstanceOrExpr?? might be wrong then, just as _e_eval should not go inside -- not sure!
##                 # more likely, it needs to go in but in a lexcontext-modified way! [061105 guess] ###@@@
        args = self._e_args
        kws = self._e_kws
        if not args and not kws:
            return self # optim
        modargs = tuple(map(func, args))
        modkws = map_dictvals(func, kws)
        if modargs == args and modkws == kws:
            # Note: requires fast == on Expr -- currently we let Python use 'is' by default. [#k in py doc, verify that's what happens]
            # Note: '==' (unlike other ops) is not meant as a formula.
            # (Could it be a formula, but with a boolean value too, stored independently??)
            #
            # Note: this is not affected by the Numeric Python design flaw (i.e. bug) about what '==' means,
            # since any Numeric arrays in args or kws have been wrapped by constant_Expr.
            # [070321, educated guess, not absolutely verified ####k]
            return self # helps prevent memory leaks (by avoiding needless reconstruction of equal exprs); might help serno too??
        printnim("replace would be wrong for an expr with subexprs but also other data -- do we have any such? ##k")##k
            #k (wouldn't it also be wrong for expr w/ other data, even if no args/kws??)
        return self.__class__(*modargs, **modkws)
    def _e_free_in(self, sym): #e name is confusing, sounds like "free of" which is the opposite -- rename to "contains_free"??
        """
        Return True if self contains sym (Symbol or its name) as a free variable, in some arg or option value.
        [some subclasses override this]
        """
        try:
            _e_args = self._e_args
            #k not sure this is defined in all exprs! indeed, not in a Widget2D python instance... ####@@@@
        except AttributeError:
            #####@@@@ warning: following is slow, even when it doesn't print -- NEEDS OPTIM ####@@@@
            printonce("debug note: _e_free_in is False since no _e_args attr in %r" % self) # print once per self
            return False ###k guess -- correct? #####@@@@@
        for arg in _e_args:
            if arg._e_free_in(sym):
                return True
        printnim("_e_free_in is nim for option vals")###@@@ btw 061114 do we still use _e_free_in at all? see if this gets printed.
        return False
    def _e_eval_to_expr(self, env, ipath, expr):#070117, revised 070118 to save ipath
        """
        #doc
        """
        assert EVAL_REFORM # otherwise exprs don't eval to self except some Symbols, and I guess those don't call this tho i forget...#k
        return lexenv_ipath_Expr(env, ipath, expr) # the full ipath might not be needed but might be ok... ###k
    # note: _e_eval is nim in this class -- it must be implemented in subclasses that need it.
    # If you want to add a default errmsg def here, first review whether its presence would affect the expr-building code!
    # [070117 comment]
    def _e_burrow_for_find_or_make(self, env, ipath): #070119 #e might rename find_or_make to instantiate or so
        """
        General case: Return (subexpr, new_env, new_ipath), where subexpr is the outermost subexpr of self
        which has no outermost local ipath or env mods, and those mods are stripped from self to get subexpr,
        and added to env, ipath to make new_env, new_ipath. Instantiating (self, env, ipath) and
        (subexpr, new_env, new_ipath) should get the same result semantically, and the implem enforces this
        by canonicalizing (self, env, ipath) using this method before instantiation. [###NIM]
           Trivial version for most expr classes: just return (self, env, ipath) unchanged.
        Overrides are only needed (so far, AFAIK) by lexenv_Expr and lexenv_ipath_Expr.
        [When IorE subclasses implement instance-sharing a la textureholders or (desired) CLE or other glue code
         (eg type coercion) objects, they too are likely to need a nontrivial implem of this, which filters the ipath
         down to the part that uniquely identifies the shared object. ##e]
        (Expr classes that can't be the result of evaluation (e.g. constant_Expr, If_expr, probably eval_Expr)
        don't need to override this, since exprs should be evalled before being instantiated. ###k)
        """
        # Is the docstring right about this not being needed in If_expr? eval_Expr? constant_Expr?? other internal exprs? ###k
        return (self, env, ipath)
    pass # end of class Expr

def safer_attrpath(obj, *attrs): #e refile, doc, rename
    for attr in attrs:
        try:
            obj = getattr(obj, attr)
        except AttributeError:
            return "<no %r in some %s>" % (attr, obj.__class__.__name__)
        continue
    return obj

class SymbolicExpr(Expr): # Symbol or OpExpr
    _e_is_symbolic = True #061113
    _e_sym_constant = False #070131, can be overridden in subclasses or instances; see class Symbol for doc
    def __call__(self, *args, **kws):
        assert not self._e_is_instance # (should never happen I think)
        return call_Expr(self, *args, **kws)
    def __getattr__(self, attr): # in class SymbolicExpr
        if attr.startswith('__'):
            # be very fast at not finding special python attrs like __repr__
            raise AttributeError, attr
        # the code after this happens when constructing exprs, not when using them,
        # so a bit of slowness should be ok.
        assert not self._e_is_instance # (should never happen I think; if it can be legal, change to raise attrerror)
        if self._e_sym_constant:
            # [this special case might be evidence that _e_sym_constant should imply something like _e_is_instance --
            #  both of them mean "eval to self", "instantiate to self". Maybe they should even be merged...
            #  idea not reviewed. Should check whether other special cases for _e_is_instance apply to _e_sym_constant. ###e 070131]
            raise AttributeError, "no attr %r in %s" % (attr, safe_repr(self))
        if attr.startswith('_i_'):
            assert self._e_is_instance, \
                   "safety rule: automatic formation of getattr_Expr not allowed for attrs starting _i_, as in %r.%s" % \
                   (self, attr)
                #k not positive this is ok, we'll see [061105]
                # 070122 this failed with _app._i_instance(testexpr_19b) (and I added text to the assertion),
                # but that just means _app needs a public instancemaker rather than just that internal one -- now it has .Instance
            # note: self._e_is_instance is defined in all pyinstance exprs, not only InstanceOrExpr.
            assert 0 # not reached
        if attr.startswith('_e_') or (attr.startswith('_') and '__' in attr): # _i_ is handled separately above
            # We won't pretend to find Expr methods/attrs starting _e_ (also used in Instances),
            # or Instance ones starting _i_ -- but do reveal which class or object we didn't find them in.
            ##e ideally we'd reveal something longer than class and shorter than object...
            # 061203: also exclude _attr__xxx since it might be name-mangled. Needed to exclude _ExprsMeta__set_attr.
            # [Not confident this exclusion is always good -- maybe what we really need is a variant of hasattr
            # which turns off or detects and ignores the effect of this __getattr__. ###k]
            raise AttributeError, "no attr %r in %s" % (attr, safe_repr(self))
        return getattr_Expr(self, attr)
    pass

class OpExpr(SymbolicExpr):
    """
    Any expression formed by an operation (treated symbolically) between exprs, or exprs and constants
    """
    _e_debug = False #e move to a superclass? [bruce 070816 new feature]
    def __init__(self, *args, **kws): # arglist would just be "self, *args, doc = None" except that it's invalid syntax
        self._e_args = tuple(map(canon_expr, args)) # tuple is required, so _e_args works directly for a format string of same length
        self._e_init_e_serno() # call this AFTER canon_expr (for sake of _e_serno order)
        doc = kws.pop('doc', None)
        self.__doc__ = doc #070207 added this keyword arg -- supplied (to a StateAttr stub) but not yet used;
            # not sure it belongs in this class rather than the subclass that needed it (State) ##k
        # don't do this: junk = kws.pop('_KLUGE_fakeoption', None)
        debug = kws.pop('_e_debug', False)
        if debug:
            # activate some debug prints for self (only used by some subclasses)
            self._e_debug = True
        assert not kws, "unexpected keyword args for %s: %r" % (self.__class__.__name__, kws.keys())
        self._e_init()
        return
    def _e_init(self):
        assert 0, "subclass of OpExpr must implement _e_init"
    def __repr__(self): # class OpExpr
        return "<%s#%d%s: %r>"% (self.__class__.__name__, self._e_serno, self._e_repr_info(), self._e_args,)
    def _e_argval(self, i, env,ipath): # see also a copy of this in IfExpr
        """
        Under the same assumptions as _e_eval (see its docstring),
        compute and return the current value of an implicit kid-instance made from self._e_args[i], at relative index i,
        doing usage-tracking into caller (i.e. doing no memoization or caching of our own).
        """
        def __debug_frame_repr__(locals):
            """return a string for inclusion in some calls of print_compact_stack"""
            # note: this will always run before res is available
            return "_e_argval(i = %r, ipath = %r), self = %r" % (i,ipath,self)
         ##e consider swapping argorder to 0,ipath,env or (0,ipath),env
        arg = self._e_args[i]
        try:
            res = arg._e_eval(env, (i,ipath))
        except:
            print "following exception concerns arg._e_eval(...) where arg = %r" % (arg,) #070228 (guess: arg is class World itself)
            raise
        return res
    def _e_kwval(self, k, env,ipath):
        """
        Like _e_argval, but return the current value of our implicit-kid-instance of self._e_kws[k], rel index k.
        """
        return self._e_kws[k]._e_eval(env, (k,ipath))
    def _e_eval(self, env, ipath):
        """
        Considering ourself implicitly instantiated by the replacements (especially _self_) in env,
        or more precisely, instantiated as a formula residing in env's _self, after replacement by env's other replacements,
        with that implicit instance using the index-path given as ipath
        (and perhaps finding explicit sub-instances using that ipath, if we ever need those),
        compute and return our current value,
        doing usage-tracking into caller (i.e. doing no memoization or caching of our own).
           Note that an expr's current value might be any Python object;
        if it happens to be an Instance or Expr or special symbol,
        we should not notice that or do any special cases based on that
        (otherwise we'll cause bugs for uses of _e_eval on internal formulas like the ones made by the Arg macro).
           Most subclasses can use this implem, by defining an _e_eval_function which is applied to their arg values.
        If they have other data, or even kws, and/or if they don't want to always evaluate all args (like If or an InstanceOrExpr),
        they should redefine this method. [We're not presently in InstanceOrExpr at all, but that might change,
        though this implem won't work there since those want to never eval their args now. 061105]
        """
        assert env #061110
        assert not self._e_kws #e remove when done with devel -- just checks that certain subclasses overrode us -- or, generalize this
        func = self._e_eval_function
            # Note: these functions would turn into bound methods here,
            # if we didn't wrap them with staticmethod when assigning them.
            # Not doing that caused the "tuple_Expr bug" (see cvs for details).
            # Another solution would have been to grab the funcs only out of
            # the class's __dict__. Using staticmethod seems clearer.
        res = apply(func, [self._e_argval(i,env,ipath) for i in range(len(self._e_args))])
        return res
    def _e_eval_lval(self, env,ipath):
        """
        #doc
        """
        assert env #061110
        assert not self._e_kws #e remove when done with devel -- just checks that certain subclasses overrode us -- or, generalize this
        func = self._e_eval_lval_function
        res = apply(func, [self._e_argval(i,env,ipath) for i in range(len(self._e_args))])
        return res
    pass # end of class OpExpr

class call_Expr(OpExpr): # note: superclass is OpExpr, not SymbolicExpr, even though it can be produced by SymbolicExpr.__call__
    ###BUG: __repr__ doesn't print self._e_kws [noticed 070119]
    def __init__(self, callee, *callargs, **kws):
        # we extend OpExpr.__init__ so we can have kws, and canon them
        self._e_kws = map_dictvals(canon_expr, kws) ###e optim: precede by "kws and"
        OpExpr.__init__(self, callee, *callargs) # call this AFTER you call canon_expr above (for sake of _e_serno order)
    def _e_init(self):
        # Store some args under more convenient names.
        # Note: this does NOT hide them from (nondestructive) _e_replace* methods,
        # since those find the original args, modify them, and construct a new expr from them.
        self._e_callee = self._e_args[0]
        self._e_call_args = self._e_args[1:]
        self._e_call_kws = self._e_kws #e could use cleanup below to not need this alias
        #e might be useful to record line number, at least for some heads like NamedLambda; see Symbol compact_stack call for how
    def __str__(self):
        if self._e_call_kws:
            return "%s(*%r, **%r)" % (self._e_callee, self._e_call_args, self._e_call_kws) #e need parens?
        elif self._e_call_args:
            return "%s%r" % (self._e_callee, self._e_call_args)
        else:
            return "%s%r" % (self._e_callee, self._e_call_args) # works the same i hope
    def _e_eval(self, env, ipath):
        """
        [the only reason the super method is not good enough is that we have _e_kws too, I think;
         maybe also the distinction of that to self._e_call_kws, but I doubt that distinction is needed -- 061105]
        """
        assert env #061110
        # 061102: we do this (_e_eval in general)
        # by imagining we've done the replacements in env (e.g. for _self) to get an instance of the expr,
        # and then using ordinary eval rules on that, which include forwarding to _value for some Instances,
        # but typically result is an Instance or a python data object.
        # So, just eval it as a call, I think.
        argvals = [self._e_argval(i,env,ipath) for i in range(len(self._e_args))] # includes value of callee as argvals[0]
        # the following assumes _e_call_kws is a subset of (or the same as) _e_kws (with its items using the same keys).
        kwvals = map_dictitems( lambda (k,v): (k,self._e_kwval(k,env,ipath)), self._e_call_kws )
        printnim('###e optim: precede by "self._e_call_kws and"') # in 2 places
        return argvals[0] ( *argvals[1:], **kwvals )
    pass

class LvalueFromObjAndAttr(object): #061204 for _e_eval_lval and LvalueArg, likely to be revised #e refile?
    #e later note 070316: we use this in toplevel expr macros to turn obj.attr into a stateref,
    # since getattr_Expr can't do that (it only makes a syntactic lval).
    # Should we rename this to e.g. getattr_StateRef, and put it into basic? (It's already in basic, since Exprs.* is.)
    # Maybe, but ONLY IF WE MAKE IT AN EXPR -- as it is, you have to use call_Expr with it.
    ##e make a variant for getitem_Expr?
    def __init__(self, obj, attr):
        self.obj = obj
        self.attr = attr
    def set_to(self, val):
        ###e probably we should rename set_to -> set_value, and define get_value and value -- see StateRefInterface [070312]
        try:
            setattr( self.obj, self.attr, val)
        except:
            print "following exception in setattr( self.obj, self.attr, val) concerns self = %r" % (self,)
            raise
        pass
    # 070312 conform to StateRefInterface
    set_value = set_to
    def get_value(self):
        return getattr(self.obj, self.attr)
    value = property( get_value, set_value)
    def __repr__(self):
        return "<%s at %#x for %r.%r>" % (self.__class__.__name__, id(self), self.obj, self.attr)
    #e some sort of .get function, .value attr (can be set or get), subscribe func, etc
    pass

class getattr_Expr(OpExpr):
    def __call__(self, *args, **kws):
        msg = "error: getattr exprs are not callable: " \
              "explicit call_Expr needed, instead of direct call " \
              "of %r with:" % self, args, kws #bruce 080528 revised msg
        print msg
        assert 0, msg
    def _e_init(self):
        assert len(self._e_args) in (2,3) #e kind of useless and slow #e should also check types? #070203 permit 3-arg form
        attr = self._e_args[1]
        assert attr #e and assert that it's a python identifier string? Note, it's actually a constant_Expr containing a string!
            # And in theory it's allowed to be some other expr which evals to a string,
            # though I don't know if we ever call it that way
            # (and we might want to represent or print it more compactly when we don't).
    def __str__(self):
        if len(self._e_args) == 2:
            return "%s.%s" % self._e_args #e need parens? need quoting of 2nd arg? Need to not say '.' if 2nd arg not a py-ident string?
        else:
            return "getattr_Expr(%s, %s, %s)" % self._e_args
    _e_eval_function = getattr # this doesn't need staticmethod, maybe since <built-in function getattr> has different type than lambda
    ## _e_eval_lval_setto_function = setattr
    _e_eval_lval_function = staticmethod(LvalueFromObjAndAttr) #061204 #k not sure if staticmethod is required; at least it works ###UNREVIEWED for 3 args
    pass

class getitem_Expr(OpExpr): #061110
    def _e_init(self):
        assert len(self._e_args) == 2 #e kind of useless and slow??
        # note, _e_args[1] is often constant_Expr(<an int as list-index> or <an attrname as dict key>), but could be anything
    def __str__(self):
        return "%s[%s]" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x,y:x[y] )
    #e _e_eval_lval_function too, variant of LvalueFromObjAndAttr?
    pass

class mul_Expr(OpExpr):
    def _e_init(self):
        assert len(self._e_args) == 2
    def __str__(self):
        return "%s * %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x,y:x*y ) # does this have a builtin name? see operators module ###k
    pass

class div_Expr(OpExpr):
    def _e_init(self):
        assert len(self._e_args) == 2
    def __str__(self):
        return "%s / %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x,y:x/y )
    pass

class add_Expr(OpExpr):
    def _e_init(self):
        assert len(self._e_args) == 2
    def __str__(self):
        return "%s + %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x,y:x+y )
    ##e refile this note (proposed): [i, ipath] is an inlined sub_index(i,ipath); [] leaves room for intern = append
    pass

class sub_Expr(OpExpr):
    def _e_init(self):
        assert len(self._e_args) == 2
    def __str__(self):
        return "%s - %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x,y:x-y )
    pass

class neg_Expr(OpExpr):
    def _e_init(self):
        assert len(self._e_args) == 1
    def __str__(self):
        return "- %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x:-x )
    pass

class pos_Expr(OpExpr):#061211
    def _e_init(self):
        assert len(self._e_args) == 1
    def __str__(self):
        return "+ %s" % self._e_args #e need parens?
    _e_eval_function = staticmethod( lambda x:+x )
    pass

class list_Expr(OpExpr): #k not well reviewed, re how it should be used, esp. in 0-arg case
    #aka ListExpr, but we want it not uppercase by convention for most OpExprs
    def _e_init(self):
        pass
    def __str__(self):
        return "%s" % (list(self._e_args),) #e need parens?
    _e_eval_function = staticmethod( lambda *args:list(args) )
        ####e consider making this a tuple_Expr synonym -- see ArgList comments [070321]
    pass

def printfunc(*args, **kws): #e refile, maybe rename dprint; compare to same-named *cannib*.py func
    prefix = kws.pop('prefix', '')
    assert not kws
    print "printfunc %s: %r" % (prefix, args)
    return args[0]

class tuple_Expr(OpExpr): #k not well reviewed, re how it should be used, esp. in 0-arg case
    def _e_init(self):
        pass
    def __str__(self):
        return "%s" % (tuple(self._e_args),) #e need parens?
    def _e_eval_function(self, *argvals):
        # only become a tuple if we contain nothing to instantiate -- otherwise a tuple_Expr -- needed for ArgList [070321]
        for val in argvals:
            if is_pure_expr(val): #k not sure this condition is exactly right
                if self._e_args == argvals:
                    return self # optimization
                return tuple_Expr(*argvals)
            continue
        return argvals # a tuple, not a tuple_Expr
    def _e_make_in(self, env, ipath): # 070321 needed for ArgList
        # we don't need to eval each arg expr, since we ourselves were just evalled (and are the result of that)
        # so all our args are evalled. But, not all evalled things have _e_make_in! Also, they went through canon_expr after eval.
        # Either we need to check both for constant_Expr (or anything else canon_expr can make ###k), and check
        # is_constant_for_instantiation like _i_instance does, or we need to actually call _i_instance,
        # depending, I think, on how much we want to cache these instances. For now I'll do what's easiest
        # (is_constant_for_instantiation, no caching) and review it later. WARNING: things like SimpleColumn
        # which declared each arg separately used to be able to cache them individually -- so THIS IS ######WRONG.
        # It'll work, I think, but be a slowdown.
        mades = [self._e_make_argval(argval, env, i, ipath) for (i,argval) in zip(range(len(self._e_args)), self._e_args)]
        return tuple(mades)
    def _e_make_argval(self, argval, env, i, ipath):
        """
        [private helper]
        """
        if is_constant_for_instantiation(argval):
            # print "fyi: tuple_Expr is_constant_for_instantiation true for %r" % (argval,)
            # this happens when an Instance is passed as an ArgList element, e.g. <PM_from_groups#40798(i)> in a SimpleColumn;
            # it's legit, so remove the print. [070322]
            return argval
        constflag, constval = expr_constant_value(argval)
        if constflag:
            # argval is a constant_Expr -- this happens here (but not in _i_instance) due to canon_expr.
            # btw, don't put _e_make_in on constant_Expr, i think - might hide bugs. (A correct def of it is there but cmted out.)
            return constval
        return argval._e_make_in(env, (i, ipath)) ###WRONG as explained in comment above.
    pass

# same as in basic.py:
from Numeric import dot
from geometry.VQT import V, norm, vlen

class V_expr(OpExpr):
    """
    Make an expr for a Numeric array of floats. Called like VQT.py's V macro.
    """
    # Note: the name contains 'expr', not 'Expr', since it's more public than the
    # typical class named op_Expr (official reason) and since it looks better in
    # contrast with V (real reason). Note that the real reason, but not the official one,
    # explains why we later used 'E' in format_Expr.]
    def _e_init(self):
        pass
    def __str__(self):
        return "V_expr%s" % (tuple(self._e_args),) #e need parens?
    _e_eval_function = staticmethod( lambda *args: V(*args) ) #e could inline as optim
    pass

# ==

# these function -> OpExpr macros are quick hacks, fine except for their printform and maybe their efficiency.

##e maybe rewrite them like this: norm_Expr = func_Expr(norm)

def norm_Expr(*args):
    return call_Expr( norm, *args)

def vlen_Expr(*args):
    return call_Expr( vlen, *args)

def dot_Expr(*args):
    return call_Expr( dot, *args)

def max_Expr(*args):
    return call_Expr( max, *args)

def min_Expr(*args):
    return call_Expr( min, *args)

def int_Expr(*args):
    return call_Expr( int, *args)

def not_Expr(arg): # maybe this is an operator so we can just make an OpExpr in usual way??
    ###e try it - try using not instead, in the call of this, to see if __not__ is the right name
    return call_Expr(lambda val: not val, arg)

def eq_Expr(arg1, arg2):
    return call_Expr(lambda a1,a2: a1 == a2, arg1, arg2)

def ne_Expr(arg1, arg2):
    return call_Expr(lambda a1,a2: a1 != a2, arg1, arg2)

def mod_Expr(arg1, arg2):
    return call_Expr( _eval_mod_Expr, arg1, arg2)

def _eval_mod_Expr(a1, a2):#070121
    """
    private helper
    """
    assert not (type(a1) == type('')), \
           "mod_Expr arg1 %r is a string, would do string formatting instead of mod by %r" % (a1, a2)
    return a1 % a2

# ==

class and_Expr(OpExpr): #061128
    """
    Evaluate only enough args (out of 2 or more)
    to return the last one if they're all true,
    otherwise the first false one.
    """
    def _e_init(self):
        assert len(self._e_args) >= 2
        assert not self._e_kws #k needed?
    def __str__(self):
        return "and_Expr%r" % self._e_args
    def _e_eval(self, env, ipath):
        assert env
        for i in range(len(self._e_args)):
            res = self._e_argval(i,env,ipath)
            if not res:
                return res # the first false res
            continue
        return res # the last res, if they're all true
    # note: operator.__and__ requires exactly two args, and couldn't help anyway since we don't always want to eval arg2
    pass

class or_Expr(OpExpr): #061128 untested
    """
    Evaluate only enough args (out of 2 or more)
    to return the last one if they're all false,
    otherwise the first true one.
    """
    def _e_init(self):
        assert len(self._e_args) >= 2
        assert not self._e_kws #k needed?
    def __str__(self):
        return "or_Expr%r" % self._e_args
    def _e_eval(self, env, ipath):
        assert env
        for i in range(len(self._e_args)):
            res = self._e_argval(i,env,ipath)
            if res:
                return res # the first true res
            continue
        return res # the last res, if they're all false
    pass

# note: see also If_expr.py

# ==

def assert_0_func(msg): #e refile #e rename
    """
    Raise an AssertionError with msg, but be a function, so we're usable in lambdas.
    Typical usage: cond and result or assert_0_func("error-description" % args).
    """
    assert 0, msg

class format_Expr(OpExpr): #061113, seems to work
    #k (tho no test yet proved it defers eval til when it needs to -- hmm, same for *all* OpExprs, until we implem statemods?
    #   no -- once something can access redraw_counter, that should provide a good enough test, for any OpExpr we make depend on that.)
    """
    Make an expr for producing the results of <format_string> % <*args>.
    (See also mod_Expr [nim ##e], for exprs based on numeric uses of the % operator. Maybe they can be expressed using % directly?)
    Note, unlike __mod__ (sp??), this is varargs, not two args.
    It would be nice to be able to say the latter directly,
    but it's hard to do without dangerously interfering with debug prints of exprs in the code
    (though it might be possible someday -- see code comments for details).
       We might rename this to sprintf or format (not printf, since that implies a side effect on stdout).
    """
    def _e_init(self):
        assert len(self._e_args) >= 2 #e later, change to >=1, since just 1 arg is legal -- I guess.
            # For now, >= 2 is usefully stricter for debugging.
            # In fact, maybe we'll keep it -- it catches use of '%' rather than ',', like in format_Expr("/tmp/%s.jpg" % testname)
        #e could assert arg0 is a string, but (1) not required until runtime, (2) hard to say anyway.
        pass
    def __str__(self):
        return "format_Expr%s" % (tuple(self._e_args),) #e need parens?
    _e_eval_function = staticmethod( lambda arg1, *args:
                                     ((type(arg1) is str) and (arg1 % args))
                                     or assert_0_func("format_Expr got non-string format %r" % arg1)
                                ) #e accept unicode arg1 too; python2.2 has an official way to express that (using the name string??)
    pass # format_Expr

# ==

class internal_Expr(Expr):
    """
    Abstract class for various kinds of low-level exprs
    for internal use that have no visible subexprs.
    """
    def __init__(self, *args, **kws):
        """
        store args & kws but don't canon_expr them -- assume they are not necessarily exprs
        (and even if they are, that they should be treated inertly)
        """
        self.args = args # not sure if the non-_e_ name is ok... if not, try _e_data_args or so? ###k
        self.kws = kws
        self._internal_Expr_init() # subclasses should override this method to do their init
        self._e_init_e_serno()
        return
    def _internal_Expr_init(self):
        assert 0, "subclass must implem"
    def __eq__(self, other):
        """
        [overrides Expr version; WARNING: must be overridden by any internal_Expr subclasses that use self.kws]
        """
        if not Expr.__eq__(self, other):
            return False
        a1 = self.args
        a2 = other.args # must be tuples
        if a1 and a2:
            if not same_vals(a1,a2):
                ####k assume same_vals works properly for Exprs [perhaps never verified -- might give false negatives];
                # we need to use it instead of just == or != due to Numeric arrays in lists or tuples
                return False
        else:
            if a1 != a2: # 'or' might be faster, and is correct, but that's less clear, so nevermind -- someday this will be in C anyway
                return False
        # the following is not yet needed by any internal_Expr subclasses so far -- so leave it out for now, but keep the code
        ##k1 = self.kws
        ##k2 = other.kws
        ##if k1 and k2:
        ##    if not same_vals(k1,k2):
        ##        return False
        ##else:
        ##    if k1 != k2:
        ##        return False
        return True
    pass

class constant_Expr(internal_Expr):
    #### NOT YET REVIEWED FOR EVAL_REFORM 070117 [should it ever wrap the result using _e_eval_to_expr -- maybe in a variant class?]
    ###k super may not be quite right -- we want some things in it, like isinstance Expr, but not the __add__ defs [not sure, actually]
    def _internal_Expr_init(self):
        (self._e_constant_value,) = self.args
    def __repr__(self): # class constant_Expr
        return "<%s#%d%s: %r>"% (self.__class__.__name__, self._e_serno, self._e_repr_info(), self._e_constant_value,)
    def __str__(self):
        return "%r" % (self._e_constant_value,) #e need parens?
            #k 061105 changed %s to %r w/o reviewing calls (guess: only affects debugging)
    def _e_eval(self, env, ipath):
        assert env #061110
        ## env._self # AttributeError if it doesn't have this [###k uses kluge in widget_env]
        # that failed (with the misleading AttrError from None due to Delegator),
        # but it's legit to fail now, since the constant can easily be in a lexenv with no binding for _self.
        return self._e_constant_value
##    def _e_make_in(self, env, ipath): ###e equiv to _e_eval? see comment in _CV__i_instance_CVdict [061105]
##        "Instantiate self in env, at the given index-path."
##        #e also a method of InstanceOrExpr, tho not yet of any common superclass --
##        # I guess we'll add to OpExpr and maybe more -- maybe Expr, but not sure needed in all exprs
##        return self._e_constant_value # thought to be completely correct, 061105 [and still, 061110, but zapping since redundant]
    pass

class hold_Expr(constant_Expr):
    #e might be renamed to something like no_eval, or we might even revise call_Expr to not always eval its args... not sure
    """
    Like constant_Expr, but (1) value has to be an expr, (2) replacements occur in value.
    Used internally to prevent eval of args to call_Expr.
    """
    def _e_replace_using_subexpr_filter(self, func): #e rename, since more like map than filter; subexpr_mapper??
        arg = self._e_constant_value #e another implem, maybe cleaner: store this data in _e_args; possible problems not reviewed
        modarg = func(arg)
        if modarg == arg:
            return self
        return self.__class__(modarg)
    pass

class eval_to_lval_Expr(internal_Expr):#070119, needed only when EVAL_REFORM
    """
    wrap a subexpr with me in order to cause _e_eval of me to only call _e_eval_lval on the subexpr
    """
    def _internal_Expr_init(self):
        ## (self._e_the_expr,) = self.args
        self._e_args = self.args # so replace sees the args
        assert len(self.args) == 1
    def _e_eval(self, env, ipath):
        assert env #061110
        the_expr = self._e_args[0] ## self._e_the_expr
        res = the_expr._e_eval_lval(env, ipath)
        ##e needs better __repr__ for its prints of self to be useful
        # print "fyi (routine): %r l-evals it to %r" % (self, res) # remove when works
        return res
    def _e_eval_lval(self, env, ipath):
        print "fyi or bug? %r didn't expect to have its _e_eval_lval called; just passing it through" % (self,)
            ## if that happens much and is not an error, remove the print once i understand why -- probably harmless
        return self._e_eval(env, ipath)
    pass

class property_Expr(internal_Expr): ##k guess, 061119, for attr 'open' in ToggleShow.py;
    # maybe just a kluge, since mixing properties with exprs is probably a temp workaround, tho in theory it might make sense...
    # if it can be rationalized then it's good to leave it in, maybe even encourage it. See also class State.
    """
    #doc;
    canon_expr will turn a python property into this
    (or maybe any misc data descriptor??)
    """
    def _internal_Expr_init(self):
        (self._e_property,) = self.args
    def __repr__(self):
        return "<%s#%d%s: %r>"% (self.__class__.__name__, self._e_serno, self._e_repr_info(), self._e_property,)
    def _e_eval(self, env, ipath):
        assert env #061110
        instance = env._self # AttributeError if it doesn't have this [###k uses kluge in widget_env]
            # if this ever fails, see comments about this construction in constant_Expr and lexenv_Expr -- it might be ok. [070118]
        prop = self._e_property
        clas = instance.__class__ ### MIGHT BE WRONG, not sure, might not matter unless someone overrides the prop attr, not sure...
        res = prop.__get__(instance, clas) #k is this right? we want to call it like the class would to any descriptor. seems to work.
        ## print "%r evals in %r to %r" % (self, instance, res)
        return res
    pass

class lexenv_Expr(internal_Expr): ##k guess, 061110 late
    """
    lexenv_Expr(env, expr) evals expr inside env, regardless of the passed env, but without altering the passed ipath.
    THIS BEHAVIOR IS INCORRECT AND WILL BE CHANGED SOON [070109 comment].
    It is opaque to replacement -- even by ExprsMeta, so it should never appear inside a class-attr value [##e should enforce that].
       WARNING [070106]: lexenv_Expr will have a major bug once we implement anything that can override dynamic env vars,
    since it should, but doesn't, inherit dynamic vars from the passed env rather than from its own env argument --
    only lexical vars should be overridden by the argument env. For more info see the discussion in widget_env.py docstring.
    To fix this bug, we need to know how to combine the lexical vars from the argument env with the dynamic ones from the passed env. ###
    """
    def _internal_Expr_init(self):
        (self._e_env0, self._e_expr0) = self.args
    def __repr__(self):
        return "<%s#%d%s: %r, %r>" % (self.__class__.__name__, self._e_serno, self._e_repr_info(),
                                      self._e_env0, self._e_expr0,)
    def _e_call_with_modified_env(self, env, ipath, whatever = 'bug'): # revised 070119
        """
        [private helper method]
        Call self._e_expr0.<whatever> with lexenv self._e_env0 and [nim] dynenv taken from the given env
        """
        # about the lval code: #061204 semi-guess; works for now. _e_eval and _e_eval_lval methods merged on 070109.
        # Generalized to whatever arg for _e_make_in and revised accordingly (for sake of EVAL_REFORM), 070117.
        #e (should the val/lval distinction be an arg in the _e_eval API?
        #   maybe only for some classes, ie variant methods for fixed arg, another for genl arg??)
        expr, env, ipath = self._e_burrow_for_find_or_make( env, ipath) ###k more efficient than, and equiv to, _1step
        submethod = getattr(expr, whatever)
        res = submethod(env, ipath)
            #e if exception, print a msg that includes whatever?
        return res
    def _e_burrow_for_find_or_make(self, env, ipath): #070119
        """
        ###redoc, since redundant with Expr implem docstring:
        Return (expr, env, ipath) in an inner form, where expr has no outermost local ipath or env.
        [overrides trivial Expr version]
           Details: General case (Expr): Return (self, env, ipath) if self can be directly instantiated in env at ipath
        (i.e. if self will find or make itself at exactly that env and ipath, since self has no outermost local mods to them),
        or an equivalent-for-instantiation (subexpr, locally_modified_env, locally_modified_ipath) if not,
        where subexpr meets the condition described above, and is formed by stripping off outer env-mods and ipath-mods from self
        and adding them onto the passed env and ipath.
           This method implements that general case for lexenv_Expr and lexenv_ipath_Expr.
        """
        new_expr, new_env, new_ipath = self._e_burrow_for_find_or_make_1step( env, ipath)
        return new_expr._e_burrow_for_find_or_make( new_env, new_ipath)
    def _e_burrow_for_find_or_make_1step(self, env, ipath):
        """
        [private helper method for _e_burrow_for_find_or_make]
        """
        new_expr = self._e_expr0
        lexenv = self._e_env0
        # now we want to combine the dynamic part of env with the lexical part of lexenv, to make a modified newenv.
        new_env = env.dynenv_with_lexenv(lexenv) # env supplies the dynenv part of new_env, lexenv the lexenv part.
            # WARNING: this is initially a stub which returns lexenv, equiv to the old code here.
            # PROBLEM: new_env is perhaps often recreated with an equal but not identical value from the same inputs,
            #  but it's not memoized or change-tracked. It can't easily be changed-tracked ... maybe ipath finding handles this... ###k]
            #e Note: This might be renamed; might be turned into a helper function rather than a method
            ###e Q: does this ever need to modify ipath, eg move some of it into or out of dynenv?
            # I don't know; ipath can be thought of as part of the dynenv, so it's proper that it's passed on, anyway. [070118 comment]
        new_ipath = self._e_locally_modify_ipath(ipath) # differs for lexenv_Expr and lexenv_ipath_Expr
        return (new_expr, new_env, new_ipath)
    def _e_locally_modify_ipath(self, ipath):
        return ipath # differs for lexenv_Expr and lexenv_ipath_Expr
    # note: the following methods are similar in two classes
    def _e_eval(self, env, ipath):
        return self._e_call_with_modified_env(env, ipath, whatever = '_e_eval')
    def _e_eval_lval(self, env, ipath):
        return self._e_call_with_modified_env(env, ipath, whatever = '_e_eval_lval')
    def _e_make_in(self, env, ipath):
        assert EVAL_REFORM # since it only happens then
        return self._e_call_with_modified_env(env, ipath, whatever = '_e_make_in')
    pass # end of class lexenv_Expr

class lexenv_ipath_Expr(lexenv_Expr): #070118
    """
    #doc
    """
    #k Q: will this need to be Symbolic, so getattr_Expr can be formed from it?
    # A: I think not, since expr.attr should become a getattr_Expr only if expr "stands for an Instance",
    # like a Symbol or Arg() or Instance() does... this needs to be better understood, formalized, documented
    # (for example, those macros turn into some sort of OpExpr, not something which says specifically "I stand for an Instance").
    # This came up since some code had an expr of this class (lexenv_ipath_Expr) which it thought was an Instance,
    # and took bleft from it, getting an AttributeError -- but if this class formed getattr_Exprs there would have been
    # no exception at all. [070212]
    def _internal_Expr_init(self):
        (self._e_env0, self._e_local_ipath, self._e_expr0) = self.args
    def __repr__(self):
        return "<%s#%d%s: %r, %r, %r>" % (self.__class__.__name__, self._e_serno, self._e_repr_info(),
                                      self._e_env0, self._e_local_ipath, self._e_expr0,)
    def _e_locally_modify_ipath(self, ipath): # WARNING: dup code for this in local_ipath_Expr and here
        localstuff = self._e_local_ipath # for now, just include it all [might work; might be too inefficient]
        if 1:
            # they are getting too long for debug prints already! [070121 morn]
            intern_ipath( ipath) # no need to use the result of this interning; not using it will make debug prints more understandable
            localstuff2 = intern_ipath( localstuff) ###e optim: do this in init? is that equivalent?? I think so... ######e
            # print "interned %r to %r" % (localstuff, localstuff2) # works
            localstuff = localstuff2
        return (localstuff, ipath)
    pass # lexenv_ipath_Expr

class local_ipath_Expr(lexenv_Expr): #070122 experimental
    """
    experimental -- just add some local ipath components to the ipath -- no change in env
    """
    #e probably, these 3 classes should be reorg'd into abstract/mixin1/mixin2/3reals,
    # so the shared code for doing more stuff (to env or to ipath) comes from mixins
    def _internal_Expr_init(self):
        (self._e_local_ipath, self._e_expr0) = self.args
    def __repr__(self):
        return "<%s#%d%s: %r, %r>" % (self.__class__.__name__, self._e_serno, self._e_repr_info(),
                                      self._e_local_ipath, self._e_expr0,)
    def _e_burrow_for_find_or_make_1step(self, env, ipath):
        """
        [overrides lexenv_Expr implem]
        [private helper method for _e_burrow_for_find_or_make]
        """
        new_expr = self._e_expr0
        new_env = env # differs from superclass
        new_ipath = self._e_locally_modify_ipath(ipath)
        return (new_expr, new_env, new_ipath)
    def _e_locally_modify_ipath(self, ipath):
        # WARNING: dup code from lexenv_ipath_Expr (differs from superclass)
        localstuff = self._e_local_ipath
        if 1:
            intern_ipath( ipath)
            localstuff2 = intern_ipath( localstuff)
            localstuff = localstuff2
        return (localstuff, ipath)
    pass # local_ipath_Expr

class eval_Expr(OpExpr):
    """
    An "eval operator", more or less. For internal use only [if not, indices need to be generalized].
    Used when you need to put an expr0 inside some other expr1 where it will be evalled later,
    but you have, instead of expr0, expr00 which will eval to expr0. In such cases, you can put eval_Expr(expr00)
    in the place where you were supposed to put expr0, and when the time comes to eval that, expr00 will be evalled twice,
    in the same env and with appropriately differing indices.
    """
    def _e_init(self):
        pass
    def _e_call_on_argval(self, env, ipath, whatever = 'bug'):
        "[private helper method]"
        # same initial comment as in lexenv_Expr applies here [as of 070117]
        assert env #061110
        (arg,) = self._e_args
        ## argval = arg._e_eval(env, 'unused-index') # I think this index can never be used; if it can be, pass ('eval_Expr',ipath)
        index = 'eval_Expr(%s)' % whatever
        argval = arg._e_eval(env, (index, ipath)) #070109 this index can in fact be used, it turns out.
            # note: it's correct that we call arg._e_eval regardless of whatever being '_e_eval' or something else.
        try:
            submethod = getattr(argval, whatever)
            res = submethod(env, ipath)
                ###BUG (likely): if argval varies, maybe this ipath should vary with it -- but I'm not sure in what way.
                # We probably have to depend on argval to have different internal ipaths when it comes from different sources --
                # but presently that's nim (nothing yet wraps exprs with local-ipath-modifiers, tho e.g. If probably should),
                # so this might lead to incorrectly overlapping ipaths. It's not at all clear how to fix this in general,
                # and most likely, most uses of eval_Expr are kluges which are wrong in some way anyway, which this issue is
                # hinting at, since it seems fundamentally unfixable in general. [070109 comment]
                # update 070118: the plan is that argval will soon have a local-ipath-modifier as its outer layer,
                # which adds something to the ipath we pass to the submethod above, thus presumably solving the problem
                # (though until we intern exprs/ipaths and/or memoize the ipath->storage association, it might make things slower).
                # update 070122: but it doesn't yet solve it for testexpr_21e or _21g, in which an ad-hoc function returns an expr
                # based on a passed argument (according to a guess at the bug cause). See discussion near testexpr_21g.
        except:
            print "following exception concerns argval.%s(...) where argval is %r and came from evalling %r" % \
                  (whatever, argval, arg) #061118, revised 070109 & 070117
            raise
        ## print "eval_Expr eval%s goes from %r to %r to %r" % (_e_eval_lval and "_lval" or "", arg, argval, res) #untested since lval
        return res
    # note: the following methods are similar in two classes
    def _e_eval(self, env, ipath):
        return self._e_call_on_argval(env, ipath, whatever = '_e_eval')
    def _e_eval_lval(self, env, ipath):
        return self._e_call_on_argval(env, ipath, whatever = '_e_eval_lval')
    def _e_make_in(self, env, ipath):
        assert EVAL_REFORM # since it only happens then
        return self._e_call_on_argval(env, ipath, whatever = '_e_make_in')
    pass # end of class eval_Expr

##from VQT import V ###e replace with a type constant -- probably there's one already in state_utils
##V_expr = tuple_Expr ### kluge; even once this is defined, in formulas you may have to use V_expr instead of V,
    # unless we redefine V to not try to use float() on exprs inside it -- right now it's def V(*v): return array(v, Float)
    # (note: that Float is from Numeric and equals 'd')
    ##e (maybe we could make a new V def try to use old def, make __float__ asfail so that would fail, then use V_expr if any expr arg)

def canon_expr(subexpr):###CALL ME FROM MORE PLACES -- a comment in Column.py says that env.understand_expr should call this...
    """
    Make subexpr an Expr, if it's not already.
       Simple Python data (e.g. ints, floats, or None, and perhaps most Python class instances)
    will be wrapped with constant_Expr.
       Python lists or tuples (or dicts?##e) can contain exprs, and will become their own kind of exprs,
    or (as a future optim #e) will also be wrapped with constant_Expr if they don't contain exprs.
       (In future, we might also intern the resulting expr or the input expr. #e)
    """
    if is_Expr(subexpr): # whether pure expr or Instance
        # bruce 070914 removing the following, since I'm not using it
        # and it's causing some (runtime) import loops (Exprs <-> instance_helpers):
##        if is_Expr_pyclass(subexpr):
##            if debug_pref("wrap expr subclasses in constant_Expr?", Choice_boolean_False, prefs_key = True):
##                # new feature 070228; not sure if it ever came up before; if it did, this change might cause trouble;
##                # therefore print something whenever it's used, for now. In fact, it is likely to be misguided so I'll make it a debug_pref.
##                print "canon_expr treating this expr class as a constant: %r" % (subexpr,) ##e print_compact_stack?
##                assert same_vals(subexpr, subexpr)
##                return constant_Expr(subexpr)
##            elif debug_pref("pseudo-customize IorE subclasses?", Choice_boolean_False, prefs_key = True):
##                # turn it into an equivalent safer expr -- but only if it's in IorE
##                from exprs.instance_helpers import InstanceOrExpr #k safe??
##                if issubclass(subexpr, InstanceOrExpr):
##                    res = subexpr( _KLUGE_fakeoption = None )
##                    print "canon_expr turning expr class %r into %s" % (subexpr,res) #### remove when thought to be safe? printfyi?
##                    return res
##                else:
##                    print "canon_expr not changing expr class %r" % (subexpr,) ####
        if subexpr._e_serno == _debug_e_serno:
            print_compact_stack( "_debug_e_serno %d seen as arg %r to canon_expr, at: " % (_debug_e_serno, subexpr))
        return subexpr
            # true for Instances too -- ok?? [070122: see cmt in IorE._e_eval when EVAL_REFORM, which accomodates this]
##    ## elif issubclass(subexpr, Expr): # TypeError: issubclass() arg 1 must be a class
##    elif isinstance(subexpr, type) and issubclass(subexpr, Expr):
##        return subexpr # for _TYPE_xxx = Widget2D, etc -- is it ever not ok? ####k
    elif isinstance(subexpr, type([])):
        return list_Expr(*subexpr) ###k is this always correct? or only in certain contexts??
            # could be always ok if list_Expr is smart enough to revert back to a list sometimes.
        #e analogous things for tuple and/or dict? not sure. or for other classes which mark themselves somehow??
    elif isinstance(subexpr, type(())):
        return tuple_Expr(*subexpr) ###e should optim when it's entirely constant, like (2,3)
            # [needed for (dx,dy) in Translate(thing, (dx,dy)), 061111]
##    elif isinstance(subexpr, type(V(1,1.0))): ###e
##        # try to handle things like V(dx,dy) too... turns out this is not yet supportable, probably never.
##        # so this is more harmful than good -- a real V() is a constant, since it can't contain exprs anyway --
##        # if we redefine V to not require floats, we might as well go all the way to V_expr inside it.
##        printnim("kluge: turning V(expr...) into a tuple_Expr for now!") #####@@@@@
##        return tuple_Expr(*subexpr) #e replace with NumericArray_expr or V_expr or so
    elif isinstance(subexpr, property):
        res = property_Expr(subexpr)
        ## print "canon_expr wrapping property %r into %r" % (subexpr, res)
        return res
    else:
        #e assert it's not various common errors, like expr classes or not-properly-reloaded exprs
        #e more checks?
        # assume it's a python constant
        #e later add checks for its type, sort of like we'd use in same_vals or so... in fact, how about this?
        assert same_vals(subexpr, subexpr)
        ###e at first i thought: we should delve into it and assert you don't find Exprs... but delve in what way, exactly?
        # if you have a way, you understand the type, and then just handle it instead of checking for the unmet need to handle it.
        # we could let data objects tell us their subobjs like they do for Undo (I forget the details, some way of scanning kids)
        return constant_Expr(subexpr)
    pass

# ==

class Symbol(SymbolicExpr):
    """
    A kind of Expr that is just a symbol with a given name.
    Often used via the __Symbols__ module.
    """
    # Default values of instance variables.
    # These are normally set (optionally) after __init__, by the code that creates the symbols,
    # and never changed after that.
    _e_sym_constant = False # caller can set this to True if it's normal for this symbol to eval to itself (not deserving of warning)
    _e_eval_forward_to = _UNSET_ # caller can set this to something if it wants this symbol to evaluate to the same thing as that does.
    def __init__(self, name = None, doc = None):
        self._e_init_e_serno()
        if name is None:
            name = "?%s" % compact_stack(skip_innermost_n = 2).split()[-1] # kluge - show line where it's defined
        self._e_name = name
        self.__doc__ = doc # default is None, for a Symbol with no individual docstring.
            # (self.__doc__ can optionally be set by caller after we return)
        return
    def __str__(self):
        return self._e_name
    def __repr__(self):
        ## return 'Symbol(%r)' % self._e_name
        ##e should only use following form when name looks like a Python identifier!
        return 'S.%s' % self._e_name
    def __eq__(self, other): #k probably not needed, since symbols are interned as they're made
        return self.__class__ is getattr(other, '__class__', None) and self._e_name == other._e_name
            #070304 bugfix: survive not hasattr(other, '__class__') [maybe not tested since i'm not sure if this is ever used]
    def __ne__(self, other):
        return not (self == other)
    def _e_eval(self, env, ipath):
        """
        As with super _e_eval, our job is:
        Imagine that env's replacements should be done in self,
        and that the resulting modified self should be instantiated within the object which is env's replacement for _self.
        Then evaluate the result at the current time.
           For self a symbol other than _self, that just means, do the replacement, worrying about symbols inside that value
        (in terms of repeated replacement if any), then evaluate the result. I am not sure what context the replacements are in,
        whether this can ever be used to create an expr result, whether _self is a special case, etc, so for now,
        print warnings (or maybe asfail) if any of those cases arise.
           For self the symbol _self, this happens all the time with env's value for _self being an instance,
        and what we want to return is that very instance. This may mean that technically env's value should be a constant expr
        which we should eval here, *or* that we should have a special case for _self here, *or* that we should never be
        recursively evaluating replacements here. For now, I'll handle this by not recursively evaluating,
        warning if _self doesn't get an Instance, and warning if self is not _self. [061105]
        """
        #pre-061105 comments, probably obs & wrong:
        ## print "how do we eval a symbol? some sort of env lookup ..."
        #[later 061027: if lookup gets instance, do we need ipath? does instance have it already? (not same one, for sure -- this is
        # like replacement). If lookup gets expr, do we instantiate it here? For now, just make _self work -- pretend expr was already
        # instantiated and in the place of _self it had an instance. So, when we hit an instance with _e_eval, what happens?
        # If we believe that getattr_Expr, it returns a value which is "self" which is exactly the same instance --
        # i.e. Thing instance evals to itself. This is not like OpExpr instance which evals to a value. I suppose If also evals
        # to not itself.... this is related to what CLE wanted to do, which is eval something to a "fixed instance" -- let's review
        # the API it proposed to use for calling that utility.... that's in GlueCodeMemoizer, it does instance.eval() but I knew it
        # might be misnamed, but I did think no point in passing it args (instance already knows them). I know some instances define
        # _value (like Boxed), maybe .eval() would go into it... probably it would. BTW, What if ._value is an expr (not Instance)?
        # What if we call it _e_value and it's defined on some expr?? ####@@@@
        # Summary guess: look up sym, then eval result with same args. If instance, they have a method which looks for _value,
        # defaults to self. This method might be _e_eval itself... or have some other name.]
        #older comments:
        ## -- in the object (env i guess) or lexenv(?? or is that replacement??) which is which?
        # maybe: replacement is for making things to instantiate (uses widget expr lexenv), eval is for using them (uses env & state)
        # env ("drawing env") will let us grab attrs/opts in object, or things from dynenv as passed to any lexcontaining expr, i think...
        if self._e_eval_forward_to is not _UNSET_:
            printfyi("forwarding %r to value of %r" % (self, self._e_eval_forward_to))###
            return env._e_eval( self._e_eval_forward_to, ipath) #070131; note this forwarding is not overridable by env (experimental)
        val = env.lexval_of_symbol(self) # note: cares mainly or only about self._e_name; renamed _e_eval_symbol -> lexval_of_symbol
            # but I'm not sure it's really more lexenv than dynenv, at least as seen w/in env... [061028] ####@@@@
        # val is an intermediate value, needs further eval [this old comment might be wrong; see docstring -- 061105]
        if self == val:
            # return self (perhaps wrapped), after perhaps printing a warning
            if self is not val:
                print "warning: %r and %r are two different Symbols with same name, thus equal" % (self, val)
            if EVAL_REFORM:#070117
                if not self._e_sym_constant: #070131 added this cond (and attr)
                    print "warning: Symbol(%r) evals to itself [perhaps wrapped by _e_eval_to_expr]" % self._e_name
                return self._e_eval_to_expr(env, ipath, self)
            else:
                if not self._e_sym_constant: #070131 added this cond (and attr)
                    print "warning: Symbol(%r) evals to itself" % self._e_name
                return self
        # reached only when self != val
        assert self != val # remove when works
        if self._e_name not in ('_self', '_my', '_app'): #k Q: does this also happen for a thisname, _this_<classname> ?
            print "warning: _e_eval of a symbol other than _self or _my is not well-reviewed or yet well-understood:", self._e_name
                # e.g. what should be in env? what if it's an expr with free vars incl _self -- are they in proper context?
                # see docstring for more info [061105]
        ## pre-061105 code did: return val._e_eval(env, ipath)
        # and that might be needed for other syms -- not sure yet [061105]
        return val
    def _e_make_in(self, env, ipath):#070131
        assert self._e_sym_constant, "only constant Symbols can be instantiated, not %r" % self
        # and (at least for now) they instantiate to themselves, like other constants do
        return self
    def _e_free_in(self, sym): ###k might be obs [070131 comment]
        """
        General case: Return True if Expr self contains sym (Symbol or its name) as a free variable, in some arg or option value.
        For this class Symbol, that means: Return True if sym is self or self's name.
        [overrides super version]
        """
        return (sym is self) or (sym == self._e_name)
    pass # end of class Symbol

# note about Instance, Arg, Option, ArgOrOption, State -- they are now in another file to ease import-recursion issues.

# end