Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 22 additions & 150 deletions src/haz3lcore/TyDi/ErrorPrint.re
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Util;
open Language;

open InfoMessage;
/* Print static errors to a string */

[@deriving (show({with_path: false}), yojson, sexp)]
Expand Down Expand Up @@ -39,154 +39,20 @@ module Print = {
let typ = (ty: Typ.t): string => term(Typ(ty));
};

let prn = Printf.sprintf;

let common_error: Info.error_common => string =
fun
| NoType(BadLabel(_)) => "Invalid label"
| NoType(InvalidLabel(_)) => "Invalid label"
| DuplicateLabel(_, _) => "Duplicate label"
| TupleLabelError(_) => "Invalid tuple label"
| NoType(UnexpectedLabelSort(_)) => "Unexpected label sort"
| NoType(BadToken(token)) => prn("\"%s\" isn't a valid token", token)
| Inconsistent(WithArrow(ty)) =>
prn("type %s is not consistent with arrow type", Print.typ(ty))
| Inconsistent(CompareFun(ty)) =>
prn("values of type %s cannot be compared", Print.typ(ty))
| NoType(FreeConstructor(_name)) => prn("Constructor is not defined")
| Inconsistent(Internal(tys)) =>
prn(
"Expecting branches to have consistent types but got types: %s",
List.map(Print.typ, tys) |> String.concat(", "),
)
| Inconsistent(Expectation({ana, syn})) =>
prn(
"Expecting type %s but got inconsistent type %s",
Print.typ(ana),
Print.typ(syn),
);

let exp_error: Info.error_exp => string =
fun
| DotOperatorRequiresTuple => "Expected a tuple"
| TupleExtensionRequiresTuples => "Expected tuples for both arguments"
| BuiltinError(ArgumentMustBeTuple) => "Argument must be a tuple"
| BuiltinError(ProjectLabelsMissingLabels(labels)) =>
prn(
"Projected tuple does not have the following labels: %s",
String.concat(", ", labels),
)
| BuiltinError(MissingLabels(labels)) =>
prn(
"Tuple does not have the following labels: %s",
String.concat(", ", labels),
)
| BuiltinError(ToLvsMissingLabelsOnTuple(ty)) =>
prn(
"All entries in the argument must have labels, but some were not provided: %s",
Print.typ(ty),
)
| BuiltinError(AtLeast2Arguments) => "Must have 2 or more direct arguments"
| BuiltinError(Exactly2Arguments) => "Must have exactly 2 direct arguments"
| BuiltinError(ArgumentMustBeListOfTuples) => "Argument must be a list of labeled tuples"
| BuiltinError(PivotLabelIsNotString(ty)) =>
prn("Pivot column must be a string, but got: %s", Print.typ(ty))
| LabelNotFound(_, _) => "Label not found"
| UnboundLivelit(_) => "Livelit unbound and not found"
| BadTrivAp(ty) =>
prn("Function argument type \"%s\" inconsistent with ()", Print.typ(ty))
| InvalidUseMode({bad_typ, _}) =>
prn(
"Cannot use type %s for number operators and literals.",
Print.typ(bad_typ),
)
| BadOperator(_) => "Invalid operator"
| BadLivelitModel(_) => "Bad internal livelit model"
| FreeVariable(name) => "Variable " ++ name ++ " is not bound"
| InexhaustiveMatch(_) => "Match is not exhaustive" //TODO: elaborate
| UnusedDeferral => "Unused deferral" //TODO: better message
| BadPartialAp(_) => "Bad partial application" //TODO: elaborate
| Common(error) => common_error(error);

let pat_error: Info.error_pat => string =
fun
| ExpectedConstructor => "Expected a constructor"
| Redundant(_) => "Redundant" //TODO: elaborate
| Common(error) => common_error(error);

let typ_error: Info.error_typ => string =
fun
| FreeTypeVariable(name) => prn("Type variable %s is not bound", name)
| BadToken(token) => prn("\"%s\" isn't a valid type token", token)
| WantConstructorFoundAp => "Expected a constructor, found application"
| WantConstructorFoundType(ty) =>
prn("Expected a constructor, found type %s", Print.typ(ty))
| WantTypeFoundAp => "Constructor application must be in sum"
| DuplicateConstructor(name) =>
prn("Constructor %s already used in this sum", name)
| WantLabel => "Expected a label"
| ParseFailure => "Parse failure"
| InvalidLabel(name, labels) =>
prn(
"Label %s is not valid. Valid labels are: %s",
name,
String.concat(", ", labels),
)
| DuplicateLabels(labels, ty) =>
prn(
"Duplicate labels in type %s: %s",
Print.typ(ty),
String.concat(", ", labels),
)
| Duplicate(name, _) => prn("Type %s is already defined", name)
| WantProduct(ty) =>
prn("Expected a tuple type, found type %s", Print.typ(ty));

let underdetermined_typ: Info.underdetermined_typ => string =
fun
| ProdExtensionUnderdetermined(tys) =>
prn(
"Cannot determine type of tuple extension with argument types: %s",
List.map(Print.typ, tys) |> String.concat(", "),
)
| ProdProjectionMissingLabel(label, labels) =>
prn(
"Cannot project label %s. Valid labels are: %s",
label,
String.concat(", ", labels),
)
| ProdProjectionBadArgs({product, label}) =>
prn(
"Cannot determine projection type because %s",
String.concat(
" and ",
[
switch (product) {
| Some(ty) => "Type is not a tuple type: " ++ Print.typ(ty)
| None => ""
},
switch (label) {
| Some(ty) => "Label is not a valid label: " ++ Print.typ(ty)
| None => ""
},
],
),
);

let tpat_error: Info.error_tpat => string =
fun
| NotAVar(_) => "Not a valid type name" //TODO: elaborate
| ShadowsType(name, _source) => "Can't shadow type " ++ name; //TODO: elaborate

let string_of: Info.error => string =
fun
| Exp(error) => exp_error(error)
| Pat(error) => pat_error(error)
| Typ(error) => typ_error(error)
| TPat(error) => tpat_error(error);
let render_string = (fragments: list(InfoMessage.fragment)): string =>
List.map(
fun
| Text(s) => s
| Code(s) => "`" ++ s ++ "`"
| Type(ty) => Print.typ(ty)
| Term(term) => Print.term(term)
| Label(s) => Token.quote_label_when_necessary(s),
fragments,
)
|> String.concat("");

let format_error = (term, error) =>
prn("Error in term:\n %s\nNature of error: %s", term, error);
let string_of: Info.t => string =
info => render_string(InfoMessage.build_message(info).fragments);

let term_string_of: Info.t => string =
fun
Expand All @@ -210,9 +76,15 @@ let all = (info_map: Statics.Map.t): list(string) => {
|> List.filter_map(info =>
switch (Info.error_of(info)) {
| None => None
| Some(error) =>
| Some(_) =>
let term = term_string_of(info);
Some(format_error(term, string_of(error)));
Some(
Printf.sprintf(
"Error in term:\n %s\nNature of error: %s",
term,
string_of(info),
),
);
}
);
};
Loading