Commit Graph

7 Commits

Author SHA1 Message Date
Zoltan Somogyi
c03b11ca48 Update the style of more test cases.
And updated expected outputs for changed line numbers.
2021-07-27 19:29:21 +10:00
Zoltan Somogyi
253378fe21 Improve error messages for malformed lambda expressions.
Do this by insisting that terms whose top level(s) look like lambda
expressions should be parsed as lambda expressions, and return error
messages if that parsing attempt fails.

I did this is in several commits to modules in the parse_tree.m package
that translated terms to the parse tree, i.e. to goal_exprs. This diff
does the same thing for lambda expressions.

NEWS:
    Document this change, as well as other, similar changes in the recent past.

compiler/superhomogeneous.m:
    When translating a var-functor unification, which has the form
    X = f(Y1, ..., Yn), to the HLDS, we parse the right hand side term,
    looking for Mercury constructs such as lambda expressions and
    field accesses. We used to do this by checking if the RHS was
    a well-formed version of the construct we were looking for,
    and falling back to parsing it as an ordinary term. That meant that
    terms that the programmer *intended* to be lambda expressions,
    but which contained a syntax error, were not diagnosed during the
    construction of the HLDS, but during a later pass. Virtually always,
    that later pass was typechecking. Since in such cases, the typechecker
    is given terms whose function symbols were *intended* to be the "keywords"
    of Mercury constructs (to the extent that Mercury *has* keywords),
    not the names of data constructors or predicates, those error messages
    were almost always confusing, and at best an *indirect* indication
    of the actual problem with the code.

    This diff changes things so that when the top function symbol on
    the RHS of a unification is a Mercury "keyword" used only in lambda
    expressions, we commit to parsing it as such. If the parsing fails,
    we now generate an error message that describes the problem *directly*.

    To make the task of generating good error messages easier, and to make it
    possible to generate *consistent* error messages for the same error
    in different contexts, unify the four separate pieces of code that
    *used* to parse different kinds of lambda expressions. These four
    pieces of code used to parse

    - predicates defined using DCG notation;
    - predicates defined using non-DCG notation;
    - functions that used the default function mode and determinism; and
    - functions that did not use the default function mode and determinism.

    The unified code allows a function lambda expression to omit the
    default argument modes *independently* of whether it omits the default
    determinism, and vice versa. The old code did not do that: if you didn't
    explicitly specify one, you couldn't explicitly specify the other either,
    probably because it would have required two more pieces of code.

    The language reference manual says, in section 8.1:

        As with ‘:- func’ declarations, if the modes and determinism
        of the function are omitted in a higher-order function term, then
        the modes default to ‘in’ for the arguments, ‘out’ for
        the function result, and the determinism defaults to ‘det’.

    This text is vague on whether the modes and determinism are *allowed*
    to be omitted independently. The old behavior was a strict reading
    of this text. The new behavior follows the most liberal possible reading,
    and thus allows all the behaviors that the old one did, and more.

    Integrate the test for big integers that are too big to be represented
    with the conversion of all ordinary functors into cons_ids, both to
    simplify the code, and to speed it up. In the process, improve the
    error message for too-big integers.

compiler/add_clause.m:
    Don't try to generate warnings for singleton variables in a clause
    if the clause had syntax errors. Part of the parser's recovery from
    those syntax errors (e.g. when they occur in lambda expressions' clause
    heads) may have included not translating parts of the original term
    into the parsed clause body, so any such warnings could be misleading.

    Such warnings could also be correct, but I expect most programmers
    would prefer to miss some correct singleton warnings while the
    syntax errors are present in their code, and get them only once
    they have fixed those syntax errors, than to have to wade through
    misleading errors messages for the initial syntax error to get to
    the real ones.

compiler/field_access.m:
    Clarify the text of an error message.

    Delete a predicate that superhomogeneous.m no longer needs.

compiler/mercury_compile_front_end.m:
    Don't proceed past typechecking if the parser found syntax errors,
    since any errors we find later, e.g. as part of mode checking,
    are quite likely to be avalanche errors caused by those syntax errors.

    The reason why this wasn't a problem in the past is that when
    the program contained malformed uses of builtin constructs such as
    lambda expressions and field accesses, the parser used to simply
    transform the terms containing the malformed constructs into the arguments
    of call goals and unifications, and it was the typechecker that discovered
    that these function symbols did not match any declared type.
    The "type errors" generated for such problems told the compiler
    not to run later compiler passes to prevent avalanche errors.

    We now report syntax errors earlier, during the construction of the HLDS,
    and it is entirely possible that the parser's recovery from those errors
    leaves *no* type errors to be reported. This is why we need to make
    the presence of syntax errors in a predicate block the invocation
    of later passes.

