コード例 #1
0
 def _init_instance(self):
     self._value = CLE(list(self._e_args)) # 061106 educated guess: self.args -> self._e_args, assuming _value is auto-instantiated
         # or that the below does that -- not reviewed now. #####@@@@@
     printnim("Column _vlaue instantiation not reviewed")
     
         #k do we need to instantiate this, or is that automatic somehow? guess: we do, though a class assignment of it would not.
     self._value = self.make(self._value)
コード例 #2
0
 def _e_override_replace(self, scanner):
     """
     This gets called by a formula scanner when it hits this object in an expr...
     it knows lots of private stuff about FormulaScanner.
     """
     attr = scanner.replacements[
         _E_ATTR]  # a constant_Expr, or an indication of error if this happens (maybe missing then?)
     attr = attr._e_constant_value
     if 1:
         # quick & dirty check for two attrs claiming one arg... come to think of it, is this wrong re inclusion?
         # no, as long as overall replace (of this) happens before this gets called, it'll be ok.
         # but, a better check & better errmsg can be done in scanner if we pass our own args to it.
         # WAIT, i bet this won't actually catch the error, since the replace would actually occur... have to do it in the scanner.
         printnim(
             "improve quick & dirty check for two attrs claiming one arg (it may not even work)"
         )  ###e
         self.attrs_ive_seen[attr] = 1
         assert len(
             self.attrs_ive_seen
         ) <= 1, "these attrs claim the same arg: %r" % self.attrs_ive_seen.keys(
         )
         # WARNING: if this works, it will break the use of Arg in future things like lambda_expr or _e_extend
         # where the same Arg() object might get passed to multiple class/attr contexts in runtime-generated exprs with Arg decls.
         # If/when that happens, this object needs to be made immutable, which can be done by removing this code (inside 'if 1'),
         # since it's probably either not working or redundant, according to the comments above and my best guess now. [070321 comment]
     required = self._e_is_required
     arglist = self._e_is_arglist
     pos = scanner.argpos(attr, required, arglist=arglist)
     res = constant_Expr(
         pos)  # this gets included in the scanner's processed expr
     return res
コード例 #3
0
ファイル: lvals.py プロジェクト: ematvey/NanoEngineer-1
 def get_value(self):
     """This is the only public method for getting the current value;
     it always usage-tracks the access, and recomputes the value if necessary.
     """
     if not self.valid:
         try:
             self._value = self._compute_value()
                 # this USED TO catch exceptions in our compute_method; as of 061118 it reraises them
         except: # note: might be LvalError_ValueIsUnset, or any other exception -- likely that best responses should differ ###e
             printnim("I need to figure out what usage to track, in what object, when a tracked attr is unset")
             pass ## self.track_use() -- THIS IS PROBABLY NEEDED SOMEDAY, see below -- ###tryit
                 # GUESS 061120 1112a [later suspected wrong, see below]:
                 # this track_use causes the duplicate track_inval bug, because we track when invalid.
                 # and (still guessing) we do this during hasattr seeing our value is unset. it's probably wrong, because when the
                 # val becomes set, why should something be invalled, unless it turned exception into a real value?
                 # what might be right is to merge all the usage at this point into whatever caller turns the exception
                 # into a real value, rather than just discarding it.
                 # surely we don't want to include it here, not only this one, but whatever was used before... but what
                 # do i mean by "here"? The real error is not in our mentioning the use here, i think, but in what
                 # the caller does with it... otoh our complaint stems entirely from what happens here, so that's wrong.
                 # I don't understand this well yet, but let's see what happens if I comment that out.
                 # ... status, 061121 late: it didn't fix the bug, later stuff did, and I suspect it's right in theory
                 # to track the use here, but that it won't matter in the near future. So, at some point, put this back
                 # and see if it works or breaks, but no hurry to put it back in general. But recall it as a possible bug cause,
                 # and if it seems to not break anything, leave it in, unlike now. 
             raise
         self.valid = True
     # do standard usage tracking into env (whether or not it was invalid & recomputed) -- API is compatible with env.prefs
     # [do it after recomputing, in case the tracking wants to record _value immediately(?)]
     self.track_use() # (defined in SelfUsageTrackingMixin) ###e note: this will need optimization
     return self._value
コード例 #4
0
 def get_value(self):
     """This is the only public method for getting the current value;
     it always usage-tracks the access, and recomputes the value if necessary.
     """
     if not self.valid:
         try:
             self._value = self._compute_value()
             # this USED TO catch exceptions in our compute_method; as of 061118 it reraises them
         except:  # note: might be LvalError_ValueIsUnset, or any other exception -- likely that best responses should differ ###e
             printnim(
                 "I need to figure out what usage to track, in what object, when a tracked attr is unset"
             )
             pass  ## self.track_use() -- THIS IS PROBABLY NEEDED SOMEDAY, see below -- ###tryit
             # GUESS 061120 1112a [later suspected wrong, see below]:
             # this track_use causes the duplicate track_inval bug, because we track when invalid.
             # and (still guessing) we do this during hasattr seeing our value is unset. it's probably wrong, because when the
             # val becomes set, why should something be invalled, unless it turned exception into a real value?
             # what might be right is to merge all the usage at this point into whatever caller turns the exception
             # into a real value, rather than just discarding it.
             # surely we don't want to include it here, not only this one, but whatever was used before... but what
             # do i mean by "here"? The real error is not in our mentioning the use here, i think, but in what
             # the caller does with it... otoh our complaint stems entirely from what happens here, so that's wrong.
             # I don't understand this well yet, but let's see what happens if I comment that out.
             # ... status, 061121 late: it didn't fix the bug, later stuff did, and I suspect it's right in theory
             # to track the use here, but that it won't matter in the near future. So, at some point, put this back
             # and see if it works or breaks, but no hurry to put it back in general. But recall it as a possible bug cause,
             # and if it seems to not break anything, leave it in, unlike now.
             raise
         self.valid = True
     # do standard usage tracking into env (whether or not it was invalid & recomputed) -- API is compatible with env.prefs
     # [do it after recomputing, in case the tracking wants to record _value immediately(?)]
     self.track_use(
     )  # (defined in SelfUsageTrackingMixin) ###e note: this will need optimization
     return self._value
コード例 #5
0
def canon_type(type_expr):###stub [note: this is not canon_expr!]
    """
    Return a symbolic expr representing a type for coercion
    """

    return Anything # for now! when we implement TypeCoerce, revise this

    printnim("canon_type is a stub; got %r" % type_expr) ## so far: Widget2D, int
    return lambda x:x #stub
コード例 #6
0
    def _init_instance(self):
        self._value = CLE(
            list(self._e_args)
        )  # 061106 educated guess: self.args -> self._e_args, assuming _value is auto-instantiated
        # or that the below does that -- not reviewed now. #####@@@@@
        printnim("Column _vlaue instantiation not reviewed")

        #k do we need to instantiate this, or is that automatic somehow? guess: we do, though a class assignment of it would not.
        self._value = self.make(self._value)
コード例 #7
0
def canon_type(type_expr):###stub [note: this is not canon_expr!]
    """
    Return a symbolic expr representing a type for coercion
    """

    return Anything # for now! when we implement TypeCoerce, revise this

    printnim("canon_type is a stub; got %r" % type_expr) ## so far: Widget2D, int
    return lambda x:x #stub
コード例 #8
0
    def toggle_open(self):
        if 'yet another shot in the dark 061120 1001p':
            self.env.glpane.selobj = None  ##### THIS SEEMS TO FIX THE BUG, at least together with other potshots and if 0 openclose.
            # theory: old selobjs are being drawn highlighted even when not drawn normally. they mask the real stuff.
            # but with if 1 openclose it doesn't fix the different bug (gets wedged into closed state). why not???
            # this is with no recycling of names, and also selobj=None in recycler.
            # guess: in if 1, the same glname is used... but it's same literal selobj too, right? and remaking is turned off.
            # I don't have a theory for 'if 1' bug cause, or for why it only affects the inner thing, not outer one.
            # Does it only affect that after it's once been hidden? ### if so, is it "you were selobj and then not drawn" that makes it
            # happen? that might fit the data but I don't see how that could work.
            # So I added a 2nd 0.5 so neither gray rect form covers the other. but first inner close hits the bug of making it
            # inactive and act non-highlighted. so i wondered if the glname really only covers the openclose? code says so.
            # I added a try/except to be sure the PopName occurs; not triggered during this if 1 bug.
            #
            # Stopping for night 061120 1027p, summary: I understand some bug causes but not all; wish I could see inside the glselect
            # reasoning, so plan to add debug prints to glpane. Need to think thru its assumptions re chaotic glname/selobj/size/
            # whether-drawn situation, see which are wrong, which might cause the bug. Also - can event processing occur during
            # paintGL? I hope not, but verify. Also maybe GLPane needs to track frame numbers for selobjs being drawn,
            # stencil bits being made, vs selobj state mods as tracked by inval....
            #
            # update 061121 953a, where I am: after basic fixes elsewhere [some stateplaces not tracked, some usage tracking disallowed],
            # and still using all kluge/workarounds from 061120, bug seems totally fixed for if 0 case, all or most for if 1 ##k.
            # IIRC it was slightly remaining before some usage tracking disallowed, but that is not complaining, which is suspicious.
            # Anyway, if if 1 works too, plan is to gradually remove the kluges and clean up and keep it working.
            # BUT it looks like if 1 (using reloaded code) has a bug of some disallowed usage... details to follow.
            # BUT after restart I don't see it. BTW I recently reenabled reloading -- could that have fixed some bugs (how???),
            # or could it be that they now occur after reloading but not before it?? indeed, this is after changing if 1->0 and reload,
            # and looks like it might relate to old state being there, and
            ###### WHAT IF RELOADED CODE USES THE SAME STATE DIFFERENTLY AND HAS A BUG? #####
            # [but, that bug aside, there is still a real problem with whatever usage tracking this
            #  set_default_attrs is doing. [fixed now]]

        if 0:  #061121 822p i've been using if 1 forever, let's see if if 0 works here: it does! either is ok, given the open property.
            old = self.transient_state.open
            self.transient_state.open = new = not old
            ## print "toggle_open changed self.transient_state.open from %r to %r" % (old, new,)
        else:
            old = self.open
            self.open = new = not old
            ## print "toggle_open changed self.open from %r to %r" % (old, new,)
            # [obs cmt re open property, but was it talking about that or a partly working State decl? as of 061121 I can't remember:]
            # should work but doesn't, see bug in notesfile, it delegates self.open eval to _value: 061118 late
            # (or is it just because the val was not initialized? GUESS, YES ###k)
            ## self.open = not self.open ### can this work??? it will call set of self.open -- what does the descriptor do for that?
            # (asfail, or not have __set__ at all?? FIND OUT. the notesfile says the same thing but for a different Q, what was it?)
            ## WE SHOULD MAKE THIS WORK even if we also make on_press = Set( open, not_Expr(open) ) work, since it's so natural.
        ### BTW what is it that will notice the inval, and the usage of this when we drew, and know that gl_update is needed?
        # the same thing that would know a display list content was invalid -- but where is it in our current code (if anywhere)?
        # I vaguely recall a discussion of that issue, in the displist chunk code or notesfile, weeks ago.
        # some way to have lvals representing displist contents or frame buffer contents, whose inval means an update is needed.
        printnim(
            "toggle_open might do a setattr which is not legal yet, and (once that's fixed) might not properly gl_update yet"
        )
        return
