Michelson: mv registration of type-checking errors in a specific file

This commit is contained in:
bruno 2018-02-05 15:15:43 +01:00
parent 21c4cc6e69
commit ff7a8abb27
5 changed files with 551 additions and 537 deletions

View File

@ -49,6 +49,7 @@
"Gas",
"Script_tc_errors",
"Script_ir_translator",
"Script_tc_errors_registration",
"Script_interpreter",
"Baking",

View File

@ -2030,17 +2030,6 @@ let parse_script
>>=? fun code ->
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
: context -> Script.expr -> type_map tzresult Lwt.t
= fun ctxt code ->
@ -2086,525 +2075,3 @@ let hash_data typ data =
let unparsed = strip_annotations @@ unparse_data typ data 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)
(* ---- 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))

View File

@ -54,9 +54,6 @@ val parse_ty :
val unparse_ty :
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
: Script.expr -> (Script.node * Script.node * Script.node * Script.node) tzresult

View File

@ -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))

View File

@ -489,7 +489,7 @@ module Helpers = struct
~description: "Typecheck a piece of code in the current context"
~query: RPC_query.empty
~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
RPC_path.(custom_root / "helpers" / "typecheck_code")