compiler/typecheck.m:
    Return whether the predicates we typechecked had syntax errors,
    to make the change in mercury_compile_front_end.m possible.

compiler/state_var.m:
    If a lambda expression has two or more arguments of the form !X,
    we now print an error message for each, with each message naming the bad
    state variable and giving the context of the argument. We used to
    print only a single message saying that *some* argument misused
    state variables this way. Similarly, we now print the correct context
    for !X appearing as a function result, whether in a lambda expression
    or at the top level of a clause.

    The actual printing of those error messages takes place elsewhere,
    but change the utility predicates exported by state_var.m to make
    the change possible.

    Change the error message we generate for !X appearing as a function
    result, to avoid suggesting a possible repair that is virtually never
    the right repair.

compiler/mode_util.m:
    Delete a predicate that was used only by superhomogeneous.m; an updated
    version of that predicate is now in superhomogeneous.m itself.

compiler/module_qual.m:
compiler/module_qual.qualify_items.m:
    Instead of exporting predicates to module qualify the whole list of
    argument modes of a lambda expression, export predicates that module
    qualify only one such mode, since that is what superhomogeneous.m
    now wants.

compiler/hlds_clauses.m:
    Add access predicates for fields of the clauses_info type that previously
    did not have them, including the one that records the presence of syntax
    errors.

    Put related fields of the clauses_info together.

    Group both the declarations and the definitions of the access predicates
    together, and put them in the same order as the fields themselves.

compiler/add_class.m:
compiler/add_pred.m:
compiler/add_pragma_type_spec.m:
compiler/higher_order.m:
compiler/hlds_pred.m:
compiler/unify_proc.m:
    Conform to the changes above.

tests/invalid/lambda_syntax_error.err_exp:
    Print one error message for each of the four malformed lambda expressions
    in this test case, instead of the 13 avalanche messages we used to get
    from the typechecker, which tried to interpret the malformed lambda
    expression heads as calls, unifications etc.

    The motivation for this diff was a set of similar set of avalanche error
    messages for a real-life syntax error in a lambda expression in a change
    I worked on a while ago.

tests/benchmarks/deriv.{m,exp}:
    This test case used to use "^" as a data constructor (to represent
    raising X to the Nth power). Since the parser now insists on treating it
    as a field access operator, replace "^" with "power". (This test has
    the excuse of predating the addition of field access syntax to Mercury
    by several years.)

tests/dppd/grammar_impl.m:
    This test case used to define a type which contained "is" as a data
    constructor. After this diff, this is no longer allowed (as part of
    "is detism", it looks to the parser like the top constructor in a
    lambda expression head, and therefore as the top constructor of
    the lambda expression as a whole if it has no body), so add the type
    name as a prefix to this data constructor. To future-proof the test case,
    do the same with the several other data constructors that also duplicate
    the names of Mercury keywords.

tests/hard_coded/pprint_test2.{m,exp}:
tests/hard_coded/write.{m,exp}:
tests/hard_coded/write_binary.{m,exp}:
    These test cases used to define a type which contained ":-" as a data
    constructor. After this diff, this is no longer allowed, so replace them
    with "?-". (The tests check how io.m formats terms whose data constructor
    is an operator, so the replacement needs to be an operator, and Mercury
    syntax does not use "?-"; library/ops.m lists it as an operator only
    because it is an operator in Prolog.)

    Update write_binary.m to conform to our current style guide, and to avoid
    using the recently-deprecated io.make_temp.

tests/invalid/invalid_int.err_exp:
    Expect the updated text of the error message for a too-big
    integer constant.

tests/invalid/record_syntax_error.err_exp:
    Expect the updated text of the error message for a malformed field name.

tests/invalid/state_vars_test3.err_exp:
    Expect the updated text of the error message for a !X appearing
    as the result of a lambda function.

tests/invalid/state_vars_test4.err_exp:
    Expect the error message for a !X lambda argument, but (since we now
    stop after typechecking in the presence of such syntax errors),
    don't expect the avalanche error messages we used to print from the
    mode checker.
2016-05-20 05:47:36 +10:00
Zoltan Somogyi
a0760327b6 Do stricter checking of mode and determinism declarations.
Specifically, we now do three new checks:

BAD_DETISM: We now generate error messages for predicate declarations
that specify a determinism without also specifying argument modes.

BAD_PREDMODE: We now generate error messages for standalone mode declarations
for predicates whose predicate declaration includes modes for the arguments.

