[m-rev.] for review: direct parsing of items

Julien Fischer jfischer at opturion.com
Sat Nov 21 22:05:49 AEDT 2015


Hi Zoltan,

On Thu, 19 Nov 2015, Zoltan Somogyi wrote:

> ZZZ compiler/prog_io_iom.m:

Delete that.

> 
> Make the parsing of items more direct.
> 
> We used to parse items (and markers) using a fallback strategy: first we
> tried to parse a term as this kind of declaration, then as that kind of marker,
> etc, and finally as a clause. This meant that if the term was a malformed
> declaration or marker (e.g. because it used the right keyword/functor with
> the wrong arity), it could be eventually parsed as a clause.
> 
> This diff changes over to a direct parsing strategy: deciding what kind
> of item or marker a term SHOULD BE given its top level functor, and
> committing to that choice.
> 
> There are only two exceptions. The first is that when we see ":- mode",
> we keep our mind open about whether this is the definition of a new named mode,
> or the declaration of a mode of a predicate or function until we see
> a functor one level down.
> 
> The second exception is that when we see a purity annotation, a variable
> quantification or a constraint at the top level. We used to handle these,
> and the "solver" annotation, as "declaration attributes". We started the
> processing of every declaration by looking for these attributes, and switching
> on the declaration's top functor only if we didn't find them. We now
> process their functors in main switch on declarations' functors ("type",
> "inst", "pred" etc). Only if one of these switch arms is taken do we go
> over into a mode where we gather atributes, and once we have processed

s/atributes/attributes/

> all the attributes in the term, we switch between only the limited set
> of declaration types that allow attributes. This avoids having to include
> a check for "there were no attributes" in the code that processes all
> the *other* kinds of declarations.
> 
> Handle the purity annotations separately from the variable quantifications
> and the constraints, since while the latter are allowed on both item_pred_decls
> and item_mode_decls, the former are allowed only on item_pred_decls.
> 
> Handle the solver annotation outside the annotation system altogether,
> since it applies only type item_type_defns, and is simple enough
> not to need e.g. loops for its processing.
> 
> In situations where the top level functor of the term being parsed tells us
> that the term SHOULD be an item or marker of a particular kind, but it isn't,
> our new approach requuires us to generate new error messages.

s/requuires/requires/

> 
> compiler/prog_io_item.m:
>     Make the changes described above. By testing the top level of the term

...

> diff --git a/compiler/prog_io_item.m b/compiler/prog_io_item.m
> index ebac133..07e1d09 100644
> --- a/compiler/prog_io_item.m
> +++ b/compiler/prog_io_item.m

...