コード例 #9
0
 def _C_delegate(self): # renamed from _eval_my_arg
     printnim("self.args[0] needs review for _e_args or setup, in GlueCodeMemoizer; see DelegatingMixin")###e 061106
     arg = self.args[0] # formula instance
     argval = arg.eval() ###k might need something passed to it (but prob not, it's an instance, it has an env)
     ####@@@@ might be arg.value instead; need to understand how it relates to _value in Boxed [061020]
         #### isn't this just get_value? well, not really, since it needs to do usage tracking into the env...
         # maybe that does, if we don't pass another place?? or call its compute_value method??
         # argval might be arg, btw; it's an instance with a fixed type (or perhaps a python constant data value, e.g. None)
     #e might look at type now, be special if not recognized or for None, depending on memo policy for those funny types
     lval = self._dict_of_lvals[argval]
     return lval.get_value()
コード例 #10
0
ファイル: ToggleShow.py プロジェクト: ematvey/NanoEngineer-1
    def toggle_open(self):
        if 'yet another shot in the dark 061120 1001p':
            self.env.glpane.selobj = None ##### THIS SEEMS TO FIX THE BUG, at least together with other potshots and if 0 openclose.
            # theory: old selobjs are being drawn highlighted even when not drawn normally. they mask the real stuff.
            # but with if 1 openclose it doesn't fix the different bug (gets wedged into closed state). why not???
            # this is with no recycling of names, and also selobj=None in recycler.
            # guess: in if 1, the same glname is used... but it's same literal selobj too, right? and remaking is turned off.
            # I don't have a theory for 'if 1' bug cause, or for why it only affects the inner thing, not outer one.
            # Does it only affect that after it's once been hidden? ### if so, is it "you were selobj and then not drawn" that makes it
            # happen? that might fit the data but I don't see how that could work.
            # So I added a 2nd 0.5 so neither gray rect form covers the other. but first inner close hits the bug of making it
            # inactive and act non-highlighted. so i wondered if the glname really only covers the openclose? code says so.
            # I added a try/except to be sure the PopName occurs; not triggered during this if 1 bug.
            #
            # Stopping for night 061120 1027p, summary: I understand some bug causes but not all; wish I could see inside the glselect
            # reasoning, so plan to add debug prints to glpane. Need to think thru its assumptions re chaotic glname/selobj/size/
            # whether-drawn situation, see which are wrong, which might cause the bug. Also - can event processing occur during
            # paintGL? I hope not, but verify. Also maybe GLPane needs to track frame numbers for selobjs being drawn,
            # stencil bits being made, vs selobj state mods as tracked by inval....
            #
            # update 061121 953a, where I am: after basic fixes elsewhere [some stateplaces not tracked, some usage tracking disallowed],
            # and still using all kluge/workarounds from 061120, bug seems totally fixed for if 0 case, all or most for if 1 ##k.
            # IIRC it was slightly remaining before some usage tracking disallowed, but that is not complaining, which is suspicious.
            # Anyway, if if 1 works too, plan is to gradually remove the kluges and clean up and keep it working.
            # BUT it looks like if 1 (using reloaded code) has a bug of some disallowed usage... details to follow.
            # BUT after restart I don't see it. BTW I recently reenabled reloading -- could that have fixed some bugs (how???),
            # or could it be that they now occur after reloading but not before it?? indeed, this is after changing if 1->0 and reload,
            # and looks like it might relate to old state being there, and
            ###### WHAT IF RELOADED CODE USES THE SAME STATE DIFFERENTLY AND HAS A BUG? #####
            # [but, that bug aside, there is still a real problem with whatever usage tracking this
            #  set_default_attrs is doing. [fixed now]]

            
        if 0: #061121 822p i've been using if 1 forever, let's see if if 0 works here: it does! either is ok, given the open property.
            old = self.transient_state.open
            self.transient_state.open = new = not old
            ## print "toggle_open changed self.transient_state.open from %r to %r" % (old, new,)
        else:
            old = self.open
            self.open = new = not old
            ## print "toggle_open changed self.open from %r to %r" % (old, new,)
            # [obs cmt re open property, but was it talking about that or a partly working State decl? as of 061121 I can't remember:]
                # should work but doesn't, see bug in notesfile, it delegates self.open eval to _value: 061118 late
                # (or is it just because the val was not initialized? GUESS, YES ###k)
                ## self.open = not self.open ### can this work??? it will call set of self.open -- what does the descriptor do for that?
                # (asfail, or not have __set__ at all?? FIND OUT. the notesfile says the same thing but for a different Q, what was it?)
                ## WE SHOULD MAKE THIS WORK even if we also make on_press = Set( open, not_Expr(open) ) work, since it's so natural.
        ### BTW what is it that will notice the inval, and the usage of this when we drew, and know that gl_update is needed?
        # the same thing that would know a display list content was invalid -- but where is it in our current code (if anywhere)?
        # I vaguely recall a discussion of that issue, in the displist chunk code or notesfile, weeks ago.
        # some way to have lvals representing displist contents or frame buffer contents, whose inval means an update is needed.
        printnim("toggle_open might do a setattr which is not legal yet, and (once that's fixed) might not properly gl_update yet")
        return
コード例 #11
0
def Instance(expr,
             _index_expr=_E_ATTR,
             _lvalue_flag=False,
             _noinstance=False,
             doc=None):
    """
    This macro is assigned to a class attr to declare that its value should be a lazily-instantiated Instance of expr (by default).
    Assuming the arg is an expr (not yet checked?), turn into the expr _self._i_instance(hold_Expr(expr), _E_ATTR),
    which is free in the symbols _self and _E_ATTR. [#e _E_ATTR might be changed to _E_INDEX, or otherwise revised.]

    This function is also used internally to help implement the Arg and Option macros;
    for their use only, it has a private _index_expr option, giving an index expr other than _E_ATTR for the new Instance
    (which is used to suggest an ipath for the new instance, relative to that of self).

    Similarly, it helps implement ArgExpr etc, for whose sake it has a private option _noinstance.

    Devel scratch comment:
    Note that the Arg and Option macros may have handy, not expr itself, but a "grabarg" expr which needs to be evaluated
    (with _self bound) to produce the expr to be instantiated. What should they pass?? eval_Expr of the expr they have.
    [#doc - reword this]

    Other private options: _lvalue_flag, _noinstance (_noinstance is only supported when EVAL_REFORM is true)
    """
    if doc:
        printnim(
            "Instance doc is not saved anywhere; should turn into a note to formulascanner to save it as metainfo, maybe"
        )  #e
    printnim(
        "review: same index is used for a public Option and a private Instance on an attr; maybe ok if no overlap possible???"
    )  ##e
    global _self  # not needed, just fyi
    if EVAL_REFORM:
        if _lvalue_flag:
            assert not _noinstance  # since it makes no sense to ask for this then, AFAIK (if ok for one, ok for all -- see below)
            #070119 bugfix to make Set(var,val) work again (eg when clicking a checkbox_pref)
            # rather than evalling var to its current value. This means _lvalue_flag never gets passed to _i_instance.
            res = call_Expr(getattr_Expr(_self, '_i_instance'),
                            eval_to_lval_Expr(expr), _index_expr)
            ####e if this works, then try simplifying it to remove the _i_instance call! (assuming the lval is never needing make)
            # (or given this macro's name, maybe it makes more sense for LvalueArg to manage to not call it...)
        elif _noinstance:  #070122
            # we ignore _index_expr, but callers can't help but pass one, so don't complain when they do
            return expr  # i.e. Instance(expr) == expr -- not useful directly, but useful as a passthru option from Arg etc.
        else:
            res = call_Expr(getattr_Expr(_self, '_i_instance'), expr,
                            _index_expr)
    else:
        assert not _noinstance, "bug: _noinstance is only supported when EVAL_REFORM is true"
        res = call_Expr(getattr_Expr(_self, '_i_instance'),
                        hold_Expr(expr),
                        _index_expr,
                        _lvalue_flag=_lvalue_flag)
    return res
コード例 #12
0
 def _C_delegate(self):  # renamed from _eval_my_arg
     printnim(
         "self.args[0] needs review for _e_args or setup, in GlueCodeMemoizer; see DelegatingMixin"
     )  ###e 061106
     arg = self.args[0]  # formula instance
     argval = arg.eval(
     )  ###k might need something passed to it (but prob not, it's an instance, it has an env)
     ####@@@@ might be arg.value instead; need to understand how it relates to _value in Boxed [061020]
     #### isn't this just get_value? well, not really, since it needs to do usage tracking into the env...
     # maybe that does, if we don't pass another place?? or call its compute_value method??
     # argval might be arg, btw; it's an instance with a fixed type (or perhaps a python constant data value, e.g. None)
     #e might look at type now, be special if not recognized or for None, depending on memo policy for those funny types
     lval = self._dict_of_lvals[argval]
     return lval.get_value()
コード例 #13
0
ファイル: debug_exprs.py プロジェクト: elfion/nanoengineer
 def draw(self):
     guy = self.delegate
     print "guy = %r" % (guy, )
     ## attrs = self.args[1:]
     attrs = self.attrs
     if type(attrs) == type("kluge"):
         attrs = [attrs]
         printnim("need to unstub ArgList in DebugPrintAttrs")
     else:
         printfyi("seems like ArgList may have worked in DebugPrintAttrs")
     if 'ipath' not in attrs:
         attrs.append('ipath')#070118; not sure it's good
     for name in attrs:
         print "guy.%s is" % name, getattr(guy,name,"<unassigned>")
     return self.drawkid( guy) ## return guy.draw()
