def event(action_id:str, role_id:str = ENV_ROLE, timestamp: int = 0, params:Optional[Dict[str, Data]] = None, eventType: Optional[EventType] = None ) -> Event: if eventType is None: eventType = EventType.env_next if role_id == ENV_ROLE else EventType.party_next params = params or dict() return Event(action_id=castid(ActionId, action_id), role_id=castid(RoleId, role_id), timestamp= timestamp, actionparam_subst=cast(ActionParamSubst, params) if params else None, actionparam_subst_list=list(params.values()) if params else None, type=eventType)
def evalTrace(it: Union[Trace, CompleteTrace], prog: L4Contract, verbose: bool = True, debug: bool = False): env = ExecEnvNF(prog) if isinstance(it, CompleteTrace): for contract_param in it.contract_param_subst: # replacing hardcoded contrat param vals with passed in ones supplied_val = it.contract_param_subst[contract_param] paramdec = prog.contract_params[castid(ContractParamId, contract_param)] assert supplied_val is not None if isinstance(paramdec.value_expr, Literal): paramdec.value_expr.lit = supplied_val else: paramdec.value_expr = L4ContractConstructor.mk_literal( supplied_val) return env.evalTrace(trace=it.events, finalSituationId=cast(SituationId, it.final_situation), final_var_vals=cast(Optional[GVarSubst], it.final_values), verbose=verbose, debug=debug) else: return env.evalTrace(trace=it, verbose=verbose, debug=debug)
def action2smtlib(self, a: Action): self.curaid = a.action_id self.commands_for_actions[a.action_id] = [] self.push() self.actionParams2smtlib(a) # preconditions hold upon entering if len(a.preconditions) > 0: self.append("; PRE begin") for pre in a.preconditions: self.appendAssert(self.term2smtlibdef(pre)) self.append("; PRE end") # assert that invariants hold when entering the state transform: for inv_assert in self.invariant_true_assertions: self.append(inv_assert) self.stateTransform2smtlib(a.state_transform) for invcheck in self.invariant_maintained_conjectures: # invcheck has the form ('=>', e1, e2) hypoth_for_printing = invcheck.args[1] self.appendProofOblig( invcheck, f"{self.curaid} INV CHECK:" + smtlib_expr_to_str(hypoth_for_printing)) self.pop() self.curaid = castid(ActionId, "")
def _get_val(s: str) -> Any: if s in prog.contract_params: return str(prog.contract_params[castid(ContractParamId, s)].value_expr) elif s in prog.contract_params_nonoperative: return str(prog.contract_params_nonoperative[s]) elif s in prog.nlg_names: return str(prog.nlg_names[s]) elif s in prog.nlg_definitions: return str(prog.nlg_definitions[s])
def __init__(self, action_id: ActionId) -> None: self.action_id = action_id self.dest_situation_id: SituationId = castid( SituationId, "to be set after constructor") self.traversal_bounds: Any = None # actually SExpr self.allowed_subjects: Any = None # actually SExpr self.action_description: Optional[str] = None self.local_vars: Dict[LocalVarId, LocalVarDec] = dict() self.is_compound = False self.following_anon_situation: Optional[Situation] = None self.state_transform: Optional[StateTransform] = None self.preconditions: List[Term] = [] self.postconditions: List[Term] = [] self.prose_refs: List[str] = [] self.param_sorts_by_name: ParamsDec = dict( ) # str param id -> str sort id self.param_names: List[ActionParamId] = [] self.param_name_to_ind: Dict[ActionParamId, int] = dict() self.nlg = "" self.nlgsection = "root"
def name(self) -> ContractParamId: # cast shouldn't be necessary return castid(ContractParamId, self.paramdec.name)
def evalTrace(self, trace: Trace, finalSituationId: Optional[SituationId] = None, final_var_vals: Optional[GVarSubst] = None, verbose=False, debug=False): prog = self.top self.evalContractParamDecs(prog.contract_params) self.evalStateVarDecs(prog.state_var_decs) for i in range(len(trace)): # print("Environ", self.environ_tostr()) eventi = trace[i] self.cur_event = eventi cur_action_id = self.cur_event.action_id cur_event_delta = self.cur_event_delta() cur_event_datetime = self.delta2datetime(cur_event_delta) cur_action = self.top.action(cur_action_id) for gvarid in self.gvarvals: if isprimed(gvarid): self.gvarvals[unprimed(gvarid)] = self.gvarvals[gvarid] self.gvarvals = { id: self.gvarvals[id] for id in self.gvarvals if not isprimed(id) } # print("last_situation_entrance_delta", self.last_situation_entrance_delta) if self.last_situation_entrance_delta is not None and self.last_situation_entrance_delta > cur_event_delta: self.evalError( f"Event timestamps must be non-decreasing, but last event timestamp " f"{self.last_situation_entrance_delta} is greater than current event timestamp {cur_event_delta}" ) if not cur_action: self.evalError(f"Don't recongize action id {cur_action_id}") if not self.top.situation_mentions_action_in_nextaction_rule( self.last_or_current_situation_id, cur_action_id): self.evalError( f"Action type indicated using a next-rule, but current situation {self.last_or_current_situation_id} " f"has no such rule for action {cur_action_id}.") self.evaluation_is_in_situation = True nextrule_assessment = self.assess_event_legal_wrt_nextrules( eventi, verbose=verbose) self.evaluation_is_in_situation = False actionstr = event_to_action_str(eventi) srcid = self.last_or_current_situation_id if isinstance(nextrule_assessment, EventOk): self.evaluation_is_in_action = True self.apply_action(cur_action, verbose) self.evaluation_is_in_action = False if verbose: print( f"[{cur_event_datetime}] {srcid} --{actionstr}--> {self.last_or_current_situation_id}\n" ) elif isinstance(nextrule_assessment, BreachResult): if verbose: print("Breach result:", nextrule_assessment) breach_situation_id = breachSituationId( *nextrule_assessment.role_ids) self.apply_action(cur_action, verbose, to_breach_situation_id=breach_situation_id) if verbose: print( f"[{cur_event_datetime}] {srcid} --{actionstr}--> {breach_situation_id}" ) # if i != len(trace) - 1: # print("Trace prefix results in a breach, but there are more events after.") assert i == len( trace ) - 1, "Trace prefix results in a breach, but there are more events after." break else: assert False, "Can't get here?" if debug: # code, IPython, pdb are other options import ipdb # type: ignore ipdb.set_trace() # type: ignore # other things tried: # code.InteractiveConsole(locals=locals()).interact() # IPython.embed() for gvarid in self.gvarvals: if isprimed(gvarid): self.gvarvals[unprimed(gvarid)] = self.gvarvals[gvarid] self.gvarvals = { id: self.gvarvals[id] for id in self.gvarvals if not isprimed(id) } if final_var_vals: for varid, expected_val in final_var_vals.items(): if varid in self.gvarvals: actual_val = self.gvarvals[castid(StateVarId, varid)] elif varid in self.writeouts: actual_val = self.writeouts[varid] else: self.evalError( f"Var {varid} in Trace object is neither a state variable nor a writeout local variable" ) assert actual_val == expected_val, f"Expected state variable {gvarid} to have value {expected_val} at end of trace, but had value {actual_val}." if finalSituationId: assert self.last_or_current_situation_id == finalSituationId, f"Trace expected to end in situation {finalSituationId} but ended in situation {self.last_or_current_situation_id}"
def param_sort(self, ind_or_name: Union[str, int]) -> Sort: if isinstance(ind_or_name, str): return self.param_sorts_by_name[castid(ActionParamId, ind_or_name)] if isinstance(ind_or_name, int): return self.param_sorts_by_name[self.param_names[ind_or_name]]
def actid2link(actid: str) -> html_tag: act = prog.action(castid(ActionId, actid)) return a(act.nlg, href=f"#{actid}")
def sitid2link(sitid: str) -> html_tag: sit = prog.situation(castid(SituationId, sitid)) return a(sit.nlg, href=f"#{sitid}")