Ejemplo n.º 1
0
    def desugar_equation(self, params, param_types, result_type, equation):
        position = equation.position
        patterns = equation.lhs.application_args()
        body = equation.rhs
        if len(patterns) != len(params):
            self.fail('equations-arity-mismatch', name=name, position=position)
        self._env.open_scope()  # Equation scope
        fvs = set()
        for var in syntax.free_variables_list(patterns):
            if not self._env.is_defined(var):
                fvs.add(var)
                self._env.define(var,
                                 syntax.Metavar(prefix="t", position=position))

        # TODO: allow forced binding by prefixing a variable with "."

        if len(equation.where) == 0:
            d_type, d_body = self.check_expr(body)
        else:
            d_type, d_body = self.check_let(
                syntax.Let(declarations=equation.where,
                           body=body,
                           position=position))
        self.unify_types(d_type, result_type)

        unif_goals = []
        for param, pattern, t_param in zip(params, patterns, param_types):
            t_pattern, e_pattern = self.check_expr(pattern)
            self.unify_types(t_param, t_pattern)
            unif_goals.append(syntax.unify(param, e_pattern))

        alternative = syntax.fresh_many(
            fvs, syntax.sequence_many1(unif_goals, d_body))
        self._env.close_scope()  # Equation scope
        return alternative
Ejemplo n.º 2
0
 def parse_program(self):
     position = self.current_position()
     self.match(token.BEGIN)
     data_declarations = []
     value_declarations = []
     while self._token.type() == token.DELIM:
         self.match(token.DELIM)
         for decl in self.parse_toplevel_declaration():
             if decl.is_data_declaration():
                 data_declarations.append(decl)
             else:
                 value_declarations.append(decl)
     self.match(token.END)
     self.match(token.EOF)
     return syntax.Program(
         data_declarations=data_declarations,
         body=syntax.Let(declarations=value_declarations,
                         body=syntax.Variable(name="main",
                                              position=position),
                         position=position),
         position=position,
     )
Ejemplo n.º 3
0
    def check_let(self, expr):
        # Check kinds and extend environment
        # to allow for recursive definitions.

        definitions, definition_keys, type_declarations = \
            self.check_let_declarations_well_formed(expr)

        # TODO: Dependency graph
        graph = self.dependency_graph(definitions)
        partition = dependencies.partition_dependencies(graph)

        desugared_declarations = []
        for part in partition:

            part_definitions = {}
            part_type_declarations = {}
            for x in part:
                part_definitions[x] = definitions[x]
                if x in type_declarations:
                    part_type_declarations[x] = type_declarations[x]
            part_definition_keys = []
            for k in definition_keys:
                if k in part_definitions:
                    part_definition_keys.append(k)

            self._env.open_scope()
            for name, defs in part_definitions.items():
                self._env.define(name,
                                 syntax.Metavar(prefix='t',
                                                position=defs[0].position))

            e_decls = []
            for name in part_definition_keys:
                e_decls.append(
                  self.desugar_definition(name, part_definitions[name])
                )

            self.generalize_types_in_current_scope()
            self.check_declared_instantiate_real(part_type_declarations) 

            # To reconstruct the final AST
            ds = []
            for e_decl in e_decls:
                t_decl = syntax.TypeDeclaration(
                             name=e_decl.lhs.name,
                             type=self._env.value(e_decl.lhs.name),
                             position=e_decl.position
                         )
                ds.append(t_decl)
                ds.append(e_decl)
            desugared_declarations.append(ds)

        t_body, e_body = self.check_expr(expr.body)
        for part in reversed(partition):
            self._env.close_scope()
            e_body = syntax.Let(
                       declarations=desugared_declarations.pop(),
                       body=e_body,
                       position=expr.position)

        return t_body, e_body
Ejemplo n.º 4
0
def p_expr_let(p: Any) -> None:
    'expr : LET sortedvar EQUAL expr IN expr'
    p[0] = syntax.Let(p.slice[1], p[2], p[4], p[6])
Ejemplo n.º 5
0
def p_expr_let(p: Any) -> None:
    'expr : LET sortedvar EQUAL expr IN expr'
    sv: syntax.SortedVar = p[2]
    val: syntax.Expr = p[4]
    body: syntax.Expr = p[6]
    p[0] = syntax.Let(sv, val, body, span=loc_join(p.slice[1], body.span))