コード例 #14
0
 def draw(self):
     guy = self.delegate
     print "guy = %r" % (guy, )
     ## attrs = self.args[1:]
     attrs = self.attrs
     if type(attrs) == type("kluge"):
         attrs = [attrs]
         printnim("need to unstub ArgList in DebugPrintAttrs")
     else:
         printfyi("seems like ArgList may have worked in DebugPrintAttrs")
     if 'ipath' not in attrs:
         attrs.append('ipath')  #070118; not sure it's good
     for name in attrs:
         print "guy.%s is" % name, getattr(guy, name, "<unassigned>")
     return self.drawkid(guy)  ## return guy.draw()
コード例 #15
0
def Instance(expr, _index_expr = _E_ATTR, _lvalue_flag = False, _noinstance = False, doc = None):
    """
    This macro is assigned to a class attr to declare that its value should be a lazily-instantiated Instance of expr (by default).
    Assuming the arg is an expr (not yet checked?), turn into the expr _self._i_instance(hold_Expr(expr), _E_ATTR),
    which is free in the symbols _self and _E_ATTR. [#e _E_ATTR might be changed to _E_INDEX, or otherwise revised.]

    This function is also used internally to help implement the Arg and Option macros;
    for their use only, it has a private _index_expr option, giving an index expr other than _E_ATTR for the new Instance
    (which is used to suggest an ipath for the new instance, relative to that of self).

    Similarly, it helps implement ArgExpr etc, for whose sake it has a private option _noinstance.

    Devel scratch comment:
    Note that the Arg and Option macros may have handy, not expr itself, but a "grabarg" expr which needs to be evaluated
    (with _self bound) to produce the expr to be instantiated. What should they pass?? eval_Expr of the expr they have.
    [#doc - reword this]

    Other private options: _lvalue_flag, _noinstance (_noinstance is only supported when EVAL_REFORM is true)
    """
    if doc:
        printnim("Instance doc is not saved anywhere; should turn into a note to formulascanner to save it as metainfo, maybe")#e
    printnim("review: same index is used for a public Option and a private Instance on an attr; maybe ok if no overlap possible???")##e
    global _self # not needed, just fyi
    if EVAL_REFORM:
        if _lvalue_flag:
            assert not _noinstance # since it makes no sense to ask for this then, AFAIK (if ok for one, ok for all -- see below)
            #070119 bugfix to make Set(var,val) work again (eg when clicking a checkbox_pref)
            # rather than evalling var to its current value. This means _lvalue_flag never gets passed to _i_instance.
            res = call_Expr( getattr_Expr(_self, '_i_instance'), eval_to_lval_Expr(expr), _index_expr )
                ####e if this works, then try simplifying it to remove the _i_instance call! (assuming the lval is never needing make)
                # (or given this macro's name, maybe it makes more sense for LvalueArg to manage to not call it...)
        elif _noinstance:#070122
            # we ignore _index_expr, but callers can't help but pass one, so don't complain when they do
            return expr # i.e. Instance(expr) == expr -- not useful directly, but useful as a passthru option from Arg etc.
        else:
            res = call_Expr( getattr_Expr(_self, '_i_instance'),                   expr,  _index_expr )
    else:
            assert not _noinstance, "bug: _noinstance is only supported when EVAL_REFORM is true"
            res = call_Expr( getattr_Expr(_self, '_i_instance'),         hold_Expr(expr), _index_expr, _lvalue_flag = _lvalue_flag )
    return res
コード例 #16
0
ファイル: staterefs.py プロジェクト: elfion/nanoengineer
class PrefsKey_StateRef(InstanceOrExpr): # guess, 061204
    """
    return something which instantiates to something with .value which is settable state,
    shared with env.prefs[key],
    properly usage-tracked in a compatible way with the rest of NE1
    """
    prefs_key = Arg(str) # note: it's probably ok if this is a time-varying formula, tho I don't know why it would be useful.
    defaultValue = ArgOrOption(Anything, None) ##e default of this should depend on type, in same way it does for Arg or Option --
        # nonetheless it's so much more common to specify a default value than a type, that I decided to put default value first.
        #
        ##BUG (optimization issue only, and not yet important in practice):
        # [re-noticed 070228 -- also the topic of the printnim and older comment just below!]
        # this defaultValue should be evaluated with usage tracking discarded, unless prefs_key changes,
        # in which case it should be reevalled once (doable if its eval pretends to use prefs_key) -- except ideally the value
        # for older prefs_keys being reused again would be cached (eg using MemoDict) (not important in practice).
        # This bug is not yet serious since the actual args so far are constants [as of 070228].
        # It's purely an optimization issue; but the worst-case effects are that the default value changes a lot more
        # often than the prefs value itself, causing needless inval propogation into the get_value caller,
        # and thus needless recomputation of an arbitrary amount of memoized results which care about the prefs value.
        # (But for all I know, the usual constant case would slow down due to the overhead of discarding usage tracking.
        #  Actually that's not an issue since we'd also rarely recompute it, not nearly on every get_value.) 
    printnim("need a way to declare that this arg should not be usage-tracked, or have its use as default val do that for that use")
        # [older version of the comment above; contains still-useful suggestions:]
        ###e we need a way to declare that this arg should not be usage-tracked re time-variation!!! or to assert it uses nothing.
        # right now, if it uses something that will silently cause bugs, probably just invisible performance bugs from extra invals.
        # CAN THERE BE A GENERAL SOLN based on what we use this for (default vals of things that don't care about updates)?
        # that is more correct in principle, since that's what matters -- eg what if someone added another use of the same arg. ###e
    type = ArgOrOption(Type, Anything) # this arg is not yet passed by anything, or used in this implem;
        # moved type from arg2->arg3, and Arg -> ArgOrOption (as being after ArgOrOption arg2 ought to force anyway), 061211 night
    def get_value(self):
        #e should coerce this to self.type before returning it -- or add glue code wrt actual type, or....
        prefs_key = self.prefs_key
        assert type(prefs_key) == type("") #k redundant?
        import foundation.env as env
        return env.prefs.get( prefs_key, self.defaultValue ) # note: this computes defaultValue at least once, even if not needed.
    def set_value(self, val): 
        #e should coerce that to self.type, or add glue code...
        prefs_key = self.prefs_key
        assert type(prefs_key) == type("") #k redundant?
        import foundation.env as env
        env.prefs[prefs_key] = val
        if 0 and debug_flags.atom_debug:
            print "fyi: %r set env.prefs[%r] = %r" % (self, prefs_key, val)
        return
    value = property(get_value, set_value)
    def _init_instance(self):
        super(PrefsKey_StateRef, self)._init_instance()
        # also set default value of this prefs key (noting that it may or may not already have a saved value) --
        # i think this (since it does .get with default arg) is the official way:
        self.get_value()
    pass
コード例 #17
0
ファイル: Rect.py プロジェクト: elfion/nanoengineer
class Rect(Widget2D):  # finally working as of 061106
    """
    Rect(width, height, color) renders as a filled x/y-aligned rectangle
    of the given dimensions and color, with the origin on bottomleft,
    and a layout box equal to its size (no margin).

    If color is not given, it will be gray [#e should be a default attrval from env].

    If height is not given, it will be a square (even if width is a formula and/or random).

    See also: RectFrame, ...
    """
    # args
    width = Arg(Width, 5)  # changed 10 to 5 late on 061109
    # Note: Widget2D defines width & height, making this seem circular, but it's ok (see comment in RectFrame)
    height = Arg(Width, width)
    color = ArgOrOption(Color, gray)
    # formulas
    if 0:
        # use this to test whatever scheme we use to detect this error, once we put one in [disabled 061105 until other things work]
        bright = width  ######@@@@@ PROBLEM: in ns, width and bright will have same value, no ordering possible -- how can it tell
        # which one should be used to name the arg? It can't, so it'll need to detect this error and make you use _self. prefix.
        # (in theory, if it could scan source code, or turn on debugging during class imports, it could figure this out...
        #  or you could put the argname in Arg or have an _args decl... but I think just using _self.attr in these cases is simpler.)
        printnim("make sure it complains about bright and width here")
        btop = height
    else:
        if debug_flags.atom_debug:
            printfyi(
                "not yet trying to trigger the error warning for 'bright = width'"
            )  # (since it's nim, even as of 061114 i think)
        bright = _self.width
        btop = _self.height
    # bbottom and bleft are not needed (same as the defaults in Widget2D), except that we use them in the formula for center;
    # it would be more correct to say bleft = _self.bleft, but less efficient I think (not much), and hasn't been tested (should be #e).
    bbottom = 0
    bleft = 0

    ##    center = V_expr( (bright - bleft) / 2.0, (btop - bbottom) / 2.0, 0.0) #070211 #e someday this could be deduced from lbox, generally
    ###e should move this def into Spacer, RectFrame, etc -- or arrange to deduce it from lbox on any Widget2D, somehow...
    #  [070227] hmm, can't it just be moved from here into Widget2D itself? Yes, that works!
    def draw(self):
        glDisable(GL_CULL_FACE)
        draw_filled_rect(
            ORIGIN, DX * self.bright, DY * self.btop, self.fix_color(
                self.color))  #e move fix_color into draw_filled_rect?
        glEnable(GL_CULL_FACE)

    pass
コード例 #18
0
 def _e_override_replace(self, scanner):
     """
     This gets called by a formula scanner when it hits this object in an expr...
     it knows lots of private stuff about FormulaScanner.
     """
     attr = scanner.replacements[_E_ATTR] # a constant_Expr, or an indication of error if this happens (maybe missing then?)
     attr = attr._e_constant_value
     if 1:
         # quick & dirty check for two attrs claiming one arg... come to think of it, is this wrong re inclusion?
         # no, as long as overall replace (of this) happens before this gets called, it'll be ok.
         # but, a better check & better errmsg can be done in scanner if we pass our own args to it.
         # WAIT, i bet this won't actually catch the error, since the replace would actually occur... have to do it in the scanner.
         printnim("improve quick & dirty check for two attrs claiming one arg (it may not even work)")###e
         self.attrs_ive_seen[attr] = 1
         assert len(self.attrs_ive_seen) <= 1, "these attrs claim the same arg: %r" % self.attrs_ive_seen.keys()
         # WARNING: if this works, it will break the use of Arg in future things like lambda_expr or _e_extend
         # where the same Arg() object might get passed to multiple class/attr contexts in runtime-generated exprs with Arg decls.
         # If/when that happens, this object needs to be made immutable, which can be done by removing this code (inside 'if 1'),
         # since it's probably either not working or redundant, according to the comments above and my best guess now. [070321 comment]
     required = self._e_is_required
     arglist = self._e_is_arglist
     pos = scanner.argpos(attr, required, arglist = arglist)
     res = constant_Expr(pos) # this gets included in the scanner's processed expr
     return res