BAD_MODE_SECTION: We now generate error messages for standalone mode
declarations that are not in the same section as the predicate's (or
function's) type declaration.

compiler/hlds_pred.m:
    Add a slot to the pred_sub_info. If the predicate is explicitly defined by
    the user in the current module, this contains the id of the section that
    contains its predicate declaration (for the BAD_MODE_SECTION check)
    and whether that predicate declaration also had modes for the arguments
    (for the BAD_PREDMODE check).

compiler/add_pred.m:
    When adding adding new predicate declarations, perform the BAD_DETISM
    check, and record the info needed for the BAD_PREDMODE and BAD_MODE_SECTION
    checks.

    When adding adding new mode declarations, perform the BAD_PREDMODE
    and BAD_MODE_SECTION checks.

compiler/add_class.m:
compiler/add_mutable_aux_preds.m:
compiler/add_pragma_tabling.m:
compiler/add_pragma_type_spec.m:
compiler/add_solver.m:
compiler/add_special_pred.m:
compiler/check_typeclass.m:
compiler/dep_par_conj.m:
compiler/higher_order.m:
compiler/make_hlds_passes.m:
compiler/table_gen.m:
compiler/unused_args.m:
    Conform to the changes above.

mdbcomp/builtin_modules.m:
    Add a utility predicate for use by new code in add_pred.m.

compiler/comp_unit_interface.m:
compiler/goal_util.m:
compiler/prog_rename.m:
compiler/quantification.m:
deep_profiler/program_representation_utils.m:
library/calendar.m:
library/mutvar.m:
library/pretty_printer.m:
library/random.m:
library/set_ctree234.m:
library/solutions.m:
library/stream.string_writer.m:
profiler/globals.m:
tests/accumulator/nonrec.m:
tests/accumulator/out_to_in.m:
tests/declarative_debugging/library_forwarding.m:
tests/dppd/applast_impl.m:
tests/dppd/grammar_impl.m:
tests/dppd/regexp.m:
tests/dppd/transpose_impl.m:
tests/hard_coded/copy_pred.m:
tests/hard_coded/ho_func_default_inst.m:
tests/recompilation/unchanged_pred_nr_2.m.1:
tests/recompilation/unchanged_pred_nr_2.m.2:
tests/valid/det_switch.m:
tests/valid/inlining_bug.m:
    Delete determinism declarations from predicate and function declarations
    that have no argument mode information, since the BAD_DETISM check
    now makes these errors.

tests/valid/two_pragma_c_codes.m:
    Move some mode declarations to the right section, since the
    BAD_MODE_SECTION check now generates an error for the old code.

tests/invalid/typeclass_bad_method_mode.{m,err_exp}:
    New test case to test for the BAD_PREDMODE check.

tests/invalid/mode_decl_in_wrong_section.{m,err_exp}:
    New test case to test for the BAD_MODE_SECTION check.

tests/invalid/bad_detism.err_exp:
    Add an expected output for this old, but never enabled test case,
    which tests for new check BAD_DETISM.

tests/invalid/Mmakefile:
    Enable the new test cases.

tests/invalid/typeclass_dup_method_mode.m:
    This test case used to have two bugs. One is now by itself in the new
    typeclass_bad_method_mode.m test case, so modify it to contain only
    the other (indistinguishable modes).

tests/invalid/func_errors.err_exp:
tests/invalid/tc_err1.err_exp:
tests/invalid/undef_lambda_mode.err_exp:
tests/invalid/undef_type_mode_qual.err_exp:
    Expect an extra error message from the BAD_DETISM check.
2016-01-13 02:03:16 +11:00
Zoltan Somogyi
0da23e02c5 Add syntax for saying what type an inst is for.
As agreed on the developers mailing dist, this syntax is

:- inst i(...) for tc/n
    --->    f1(...)
    ;       f2(...)
    ...
    ;       fn(...).

It also works on the equivalent syntax

:- inst i(...) for tc/n == bound(...).

The type constructor may be specified only for insts that are being
defined to be equivalent to bound insts, since only for these can we
check that the top level function symbols belong to the specified type
constructor.

There is no documentation of the new language extension yet, since it is
not yet really useful. That would come later, when we check that an inst
specified as for being for a specific type is used only on values
of that type. We would also need to resolve the two issues marked with
"XXX IFTC" in the diff.

compiler/prog_item.m:
    Add a field to the parse tree representation of inst definitions
    to record the absence or presence of the "for type" type constructor.

