Skip to content
Snippets Groups Projects

Draft: Resolve "Short circuiting and lazy evaluation"

Open Ivan Kondov requested to merge 49-short-circuiting-and-lazy-evaluation into master
3 files
+ 99
42
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -346,8 +346,7 @@ def func_value(self):
get_logger(__name__).debug('func_value:%s', repr(self))
func, pars = self.func
assert all(isinstance_m(p, ['Variable', 'ObjectImport']) for p in pars)
model = get_model(self)
if all(p in model.nonstrict or get_par_value(p) is not NC for p in pars):
if all(not p.strict or get_par_value(p) is not NC for p in pars):
return func(*[get_par_value(p) for p in pars])
return NC
@@ -394,7 +393,8 @@ def get_fw_ids_torun(self):
and not get_parent_of_type('Type', x))
for prnt in get_children(lambda x: isinstance_m(x, ('Print', 'View')), self):
vars_.update(vref.ref for vref in get_children(select_vars, prnt))
vars_ -= get_nonstrict(self)
_update_strictness(self)
vars_ -= set(filter(lambda x: not x.strict, vars_))
fw_ids = []
for var in iter(vars_):
fw_ids.extend(self.lpad.get_fw_ids({'name': var.__fw_name}))
@@ -580,55 +580,60 @@ def update_meta_node(model):
formatter(tag_dct))
def get_if_nonstrict(obj):
"""get a set of non-strict parameters of IF function/expression"""
def get_if_strict(obj):
"""get a set of strict parameters of IF function/expression"""
if get_par_value(obj.expr) is NC:
return set(obj.true_.func[1]) | set(obj.false_.func[1])
return set(obj.expr.func[1])
if obj.expr.value:
return set(obj.false_.func[1])
return set(obj.true_.func[1])
return set(obj.true_.func[1])
return set(obj.false_.func[1])
def get_or_nonstrict(obj):
"""get a set of non-strict parameters of OR expression"""
operands = list(obj.operands)
while operands:
operand = operands.pop(0)
def get_or_strict(obj):
"""get a set of strict parameters of OR expression"""
strict = set()
for operand in obj.operands:
strict.update(set(operand.func[1]))
if get_par_value(operand) is NC or operand.value:
return set().union(*(op.func[1] for op in operands))
return set()
return strict
return strict
def get_and_nonstrict(obj):
"""get a set of non-strict parameters of AND expression"""
operands = list(obj.operands)
while operands:
operand = operands.pop(0)
def get_and_strict(obj):
"""get a set of strict parameters of AND expression"""
strict = set()
for operand in obj.operands:
strict.update(set(operand.func[1]))
if get_par_value(operand) is NC or not operand.value:
return set().union(*(op.func[1] for op in operands))
return set()
return strict
return strict
def get_nonstrict(model):
"""return a set of globally non-strict variables in the model"""
refs = get_children_of_type('GeneralReference', model)
refs = filter(lambda x: isinstance_m(x.ref, ('Variable',)), refs)
refs = filter(lambda x: not get_parent_of_type('IfFunction', x), refs)
refs = filter(lambda x: not get_parent_of_type('IfExpression', x), refs)
refs = filter(lambda x: not get_parent_of_type('Or', x), refs)
refs = filter(lambda x: not get_parent_of_type('And', x), refs)
non_strict = set()
def _update_strictness(model):
"""refresh the strictness properties, some non-strict are getting strict"""
strict = set()
ifs = get_children(lambda x: isinstance_m(x, ('IfFunction', 'IfExpression')), model)
ifs = filter(lambda x: not get_parent_of_type('FunctionDefinition', x), ifs)
ifs = filter(lambda x: not get_parent_of_type('Lambda', x), ifs)
for if_ in ifs:
non_strict.update(get_if_nonstrict(if_))
for and_ in get_children_of_type('And', model):
non_strict.update(get_and_nonstrict(and_))
for or_ in get_children_of_type('Or', model):
non_strict.update(get_or_nonstrict(or_))
non_strict -= set(r.ref for r in refs)
get_logger(__name__).debug('non-strict vars: %s', non_strict)
return non_strict
strict.update(get_if_strict(if_))
ands = get_children_of_type('And', model)
ands = filter(lambda x: not get_parent_of_type('FunctionDefinition', x), ands)
ands = filter(lambda x: not get_parent_of_type('Lambda', x), ands)
for and_ in ands:
strict.update(get_and_strict(and_))
ors = get_children_of_type('Or', model)
ors = filter(lambda x: not get_parent_of_type('FunctionDefinition', x), ors)
ors = filter(lambda x: not get_parent_of_type('Lambda', x), ors)
for or_ in ors:
strict.update(get_or_strict(or_))
for var in strict:
var.strict = True
all_vars = get_children_of_type('Variable', model)
strict = filter(lambda x: x.strict, all_vars)
non_strict = filter(lambda x: not x.strict, all_vars)
get_logger(__name__).debug('non-strict vars: %s', list(non_strict))
get_logger(__name__).debug('strict vars: %s', list(strict))
def workflow_model_processor(model, metamodel):
@@ -637,6 +642,7 @@ def workflow_model_processor(model, metamodel):
if not textx_isinstance(model, metamodel['Program']):
assert model == ''
logger.info('empty model')
return
model_params = getattr(model, '_tx_model_params')
if model_params['model_instance']['uuid'] is None:
logger.info('creating model from scratch')
@@ -666,4 +672,4 @@ def workflow_model_processor(model, metamodel):
run_fireworks(model.lpad, fws_to_run, worker_name=model.worker_name,
create_subdirs=unique_launchdir)
fws_to_run = get_fws_torun()
setattr(model, 'nonstrict', get_nonstrict(model))
_update_strictness(model)
Loading