Example #1
0
def default_expr_from_type_expr(type_expr): #061115
    ## note [070115], this would be impossible for time-dependent types! and for self-dep ones, possible but harder than current code.
    """
    #doc
    """
##    assert type_expr is Stub # only permitted for these ones; not even correct for all of them, but surely not for others like int
# Stub is not defined here, never mind
    return canon_expr(None) # stub; only right for Action, wrong for int, str, etc ###e might need revision for ArgList?
Example #2
0
def default_expr_from_type_expr(type_expr): #061115
    ## note [070115], this would be impossible for time-dependent types! and for self-dep ones, possible but harder than current code.
    """
    #doc
    """
##    assert type_expr is Stub # only permitted for these ones; not even correct for all of them, but surely not for others like int
# Stub is not defined here, never mind
    return canon_expr(None) # stub; only right for Action, wrong for int, str, etc ###e might need revision for ArgList?
Example #3
0
def If(cond, _then, _else = None):
    # note: the default value None for _else doesn't yet work in most uses, due to a nontrivial logic bug
    # mentioned in ToggleShow.py (I think) and discussed in a notesfile (not in cvs). [IIRC 061128]
    cond = canon_expr(cond)
        # (but not on _then or _else to make this work better for immediate use. (might be deprecated, not sure))
    constflag, condval = expr_constant_value(cond)

    if not constflag:
        return If_expr(cond, _then, _else)
            #e maybe this will typecheck cond someday (in a way that would complain if it was a pyclass)
    elif condval:
        print "using then immediately"### leave these in awhile, since they're rare and might indicate a bug
        return _then ##k whether or not it's an expr?? (I think so... this is then a primitive form of expr-simplification, I guess)
    else:
        print "using else immediately; it's", _else ### print_compact_stack()? yes for temporarily###
        print_compact_stack("using else immediately: ")
        return _else
    pass
Example #4
0
 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)
Example #5
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
Example #6
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
Example #7
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
Example #8
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
Example #9
0
 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)