+#### Error reporting
+
+When analysis discovers an inconsistency it needs to report an error;
+just refusing to run the code esure that the error doesn't cascade,
+but by itself it isn't very useful. A clear understand of the sort of
+error message that are useful will help guide the process of analysis.
+
+At a simplistic level, the only sort of error that type analysis can
+report is that the type of some construct doesn't match a contextual
+requirement. For example, in `4 + "hello"` the addition provides a
+contextual requirement for numbers, but `"hello"` is not a number. In
+this particular example no further information is needed as the types
+are obvious from local information. When a variable is involved that
+isn't the case. It may be helpful to explain why the variable has a
+particular type, by indicating the location where the type was set,
+whether by declaration or usage.
+
+Using a recursive-descent analysis we can easily detect a problem at
+multiple locations. In "`hello:= "there"; 4 + hello`" the addition
+will detect that one argument is not a number and the usage of `hello`
+will detect that a number was wanted, but not provided. In this
+(early) version of the language, we will generate error reports at
+multiple locations, to the use of `hello` will report an error and
+explain were the value was set, and the addition will report an error
+and say why numbers are needed. To be able to report locations for
+errors, each language element will need to record a file location
+(line and column) and each variable will need to record the language
+element where its type was set. For now we will assume that each line
+of an error message indicates one location in the file, and up to 2
+types. So we provide a `printf`-like function which takes a format, a
+language (a `struct exec` which has not yet been introduced), and 2
+types. "`$1`" reports the first type, "`$2`" reports the second. We
+will need a function to print the location, once we know how that is
+stored.
+
+###### forward decls
+
+ static void fput_loc(struct exec *loc, FILE *f);
+
+###### core functions
+
+ static void type_err(struct parse_context *c,
+ char *fmt, struct exec *loc,
+ enum vtype t1, enum vtype t2)
+ {
+ fprintf(stderr, "%s:", c->file_name);
+ fput_loc(loc, stderr);
+ for (; *fmt ; fmt++) {
+ if (*fmt != '%') {
+ fputc(*fmt, stderr);
+ continue;
+ }
+ fmt++;
+ switch (*fmt) {
+ case '%': fputc(*fmt, stderr); break;
+ default: fputc('?', stderr); break;
+ case '1':
+ fputs(vtype_names[t1], stderr);
+ break;
+ case '2':
+ fputs(vtype_names[t2], stderr);
+ break;
+ ## format cases
+ }
+ }
+ fputs("\n", stderr);
+ }
+