> @@ -1342,91 +1598,118 @@ get_class_context_and_inst_constraints(ModuleName, VarSet, RevAttributes0,
>      % practice it seems there would be little benefit in allowing that
>      % flexibility, so we don't.
>      %
> +    % NOTE We do NOT check that the order above is actually followed.
> +    %
>      % Universal quantification is the default, so we just ignore
> -    % universal quantifiers.  (XXX It might be a good idea to check
> -    % that any universally quantified type variables do actually
> -    % occur somewhere in the type declaration, and are not also
> -    % existentially quantified, and if not, issue a warning or
> -    % error message.)
> -
> -    list.reverse(RevAttributes0, Attributes0),
> -    get_quant_vars(quant_type_univ, ModuleName, Attributes0, Attributes1,
> -        [], _UnivQVars),
> -    get_quant_vars(quant_type_exist, ModuleName, Attributes1, Attributes2,
> -        [], ExistQVars0),
> +    % universal quantifiers. (XXX It might be a good idea to check that
> +    % any universally quantified type variables do actually occur SOMEWHERE
> +    % in the type declaration, and are not also existentially quantified,
> +    % and if not, issue a warning or error message.)
> +
> +    get_class_context_and_inst_constraints_loop(ModuleName, VarSet,
> +        QuantConstrAttrs, [], Specs,
> +        cord.init, _UnivQVarsCord, cord.init, ExistQVarsCord,
> +        cord.init, UnivClassConstraints, map.init, UnivInstConstraints,
> +        cord.init, ExistClassConstraints, map.init, ExistInstConstraints),
> +
> +    ExistQVars0 = cord.list(ExistQVarsCord),
>      list.map(term.coerce_var, ExistQVars0, ExistQVars),
> -    get_constraints(quant_type_univ, ModuleName, VarSet, Attributes2,
> -        Attributes3, MaybeUnivConstraints),
> -    get_constraints(quant_type_exist, ModuleName, VarSet, Attributes3,
> -        Attributes, MaybeExistConstraints),
> -    list.reverse(Attributes, RevAttributes),
> -
> -    ( if
> -        MaybeUnivConstraints = ok2(UnivConstraints, UnivInstConstraints),
> -        MaybeExistConstraints = ok2(ExistConstraints, ExistInstConstraints)
> -    then
> -        ClassConstraints = constraints(UnivConstraints, ExistConstraints),
> +    (
> +        Specs = [],
> +        ClassConstraints = constraints(
> +            cord.list(UnivClassConstraints),
> +            cord.list(ExistClassConstraints)),
>          InstConstraints =
>              map.old_merge(UnivInstConstraints, ExistInstConstraints),
>          MaybeExistClassInstContext = ok3(ExistQVars, ClassConstraints,
>              InstConstraints)
> -    else
> -        Specs = get_any_errors2(MaybeUnivConstraints) ++
> -            get_any_errors2(MaybeExistConstraints),
> +    ;
> +        Specs = [_ | _],
>          MaybeExistClassInstContext = error3(Specs)
>      ).
> 
> -:- pred get_constraints(quantifier_type::in, module_name::in, varset::in,
> -    decl_attrs::in, decl_attrs::out, maybe_class_and_inst_constraints::out)
> -    is det.
> -
> -get_constraints(QuantType, ModuleName, VarSet, !Attributes,
> -        MaybeClassInstConstraints) :-
> -    ( if
> -        !.Attributes = [
> -            decl_attr_constraints(QuantType, ConstraintsTerm) - _Term
> -            | !:Attributes]
> -    then
> +:- pred get_class_context_and_inst_constraints_loop(module_name::in,
> +    varset::in, list(quant_constr_attr)::in,
> +    list(error_spec)::in, list(error_spec)::out,
> +    cord(var)::in, cord(var)::out, cord(var)::in, cord(var)::out,
> +    cord(prog_constraint)::in, cord(prog_constraint)::out,
> +    inst_var_sub::in, inst_var_sub::out,
> +    cord(prog_constraint)::in, cord(prog_constraint)::out,
> +    inst_var_sub::in, inst_var_sub::out) is det.
> +
> +get_class_context_and_inst_constraints_loop(_ModuleName, _VarSet,
> +        [], !Specs, !UnivQVars, !ExistQVars,
> +        !UnivClassConstraints, !UnivInstConstraints,
> +        !ExistvClassConstraints, !ExistvInstConstraints).
> +get_class_context_and_inst_constraints_loop(ModuleName, VarSet,
> +        [QuantConstrAttr | QuantConstrAttrs], !Specs, !UnivQVars, !ExistQVars,
> +        !UnivClassConstraints, !UnivInstConstraints,
> +        !ExistClassConstraints, !ExistInstConstraints) :-
> +    (
> +        QuantConstrAttr = qca_quant_vars(QuantType, VarsTerm),
> +        (
> +            QuantType = quant_type_exist,
> +            ContextPieces = [words("in first argument of `some':")]

Don't hardcode the quoting style in the error message, use quote/1 instead.

> +        ;
> +            QuantType = quant_type_univ,
> +            ContextPieces = [words("in first argument of `all':")]

Ditto.

...

> diff --git a/compiler/prog_io_type_defn.m b/compiler/prog_io_type_defn.m
> index 43b983b..ba520dd 100644
> --- a/compiler/prog_io_type_defn.m
> +++ b/compiler/prog_io_type_defn.m

...

> @@ -241,32 +286,33 @@ parse_constructors_loop(ModuleName, VarSet, Head, Tail, MaybeConstructors) :-
>          )
>      ).
> 
> -:- func parse_constructor(module_name, varset, term) = maybe1(constructor).
> +:- pred parse_maybe_exist_quant_constructor(module_name::in, varset::in,
> +    term::in, maybe1(constructor)::out) is det.
> 
> -parse_constructor(ModuleName, VarSet, Term) = MaybeConstructor :-
> +parse_maybe_exist_quant_constructor(ModuleName, VarSet, Term,
> +        MaybeConstructor) :-
>      ( if Term = term.functor(term.atom("some"), [VarsTerm, SubTerm], _) then
> -        ( if parse_list_of_vars(VarsTerm, ExistQVars) then
> +        ContextPieces = [words("in first argument of `some':")],

Ditto.

The diff looks fine otherwise.

Julien.



More information about the reviews mailing list