def relaxation_action_def(prog: syntax.Program,
                          actives: Optional[Dict[syntax.SortDecl,
                                                 syntax.RelationDecl]] = None,
                          fresh: bool = True) -> syntax.DefinitionDecl:
    decrease_name = (prog.scope.fresh('decrease_domain')
                     if fresh else 'decrease_domain')
    mods: Tuple[syntax.ModifiesClause, ...] = ()
    conjs: List[Expr] = []
    if actives is None:
        actives = active_rel_by_sort(prog)

    # a conjunct allowing each domain to decrease
    new_mods, new_conjs = relax_actives_action_chunk(prog.scope, actives)
    mods += new_mods
    conjs += new_conjs

    # constants are active
    for const in prog.constants():
        conjs.append(
            syntax.New(
                syntax.Apply(
                    actives[syntax.get_decl_from_sort(const.sort)].name,
                    (syntax.Id(const.name), ))))

    # functions map active to active
    for func in prog.functions():
        names: List[str] = []
        func_conjs = []
        for arg_sort in func.arity:
            arg_sort_decl = syntax.get_decl_from_sort(arg_sort)
            name = prog.scope.fresh(arg_sort_decl.name[0].upper(),
                                    also_avoid=names)
            names.append(name)
            func_conjs.append(
                syntax.New(
                    syntax.Apply(actives[arg_sort_decl].name,
                                 (syntax.Id(name), ))))
        ap_func = syntax.Apply(func.name,
                               tuple(syntax.Id(name) for name in names))
        name = prog.scope.fresh('y', also_avoid=names)
        active_func = syntax.Let(
            syntax.SortedVar(name, func.sort), ap_func,
            syntax.New(
                syntax.Apply(
                    actives[syntax.get_decl_from_sort(func.sort)].name,
                    (syntax.Id(name), ))))
        conjs.append(
            syntax.Forall(
                tuple(syntax.SortedVar(name, None) for name in names),
                syntax.Implies(syntax.And(*func_conjs), active_func)))

    # (relativized) axioms hold after relaxation
    for axiom in prog.axioms():
        if not syntax.is_universal(axiom.expr):
            conjs.append(syntax.relativize_quantifiers(actives, axiom.expr))

    # derived relations have the same interpretation on the active domain
    for rel in prog.derived_relations():
        names = []
        rel_conjs = []
        for arg_sort in rel.arity:
            arg_sort_decl = syntax.get_decl_from_sort(arg_sort)
            name = prog.scope.fresh(arg_sort_decl.name[0].upper(),
                                    also_avoid=names)
            names.append(name)
            rel_conjs.append(
                syntax.Apply(actives[arg_sort_decl].name, (syntax.Id(name), )))
        ap_rel = syntax.Apply(rel.name,
                              tuple(syntax.Id(name) for name in names))
        conjs.append(
            syntax.Forall(
                tuple(syntax.SortedVar(name, None) for name in names),
                syntax.Implies(syntax.And(*rel_conjs),
                               syntax.Iff(syntax.New(ap_rel), ap_rel))))

    return syntax.DefinitionDecl(is_public_transition=True,
                                 num_states=2,
                                 name=decrease_name,
                                 params=(),
                                 mods=mods,
                                 expr=syntax.And(*conjs))
Ejemplo n.º 7
0
    def check_let(self, expr):
        # Check kinds and extend environment
        # to allow for recursive definitions.
        declared_names = set()
        definitions = {}
        definition_keys = []
        self._env.open_scope()
        type_declarations = []
        for decl in expr.declarations:
            if decl.is_type_declaration():
                decl = self.check_type_declaration(decl)
                declared_names.add(decl.name)
                type_declarations.append(decl)
            elif decl.is_definition():
                head = decl.lhs.application_head()
                if not head.is_variable():
                    self.fail('declaration-head-is-not-variable',
                              head=head,
                              position=decl.position)
                declared_names.add(head.name)
                if head.name not in definitions:
                    definition_keys.append(head.name)
                    definitions[head.name] = []
                definitions[head.name].append(decl)
                if not self._env.is_locally_defined(head.name):
                    self._env.define(
                        head.name,
                        syntax.Metavar(prefix='t', position=decl.position))
            else:
                raise Exception('Check for declaration not implemented.')

        defined_names = set(definitions.keys())
        if declared_names != defined_names:
            missing = declared_names - defined_names
            self.fail('name-declared-but-not-defined',
                      name=missing.pop(),
                      position=expr.position)

        e_decls = []
        for name in definition_keys:
            e_decls.append(self.desugar_definition(name, definitions[name]))

        self.generalize_types_in_current_scope()
        self.check_declared_instantiate_real(type_declarations)

        body_type, desugared_body = self.check_expr(expr.body)

        # To reconstruct the final AST
        desugared_declarations = []
        for e_decl in e_decls:
            t_decl = syntax.TypeDeclaration(name=e_decl.lhs.name,
                                            type=self._env.value(
                                                e_decl.lhs.name),
                                            position=e_decl.position)
            desugared_declarations.append(t_decl)
            desugared_declarations.append(e_decl)

        self._env.close_scope()
        return (body_type,
                syntax.Let(declarations=desugared_declarations,
                           body=desugared_body,
                           position=expr.position))