コード例 #19
0
class Widget2D(Widget):
    """1. superclass for widget instances with 2D layout boxes (with default layout-box formulas).
    Also an expr-forming helper class, in this role
    (as is any InstanceOrExpr).
    2. can coerce most drawable instances into (1).
    WARNING: I DON'T YET KNOW IF THOSE TWO ROLES ARE COMPATIBLE.
    """
    # default layout-box formulas
    # bright is bbox size on right, bleft on left (both positive or zero) #e rename, bright is a word
    printnim("lbox defaults are not customizable -- wrong??")
        #k is this still true?? if so, is it wrong? IIRC old cmts suggest a fix... [070121]
    bright = 0
    btop = 0
    bleft = 0
    bbottom = 0
##    width =  bleft   + bright # this would be ok if bleft etc were exprs; since they're constants we have to say _self explicitly
##    height = bbottom + btop
    width =  _self.bleft   + _self.bright
    height = _self.bbottom + _self.btop
    center = V_expr( (_self.bright - _self.bleft) / 2.0, (_self.btop - _self.bbottom) / 2.0, 0.0) # 070227 moved here from Rect
    pass # end of class Widget2D
コード例 #20
0
class CLE(GlueCodeMemoizer):  # not reviewed recently
    """Column list element:
    - handles 0 or more actual rows, perhaps varying in time, as described by one formula arg to Column
    - for each instance that formula evals to, this adds type-specific glue code (memoized for that instance) and delegates to it,
      also making the result available as the value of self.delegate
    - also contains the type-specific glue code ### as methods or classes?
    """
    printnim("CLE not reviewed recently")  ###k

    def _make_wrapped_obj(
        self, fixed_type_instance
    ):  # _c_ means "informal compute method" (not called in standard way)
        "make a new helper object for any fixed_type_instance, based on its type"
        ###e note, the only real "meat" here is a map from .type to the wrapper class CW/CL (and maybe an error value or None value),
        # so we might want an easier way, so you can just give a dict of types -> classes, or so
        t = fixed_type_instance.type  #k
        if t is ListInstanceType:  ####@@@@
            helper = CL(fixed_type_instance)
        else:
            helper = CW(fixed_type_instance)  ###stub, also handle None, error
        return helper

    pass
コード例 #21
0
class widget_env(Delegator):
    "represent an environment for the instantiation and use of widget exprs (with rules and staterefs)"
    # I intend to add this soon here (default value): _self = None
    printnim("SOON I need to add _self = None to class widget_env")  #####@@@@@

    def __init__(self, glpane, staterefs, delegate=None, lexmods={}):
        #e rename glpane?
        #e type of staterefs? [just an external dict, as of 061116 calling code; the 'refs' in the name is to remind you it's not owned]
        #e rules/lexenv too?
        #e ipath? [061116: no, that's separate, tho if we end up splitting it by state-layer,
        #    we might have to change that, or let env have ipaths per layer with the separately-passed one relative to all those ]
        self.glpane = glpane
        self.staterefs = staterefs  ###k
        ###KLUGES, explained below [061028]:
        Delegator.__init__(self,
                           delegate)  # this will be None or the parent env
        for k, v in lexmods.iteritems():
            setattr(
                self, k, v
            )  # worst part of the kluge -- dangerous if symnames overlap method names
            # next worst part: special methods like __repr__ end up delegating
        pass

    def __repr__(
        self
    ):  # without this, Delegator delegates __repr__ ultimately to None, so "%r" % self == "None"!!!
        return "<widget_env at %#x (_self = %r)>" % (
            id(self), getattr(self, '_self', '<none>'))  # revised 070120

    __str__ = __repr__  #k guess: might be needed for same reason as __repr__

    def understand_expr(self, expr, lexmods=None):
        print "understand_expr ran"  ###070112 -- never happens
        "#doc; retval contains env + lexmods, and can be trusted to understand itself."
        # only the "rules" in self are needed for this, not the glpane & staterefs! so put this method in a subobject! #e
        assert not lexmods, "lexmods are nim"  ###@@@
        return expr  ####@@@@ STUB but might sometimes work
        #e [if we ever need this, can we just use something like lexenv_Expr?? but with dynenv bindings too? 070112 guess comment]
    def make(self, expr, ipath, eval=True):  #k args?? ####@@@@
        """Make and return an instance of the given expr (understood or not) in self.
        The instance should store its state under the index-path ipath [#doc format].
        """
        # print "make ran (eval = %r)" % eval # happens before you make a new main instance... 070121 or when demo_drag makes a node
        #e ipath guess: a list of 2 or 3 elts, linked list inner first, maybe append an interning of it
        #e look for rules; check if understood;
        #e Q: is this memoized? does it allocate anything like a state obj ref, or was that already done by customizing this env?
        ## print "making",expr,ipath
        # assume it's an understood expr at this point
        #
        # update 070117 re EVAL_REFORM: maybe we'll need to be an explicit noop for numbers or Instances (non-pure-exprs) --
        # we will if some calls to _e_make_in are changed into calls to this, which seems likely. #k
        # The way to do that is to do what _i_instance does -- it calls some helper function to decide what's idempotent for make.
        if eval:
            # new feature 070118 -- fixes testexpr_19f when no testbed and when not EVAL_REFORM
            # (guess, unconfirmed: its failure then is an old bug predating EVAL_REFORM, not a new bug)
            eval_ipath = (
                '!env-eval', ipath
            )  # I'm guessing this had better differ from the one passed to _e_make_in -- not sure
            expr = expr._e_eval(self, eval_ipath)
            #e it'd be nice to print a notice if this changed it, but it surely will by wrapping a new lexenv_Expr if nothing else,
            # so it's too hard to tell if it *really* did.
        try:
            res = expr._e_make_in(self, ipath)
        except:  #070118
            print "following exception in env.make's _e_make_in call concerns expr %r and ipath %r: " % (
                expr, ipath)
            raise
        return res

    def with_literal_lexmods(self, **lexmods):
        "Return a new rule-env inheriting from this one, different in the lexmods expressed as keyword arguments"
        return self.with_lexmods(lexmods)

    def with_lexmods(self, lexmods):
        "Return a new rule-env inheriting from this one, different in the given lexmods (a dict from symbolnames to values)"
        ###e need to know if env vars are accessed by attr, key, or private access function only, like lexval_of_symbol;
        # and whether glpane is a lexvar like the rest (and if so, its toplevel symbol name);
        # and about staterefs.
        # For now, to make tests work, it's enough if there's some way to grab syms with inheritance...
        # use Delegator? it caches, that's undesirable, and it uses attr not key, which seems wrong... otoh it's easy to try.
        # So I'll try it temporarily, but not depend on attr access to syms externally. [061028]
        return self.__class__(self.glpane,
                              self.staterefs,
                              delegate=self,
                              lexmods=lexmods)

    def lexval_of_symbol(self, sym):
        # 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] ####@@@@
        # btw, so far this is probably only used for _self.
        # As of 061114, also for _this_whatever -- no, that uses our helper lexval_of_symbolname.
        name = sym._e_name
        return self.lexval_of_symbolname(name, sym)

    def lexval_of_symbolname(self, name, dflt):
        #e default for dflt? used to be the sym, even now could be an imported (so identical) sym
        # removed printfyi warning, 070131:
        ##        if name not in ('_self','_app') and not name.startswith('_this_'):
        ##            printfyi("lexval_of_symbolname other than _self, _app, or _this_xxx: %s" % (name,) )
        # kluge:
        return getattr(self, name, dflt)

    ## newenv = dynenv.dynenv_with_lexenv(lexenv) #e might be renamed; might be turned into a helper function rather than a method
    def dynenv_with_lexenv(self, lexenv):
        "#doc"
        return lexenv  ##### 070109 is _app bug fixed even w/ this? yes, it was unrelated. WE STILL NEED NEW CODE HERE. ####BUG
        # kluge 070109: do just enough to see if using this fixes the bug i suspect it might -- ###WRONG IN GENERAL (and disabled too)
        if getattr(self, '_app', None) is not getattr(lexenv, '_app', None):
            print "fyi: dynenv_with_lexenv makes a difference for _app: %r vs %r" % \
                  ( getattr(self, '_app', None) , getattr(lexenv, '_app', None) ) ### remove when works
        if not hasattr(self, '_app'):
            return lexenv
        return lexenv.with_literal_lexmods(
            _app=self._app
        )  # really this is a "dynamic mod" as hardcoded in the name _app (w/in current kluge)

    def _e_eval(self, expr, ipath):  #070131
        "evaluate an expr (or constant) in this env, with given ipath"
        return canon_expr(expr)._e_eval(self, ipath)

    pass
コード例 #22
0
    def _e_eval_lval(
            self, env,
            ipath):  #070119 also print _e_eval_lval calls [maybe untested]
        assert env
        the_expr = self._e_args[0]
        res = the_expr._e_eval_lval(env, ipath)
        print_compact_stack(
            "debug_evals_of_Expr(%r) eval-lvals it to %r at: " %
            (the_expr, res))  #k does this ever happen?
        return res

    pass


printnim(
    "bug in DebugPrintAttrs, should inherit from IorE not Widget, to not mask what that adds to IorE from DelegatingMixin"
)  ###BUG


class DebugPrintAttrs(
        Widget, DelegatingMixin
):  # guess 061106; revised 061109, works now (except for ArgList kluge)
    """delegate to our arg, but print specified attrvalues before each draw call
    """
    #e might be useful to also print things like x,y,depth hitpoint window coords & 3d coords (see obs code DebugDraw, removed after cvs rev 1.3)
    delegate = Arg(Anything)
    ## attrs = ArgList(str) # as of 061109 this is a stub equal to Arg(Anything)
    attrs = Arg(Anything, [])

    def draw(self):
        guy = self.delegate
