Michelson: mv registration of type-checking errors in a specific file
This commit is contained in:
parent
21c4cc6e69
commit
ff7a8abb27
@ -49,6 +49,7 @@
|
|||||||
"Gas",
|
"Gas",
|
||||||
"Script_tc_errors",
|
"Script_tc_errors",
|
||||||
"Script_ir_translator",
|
"Script_ir_translator",
|
||||||
|
"Script_tc_errors_registration",
|
||||||
"Script_interpreter",
|
"Script_interpreter",
|
||||||
|
|
||||||
"Baking",
|
"Baking",
|
||||||
|
@ -2030,17 +2030,6 @@ let parse_script
|
|||||||
>>=? fun code ->
|
>>=? fun code ->
|
||||||
return (Ex_script { code; arg_type; ret_type; storage; storage_type })
|
return (Ex_script { code; arg_type; ret_type; storage; storage_type })
|
||||||
|
|
||||||
let type_map_enc =
|
|
||||||
let open Data_encoding in
|
|
||||||
list
|
|
||||||
(conv
|
|
||||||
(fun (loc, (bef, aft)) -> (loc, bef, aft))
|
|
||||||
(fun (loc, bef, aft) -> (loc, (bef, aft)))
|
|
||||||
(obj3
|
|
||||||
(req "location" Script.location_encoding)
|
|
||||||
(req "stackBefore" (list Script.expr_encoding))
|
|
||||||
(req "stackAfter" (list Script.expr_encoding))))
|
|
||||||
|
|
||||||
let typecheck_code
|
let typecheck_code
|
||||||
: context -> Script.expr -> type_map tzresult Lwt.t
|
: context -> Script.expr -> type_map tzresult Lwt.t
|
||||||
= fun ctxt code ->
|
= fun ctxt code ->
|
||||||
@ -2086,525 +2075,3 @@ let hash_data typ data =
|
|||||||
let unparsed = strip_annotations @@ unparse_data typ data in
|
let unparsed = strip_annotations @@ unparse_data typ data in
|
||||||
let bytes = Data_encoding.Binary.to_bytes expr_encoding (Micheline.strip_locations unparsed) in
|
let bytes = Data_encoding.Binary.to_bytes expr_encoding (Micheline.strip_locations unparsed) in
|
||||||
Tezos_hash.Script_expr_hash.(hash_bytes [ bytes ] |> to_b58check)
|
Tezos_hash.Script_expr_hash.(hash_bytes [ bytes ] |> to_b58check)
|
||||||
|
|
||||||
(* ---- Error registration --------------------------------------------------*)
|
|
||||||
|
|
||||||
let ex_ty_enc =
|
|
||||||
Data_encoding.conv
|
|
||||||
(fun (Ex_ty ty) -> strip_locations (unparse_ty None ty))
|
|
||||||
(fun expr ->
|
|
||||||
match parse_ty (root expr) with
|
|
||||||
| Ok (Ex_ty ty, _) -> Ex_ty ty
|
|
||||||
| _ -> Ex_ty Unit_t (* FIXME: ? *))
|
|
||||||
Script.expr_encoding
|
|
||||||
|
|
||||||
let () =
|
|
||||||
let open Data_encoding in
|
|
||||||
let located enc =
|
|
||||||
merge_objs
|
|
||||||
(obj1 (req "location" Script.location_encoding))
|
|
||||||
enc in
|
|
||||||
let arity_enc =
|
|
||||||
int8 in
|
|
||||||
let namespace_enc =
|
|
||||||
def "primitiveNamespace" @@
|
|
||||||
describe
|
|
||||||
~title: "Primitive namespace"
|
|
||||||
~description:
|
|
||||||
"One of the three possible namespaces of primitive \
|
|
||||||
(data constructor, type name or instruction)." @@
|
|
||||||
string_enum [ "type", Type_namespace ;
|
|
||||||
"constant", Constant_namespace ;
|
|
||||||
"instruction", Instr_namespace ] in
|
|
||||||
let kind_enc =
|
|
||||||
def "expressionKind" @@
|
|
||||||
describe
|
|
||||||
~title: "Expression kind"
|
|
||||||
~description:
|
|
||||||
"One of the four possible kinds of expression \
|
|
||||||
(integer, string, primitive application or sequence)." @@
|
|
||||||
string_enum [ "integer", Int_kind ;
|
|
||||||
"string", String_kind ;
|
|
||||||
"primitiveApplication", Prim_kind ;
|
|
||||||
"sequence", Seq_kind ] in
|
|
||||||
let ex_stack_ty_enc =
|
|
||||||
let rec unfold = function
|
|
||||||
| Ex_stack_ty (Item_t (ty, rest, annot)) ->
|
|
||||||
(Ex_ty ty, annot) :: unfold (Ex_stack_ty rest)
|
|
||||||
| Ex_stack_ty Empty_t -> [] in
|
|
||||||
let rec fold = function
|
|
||||||
| (Ex_ty ty, annot) :: rest ->
|
|
||||||
let Ex_stack_ty rest = fold rest in
|
|
||||||
Ex_stack_ty (Item_t (ty, rest, annot))
|
|
||||||
| [] -> Ex_stack_ty Empty_t in
|
|
||||||
conv unfold fold (list (tup2 ex_ty_enc (option string))) in
|
|
||||||
(* -- Structure errors ---------------------- *)
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidArityTypeError"
|
|
||||||
~title: "Invalid arity (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive was applied \
|
|
||||||
to an unsupported number of arguments."
|
|
||||||
(located (obj3
|
|
||||||
(req "primitiveName" Script.prim_encoding)
|
|
||||||
(req "expectedArity" arity_enc)
|
|
||||||
(req "wrongArity" arity_enc)))
|
|
||||||
(function
|
|
||||||
| Invalid_arity (loc, name, exp, got) ->
|
|
||||||
Some (loc, (name, exp, got))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (name, exp, got)) ->
|
|
||||||
Invalid_arity (loc, name, exp, got)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"missingScriptField"
|
|
||||||
~title:"Script is missing a field (parse error)"
|
|
||||||
~description:
|
|
||||||
"When parsing script, a field was expected, but not provided"
|
|
||||||
(obj1 (req "prim" prim_encoding))
|
|
||||||
(function Missing_field prim -> Some prim | _ -> None)
|
|
||||||
(fun prim -> Missing_field prim) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"duplicateScriptField"
|
|
||||||
~title:"Script has a duplicated field (parse error)"
|
|
||||||
~description:
|
|
||||||
"When parsing script, a field was found more than once"
|
|
||||||
(obj2
|
|
||||||
(req "loc" location_encoding)
|
|
||||||
(req "prim" prim_encoding))
|
|
||||||
(function Duplicate_field (loc, prim) -> Some (loc, prim) | _ -> None)
|
|
||||||
(fun (loc, prim) -> Duplicate_field (loc, prim)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidPrimitiveTypeError"
|
|
||||||
~title: "Invalid primitive (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive was unknown."
|
|
||||||
(located (obj2
|
|
||||||
(dft "expectedPrimitiveNames" (list prim_encoding) [])
|
|
||||||
(req "wrongPrimitiveName" prim_encoding)))
|
|
||||||
(function
|
|
||||||
| Invalid_primitive (loc, exp, got) -> Some (loc, (exp, got))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (exp, got)) ->
|
|
||||||
Invalid_primitive (loc, exp, got)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidExpressionKindTypeError"
|
|
||||||
~title: "Invalid expression kind (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, an expression was of the wrong kind \
|
|
||||||
(for instance a string where only a primitive applications can appear)."
|
|
||||||
(located (obj2
|
|
||||||
(req "expectedKinds" (list kind_enc))
|
|
||||||
(req "wrongKind" kind_enc)))
|
|
||||||
(function
|
|
||||||
| Invalid_kind (loc, exp, got) -> Some (loc, (exp, got))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (exp, got)) ->
|
|
||||||
Invalid_kind (loc, exp, got)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidPrimitiveNamespaceTypeError"
|
|
||||||
~title: "Invalid primitive namespace (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"In a script or data expression, a primitive was of the wrong namespace."
|
|
||||||
(located (obj3
|
|
||||||
(req "primitiveName" prim_encoding)
|
|
||||||
(req "expectedNamespace" namespace_enc)
|
|
||||||
(req "wrongNamespace" namespace_enc)))
|
|
||||||
(function
|
|
||||||
| Invalid_namespace (loc, name, exp, got) -> Some (loc, (name, exp, got))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (name, exp, got)) ->
|
|
||||||
Invalid_namespace (loc, name, exp, got)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"unorderedMapLiteral"
|
|
||||||
~title:"Invalid map key order"
|
|
||||||
~description:"Map keys must be in strictly increasing order"
|
|
||||||
(obj2
|
|
||||||
(req "location" Script.location_encoding)
|
|
||||||
(req "item" Script.expr_encoding))
|
|
||||||
(function
|
|
||||||
| Unordered_map_keys (loc, expr) -> Some (loc, expr)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, expr) -> Unordered_map_keys (loc, expr));
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"duplicateMapKeys"
|
|
||||||
~title:"Duplicate map keys"
|
|
||||||
~description:"Map literals cannot contain duplicated keys"
|
|
||||||
(obj2
|
|
||||||
(req "location" Script.location_encoding)
|
|
||||||
(req "item" Script.expr_encoding))
|
|
||||||
(function
|
|
||||||
| Duplicate_map_keys (loc, expr) -> Some (loc, expr)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, expr) -> Duplicate_map_keys (loc, expr));
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"unorderedSetLiteral"
|
|
||||||
~title:"Invalid set value order"
|
|
||||||
~description:"Set values must be in strictly increasing order"
|
|
||||||
(obj2
|
|
||||||
(req "location" Script.location_encoding)
|
|
||||||
(req "value" Script.expr_encoding))
|
|
||||||
(function
|
|
||||||
| Unordered_set_values (loc, expr) -> Some (loc, expr)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, expr) -> Unordered_set_values (loc, expr));
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"duplicateSetValuesInLiteral"
|
|
||||||
~title:"Sets literals cannot contain duplicate elements"
|
|
||||||
~description:"Set literals cannot contain duplicate elements, \
|
|
||||||
but a duplicae was found while parsing."
|
|
||||||
(obj2
|
|
||||||
(req "location" Script.location_encoding)
|
|
||||||
(req "value" Script.expr_encoding))
|
|
||||||
(function
|
|
||||||
| Duplicate_set_values (loc, expr) -> Some (loc, expr)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, expr) -> Duplicate_set_values (loc, expr));
|
|
||||||
(* -- Instruction typing errors ------------- *)
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"failNotInTailPositionTypeError"
|
|
||||||
~title: "FAIL not in tail position (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"There is non trivial garbage code after a FAIL instruction."
|
|
||||||
(located empty)
|
|
||||||
(function
|
|
||||||
| Fail_not_in_tail_position loc -> Some (loc, ())
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, ()) ->
|
|
||||||
Fail_not_in_tail_position loc) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"undefinedBinopTypeError"
|
|
||||||
~title: "Undefined binop (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A binary operation is called on operands of types \
|
|
||||||
over which it is not defined."
|
|
||||||
(located (obj3
|
|
||||||
(req "operatorName" prim_encoding)
|
|
||||||
(req "wrongLeftOperandType" ex_ty_enc)
|
|
||||||
(req "wrongRightOperandType" ex_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Undefined_binop (loc, n, tyl, tyr) ->
|
|
||||||
Some (loc, (n, Ex_ty tyl, Ex_ty tyr))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (n, Ex_ty tyl, Ex_ty tyr)) ->
|
|
||||||
Undefined_binop (loc, n, tyl, tyr)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"undefinedUnopTypeError"
|
|
||||||
~title: "Undefined unop (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A unary operation is called on an operand of type \
|
|
||||||
over which it is not defined."
|
|
||||||
(located (obj2
|
|
||||||
(req "operatorName" prim_encoding)
|
|
||||||
(req "wrongOperandType" ex_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Undefined_unop (loc, n, ty) ->
|
|
||||||
Some (loc, (n, Ex_ty ty))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (n, Ex_ty ty)) ->
|
|
||||||
Undefined_unop (loc, n, ty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"badReturnTypeError"
|
|
||||||
~title: "Bad return (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"Unexpected stack at the end of a lambda or script."
|
|
||||||
(located (obj2
|
|
||||||
(req "expectedReturnType" ex_ty_enc)
|
|
||||||
(req "wrongStackType" ex_stack_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Bad_return (loc, sty, ty) -> Some (loc, (Ex_ty ty, Ex_stack_ty sty))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (Ex_ty ty, Ex_stack_ty sty)) ->
|
|
||||||
Bad_return (loc, sty, ty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"badStackTypeError"
|
|
||||||
~title: "Bad stack (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"The stack has an unexpected length or contents."
|
|
||||||
(located (obj3
|
|
||||||
(req "primitiveName" prim_encoding)
|
|
||||||
(req "relevantStackPortion" int16)
|
|
||||||
(req "wrongStackType" ex_stack_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, Ex_stack_ty sty))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (name, s, Ex_stack_ty sty)) ->
|
|
||||||
Bad_stack (loc, name, s, sty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"inconsistentAnnotations"
|
|
||||||
~title:"Annotations inconsistent between branches"
|
|
||||||
~description:"The annotations on two types could not be merged"
|
|
||||||
(obj2
|
|
||||||
(req "annot1" string)
|
|
||||||
(req "annot2" string))
|
|
||||||
(function Inconsistent_annotations (annot1, annot2) -> Some (annot1, annot2)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (annot1, annot2) -> Inconsistent_annotations (annot1, annot2)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"inconsistentTypeAnnotations"
|
|
||||||
~title:"Types contain inconsistent annotations"
|
|
||||||
~description:"The two types contain annotations that do not match"
|
|
||||||
(located (obj2
|
|
||||||
(req "type1" ex_ty_enc)
|
|
||||||
(req "type2" ex_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Inconsistent_type_annotations (loc, ty1, ty2) -> Some (loc, (Ex_ty ty1, Ex_ty ty2))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (Ex_ty ty1, Ex_ty ty2)) -> Inconsistent_type_annotations (loc, ty1, ty2)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"unexpectedAnnotation"
|
|
||||||
~title:"An annotation was encountered where no annotation is expected"
|
|
||||||
~description:"A node in the syntax tree was impropperly annotated"
|
|
||||||
(located empty)
|
|
||||||
(function Unexpected_annotation loc -> Some (loc, ())
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, ()) -> Unexpected_annotation loc);
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"unmatchedBranchesTypeError"
|
|
||||||
~title: "Unmatched branches (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"At the join point at the end of two code branches \
|
|
||||||
the stacks have inconsistent lengths or contents."
|
|
||||||
(located (obj2
|
|
||||||
(req "firstStackType" ex_stack_ty_enc)
|
|
||||||
(req "otherStackType" ex_stack_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Unmatched_branches (loc, stya, styb) ->
|
|
||||||
Some (loc, (Ex_stack_ty stya, Ex_stack_ty styb))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (Ex_stack_ty stya, Ex_stack_ty styb)) ->
|
|
||||||
Unmatched_branches (loc, stya, styb)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"badStackItemTypeError"
|
|
||||||
~title: "Bad stack item (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"The type of a stack item is unexpected \
|
|
||||||
(this error is always accompanied by a more precise one)."
|
|
||||||
(obj1 (req "itemLevel" int16))
|
|
||||||
(function
|
|
||||||
| Bad_stack_item n -> Some n
|
|
||||||
| _ -> None)
|
|
||||||
(fun n ->
|
|
||||||
Bad_stack_item n) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"TransferInLambdaTypeError"
|
|
||||||
~title: "Transfer in lambda (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A TRANSFER_TOKENS instruction was encountered in a lambda expression."
|
|
||||||
(located empty)
|
|
||||||
(function
|
|
||||||
| Transfer_in_lambda loc -> Some (loc, ())
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, ()) ->
|
|
||||||
Transfer_in_lambda loc) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"selfInLambda"
|
|
||||||
~title: "SELF instruction in lambda (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A SELF instruction was encountered in a lambda expression."
|
|
||||||
(located empty)
|
|
||||||
(function
|
|
||||||
| Self_in_lambda loc -> Some (loc, ())
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, ()) ->
|
|
||||||
Self_in_lambda loc) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"inconsistentStackLengthsTypeError"
|
|
||||||
~title: "Inconsistent stack lengths (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A stack was of an unexpected length \
|
|
||||||
(this error is always in the context of a located error)."
|
|
||||||
empty
|
|
||||||
(function
|
|
||||||
| Bad_stack_length -> Some ()
|
|
||||||
| _ -> None)
|
|
||||||
(fun () ->
|
|
||||||
Bad_stack_length) ;
|
|
||||||
(* -- Value typing errors ------------------- *)
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidConstantTypeError"
|
|
||||||
~title: "Invalid constant (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A data expression was invalid for its expected type."
|
|
||||||
(located (obj2
|
|
||||||
(req "expectedType" ex_ty_enc)
|
|
||||||
(req "wrongExpression" Script.expr_encoding)))
|
|
||||||
(function
|
|
||||||
| Invalid_constant (loc, expr, ty) ->
|
|
||||||
Some (loc, (Ex_ty ty, expr))
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, (Ex_ty ty, expr)) ->
|
|
||||||
Invalid_constant (loc, expr, ty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidContractTypeError"
|
|
||||||
~title: "Invalid contract (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A script or data expression references a contract that does not \
|
|
||||||
exist or assumes a wrong type for an existing contract."
|
|
||||||
(located (obj1 (req "contract" Contract.encoding)))
|
|
||||||
(function
|
|
||||||
| Invalid_contract (loc, c) ->
|
|
||||||
Some (loc, c)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, c) ->
|
|
||||||
Invalid_contract (loc, c)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"comparableTypeExpectedTypeError"
|
|
||||||
~title: "Comparable type expected (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"A non comparable type was used in a place where \
|
|
||||||
only comparable types are accepted."
|
|
||||||
(located (obj1 (req "wrongType" ex_ty_enc)))
|
|
||||||
(function
|
|
||||||
| Comparable_type_expected (loc, ty) -> Some (loc, Ex_ty ty)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, Ex_ty ty) ->
|
|
||||||
Comparable_type_expected (loc, ty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"InconsistentTypesTypeError"
|
|
||||||
~title: "Inconsistent types (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"This is the basic type clash error, \
|
|
||||||
that appears in several places where the equality of \
|
|
||||||
two types have to be proven, it is always accompanied \
|
|
||||||
with another error that provides more context."
|
|
||||||
(obj2
|
|
||||||
(req "firstType" ex_ty_enc)
|
|
||||||
(req "otherType" ex_ty_enc))
|
|
||||||
(function
|
|
||||||
| Inconsistent_types (tya, tyb) ->
|
|
||||||
Some (Ex_ty tya, Ex_ty tyb)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (Ex_ty tya, Ex_ty tyb) ->
|
|
||||||
Inconsistent_types (tya, tyb)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidMapBody"
|
|
||||||
~title: "Invalid map body"
|
|
||||||
~description:
|
|
||||||
"The body of a map block did not match the expected type"
|
|
||||||
(obj2
|
|
||||||
(req "loc" Script.location_encoding)
|
|
||||||
(req "bodyType" ex_stack_ty_enc))
|
|
||||||
(function
|
|
||||||
| Invalid_map_body (loc, stack) ->
|
|
||||||
Some (loc, Ex_stack_ty stack)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, Ex_stack_ty stack) ->
|
|
||||||
Invalid_map_body (loc, stack)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidMapBlockFail"
|
|
||||||
~title:"FAIL instruction occurred as body of map block"
|
|
||||||
~description:"FAIL cannot be the only instruction in the body. \
|
|
||||||
The propper type of the return list cannot be inferred."
|
|
||||||
(obj1 (req "loc" Script.location_encoding))
|
|
||||||
(function
|
|
||||||
| Invalid_map_block_fail loc -> Some loc
|
|
||||||
| _ -> None)
|
|
||||||
(fun loc -> Invalid_map_block_fail loc) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"invalidIterBody"
|
|
||||||
~title:"ITER body returned wrong stack type"
|
|
||||||
~description:"The body of an ITER instruction \
|
|
||||||
must result in the same stack type as before \
|
|
||||||
the ITER."
|
|
||||||
(obj3
|
|
||||||
(req "loc" Script.location_encoding)
|
|
||||||
(req "befStack" ex_stack_ty_enc)
|
|
||||||
(req "aftStack" ex_stack_ty_enc))
|
|
||||||
(function
|
|
||||||
| Invalid_iter_body (loc, bef, aft) -> Some (loc, Ex_stack_ty bef, Ex_stack_ty aft)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, Ex_stack_ty bef, Ex_stack_ty aft) -> Invalid_iter_body (loc, bef, aft)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"typeTooLarge"
|
|
||||||
~title:"Stack item type too large"
|
|
||||||
~description:"An instruction generated a type larger than the limit."
|
|
||||||
(obj3
|
|
||||||
(req "loc" Script.location_encoding)
|
|
||||||
(req "typeSize" uint16)
|
|
||||||
(req "maximumTypeSize" uint16))
|
|
||||||
(function
|
|
||||||
| Type_too_large (loc, ts, maxts) -> Some (loc, ts, maxts)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (loc, ts, maxts) -> Type_too_large (loc, ts, maxts)) ;
|
|
||||||
(* Toplevel errors *)
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"illTypedDataTypeError"
|
|
||||||
~title: "Ill typed data (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"The toplevel error thrown when trying to typecheck \
|
|
||||||
a data expression against a given type \
|
|
||||||
(always followed by more precise errors)."
|
|
||||||
(obj3
|
|
||||||
(opt "identifier" string)
|
|
||||||
(req "expectedType" ex_ty_enc)
|
|
||||||
(req "illTypedExpression" Script.expr_encoding))
|
|
||||||
(function
|
|
||||||
| Ill_typed_data (name, expr, ty) -> Some (name, Ex_ty ty, expr)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (name, Ex_ty ty, expr) ->
|
|
||||||
Ill_typed_data (name, expr, ty)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"illFormedTypeTypeError"
|
|
||||||
~title: "Ill formed type (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"The toplevel error thrown when trying to parse a type expression \
|
|
||||||
(always followed by more precise errors)."
|
|
||||||
(obj3
|
|
||||||
(opt "identifier" string)
|
|
||||||
(req "illFormedExpression" Script.expr_encoding)
|
|
||||||
(req "location" Script.location_encoding))
|
|
||||||
(function
|
|
||||||
| Ill_formed_type (name, expr, loc) -> Some (name, expr, loc)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (name, expr, loc) ->
|
|
||||||
Ill_formed_type (name, expr, loc)) ;
|
|
||||||
register_error_kind
|
|
||||||
`Permanent
|
|
||||||
~id:"illTypedContractTypeError"
|
|
||||||
~title: "Ill typed contract (typechecking error)"
|
|
||||||
~description:
|
|
||||||
"The toplevel error thrown when trying to typecheck \
|
|
||||||
a contract code against given input, output and storage types \
|
|
||||||
(always followed by more precise errors)."
|
|
||||||
(obj2
|
|
||||||
(req "illTypedCode" Script.expr_encoding)
|
|
||||||
(req "typeMap" type_map_enc))
|
|
||||||
(function
|
|
||||||
| Ill_typed_contract (expr, type_map) ->
|
|
||||||
Some (expr, type_map)
|
|
||||||
| _ -> None)
|
|
||||||
(fun (expr, type_map) ->
|
|
||||||
Ill_typed_contract (expr, type_map))
|
|
||||||
|
@ -54,9 +54,6 @@ val parse_ty :
|
|||||||
val unparse_ty :
|
val unparse_ty :
|
||||||
string option -> 'a Script_typed_ir.ty -> Script.node
|
string option -> 'a Script_typed_ir.ty -> Script.node
|
||||||
|
|
||||||
val type_map_enc : type_map Data_encoding.encoding
|
|
||||||
val ex_ty_enc : ex_ty Data_encoding.encoding
|
|
||||||
|
|
||||||
val parse_toplevel
|
val parse_toplevel
|
||||||
: Script.expr -> (Script.node * Script.node * Script.node * Script.node) tzresult
|
: Script.expr -> (Script.node * Script.node * Script.node * Script.node) tzresult
|
||||||
|
|
||||||
|
@ -0,0 +1,549 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2017. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
open Tezos_context
|
||||||
|
open Micheline
|
||||||
|
open Script
|
||||||
|
open Script_typed_ir
|
||||||
|
open Script_tc_errors
|
||||||
|
open Script_ir_translator
|
||||||
|
|
||||||
|
(* Helpers for encoding *)
|
||||||
|
let type_map_enc =
|
||||||
|
let open Data_encoding in
|
||||||
|
list
|
||||||
|
(conv
|
||||||
|
(fun (loc, (bef, aft)) -> (loc, bef, aft))
|
||||||
|
(fun (loc, bef, aft) -> (loc, (bef, aft)))
|
||||||
|
(obj3
|
||||||
|
(req "location" Script.location_encoding)
|
||||||
|
(req "stackBefore" (list Script.expr_encoding))
|
||||||
|
(req "stackAfter" (list Script.expr_encoding))))
|
||||||
|
|
||||||
|
let ex_ty_enc =
|
||||||
|
Data_encoding.conv
|
||||||
|
(fun (Ex_ty ty) -> strip_locations (unparse_ty None ty))
|
||||||
|
(fun expr ->
|
||||||
|
match parse_ty (root expr) with
|
||||||
|
| Ok (Ex_ty ty, _) -> Ex_ty ty
|
||||||
|
| _ -> Ex_ty Unit_t (* FIXME: ? *))
|
||||||
|
Script.expr_encoding
|
||||||
|
|
||||||
|
(* main registration *)
|
||||||
|
let () =
|
||||||
|
let open Data_encoding in
|
||||||
|
let located enc =
|
||||||
|
merge_objs
|
||||||
|
(obj1 (req "location" Script.location_encoding))
|
||||||
|
enc in
|
||||||
|
let arity_enc =
|
||||||
|
int8 in
|
||||||
|
let namespace_enc =
|
||||||
|
def "primitiveNamespace" @@
|
||||||
|
describe
|
||||||
|
~title: "Primitive namespace"
|
||||||
|
~description:
|
||||||
|
"One of the three possible namespaces of primitive \
|
||||||
|
(data constructor, type name or instruction)." @@
|
||||||
|
string_enum [ "type", Type_namespace ;
|
||||||
|
"constant", Constant_namespace ;
|
||||||
|
"instruction", Instr_namespace ] in
|
||||||
|
let kind_enc =
|
||||||
|
def "expressionKind" @@
|
||||||
|
describe
|
||||||
|
~title: "Expression kind"
|
||||||
|
~description:
|
||||||
|
"One of the four possible kinds of expression \
|
||||||
|
(integer, string, primitive application or sequence)." @@
|
||||||
|
string_enum [ "integer", Int_kind ;
|
||||||
|
"string", String_kind ;
|
||||||
|
"primitiveApplication", Prim_kind ;
|
||||||
|
"sequence", Seq_kind ] in
|
||||||
|
let ex_stack_ty_enc =
|
||||||
|
let rec unfold = function
|
||||||
|
| Ex_stack_ty (Item_t (ty, rest, annot)) ->
|
||||||
|
(Ex_ty ty, annot) :: unfold (Ex_stack_ty rest)
|
||||||
|
| Ex_stack_ty Empty_t -> [] in
|
||||||
|
let rec fold = function
|
||||||
|
| (Ex_ty ty, annot) :: rest ->
|
||||||
|
let Ex_stack_ty rest = fold rest in
|
||||||
|
Ex_stack_ty (Item_t (ty, rest, annot))
|
||||||
|
| [] -> Ex_stack_ty Empty_t in
|
||||||
|
conv unfold fold (list (tup2 ex_ty_enc (option string))) in
|
||||||
|
(* -- Structure errors ---------------------- *)
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidArityTypeError"
|
||||||
|
~title: "Invalid arity (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"In a script or data expression, a primitive was applied \
|
||||||
|
to an unsupported number of arguments."
|
||||||
|
(located (obj3
|
||||||
|
(req "primitiveName" Script.prim_encoding)
|
||||||
|
(req "expectedArity" arity_enc)
|
||||||
|
(req "wrongArity" arity_enc)))
|
||||||
|
(function
|
||||||
|
| Invalid_arity (loc, name, exp, got) ->
|
||||||
|
Some (loc, (name, exp, got))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (name, exp, got)) ->
|
||||||
|
Invalid_arity (loc, name, exp, got)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"missingScriptField"
|
||||||
|
~title:"Script is missing a field (parse error)"
|
||||||
|
~description:
|
||||||
|
"When parsing script, a field was expected, but not provided"
|
||||||
|
(obj1 (req "prim" prim_encoding))
|
||||||
|
(function Missing_field prim -> Some prim | _ -> None)
|
||||||
|
(fun prim -> Missing_field prim) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidPrimitiveTypeError"
|
||||||
|
~title: "Invalid primitive (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"In a script or data expression, a primitive was unknown."
|
||||||
|
(located (obj2
|
||||||
|
(dft "expectedPrimitiveNames" (list prim_encoding) [])
|
||||||
|
(req "wrongPrimitiveName" prim_encoding)))
|
||||||
|
(function
|
||||||
|
| Invalid_primitive (loc, exp, got) -> Some (loc, (exp, got))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (exp, got)) ->
|
||||||
|
Invalid_primitive (loc, exp, got)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidExpressionKindTypeError"
|
||||||
|
~title: "Invalid expression kind (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"In a script or data expression, an expression was of the wrong kind \
|
||||||
|
(for instance a string where only a primitive applications can appear)."
|
||||||
|
(located (obj2
|
||||||
|
(req "expectedKinds" (list kind_enc))
|
||||||
|
(req "wrongKind" kind_enc)))
|
||||||
|
(function
|
||||||
|
| Invalid_kind (loc, exp, got) -> Some (loc, (exp, got))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (exp, got)) ->
|
||||||
|
Invalid_kind (loc, exp, got)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidPrimitiveNamespaceTypeError"
|
||||||
|
~title: "Invalid primitive namespace (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"In a script or data expression, a primitive was of the wrong namespace."
|
||||||
|
(located (obj3
|
||||||
|
(req "primitiveName" prim_encoding)
|
||||||
|
(req "expectedNamespace" namespace_enc)
|
||||||
|
(req "wrongNamespace" namespace_enc)))
|
||||||
|
(function
|
||||||
|
| Invalid_namespace (loc, name, exp, got) -> Some (loc, (name, exp, got))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (name, exp, got)) ->
|
||||||
|
Invalid_namespace (loc, name, exp, got)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"duplicateScriptField"
|
||||||
|
~title:"Script has a duplicated field (parse error)"
|
||||||
|
~description:
|
||||||
|
"When parsing script, a field was found more than once"
|
||||||
|
(obj2
|
||||||
|
(req "loc" location_encoding)
|
||||||
|
(req "prim" prim_encoding))
|
||||||
|
(function Duplicate_field (loc, prim) -> Some (loc, prim) | _ -> None)
|
||||||
|
(fun (loc, prim) -> Duplicate_field (loc, prim)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"unorderedMapLiteral"
|
||||||
|
~title:"Invalid map key order"
|
||||||
|
~description:"Map keys must be in strictly increasing order"
|
||||||
|
(obj2
|
||||||
|
(req "location" Script.location_encoding)
|
||||||
|
(req "item" Script.expr_encoding))
|
||||||
|
(function
|
||||||
|
| Unordered_map_keys (loc, expr) -> Some (loc, expr)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, expr) -> Unordered_map_keys (loc, expr));
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"duplicateMapKeys"
|
||||||
|
~title:"Duplicate map keys"
|
||||||
|
~description:"Map literals cannot contain duplicated keys"
|
||||||
|
(obj2
|
||||||
|
(req "location" Script.location_encoding)
|
||||||
|
(req "item" Script.expr_encoding))
|
||||||
|
(function
|
||||||
|
| Duplicate_map_keys (loc, expr) -> Some (loc, expr)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, expr) -> Duplicate_map_keys (loc, expr));
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"unorderedSetLiteral"
|
||||||
|
~title:"Invalid set value order"
|
||||||
|
~description:"Set values must be in strictly increasing order"
|
||||||
|
(obj2
|
||||||
|
(req "location" Script.location_encoding)
|
||||||
|
(req "value" Script.expr_encoding))
|
||||||
|
(function
|
||||||
|
| Unordered_set_values (loc, expr) -> Some (loc, expr)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, expr) -> Unordered_set_values (loc, expr));
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"duplicateSetValuesInLiteral"
|
||||||
|
~title:"Sets literals cannot contain duplicate elements"
|
||||||
|
~description:"Set literals cannot contain duplicate elements, \
|
||||||
|
but a duplicae was found while parsing."
|
||||||
|
(obj2
|
||||||
|
(req "location" Script.location_encoding)
|
||||||
|
(req "value" Script.expr_encoding))
|
||||||
|
(function
|
||||||
|
| Duplicate_set_values (loc, expr) -> Some (loc, expr)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, expr) -> Duplicate_set_values (loc, expr));
|
||||||
|
(* -- Instruction typing errors ------------- *)
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"failNotInTailPositionTypeError"
|
||||||
|
~title: "FAIL not in tail position (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"There is non trivial garbage code after a FAIL instruction."
|
||||||
|
(located empty)
|
||||||
|
(function
|
||||||
|
| Fail_not_in_tail_position loc -> Some (loc, ())
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, ()) ->
|
||||||
|
Fail_not_in_tail_position loc) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"undefinedBinopTypeError"
|
||||||
|
~title: "Undefined binop (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A binary operation is called on operands of types \
|
||||||
|
over which it is not defined."
|
||||||
|
(located (obj3
|
||||||
|
(req "operatorName" prim_encoding)
|
||||||
|
(req "wrongLeftOperandType" ex_ty_enc)
|
||||||
|
(req "wrongRightOperandType" ex_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Undefined_binop (loc, n, tyl, tyr) ->
|
||||||
|
Some (loc, (n, Ex_ty tyl, Ex_ty tyr))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (n, Ex_ty tyl, Ex_ty tyr)) ->
|
||||||
|
Undefined_binop (loc, n, tyl, tyr)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"undefinedUnopTypeError"
|
||||||
|
~title: "Undefined unop (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A unary operation is called on an operand of type \
|
||||||
|
over which it is not defined."
|
||||||
|
(located (obj2
|
||||||
|
(req "operatorName" prim_encoding)
|
||||||
|
(req "wrongOperandType" ex_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Undefined_unop (loc, n, ty) ->
|
||||||
|
Some (loc, (n, Ex_ty ty))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (n, Ex_ty ty)) ->
|
||||||
|
Undefined_unop (loc, n, ty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"badReturnTypeError"
|
||||||
|
~title: "Bad return (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"Unexpected stack at the end of a lambda or script."
|
||||||
|
(located (obj2
|
||||||
|
(req "expectedReturnType" ex_ty_enc)
|
||||||
|
(req "wrongStackType" ex_stack_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Bad_return (loc, sty, ty) -> Some (loc, (Ex_ty ty, Ex_stack_ty sty))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (Ex_ty ty, Ex_stack_ty sty)) ->
|
||||||
|
Bad_return (loc, sty, ty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"badStackTypeError"
|
||||||
|
~title: "Bad stack (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"The stack has an unexpected length or contents."
|
||||||
|
(located (obj3
|
||||||
|
(req "primitiveName" prim_encoding)
|
||||||
|
(req "relevantStackPortion" int16)
|
||||||
|
(req "wrongStackType" ex_stack_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Bad_stack (loc, name, s, sty) -> Some (loc, (name, s, Ex_stack_ty sty))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (name, s, Ex_stack_ty sty)) ->
|
||||||
|
Bad_stack (loc, name, s, sty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"inconsistentAnnotations"
|
||||||
|
~title:"Annotations inconsistent between branches"
|
||||||
|
~description:"The annotations on two types could not be merged"
|
||||||
|
(obj2
|
||||||
|
(req "annot1" string)
|
||||||
|
(req "annot2" string))
|
||||||
|
(function Inconsistent_annotations (annot1, annot2) -> Some (annot1, annot2)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (annot1, annot2) -> Inconsistent_annotations (annot1, annot2)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"inconsistentTypeAnnotations"
|
||||||
|
~title:"Types contain inconsistent annotations"
|
||||||
|
~description:"The two types contain annotations that do not match"
|
||||||
|
(located (obj2
|
||||||
|
(req "type1" ex_ty_enc)
|
||||||
|
(req "type2" ex_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Inconsistent_type_annotations (loc, ty1, ty2) -> Some (loc, (Ex_ty ty1, Ex_ty ty2))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (Ex_ty ty1, Ex_ty ty2)) -> Inconsistent_type_annotations (loc, ty1, ty2)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"unexpectedAnnotation"
|
||||||
|
~title:"An annotation was encountered where no annotation is expected"
|
||||||
|
~description:"A node in the syntax tree was impropperly annotated"
|
||||||
|
(located empty)
|
||||||
|
(function Unexpected_annotation loc -> Some (loc, ())
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, ()) -> Unexpected_annotation loc);
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"unmatchedBranchesTypeError"
|
||||||
|
~title: "Unmatched branches (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"At the join point at the end of two code branches \
|
||||||
|
the stacks have inconsistent lengths or contents."
|
||||||
|
(located (obj2
|
||||||
|
(req "firstStackType" ex_stack_ty_enc)
|
||||||
|
(req "otherStackType" ex_stack_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Unmatched_branches (loc, stya, styb) ->
|
||||||
|
Some (loc, (Ex_stack_ty stya, Ex_stack_ty styb))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (Ex_stack_ty stya, Ex_stack_ty styb)) ->
|
||||||
|
Unmatched_branches (loc, stya, styb)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"badStackItemTypeError"
|
||||||
|
~title: "Bad stack item (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"The type of a stack item is unexpected \
|
||||||
|
(this error is always accompanied by a more precise one)."
|
||||||
|
(obj1 (req "itemLevel" int16))
|
||||||
|
(function
|
||||||
|
| Bad_stack_item n -> Some n
|
||||||
|
| _ -> None)
|
||||||
|
(fun n ->
|
||||||
|
Bad_stack_item n) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"TransferInLambdaTypeError"
|
||||||
|
~title: "Transfer in lambda (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A TRANSFER_TOKENS instruction was encountered in a lambda expression."
|
||||||
|
(located empty)
|
||||||
|
(function
|
||||||
|
| Transfer_in_lambda loc -> Some (loc, ())
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, ()) ->
|
||||||
|
Transfer_in_lambda loc) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"selfInLambda"
|
||||||
|
~title: "SELF instruction in lambda (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A SELF instruction was encountered in a lambda expression."
|
||||||
|
(located empty)
|
||||||
|
(function
|
||||||
|
| Self_in_lambda loc -> Some (loc, ())
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, ()) ->
|
||||||
|
Self_in_lambda loc) ;
|
||||||
|
(* Bad stack length *)
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"inconsistentStackLengthsTypeError"
|
||||||
|
~title: "Inconsistent stack lengths (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A stack was of an unexpected length \
|
||||||
|
(this error is always in the context of a located error)."
|
||||||
|
empty
|
||||||
|
(function
|
||||||
|
| Bad_stack_length -> Some ()
|
||||||
|
| _ -> None)
|
||||||
|
(fun () ->
|
||||||
|
Bad_stack_length) ;
|
||||||
|
(* -- Value typing errors ------------------- *)
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidConstantTypeError"
|
||||||
|
~title: "Invalid constant (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A data expression was invalid for its expected type."
|
||||||
|
(located (obj2
|
||||||
|
(req "expectedType" ex_ty_enc)
|
||||||
|
(req "wrongExpression" Script.expr_encoding)))
|
||||||
|
(function
|
||||||
|
| Invalid_constant (loc, expr, ty) ->
|
||||||
|
Some (loc, (Ex_ty ty, expr))
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, (Ex_ty ty, expr)) ->
|
||||||
|
Invalid_constant (loc, expr, ty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidContractTypeError"
|
||||||
|
~title: "Invalid contract (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A script or data expression references a contract that does not \
|
||||||
|
exist or assumes a wrong type for an existing contract."
|
||||||
|
(located (obj1 (req "contract" Contract.encoding)))
|
||||||
|
(function
|
||||||
|
| Invalid_contract (loc, c) ->
|
||||||
|
Some (loc, c)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, c) ->
|
||||||
|
Invalid_contract (loc, c)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"comparableTypeExpectedTypeError"
|
||||||
|
~title: "Comparable type expected (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"A non comparable type was used in a place where \
|
||||||
|
only comparable types are accepted."
|
||||||
|
(located (obj1 (req "wrongType" ex_ty_enc)))
|
||||||
|
(function
|
||||||
|
| Comparable_type_expected (loc, ty) -> Some (loc, Ex_ty ty)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, Ex_ty ty) ->
|
||||||
|
Comparable_type_expected (loc, ty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"InconsistentTypesTypeError"
|
||||||
|
~title: "Inconsistent types (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"This is the basic type clash error, \
|
||||||
|
that appears in several places where the equality of \
|
||||||
|
two types have to be proven, it is always accompanied \
|
||||||
|
with another error that provides more context."
|
||||||
|
(obj2
|
||||||
|
(req "firstType" ex_ty_enc)
|
||||||
|
(req "otherType" ex_ty_enc))
|
||||||
|
(function
|
||||||
|
| Inconsistent_types (tya, tyb) ->
|
||||||
|
Some (Ex_ty tya, Ex_ty tyb)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (Ex_ty tya, Ex_ty tyb) ->
|
||||||
|
Inconsistent_types (tya, tyb)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidMapBody"
|
||||||
|
~title: "Invalid map body"
|
||||||
|
~description:
|
||||||
|
"The body of a map block did not match the expected type"
|
||||||
|
(obj2
|
||||||
|
(req "loc" Script.location_encoding)
|
||||||
|
(req "bodyType" ex_stack_ty_enc))
|
||||||
|
(function
|
||||||
|
| Invalid_map_body (loc, stack) ->
|
||||||
|
Some (loc, Ex_stack_ty stack)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, Ex_stack_ty stack) ->
|
||||||
|
Invalid_map_body (loc, stack)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidMapBlockFail"
|
||||||
|
~title:"FAIL instruction occurred as body of map block"
|
||||||
|
~description:"FAIL cannot be the only instruction in the body. \
|
||||||
|
The propper type of the return list cannot be inferred."
|
||||||
|
(obj1 (req "loc" Script.location_encoding))
|
||||||
|
(function
|
||||||
|
| Invalid_map_block_fail loc -> Some loc
|
||||||
|
| _ -> None)
|
||||||
|
(fun loc -> Invalid_map_block_fail loc) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"invalidIterBody"
|
||||||
|
~title:"ITER body returned wrong stack type"
|
||||||
|
~description:"The body of an ITER instruction \
|
||||||
|
must result in the same stack type as before \
|
||||||
|
the ITER."
|
||||||
|
(obj3
|
||||||
|
(req "loc" Script.location_encoding)
|
||||||
|
(req "befStack" ex_stack_ty_enc)
|
||||||
|
(req "aftStack" ex_stack_ty_enc))
|
||||||
|
(function
|
||||||
|
| Invalid_iter_body (loc, bef, aft) -> Some (loc, Ex_stack_ty bef, Ex_stack_ty aft)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, Ex_stack_ty bef, Ex_stack_ty aft) -> Invalid_iter_body (loc, bef, aft)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"typeTooLarge"
|
||||||
|
~title:"Stack item type too large"
|
||||||
|
~description:"An instruction generated a type larger than the limit."
|
||||||
|
(obj3
|
||||||
|
(req "loc" Script.location_encoding)
|
||||||
|
(req "typeSize" uint16)
|
||||||
|
(req "maximumTypeSize" uint16))
|
||||||
|
(function
|
||||||
|
| Type_too_large (loc, ts, maxts) -> Some (loc, ts, maxts)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (loc, ts, maxts) -> Type_too_large (loc, ts, maxts)) ;
|
||||||
|
(* Toplevel errors *)
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"illTypedDataTypeError"
|
||||||
|
~title: "Ill typed data (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"The toplevel error thrown when trying to typecheck \
|
||||||
|
a data expression against a given type \
|
||||||
|
(always followed by more precise errors)."
|
||||||
|
(obj3
|
||||||
|
(opt "identifier" string)
|
||||||
|
(req "expectedType" ex_ty_enc)
|
||||||
|
(req "illTypedExpression" Script.expr_encoding))
|
||||||
|
(function
|
||||||
|
| Ill_typed_data (name, expr, ty) -> Some (name, Ex_ty ty, expr)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (name, Ex_ty ty, expr) ->
|
||||||
|
Ill_typed_data (name, expr, ty)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"illFormedTypeTypeError"
|
||||||
|
~title: "Ill formed type (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"The toplevel error thrown when trying to parse a type expression \
|
||||||
|
(always followed by more precise errors)."
|
||||||
|
(obj3
|
||||||
|
(opt "identifier" string)
|
||||||
|
(req "illFormedExpression" Script.expr_encoding)
|
||||||
|
(req "location" Script.location_encoding))
|
||||||
|
(function
|
||||||
|
| Ill_formed_type (name, expr, loc) -> Some (name, expr, loc)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (name, expr, loc) ->
|
||||||
|
Ill_formed_type (name, expr, loc)) ;
|
||||||
|
register_error_kind
|
||||||
|
`Permanent
|
||||||
|
~id:"illTypedContractTypeError"
|
||||||
|
~title: "Ill typed contract (typechecking error)"
|
||||||
|
~description:
|
||||||
|
"The toplevel error thrown when trying to typecheck \
|
||||||
|
a contract code against given input, output and storage types \
|
||||||
|
(always followed by more precise errors)."
|
||||||
|
(obj2
|
||||||
|
(req "illTypedCode" Script.expr_encoding)
|
||||||
|
(req "typeMap" type_map_enc))
|
||||||
|
(function
|
||||||
|
| Ill_typed_contract (expr, type_map) ->
|
||||||
|
Some (expr, type_map)
|
||||||
|
| _ -> None)
|
||||||
|
(fun (expr, type_map) ->
|
||||||
|
Ill_typed_contract (expr, type_map))
|
@ -489,7 +489,7 @@ module Helpers = struct
|
|||||||
~description: "Typecheck a piece of code in the current context"
|
~description: "Typecheck a piece of code in the current context"
|
||||||
~query: RPC_query.empty
|
~query: RPC_query.empty
|
||||||
~input: Script.expr_encoding
|
~input: Script.expr_encoding
|
||||||
~output: (wrap_tzerror Script_ir_translator.type_map_enc)
|
~output: (wrap_tzerror Script_tc_errors_registration.type_map_enc)
|
||||||
~error: Data_encoding.empty
|
~error: Data_encoding.empty
|
||||||
RPC_path.(custom_root / "helpers" / "typecheck_code")
|
RPC_path.(custom_root / "helpers" / "typecheck_code")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user