compiler/hlds_data.m:
    Modify the representation of inst definitions to allow recording
    the fact that an inst is declared to be for a specified type constructor,
    to allow recording the presence of an error in this regard (the inst
    is not for the type, or the inst is exported to places where the type
    is not visible). Differentiate between no type constructor being associated
    with the type because (a) it would not make sense, and (b) it would make
    sense, but no type constructor was specified. (After type-constructor-
    specific insts have been in the language long enough, we may want to
    generate a warning or even an error for the latter.)

library/ops.m:
    Add "for" as an operator, as discussed on the mailing list.

NEWS:
doc/reference_manual.texi:
    Announce and document the new operator.

compiler/prog_io_mode_defn.m:
    Parse the new bit of syntax.

    Give a predicate a more meaningful name.

compiler/parse_tree_out.m:
    Output the new piece of syntax in inst definitions if needed.

compiler/add_mode.m:
    When adding an inst defn in the parse tree to the HLDS, record the
    absence or presence of the "for type" type constructor, and if it is
    absent, whether it would have made sense for one to be present. Generate
    an error message if one is present when it doesn't make sense for it to be
    present.

compiler/equiv_type.m:
    Note that we should expand the type constructors in inst defns,
    and note a related issue that is probably a very old bug.

compiler/inst_check.m:
    For insts that are declared to be a specific type constructor, don't
    check whether there is SOME type constructor they are compatible with.
    Check whether they are compatible with their declared type, and if they
    aren't, generate an error, not a warning.

compiler/module_qual.m:
    Module qualify any type constructors in inst definitions.

compiler/inst_user.m:
compiler/intermod.m:
compiler/prog_io_util.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/recompilation.version.m:
compiler/write_module_interface_files.m:
    Conform to the changes above.

tests/dppd/grammar_impl.m:
    Protect a function symbol named "for" against being considered an operator.

tests/invalid/bad_inst_for_type.{m,err_exp}:
    A new test case, to see whether we get the expected set of error messages
    for incorrect use of the new language extension; no more, and no less.

tests/invalid/Mmakefile:
    Enable the new test case.
2015-10-04 18:06:33 +11:00
Zoltan Somogyi
33eb3028f5 Clean up the tests in half the test directories.
tests/accumulator/*.m:
tests/analysis_*/*.m:
tests/benchmarks*/*.m:
tests/debugger*/*.{m,exp,inp}:
tests/declarative_debugger*/*.{m,exp,inp}:
tests/dppd*/*.m:
tests/exceptions*/*.m:
tests/general*/*.m:
tests/grade_subdirs*/*.m:
tests/hard_coded*/*.m:
    Make these tests use four-space indentation, and ensure that
    each module is imported on its own line. (I intend to use the latter
    to figure out which subdirectories' tests can be executed in parallel.)

    These changes usually move code to different lines. For the debugger tests,
    specify the new line numbers in .inp files and expect them in .exp files.
2015-02-14 20:14:03 +11:00
Fergus Henderson
791a0e170b Clean up tests/dppd so that it uses the new test suite framework properly,
Estimated hours taken: 1.5
Branches: main

Clean up tests/dppd so that it uses the new test suite framework properly,
all the tests are enabled, and all tests pass.

tests/dppd/Mmakefile:
	- Don't set MLFLAGS = --static.
	- Add "%.runtest: %.res", as required by tests/Mmake.common.
	- Likewise set THIS_DIR, TESTS, and SUBDIRS, as required by
	  tests/Mmake.common.  TESTS is set to just the single test "run",
	  which is actually a Mercury test harness which invokes all the tests.
	- Delete the rule "default_target: run", since the default target
	  is handled by tests/Mmake.common.

tests/dppd/grammar.m:
tests/dppd/grammar_impl.m:
	Fix various type, mode, and determinism errors.
	(Apparently this test had not yet been fully converted to Mercury.)

tests/dppd/run.m:
	- Enable the "grammar", "ssuply", and "maxlength" tests.
	- Don't define the inst "pair/2", since that is defined in std_util.m.
	- Use "garbage_collect" from the standard library "gc" module,
	  rather than defining our own version of "collect" here, since it is
	  now defined in the standard library, and the definition here was
	  broken for grades that don't use conservative GC.

tests/dppd/map_reduce.m:
	Work around a Mercury compiler bug, due to the lack of support for
	partially instantiated data structures.

tests/dppd/bug.m:
	Add some XXX comments.
2003-01-10 13:33:41 +00:00
Peter Ross
51497341cc Add the DPPD (dozens of problems in partial deduction) suite to the
Estimated hours taken: 0.1

Add the DPPD (dozens of problems in partial deduction) suite to the
tests directory.
1999-02-20 11:34:42 +00:00