コード例 #23
0
    def _CV__i_instance_CVdict(self, index):
        """
        [private]
        value-recomputing function for self._i_instance_CVdict.
        Before calling this, the caller must store an expr for this instance
        into self._i_instance_decl_data[index] (an ordinary dict).
           If it's permitted for that expr to change with time (which I doubt, but don't know yet for sure #k),
        then whenever the caller changes it (other than when initially setting it), the caller must invalidate
        the entry with the same key (our index arg) in the LvalDict2 that implements self._i_instance_CVdict
        (but the API for the caller to do that is not yet worked out #e).
           (Implem note: _CV_ stands for "compute value" to ExprsMeta, which implements the LvalDict2 associated with this.
        This method needs no corresponding _CK_ keylist function, since any key (instance index) asked for is assumed valid.)
        """
        assert self._e_is_instance
        # This method needs to create a new instance, by instantiating expr and giving it index.
        # Implem notes:
        # - the glue code added by _CV_ from self._i_instance_CVdict to this method (by ExprsMeta) uses LvalDict2
        #   to cache values computed by this method, and recompute them if needed (which may never happen, I'm not sure).
        # - the access to self._i_instance_decl_data[index] is not usage tracked;
        #   thus if we change it above w/o error, an inval is needed.
        data = self._i_instance_decl_data[index]
        expr, lvalflag = data # 061204
        ## print "fyi, using kid expr %r" % expr
        # (these tend to be longish, and start with eval_Expr -- what we'd rather print is the result of the first eval it does)
            # Note, this expr can be very simplifiable, if it came from an Arg macro,
            # but present code [061105] reevals the full macro expansion each time -- suboptimal.
            # To fix, we'd need an "expr simplify", whether we used it only once or not...
            # the reason to use it more than once is if it becomes partly final at some later point than when it starts out.
            # The simplify implem would need decls about finality of, e.g., getting of some bound methods and (determinism of)
            # their retvals -- namely (for Arg macro etc) for _i_instance and _i_grabarg and maybe more.
            # Feasible but not simple; worthwhile optim someday but not right away. ##e
        if not EVAL_REFORM:
            # three increasingly strict asserts:
            assert expr is not None
            assert is_Expr(expr), "not is_Expr: %r" % (expr,)
            assert is_pure_expr(expr) ###k?? what if someone passes an instance -- is that permitted, but a noop for instantiation??
            assert is_Expr_pyinstance(expr), "can't instantiate a class: %r" % (expr,) # new, 070117, untested### -- i'm not even sure it's correct
            # also assume expr is "canonicalized" and even "understood" -- not sure if this is justified
            printnim("don't we need understand_expr somewhere in here? (before kidmaking in IorE)") ###@@@
        else:
            # EVAL_REFORM case 070117
            if not (is_pure_expr(expr) and is_Expr_pyinstance(expr)):
                print "this should never happen as of 070118 since we handle it above: non pure expr %r in _CV__i_instance_CVdict" % (expr,)
                ## print "FYI: EVAL_REFORM: _CV__i_instance_CVdict is identity on %r" % (expr,)
                # this is routine on e.g. None, small ints, colors, other tuples... and presumably Instances (not tested)
                assert not lvalflag # see comments at start of _i_instance
                return expr
            pass
        ####e:  [061105] is _e_eval actually needing to be different from _e_make_in?? yes, _e_eval needs to be told _self
        # and the other needs to make one... no wait, wrong, different selves --
        # the _self told to eval is the one _make_in *should make something inside of*! (ie should make a kid of)
        # So it may be that these are actually the same thing. (See paper notes from today for more about this.)
        # For now, tho, we'll define _e_make_in on OpExpr to use eval. [not done, where i am]
        # actually this is even faster -- review sometime (note, in constant_Expr they're both there & equiv #k): ###@@@
        ## this is just the kid expr: print "_CV__i_instance_CVdict needs to make expr %r" % (expr,)
##        if hasattr(expr, '_e_make_in'):
##            print("REJECTED using _e_make_in case, on a pyinstance of class %s" % expr.__class__.__name__)###was printfyi til 061208 921p
##            ## res = expr._e_make_in(env, index_path)
##                #k we might have to fix bugs caused by not using this case, by defining (or modifying?) defs of _e_eval on some classes;
##                # addendum 061212, we now do that on If_expr.
        if not EVAL_REFORM:
            # WARNING: following code is very similar to _i_eval_dfltval_expr as of 061203
            # printfyi("used _e_eval case (via _e_compute_method)") # this case is usually used, as of 061108 -- now always, 061110
            # note: this (used-to-be-redundantly) grabs env from self
            try:
                res = expr._e_compute_method(self, index, _lvalue_flag = lvalflag)() ##e optim someday: inline this
                    # 061105 bug3, if bug2 was in held_dflt_expr and bug1 was 'dflt 10'
            except:
                # we expect caller to exit now, so we might as well print this first: [061114]
                print "following exception concerns self = %r, index = %r in _CV__i_instance_CVdict calling _e_compute_method" % \
                      (self, index)
                raise
        else:
            # EVAL_REFORM case, 070117
            if kluge070119:
                # also pass an env retrieved from...
                env = self._i_instance_decl_env[index]
                env, ipath = self._i_env_ipath_for_formula_at_index( index, env) # note: retval's env is modified from the one passed
                    # THIS MUST BE WHERE THE INCORRECT BINDING _self = self gets added, in the kluge070119 ###BUG in _5x! [070120 844p]
                    #   GUESS at basic bug: an Instance self really needs to know two envs: the one for its args (_self refers to
                    # whoeever lexically created the expr they were made from), and the one for their internal formulae (_self = self).
                    # self.env is the one for the args (since it's thought of as "self's (outer) environment"),
                    # and the one for internal formulae has (until now -- this should change #e) been recreated as needed in
                    # _e_compute_method and now in _i_env_ipath_for_formula_at_index, by extending self.env by _self = self.
                    #   But to be correct, this should be done BEFORE the burrowing and env-extension done by the kluge070119,
                    # but in this wrong current code it's done after it. The old code also had wrongness of order, in principle
                    # (doing this _self addition here rather than in env_for_args, with env_for_args done first when it should
                    # be done 2nd), but it didn't matter since env_for_args only added _this_xxx and _my. WAIT, THAT'S WRONG --
                    # env_for_args is for external (in lexenv) args, so it should have SAME _self as self.env, so it's correct now,
                    # and never gets or needs _self = self, either before or after its _my and _this_xxx bindings.
                    #   What we need here is NOT env_for_args but env_for_internal_formulae. It should be used for dflt exprs in Arg,
                    # and for all exprs sitting on class assignments. We've been making it before *using* those formulae
                    # (probably getting it onto dflt exprs only because they end up being *used* in the right place for that).
                    # We've been making it in each call of _i_env_ipath_for_formula_at_index or _e_compute_method, but we ought to
                    # make it once and let those use it, and make sure that happens before the env mods from the burrowing done by
                    # kluge070119. (We can't make it in the class (eg ExprsMeta) -- we have to wait until _init_instance or so,
                    # because it depends on self which is only known around then.)
                    # 
                    # SUGGESTED FIX ###e: make self.env_for_internal_formulae (#e shorter name -- env_for_formulae?)
                    # before (??) calling _init_instance [or after if _init_instance can modify self.env ##k];
                    # use it in _i_env_ipath_for_formula_at_index and some of our uses of _e_compute_method;
                    # and review all uses of self.env for whether they ought to be env_for_formulae.
                    # Doing it 070120 circa 942p -- I made _C_env_for_formulae instead of setting it in _init_instance
                    # (optim, since some Instances never need it (I hope -- not sure) and since it creates a cyclic ref.
            else:
                env, ipath = self._i_env_ipath_for_formula_at_index( index) # equivalent to how above other case computes them
            assert not lvalflag # see comments at start of _i_instance
            res = expr._e_make_in(env,ipath) # only pure IorE exprs have this method; should be ok since only they are returned from expr evals
        return res # from _CV__i_instance_CVdict
コード例 #24
0
def _ArgOption_helper(attr_expr,
                      argpos_expr,
                      type_expr,
                      dflt_expr,
                      _lvalue_flag=False,
                      _arglist=False,
                      **moreopts):
    """
    [private helper for Arg, Option, and maybe ArgOrOption]

    attr_expr should be None, or some sort of expr (in practice always _E_ATTR so far)
      that will get replaced by a constant_Expr for the current attr (in ExprsMeta's FormulaScanner),
      according to whether the current attr should be part of the index and a public option-name for supplying the arg
      (we make sure those conditions are the same). [#e Note that if someday we wanted to include f(attr) in the index,
      but still use attr alone as an option name, we'd have to modify this to permit both f(attr) (or f) and attr to be passed.]

    argpos_expr should similarly be None, or some sort of expr (in practice a private subclass of internal_Expr)
      that will get replaced by a constant_Expr for the argument position (an int) that should be allocated to the current attr's arg
      (determined in ExprsMeta's FormulaScanner by allocating posns 0,1,2,etc to newly seen arg-attrs, whether or not the attr itself
      is public for that arg).

    type_expr ###doc, passed herein to canon_type

    dflt_expr ###doc, can also be _E_DFLT_FROM_TYPE_ or [handled in caller i think, but survives here unmatteringly] _E_REQUIRED_ARG_;
        will be passed through canon_expr

    _lvalue_flag is a private option used by LvalueArg.

    _arglist is a private option used by ArgList.
    """
    if _lvalue_flag:
        printnim("_lvalue_flag's proper interaction with dflt_expr is nim"
                 )  # in all cases below
        ### guess: we want it to be an expr for a default stateref
    global _self  # fyi
    type_expr = canon_type(type_expr)
    printnim(
        "can type_expr legally be self-dependent and/or time-dependent? ###k I guess that's nim in current code!"
    )  #070115 comment
    if _arglist:
        # new feature 070321. The type is applied to each element, but the default value is for the entire list --
        # OTOH, when would it ever be used, since even if no args are supplied, the list can be formed??
        # Probably it would only be used when the list was 0 length, and could meaningfully be [], (), or another list-like thing...
        # this is all a guess and I probably won't even review this code for this issue now, unless it fails when tried. ####k
        type_expr = tuple_Expr(
            type_expr
        )  # type-coerce the value to a list of the given type [070321 guess] ###e or list_Expr???
    if dflt_expr is _E_DFLT_FROM_TYPE_:
        dflt_expr = default_expr_from_type_expr(type_expr)
        ## note [070115], this would be impossible for time-dependent types! and for self-dep ones, possible but harder than current code.
        assert is_pure_expr(dflt_expr)  #k guess 061105
    else:
        dflt_expr = canon_expr(
            dflt_expr
        )  # hopefully this finally will fix dflt 10 bug, 061105 guesshope ###k [works for None, 061114]
        assert is_pure_expr(
            dflt_expr
        )  # not sure this is redundant, since not sure if canon_expr checks for Instance ###k
        printnim("not sure if canon_expr checks for Instance")
    # Note on why we use explicit call_Expr & getattr_Expr below,
    # rather than () and . notation like you can use in user-level formulae (which python turns into __call__ and getattr),
    # to construct Exprs like _self._i_grabarg( attr_expr, ...):
    # it's only to work around safety features which normally detect that kind of Expr-formation (getattr on _i_* or _e_*,
    # or getattr then call) as a likely error. These safety features are very important, catching errors that would often lead
    # to hard-to-diagnose bugs (when our code has an Expr but thinks it has an Instance), so it's worth the trouble.
    held_dflt_expr = hold_Expr(dflt_expr)
    # Note, this gets evalled back into dflt_expr (treated as inert, may or may not be an expr depending on what it is right here)
    # by the time _i_grabarg sees it (the eval is done when the call_Expr evals its args before doing the call).
    # So if we wanted _i_grabarg to want None rather than _E_REQUIRED_ARG_ as a special case, we could change to that (there & here).
    grabopts = {}
    if _arglist:
        grabopts.update(dict(_arglist=constant_Expr(_arglist)))
    grabarg_expr = call_Expr(getattr_Expr(_self, '_i_grabarg'), attr_expr,
                             argpos_expr, held_dflt_expr, **grabopts)
    # comments 070115:
    # - This will eval to an expr which depends on self but not on time. We could optim by wrapping it
    # (or declaring it final) in a way which effectively replaced it with its value-expr when first used.
    # (But it's not obvious where to store the result of that, since the exprs being returned now are assigned to classes
    #  and will never be specific to single selfs. Do we need an expr to use here, which can cache its own info in self??
    #  Note: AFAIK, self will be the same as what _self gets replaced with when this is used. (We ought to assert that.) ###e)
    # - Further, grabarg_expr is probably supposed to be wrapped *directly* by eval_Expr, not with type_expr inside. I think I'll
    # make that change right now and test it with EVAL_REFORM still False, since I think it's always been required, as said
    # in other comments here. DOING THIS NOW.
    if attr_expr is not None and argpos_expr is not None:
        # for ArgOrOption, use a tuple of a string and int (attr and argpos) as the index
        index_expr = tuple_Expr(attr_expr, argpos_expr)
    elif attr_expr is None and argpos_expr is None:
        assert 0, "attr_expr is None and argpos_expr is None ..."
    elif attr_expr is not None:
        # for Option, use a plain attr string as the index
        index_expr = attr_expr
    else:
        assert argpos_expr is not None
        # for Arg, use a plain int as the index
        # (note: ExprsMeta replaces argpos_expr with that int wrapped in constant_Expr, but later eval pulls out the raw int)
        index_expr = argpos_expr


