Module ErgoSpec.Common.Utils.Result
Require
Import
Ascii
.
Require
Import
String
.
Require
Import
List
.
Require
Import
ZArith
.
Require
Import
ErgoSpec.Backend.ErgoBackend
.
Require
Import
ErgoSpec.Common.Utils.Provenance
.
Require
Import
ErgoSpec.Common.Utils.Names
.
Section
Result
.
Inductive
eerror
:
Set
:=
|
ESystemError
:
provenance
->
string
->
eerror
|
EParseError
:
provenance
->
string
->
eerror
|
ECompilationError
:
provenance
->
string
->
eerror
|
ETypeError
:
provenance
->
string
->
eerror
|
ERuntimeError
:
provenance
->
string
->
eerror
.
Definition
eresult
(
A
:
Set
) :=
Result
A
eerror
.
Definition
esuccess
{
A
:
Set
} (
a
:
A
) :
eresult
A
:=
Success
A
eerror
a
.
Definition
efailure
{
A
:
Set
} (
e
:
eerror
) :
eresult
A
:=
Failure
A
eerror
e
.
Section
Lift
.
Definition
eolift
{
A
B
:
Set
} (
f
:
A
->
eresult
B
) (
a
:
eresult
A
) :
eresult
B
:=
lift_failure
f
a
.
Definition
elift
{
A
B
:
Set
} (
f
:
A
->
B
) (
a
:
eresult
A
) :
eresult
B
:=
lift_failure_in
f
a
.
Definition
elift2
{
A
B
C
:
Set
} (
f
:
A
->
B
->
C
) (
a
:
eresult
A
) (
b
:
eresult
B
) :
eresult
C
:=
lift_failure_in_two
f
a
b
.
Definition
elift3
{
A
B
C
D
:
Set
} (
f
:
A
->
B
->
C
->
D
)
(
a
:
eresult
A
) (
b
:
eresult
B
) (
c
:
eresult
C
) :
eresult
D
:=
lift_failure_in_three
f
a
b
c
.
Definition
elift4
{
A
B
C
D
E
:
Set
} (
f
:
A
->
B
->
C
->
D
->
E
)
(
a
:
eresult
A
) (
b
:
eresult
B
) (
c
:
eresult
C
) (
d
:
eresult
D
) :
eresult
E
:=
eolift
(
fun
x
=>
elift
(
fun
g
=>
g
x
) (
elift3
f
a
b
c
))
d
.
Definition
elift5
{
A
B
C
D
E
F
:
Set
} (
f
:
A
->
B
->
C
->
D
->
E
->
F
)
(
a
:
eresult
A
) (
b
:
eresult
B
) (
c
:
eresult
C
) (
d
:
eresult
D
) (
e
:
eresult
E
) :
eresult
F
:=
eolift
(
fun
x
=>
elift
(
fun
g
=>
g
x
) (
elift4
f
a
b
c
d
))
e
.
Definition
emaplift
{
A
B
:
Set
} (
f
:
A
->
eresult
B
) (
al
:
list
A
) :
eresult
(
list
B
) :=
lift_failure_map
f
al
.
Definition
eresult_of_option
{
A
:
Set
} (
a
:
option
A
) (
e
:
eerror
) :=
result_of_option
a
e
.
Definition
elift_both
{
A
B
:
Set
} (
f
:
A
->
B
) (
g
:
eerror
->
B
) (
a
:
eresult
A
) :
B
:=
match
a
with
|
Success
_
_
s
=>
f
s
|
Failure
_
_
e
=>
g
e
end
.
Definition
elift2_both
{
A
B
C
:
Set
} (
f
:
A
->
B
->
C
) (
g
:
eerror
->
C
) (
a
:
eresult
A
) (
b
:
eresult
B
) :
C
:=
match
a
with
|
Success
_
_
s1
=>
match
b
with
|
Success
_
_
s2
=>
f
s1
s2
|
Failure
_
_
e
=>
g
e
end
|
Failure
_
_
e
=>
g
e
end
.
Definition
elift_maybe
{
A
:
Set
} (
f
:
A
->
option
(
eresult
A
)) (
a
:
eresult
A
) :
eresult
A
:=
match
elift
f
a
with
|
Success
_
_
(
Some
s
) =>
s
|
Success
_
_
None
=>
a
|
Failure
_
_
e
=>
efailure
e
end
.
Definition
eolift2
{
A
B
C
:
Set
} (
f
:
A
->
B
->
eresult
C
) (
a
:
eresult
A
) (
b
:
eresult
B
) :
eresult
C
:=
match
elift2
f
a
b
with
|
Failure
_
_
f
=>
efailure
f
|
Success
_
_
s
=>
s
end
.
Definition
elift_fold_left
{
A
:
Set
} {
B
:
Set
}
(
f
:
A
->
B
->
eresult
A
) (
l
:
list
B
) (
a
:
A
) :
eresult
A
:=
let
proc_one
(
acc
:
eresult
A
) (
x
:
B
)
:
eresult
A
:=
eolift
(
fun
acc
=>
f
acc
x
)
acc
in
fold_left
proc_one
l
(
esuccess
a
).
Definition
elift_context_fold_left_alt
{
A
:
Set
} {
B
:
Set
} {
C
:
Set
}
(
f
:
C
->
A
->
eresult
(
B
*
C
)) (
l
:
list
A
) (
c
:
C
) :
eresult
(
list
B
*
C
) :=
elift_fold_left
(
fun
acc
c
=>
elift
(
fun
mc
=> ((
fst
acc
)++((
fst
mc
)::
nil
),
snd
mc
)) (
f
(
snd
acc
)
c
))
l
(
nil
,
c
).
Definition
elift_context_fold_left
{
A
:
Set
} {
B
:
Set
} {
C
:
Set
}
(
f
:
C
->
A
->
eresult
(
B
*
C
)) (
l
:
list
A
) (
c
:
C
) :
eresult
(
list
B
*
C
) :=
elift_fold_left
(
fun
acc
c
=>
elift
(
fun
mc
=> ((
fst
acc
)++((
fst
mc
)::
nil
),
snd
mc
)) (
f
(
snd
acc
)
c
))
l
(
nil
,
c
).
Definition
eflatmaplift
{
A
B
:
Set
} (
f
:
A
->
eresult
(
list
B
)) (
al
:
list
A
) :
eresult
(
list
B
) :=
elift_fold_left
(
fun
acc
c
=>
elift
(
fun
mc
=>
acc
++
mc
) (
f
c
))
al
nil
.
Section
qcert
.
Definition
eerror_of_qerror
(
prov
:
provenance
) (
qe
:
qerror
) :=
match
qe
with
|
QResult.CompilationError
msg
=>
ECompilationError
prov
msg
|
QResult.TypeError
msg
=>
ETypeError
prov
msg
|
QResult.UserError
msg
=>
ESystemError
prov
"
User
error
occured
in
backend
"
end
.
Definition
eresult_of_qresult
{
A
:
Set
} (
prov
:
provenance
) (
a
:
qresult
A
) :
eresult
A
:=
match
a
with
|
Result.Success
_
_
s
=>
esuccess
s
|
Result.Failure
_
_
e
=>
efailure
(
eerror_of_qerror
prov
e
)
end
.
Definition
option_of_eresult
{
A
:
Set
} (
a
:
eresult
A
) :
option
A
:=
option_of_result
a
.
End
qcert
.
End
Lift
.
Section
Fmt
.
Definition
format_error
(
name
:
string
) (
prov
:
provenance
) (
msg
:
string
) :=
let
loc
:=
loc_of_provenance
prov
in
(
name
++ "
at
" ++ (
string_of_location
loc
) ++ " '" ++
msg
++ "'")%
string
.
End
Fmt
.
Built-in errors
Section
Builtin
.
Definition
clause_call_not_on_contract_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Cannot
call
a
clause
except
on
'
contract
'").
Definition
use_contract_not_in_contract_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Cannot
use
'
contract
'
variable
outside
of
a
contract
").
Definition
call_clause_not_in_contract_error
{
A
}
prov
clname
:
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
call
clause
" ++
clname
++ "
outside
of
a
contract
")).
Definition
not_in_clause_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Cannot
use
'
clause
'
variable
outside
of
a
clause
").
Definition
import_not_found_error
{
A
}
prov
(
import
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Import
not
found
: " ++
import
)).
Definition
type_name_not_found_error
{
A
}
prov
(
ln
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
find
type
with
name
'" ++
ln
++ "'")).
Definition
variable_name_not_found_error
{
A
}
prov
(
ln
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
find
variable
with
name
'" ++
ln
++ "'")).
Definition
function_name_not_found_error
{
A
}
prov
(
ln
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
find
function
with
name
'" ++
ln
++ "'")).
Definition
contract_name_not_found_error
{
A
}
prov
(
ln
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
find
contract
with
name
'" ++
ln
++ "'")).
Definition
import_name_not_found_error
{
A
}
prov
(
namespace
:
string
) (
name_ref
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
import
name
'" ++
name_ref
++ "'
in
CTO
with
namespace
" ++
namespace
)).
Main clause creation errors
Definition
main_parameter_mismatch_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Parameter
mismatch
during
main
creation
").
Definition
main_at_least_one_parameter_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Cannot
create
main
if
not
at
least
one
parameter
").
Definition
main_not_a_class_error
{
A
}
prov
(
cname
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Cannot
create
main
for
non
-
class
type
"++
cname
)).
Call errors
Definition
function_not_found_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Function
'" ++
fname
++ "'
not
found
")).
Definition
eval_function_not_found_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ERuntimeError
prov
("
Function
'" ++
fname
++ "'
not
found
during
eval
")).
Definition
clause_not_found_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Clause
'" ++
fname
++ "'
not
found
")).
Definition
call_params_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ECompilationError
prov
("
Parameter
mismatch
when
calling
function
'" ++
fname
++ "'")).
Other runtime errors
Definition
eval_unary_op_error
{
A
}
prov
(
op
:
ErgoOps.Unary.op
) :
eresult
A
:=
efailure
(
ERuntimeError
prov
"
Unary
operation
failed
.").
Definition
eval_binary_op_error
{
A
}
prov
(
op
:
ErgoOps.Binary.op
) :
eresult
A
:=
efailure
(
ERuntimeError
prov
"
Binary
operation
failed
.").
Definition
eval_if_not_boolean_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ERuntimeError
prov
"'
If
'
condition
not
boolean
.").
Definition
eval_match_let_optional_not_on_option_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ERuntimeError
prov
"
Matched
LetOption
without
an
option
.").
Definition
eval_foreach_not_on_array_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ERuntimeError
prov
"
Foreach
needs
to
be
called
on
an
array
").
System errors
Definition
no_ergo_module_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ESystemError
prov
("
No
input
ergo
found
")).
Definition
built_in_function_not_found_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ESystemError
prov
("
Built
in
function
" ++
fname
++ "
not
found
")).
Definition
built_in_function_without_body_error
{
A
}
prov
(
fname
:
string
) :
eresult
A
:=
efailure
(
ESystemError
prov
("
Built
in
function
" ++
fname
++ "
does
not
have
a
body
")).
Definition
TODO
{
A
:
Set
}
prov
(
feature
:
string
) :
eresult
A
:=
efailure
(
ESystemError
prov
("
Feature
" ++
feature
++ "
not
implemented
.")%
string
).
Definition
enforce_error_content
(
prov
:
provenance
) (
msg
:
string
) :
ErgoData.data
:=
let
message
:=
format_error
"
Enforce
Error
"
prov
msg
in
ErgoData.dbrand
(
default_error_absolute_name
::
nil
)
(
ErgoData.drec
(("
message
"%
string
,
ErgoData.dstring
message
)::
nil
)).
Definition
default_match_error_content
(
prov
:
provenance
) (
msg
:
string
) :
ErgoData.data
:=
let
message
:=
format_error
"
DefaultMatch
Error
"
prov
msg
in
ErgoData.dbrand
(
default_error_absolute_name
::
nil
)
(
ErgoData.drec
(("
message
"%
string
,
ErgoData.dstring
message
)::
nil
)).
Definition
unresolved_name_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Unresolved
name
").
Definition
should_have_one_contract_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ECompilationError
prov
"
Should
have
exactly
one
contract
").
Definition
contract_in_calculus_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ESystemError
prov
"
Should
not
find
'
contract
'
in
Ergo
Calculus
").
Definition
clause_in_calculus_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ESystemError
prov
"
Should
not
find
'
clause
'
in
Ergo
Calculus
").
Definition
state_in_calculus_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ESystemError
prov
"
Should
not
find
'
state
'
in
Ergo
Calculus
").
Definition
complex_foreach_in_calculus_error
{
A
}
prov
:
eresult
A
:=
efailure
(
ESystemError
prov
"
Should
only
have
single
loop
foreach
in
Ergo
Calculus
").
Definition
function_not_inlined_error
{
A
}
prov
fname
:
eresult
A
:=
efailure
(
ESystemError
prov
("
Function
" ++
fname
++ "
did
not
get
inlined
")).
Definition
function_in_group_not_inlined_error
{
A
}
prov
gname
fname
:
eresult
A
:=
efailure
(
ESystemError
prov
("
Clause
" ++
fname
++ "
in
contract
" ++
gname
++ "
did
not
get
inlined
")).
End
Builtin
.
End
Result
.