# see if this is fixed now, not that it means much since we were using a stub... but who knows, maybe the stub was buggy
# and we compensated for that and this could if so cause a bug:
##    printnim("I suspect type_expr (stub now) is included wrongly re eval_Expr in _ArgOption_helper, in hindsight 061117")
##        ### I suspect the above, because grabarg expr needs to be evalled to get the expr whose type coercion we want to instantiate
    res = Instance(_type_coercion_expr(type_expr, eval_Expr(grabarg_expr)),
                   _index_expr=index_expr,
                   _lvalue_flag=_lvalue_flag,
                   **moreopts)
    # note: moreopts might contain _noinstance = True, and if so, Instance normally returns its first arg unchanged
    # (depending on other options).
    # 070115 replaced eval_Expr( type_expr( grabarg_expr)) with _type_coercion_expr( type_expr, eval_Expr(grabarg_expr) )
    return res  # from _ArgOption_helper
コード例 #25
0
 def _i_grabarg_0(self, attr, argpos, dflt_expr, _arglist=False):
     """
     [private helper for _i_grabarg]
     return the pair (external-flag, expr to use for this arg)
     """
     # i think dflt_expr can be _E_REQUIRED_ARG_, or any (other) expr
     if dflt_expr is _E_REQUIRED_ARG_:
         required = True
     else:
         required = False
         if isinstance(dflt_expr, _E_REQUIRED_ARG_.__class__
                       ) and dflt_expr._e_name.startswith("_E_"):
             print "possible bug: dflt_expr for arg %r in %r is a Symbol %r named _E_* (suspicious internal symbol??)" % \
                   ( (attr, argpos), self, dflt_expr )
             # kluge sanity check for _E_ATTR or other internal symbols [revised 070131]
     if attr is not None and argpos is not None:
         printnim(
             "should assert that no expr gets same arg twice (positionally and as named option)"
         )  ###e
     if attr is not None:
         # try to find it in _e_kws; I suppose the cond is an optim or for clarity, since None won't be a key of _e_kws
         try:
             return True, self._e_kws[attr]
         except KeyError:
             pass
     if argpos is not None:
         try:
             res = self._e_args[argpos]
         except IndexError:  # "tuple index out of range"
             pass
         else:
             # res was the arg provided at argpos
             if _arglist:
                 res = tuple_Expr(*self._e_args[argpos:])
             return True, res
     # no arg was provided at argpos
     if _arglist:
         # [_arglist supports ArgList, a new feature 070321]
         # no args were provided for an ArgList -- use dflt_expr, or tuple_Expr().
         # (Note: we don't use list_Expr. See comments near def of ArgList.)
         if required:
             return False, tuple_Expr()  #k probably equiv to canon_expr(())
             ##k optim-related Q: what should external_flag be in this case? [070321 Q]
         else:
             return False, dflt_expr  # note: nothing fundamental requires that dflt_expr evals/instantiates to a list or tuple,
             # though it would usually be an error if it doesn't (depending on how the class body formulae were written).
             # It's not an error per se, just likely to be one given how ArgList is conventionally used.
     else:
         # ordinary arg was not provided -- error or use dflt_expr
         if required:
             print "error: required arg %r or %r not provided to %r. [#e Instance-maker should have complained!] Using None." % \
                   (attr, argpos, self)
             # Note: older code returned literally None, not an expr, which caused a bug in caller which tried to _e_eval the result.
             # Once we've printed the above, we might as well be easier to debug and not cause that bug right now,
             # so we'll return a legal expr -- in some few cases this will not cause an error, making this effectively a warning,
             # "missing args are interpreted as None". Review this later. [061118]
             printnim(
                 "a better error retval might be a visible error indicator, if the type happens to be a widget"
             )  ###e
             #e I think we don't know the type here -- but we can return a general error-meaning-thing (incl error msg text)
             # and let the type-coercers do with it what they will. Or we could return something equivalent to an exception
             # (in our interpreted language) and revise our eval semantics to handle that kind of thing. [061118]
             return False, canon_expr(None)
             ##k optim-related Q: what should external_flag be in this case? [070321 Q]
         else:
             return False, dflt_expr
     pass  # above should not _e_eval or canon_expr without review -- should return an arg or dflt expr, not its value
コード例 #26
0
    def _CV__i_instance_CVdict(self, index):
        """
        [private]
        value-recomputing function for self._i_instance_CVdict.
        Before calling this, the caller must store an expr for this instance
        into self._i_instance_decl_data[index] (an ordinary dict).
           If it's permitted for that expr to change with time (which I doubt, but don't know yet for sure #k),
        then whenever the caller changes it (other than when initially setting it), the caller must invalidate
        the entry with the same key (our index arg) in the LvalDict2 that implements self._i_instance_CVdict
        (but the API for the caller to do that is not yet worked out #e).
           (Implem note: _CV_ stands for "compute value" to ExprsMeta, which implements the LvalDict2 associated with this.
        This method needs no corresponding _CK_ keylist function, since any key (instance index) asked for is assumed valid.)
        """
        assert self._e_is_instance
        # This method needs to create a new instance, by instantiating expr and giving it index.
        # Implem notes:
        # - the glue code added by _CV_ from self._i_instance_CVdict to this method (by ExprsMeta) uses LvalDict2
        #   to cache values computed by this method, and recompute them if needed (which may never happen, I'm not sure).
        # - the access to self._i_instance_decl_data[index] is not usage tracked;
        #   thus if we change it above w/o error, an inval is needed.
        data = self._i_instance_decl_data[index]
        expr, lvalflag = data  # 061204
        ## print "fyi, using kid expr %r" % expr
        # (these tend to be longish, and start with eval_Expr -- what we'd rather print is the result of the first eval it does)
        # Note, this expr can be very simplifiable, if it came from an Arg macro,
        # but present code [061105] reevals the full macro expansion each time -- suboptimal.
        # To fix, we'd need an "expr simplify", whether we used it only once or not...
        # the reason to use it more than once is if it becomes partly final at some later point than when it starts out.
        # The simplify implem would need decls about finality of, e.g., getting of some bound methods and (determinism of)
        # their retvals -- namely (for Arg macro etc) for _i_instance and _i_grabarg and maybe more.
        # Feasible but not simple; worthwhile optim someday but not right away. ##e
        if not EVAL_REFORM:
            # three increasingly strict asserts:
            assert expr is not None
            assert is_Expr(expr), "not is_Expr: %r" % (expr, )
            assert is_pure_expr(
                expr
            )  ###k?? what if someone passes an instance -- is that permitted, but a noop for instantiation??
            assert is_Expr_pyinstance(
                expr), "can't instantiate a class: %r" % (
                    expr,
                )  # new, 070117, untested### -- i'm not even sure it's correct
            # also assume expr is "canonicalized" and even "understood" -- not sure if this is justified
            printnim(
                "don't we need understand_expr somewhere in here? (before kidmaking in IorE)"
            )  ###@@@
        else:
            # EVAL_REFORM case 070117
            if not (is_pure_expr(expr) and is_Expr_pyinstance(expr)):
                print "this should never happen as of 070118 since we handle it above: non pure expr %r in _CV__i_instance_CVdict" % (
                    expr, )
                ## print "FYI: EVAL_REFORM: _CV__i_instance_CVdict is identity on %r" % (expr,)
                # this is routine on e.g. None, small ints, colors, other tuples... and presumably Instances (not tested)
                assert not lvalflag  # see comments at start of _i_instance
                return expr
            pass
        ####e:  [061105] is _e_eval actually needing to be different from _e_make_in?? yes, _e_eval needs to be told _self
        # and the other needs to make one... no wait, wrong, different selves --
        # the _self told to eval is the one _make_in *should make something inside of*! (ie should make a kid of)
        # So it may be that these are actually the same thing. (See paper notes from today for more about this.)
        # For now, tho, we'll define _e_make_in on OpExpr to use eval. [not done, where i am]
        # actually this is even faster -- review sometime (note, in constant_Expr they're both there & equiv #k): ###@@@
        ## this is just the kid expr: print "_CV__i_instance_CVdict needs to make expr %r" % (expr,)
##        if hasattr(expr, '_e_make_in'):
##            print("REJECTED using _e_make_in case, on a pyinstance of class %s" % expr.__class__.__name__)###was printfyi til 061208 921p
##            ## res = expr._e_make_in(env, index_path)
##                #k we might have to fix bugs caused by not using this case, by defining (or modifying?) defs of _e_eval on some classes;
##                # addendum 061212, we now do that on If_expr.
        if not EVAL_REFORM:
            # WARNING: following code is very similar to _i_eval_dfltval_expr as of 061203
            # printfyi("used _e_eval case (via _e_compute_method)") # this case is usually used, as of 061108 -- now always, 061110
            # note: this (used-to-be-redundantly) grabs env from self
            try:
                res = expr._e_compute_method(
                    self, index,
                    _lvalue_flag=lvalflag)()  ##e optim someday: inline this
                # 061105 bug3, if bug2 was in held_dflt_expr and bug1 was 'dflt 10'
            except:
                # we expect caller to exit now, so we might as well print this first: [061114]
                print "following exception concerns self = %r, index = %r in _CV__i_instance_CVdict calling _e_compute_method" % \
                      (self, index)
                raise
        else:
            # EVAL_REFORM case, 070117
            if kluge070119:
                # also pass an env retrieved from...
                env = self._i_instance_decl_env[index]
                env, ipath = self._i_env_ipath_for_formula_at_index(
                    index,
                    env)  # note: retval's env is modified from the one passed
                # THIS MUST BE WHERE THE INCORRECT BINDING _self = self gets added, in the kluge070119 ###BUG in _5x! [070120 844p]
                #   GUESS at basic bug: an Instance self really needs to know two envs: the one for its args (_self refers to
                # whoeever lexically created the expr they were made from), and the one for their internal formulae (_self = self).
                # self.env is the one for the args (since it's thought of as "self's (outer) environment"),
                # and the one for internal formulae has (until now -- this should change #e) been recreated as needed in
                # _e_compute_method and now in _i_env_ipath_for_formula_at_index, by extending self.env by _self = self.
                #   But to be correct, this should be done BEFORE the burrowing and env-extension done by the kluge070119,
                # but in this wrong current code it's done after it. The old code also had wrongness of order, in principle
                # (doing this _self addition here rather than in env_for_args, with env_for_args done first when it should
                # be done 2nd), but it didn't matter since env_for_args only added _this_xxx and _my. WAIT, THAT'S WRONG --
                # env_for_args is for external (in lexenv) args, so it should have SAME _self as self.env, so it's correct now,
                # and never gets or needs _self = self, either before or after its _my and _this_xxx bindings.
                #   What we need here is NOT env_for_args but env_for_internal_formulae. It should be used for dflt exprs in Arg,
                # and for all exprs sitting on class assignments. We've been making it before *using* those formulae
                # (probably getting it onto dflt exprs only because they end up being *used* in the right place for that).
                # We've been making it in each call of _i_env_ipath_for_formula_at_index or _e_compute_method, but we ought to
                # make it once and let those use it, and make sure that happens before the env mods from the burrowing done by
                # kluge070119. (We can't make it in the class (eg ExprsMeta) -- we have to wait until _init_instance or so,
                # because it depends on self which is only known around then.)
                #
                # SUGGESTED FIX ###e: make self.env_for_internal_formulae (#e shorter name -- env_for_formulae?)
                # before (??) calling _init_instance [or after if _init_instance can modify self.env ##k];
                # use it in _i_env_ipath_for_formula_at_index and some of our uses of _e_compute_method;
                # and review all uses of self.env for whether they ought to be env_for_formulae.
                # Doing it 070120 circa 942p -- I made _C_env_for_formulae instead of setting it in _init_instance
                # (optim, since some Instances never need it (I hope -- not sure) and since it creates a cyclic ref.
            else:
                env, ipath = self._i_env_ipath_for_formula_at_index(
                    index)  # equivalent to how above other case computes them
            assert not lvalflag  # see comments at start of _i_instance
            res = expr._e_make_in(
                env, ipath
            )  # only pure IorE exprs have this method; should be ok since only they are returned from expr evals
        return res  # from _CV__i_instance_CVdict
コード例 #27
0
 def _i_grabarg_0( self, attr, argpos, dflt_expr, _arglist = False):
     """
     [private helper for _i_grabarg]
     return the pair (external-flag, expr to use for this arg)
     """
     # i think dflt_expr can be _E_REQUIRED_ARG_, or any (other) expr
     if dflt_expr is _E_REQUIRED_ARG_:
         required = True
     else:
         required = False
         if isinstance(dflt_expr, _E_REQUIRED_ARG_.__class__) and dflt_expr._e_name.startswith("_E_"):
             print "possible bug: dflt_expr for arg %r in %r is a Symbol %r named _E_* (suspicious internal symbol??)" % \
                   ( (attr, argpos), self, dflt_expr )
             # kluge sanity check for _E_ATTR or other internal symbols [revised 070131]
     if attr is not None and argpos is not None:
         printnim("should assert that no expr gets same arg twice (positionally and as named option)")###e
     if attr is not None:
         # try to find it in _e_kws; I suppose the cond is an optim or for clarity, since None won't be a key of _e_kws
         try:
             return True, self._e_kws[attr]
         except KeyError:
             pass
     if argpos is not None:
         try:
             res = self._e_args[argpos]
         except IndexError: # "tuple index out of range"
             pass
         else:
             # res was the arg provided at argpos
             if _arglist:
                 res = tuple_Expr(* self._e_args[argpos:])
             return True, res                
     # no arg was provided at argpos
     if _arglist:
         # [_arglist supports ArgList, a new feature 070321]
         # no args were provided for an ArgList -- use dflt_expr, or tuple_Expr().
         # (Note: we don't use list_Expr. See comments near def of ArgList.)
         if required:
             return False, tuple_Expr() #k probably equiv to canon_expr(())
                  ##k optim-related Q: what should external_flag be in this case? [070321 Q]
         else:
             return False, dflt_expr # note: nothing fundamental requires that dflt_expr evals/instantiates to a list or tuple,
                 # though it would usually be an error if it doesn't (depending on how the class body formulae were written).
                 # It's not an error per se, just likely to be one given how ArgList is conventionally used.
     else:
         # ordinary arg was not provided -- error or use dflt_expr
         if required:
             print "error: required arg %r or %r not provided to %r. [#e Instance-maker should have complained!] Using None." % \
                   (attr, argpos, self)
             # Note: older code returned literally None, not an expr, which caused a bug in caller which tried to _e_eval the result.
             # Once we've printed the above, we might as well be easier to debug and not cause that bug right now,
             # so we'll return a legal expr -- in some few cases this will not cause an error, making this effectively a warning,
             # "missing args are interpreted as None". Review this later. [061118]
             printnim("a better error retval might be a visible error indicator, if the type happens to be a widget")###e
                 #e I think we don't know the type here -- but we can return a general error-meaning-thing (incl error msg text)
                 # and let the type-coercers do with it what they will. Or we could return something equivalent to an exception
                 # (in our interpreted language) and revise our eval semantics to handle that kind of thing. [061118]
             return False, canon_expr(None)
                 ##k optim-related Q: what should external_flag be in this case? [070321 Q]
         else:
             return False, dflt_expr
     pass # above should not _e_eval or canon_expr without review -- should return an arg or dflt expr, not its value
コード例 #28
0
ファイル: debug_exprs.py プロジェクト: elfion/nanoengineer
        assert len(self.args) == 1
    def _e_eval(self, env, ipath):
        assert env
        the_expr = self._e_args[0]
        res = the_expr._e_eval(env, ipath)
        print_compact_stack("debug_evals_of_Expr(%r) evals it to %r at: " % (the_expr, res)) # this works
        return res
    def _e_eval_lval(self, env, ipath):#070119 also print _e_eval_lval calls [maybe untested]
        assert env
        the_expr = self._e_args[0]
        res = the_expr._e_eval_lval(env, ipath)
        print_compact_stack("debug_evals_of_Expr(%r) eval-lvals it to %r at: " % (the_expr, res)) #k does this ever happen?
        return res
    pass

printnim("bug in DebugPrintAttrs, should inherit from IorE not Widget, to not mask what that adds to IorE from DelegatingMixin")###BUG
class DebugPrintAttrs(Widget, DelegatingMixin): # guess 061106; revised 061109, works now (except for ArgList kluge)
    """delegate to our arg, but print specified attrvalues before each draw call
    """
    #e might be useful to also print things like x,y,depth hitpoint window coords & 3d coords (see obs code DebugDraw, removed after cvs rev 1.3)
    delegate = Arg(Anything)
    ## attrs = ArgList(str) # as of 061109 this is a stub equal to Arg(Anything)
    attrs = Arg(Anything, [])
    def draw(self):
        guy = self.delegate
        print "guy = %r" % (guy, )
        ## attrs = self.args[1:]
        attrs = self.attrs
        if type(attrs) == type("kluge"):
            attrs = [attrs]
            printnim("need to unstub ArgList in DebugPrintAttrs")
コード例 #29
0
def _ArgOption_helper( attr_expr, argpos_expr, type_expr, dflt_expr, _lvalue_flag = False, _arglist = False, **moreopts ):
    """
    [private helper for Arg, Option, and maybe ArgOrOption]

    attr_expr should be None, or some sort of expr (in practice always _E_ATTR so far)
      that will get replaced by a constant_Expr for the current attr (in ExprsMeta's FormulaScanner),
      according to whether the current attr should be part of the index and a public option-name for supplying the arg
      (we make sure those conditions are the same). [#e Note that if someday we wanted to include f(attr) in the index,
      but still use attr alone as an option name, we'd have to modify this to permit both f(attr) (or f) and attr to be passed.]

    argpos_expr should similarly be None, or some sort of expr (in practice a private subclass of internal_Expr)
      that will get replaced by a constant_Expr for the argument position (an int) that should be allocated to the current attr's arg
      (determined in ExprsMeta's FormulaScanner by allocating posns 0,1,2,etc to newly seen arg-attrs, whether or not the attr itself
      is public for that arg).

    type_expr ###doc, passed herein to canon_type

    dflt_expr ###doc, can also be _E_DFLT_FROM_TYPE_ or [handled in caller i think, but survives here unmatteringly] _E_REQUIRED_ARG_;
        will be passed through canon_expr

    _lvalue_flag is a private option used by LvalueArg.

    _arglist is a private option used by ArgList.
    """
    if _lvalue_flag:
        printnim("_lvalue_flag's proper interaction with dflt_expr is nim") # in all cases below
            ### guess: we want it to be an expr for a default stateref
    global _self # fyi
    type_expr = canon_type( type_expr)
    printnim("can type_expr legally be self-dependent and/or time-dependent? ###k I guess that's nim in current code!")#070115 comment
    if _arglist:
        # new feature 070321. The type is applied to each element, but the default value is for the entire list --
        # OTOH, when would it ever be used, since even if no args are supplied, the list can be formed??
        # Probably it would only be used when the list was 0 length, and could meaningfully be [], (), or another list-like thing...
        # this is all a guess and I probably won't even review this code for this issue now, unless it fails when tried. ####k
        type_expr = tuple_Expr(type_expr) # type-coerce the value to a list of the given type [070321 guess] ###e or list_Expr???
    if dflt_expr is _E_DFLT_FROM_TYPE_:
        dflt_expr = default_expr_from_type_expr( type_expr)
            ## note [070115], this would be impossible for time-dependent types! and for self-dep ones, possible but harder than current code.
        assert is_pure_expr(dflt_expr) #k guess 061105
    else:
        dflt_expr = canon_expr(dflt_expr) # hopefully this finally will fix dflt 10 bug, 061105 guesshope ###k [works for None, 061114]
        assert is_pure_expr(dflt_expr) # not sure this is redundant, since not sure if canon_expr checks for Instance ###k
        printnim("not sure if canon_expr checks for Instance")
    # Note on why we use explicit call_Expr & getattr_Expr below,
    # rather than () and . notation like you can use in user-level formulae (which python turns into __call__ and getattr),
    # to construct Exprs like _self._i_grabarg( attr_expr, ...):
    # it's only to work around safety features which normally detect that kind of Expr-formation (getattr on _i_* or _e_*,
    # or getattr then call) as a likely error. These safety features are very important, catching errors that would often lead
    # to hard-to-diagnose bugs (when our code has an Expr but thinks it has an Instance), so it's worth the trouble.
    held_dflt_expr = hold_Expr(dflt_expr) 
        # Note, this gets evalled back into dflt_expr (treated as inert, may or may not be an expr depending on what it is right here)
        # by the time _i_grabarg sees it (the eval is done when the call_Expr evals its args before doing the call).
        # So if we wanted _i_grabarg to want None rather than _E_REQUIRED_ARG_ as a special case, we could change to that (there & here).
    grabopts = {}
    if _arglist:
        grabopts.update(dict(_arglist = constant_Expr(_arglist)))
    grabarg_expr = call_Expr( getattr_Expr(_self, '_i_grabarg'), attr_expr, argpos_expr, held_dflt_expr, **grabopts )
        # comments 070115:
        # - This will eval to an expr which depends on self but not on time. We could optim by wrapping it
        # (or declaring it final) in a way which effectively replaced it with its value-expr when first used.
        # (But it's not obvious where to store the result of that, since the exprs being returned now are assigned to classes
        #  and will never be specific to single selfs. Do we need an expr to use here, which can cache its own info in self??
        #  Note: AFAIK, self will be the same as what _self gets replaced with when this is used. (We ought to assert that.) ###e)
        # - Further, grabarg_expr is probably supposed to be wrapped *directly* by eval_Expr, not with type_expr inside. I think I'll
        # make that change right now and test it with EVAL_REFORM still False, since I think it's always been required, as said
        # in other comments here. DOING THIS NOW.
    if attr_expr is not None and argpos_expr is not None:
        # for ArgOrOption, use a tuple of a string and int (attr and argpos) as the index
        index_expr = tuple_Expr( attr_expr, argpos_expr )
    elif attr_expr is None and argpos_expr is None:
        assert 0, "attr_expr is None and argpos_expr is None ..."
    elif attr_expr is not None:
        # for Option, use a plain attr string as the index
        index_expr = attr_expr
    else:
        assert argpos_expr is not None
        # for Arg, use a plain int as the index
        # (note: ExprsMeta replaces argpos_expr with that int wrapped in constant_Expr, but later eval pulls out the raw int)
        index_expr = argpos_expr
# see if this is fixed now, not that it means much since we were using a stub... but who knows, maybe the stub was buggy
# and we compensated for that and this could if so cause a bug:
##    printnim("I suspect type_expr (stub now) is included wrongly re eval_Expr in _ArgOption_helper, in hindsight 061117")
##        ### I suspect the above, because grabarg expr needs to be evalled to get the expr whose type coercion we want to instantiate
    res = Instance( _type_coercion_expr( type_expr, eval_Expr(grabarg_expr) ),
                     _index_expr = index_expr, _lvalue_flag = _lvalue_flag, **moreopts )
        # note: moreopts might contain _noinstance = True, and if so, Instance normally returns its first arg unchanged
        # (depending on other options).
        # 070115 replaced eval_Expr( type_expr( grabarg_expr)) with _type_coercion_expr( type_expr, eval_Expr(grabarg_expr) )
    return res # from _ArgOption_helper
コード例 #30
0
ファイル: lvals.py プロジェクト: ematvey/NanoEngineer-1
    def _set_defaultValue(self, defaultValue):
        """If attr is not set, set it to defaultValue; never do any usage or change tracking.
        (WARNING: This will cause bugs unless all providers of access to a given attribute-instance
         use this consistently (same default value, and all of them using this rather than some of
         them providing access to the attr with no default value); they must all use it before
         providing access to that attr to any client object.)
        """
        # see comments in set_default_attrs about why we need this to do no usage or change tracking
        if self.valid:
            return # easy case

        # Dilemma: we might have no value, or we might have one computable by an initial-value compute method...
        # or we might have such a method which will raise LvalError_ValueIsUnset when we try it
        # (e.g. valfunc method in some client code). The only way to find out is to use that method,
        # but what if doing so tracked some usage? I think it's normal for that to happen...
        # OTOH, it's not correct, I think, to have two inconsistent ways of setting a default value --
        # code that calls this, vs. code that supplies an initial-value compute method that actually works.
        # So, maybe we should be able to ask the method which kind it is... but for now, assume it could
        # be either. If it computes a real value, we better not run it now, since usage would get tracked...
        # though that's an error... one way to detect is to return now and let it run, but that led to infrecur
        # in self.delegate in If.cond (don't know why). But setting defaultValue now risks hiding bugs.
        # That leaves: run it now, asserting no usage tracking. [Note: current calling code redundantly asserts the same thing. #e]
        #
        # One case which is not covered: something asked if we were set, was told "we're unset", and tracked its usage of us.
        # Ideally we'd assert right here that we have no current inval-subscribers. ####e DOIT
        # (For now, if we *do* have subscribers who learned we were unset, and if we leave them untouched,
        # it's indeed a bug that they asked that before we were initialized, but it's not so bad that they'll
        # get invalled when something changes us later.)
        printnim("assert no current inval-subscribers")
        
        mc = changes.begin_disallowing_usage_tracking('_set_defaultValue in %r' % self)
            # note: the argument is just an explanation for use in error messages ##e OPTIM: don't precompute that arg
        try:
            try:
                val = self._compute_value() # don't call get_value since it calls track_use
            except LvalError_ValueIsUnset:
                # this is the only non-error case!
                # (the following just inlines self.set_constant_value(defaultValue):)
                self._value = defaultValue
                self.valid = True
                ## print "_set_defaultValue returning after set"
                return
            except:
                # any other exception, including discovering usage tracking in that computation [once that works when it happens],
                # should be reported, but then (I think) needn't prevent this from working.
                print_compact_traceback("error: exception (ignored) in _set_defaultValue trying initval-computation in %r: " % self)
                self._value = defaultValue
                self.valid = True
                return
            else:
                # If a value was computed, that conflicts with using this method... report that error (even if the values agree),
                # but which value should we use? Let's use the computed one for now.
                #   NOTE: In present code [061121], this can also happen if usage tracking occurred, since it's not detected
                # until the end_disallowing_usage_tracking call below (since begin_disallowing_usage_tracking is not fully
                # implemented).
                print "error: %r computed initial value %r (using it) but was also given an explicit _set_defaultValue(%r)" % \
                      (self, val, defaultValue)
                self._value = val
                self.valid = True
                return
            pass
        finally:
            changes.end_disallowing_usage_tracking(mc)
        pass # end of method _set_defaultValue
コード例 #31
0
    def _set_defaultValue(self, defaultValue):
        """If attr is not set, set it to defaultValue; never do any usage or change tracking.
        (WARNING: This will cause bugs unless all providers of access to a given attribute-instance
         use this consistently (same default value, and all of them using this rather than some of
         them providing access to the attr with no default value); they must all use it before
         providing access to that attr to any client object.)
        """
        # see comments in set_default_attrs about why we need this to do no usage or change tracking
        if self.valid:
            return  # easy case

        # Dilemma: we might have no value, or we might have one computable by an initial-value compute method...
        # or we might have such a method which will raise LvalError_ValueIsUnset when we try it
        # (e.g. valfunc method in some client code). The only way to find out is to use that method,
        # but what if doing so tracked some usage? I think it's normal for that to happen...
        # OTOH, it's not correct, I think, to have two inconsistent ways of setting a default value --
        # code that calls this, vs. code that supplies an initial-value compute method that actually works.
        # So, maybe we should be able to ask the method which kind it is... but for now, assume it could
        # be either. If it computes a real value, we better not run it now, since usage would get tracked...
        # though that's an error... one way to detect is to return now and let it run, but that led to infrecur
        # in self.delegate in If.cond (don't know why). But setting defaultValue now risks hiding bugs.
        # That leaves: run it now, asserting no usage tracking. [Note: current calling code redundantly asserts the same thing. #e]
        #
        # One case which is not covered: something asked if we were set, was told "we're unset", and tracked its usage of us.
        # Ideally we'd assert right here that we have no current inval-subscribers. ####e DOIT
        # (For now, if we *do* have subscribers who learned we were unset, and if we leave them untouched,
        # it's indeed a bug that they asked that before we were initialized, but it's not so bad that they'll
        # get invalled when something changes us later.)
        printnim("assert no current inval-subscribers")

        mc = changes.begin_disallowing_usage_tracking(
            '_set_defaultValue in %r' % self)
        # note: the argument is just an explanation for use in error messages ##e OPTIM: don't precompute that arg
        try:
            try:
                val = self._compute_value(
                )  # don't call get_value since it calls track_use
            except LvalError_ValueIsUnset:
                # this is the only non-error case!
                # (the following just inlines self.set_constant_value(defaultValue):)
                self._value = defaultValue
                self.valid = True
                ## print "_set_defaultValue returning after set"
                return
            except:
                # any other exception, including discovering usage tracking in that computation [once that works when it happens],
                # should be reported, but then (I think) needn't prevent this from working.
                print_compact_traceback(
                    "error: exception (ignored) in _set_defaultValue trying initval-computation in %r: "
                    % self)
                self._value = defaultValue
                self.valid = True
                return
            else:
                # If a value was computed, that conflicts with using this method... report that error (even if the values agree),
                # but which value should we use? Let's use the computed one for now.
                #   NOTE: In present code [061121], this can also happen if usage tracking occurred, since it's not detected
                # until the end_disallowing_usage_tracking call below (since begin_disallowing_usage_tracking is not fully
                # implemented).
                print "error: %r computed initial value %r (using it) but was also given an explicit _set_defaultValue(%r)" % \
                      (self, val, defaultValue)
                self._value = val
                self.valid = True
                return
            pass
        finally:
            changes.end_disallowing_usage_tracking(mc)
        pass  # end of method _set_defaultValue