41f1407ca8
Bug: Change-Id: Ib7272cbe377f9e8c71ca4d289d170a0cc173ba6b Reviewed-on: https://dart-review.googlesource.com/12640 Reviewed-by: Samir Jindel <sjindel@google.com>
1386 lines
50 KiB
V
1386 lines
50 KiB
V
(* Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||
* for details. All rights reserved. Use of this source code is governed by a
|
||
* BSD-style license that can be found in the LICENSE file. *)
|
||
|
||
|
||
Require Import Coq.Lists.List.
|
||
Require Import Common.
|
||
Require Import Syntax.
|
||
Require Import ObjectModel.
|
||
|
||
|
||
Import ObjectModel.Subtyping.
|
||
|
||
Notation "s <: t" := (subtype (s, t) = true) (at level 70, no associativity).
|
||
|
||
|
||
Section OperationalSemantics.
|
||
|
||
|
||
(** The well-formedness hypothesis is that the environments are built via
|
||
[lib_to_env] function from the object model module. [program_wf] theorem
|
||
defined there provides the rest of the well-formedness properties. In
|
||
[OperationalSemantics] sections we don't need the hypothesis itself, just the
|
||
environments. *)
|
||
Variable CE : class_env.
|
||
Variable ME : member_env.
|
||
|
||
|
||
(** [runtime_value] represents the runtime values used in the abstract machine
|
||
during program execution. The values are typed and have some relation to
|
||
syntactic types and internal representation of their interfaces. Currently a
|
||
runtime value doesn't have a state, it only has a type. It should have a
|
||
state when a broader subset of Kernel is formalized. *)
|
||
Record runtime_value := mk_runtime_value {
|
||
|
||
(** Null is currently modelled using None as the value of [runtime_type].
|
||
It may change in future once [dart_type] includes a constructor for Null
|
||
or Bottom. Also, in the current subset of Kernel type Null can't be
|
||
expressed syntactically; therefore, it can't be a declared type of a method
|
||
parameter, a declared type of a variable, etc. The only use of Null in the
|
||
current subset of Kernel is that of a runtime type of a runtime value. In
|
||
that case the declared type of the variable holding such value and the
|
||
runtime type of the value do not match. *)
|
||
runtime_type : option dart_type;
|
||
}.
|
||
|
||
|
||
(** [value_of_type] defines the meaning of statement "the runtime value has the
|
||
given interface and the given type". *)
|
||
Inductive value_of_type :
|
||
runtime_value -> interface -> option dart_type -> Prop :=
|
||
|
||
(** If the type of the runtime value is an interface type, then the
|
||
corresponding interface should be in the global class environment. *)
|
||
| RFS_Interface_Type :
|
||
forall val intf type class_id,
|
||
type = DT_Interface_Type (Interface_Type class_id) ->
|
||
NatMap.find class_id CE = Some intf ->
|
||
(runtime_type val) = Some type ->
|
||
value_of_type val intf (Some type)
|
||
|
||
(** If the type of the runtime value is a function type, then the
|
||
corresponding interface may or may not be in the global class environment,
|
||
but should have a particular shape. *)
|
||
| RFS_Function_Type :
|
||
forall val intf ftype memb_id proc,
|
||
(procedures intf) = (mk_procedure_desc "call" memb_id ftype) :: nil ->
|
||
(getters intf) =
|
||
(mk_getter_desc "call" memb_id (DT_Function_Type ftype)) :: nil ->
|
||
NatMap.MapsTo memb_id (M_Procedure proc) ME ->
|
||
(runtime_type val) = Some (DT_Function_Type ftype) ->
|
||
value_of_type val intf (Some (DT_Function_Type ftype))
|
||
|
||
(** Null values are currently represented as runtime values that have [None]
|
||
in place of their type. In future, for example when the Bottom type or
|
||
explicit Null type are added to the syntax of dart types, the
|
||
representation may change. *)
|
||
| RFS_Null_Type :
|
||
forall val intf,
|
||
(procedures intf) = nil ->
|
||
(getters intf) = nil ->
|
||
(runtime_type val) = None ->
|
||
value_of_type val intf None.
|
||
|
||
|
||
(** Describes that the given dart type has a method with the given name. The
|
||
predicate can be applied to runtime types of values, so it should accept None
|
||
as the first parameter to account for `null` values.
|
||
|
||
Currently, values of function type only have "call" methods, and null doesn't
|
||
have any methods. *)
|
||
Inductive method_exists : option dart_type -> string -> Prop :=
|
||
|
||
| ME_Interface_Type :
|
||
forall name intf desc class_id type,
|
||
type = (DT_Interface_Type (Interface_Type class_id)) ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some type)) intf (Some type) ->
|
||
List.In desc (procedures intf) ->
|
||
((pr_name desc) = name)%string ->
|
||
method_exists (Some type) name
|
||
|
||
| ME_Function_Type :
|
||
forall type intf desc ftype,
|
||
type = (DT_Function_Type ftype) ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some type)) intf (Some type) ->
|
||
List.In desc (procedures intf) ->
|
||
((pr_name desc) = "call")%string ->
|
||
method_exists (Some type) "call".
|
||
|
||
|
||
(** Describes that the method with the given name of the given dart type
|
||
accepts arguments of the given type. The predicate can be applied to runtime
|
||
types of values, so it should accept None as the first parameter to account
|
||
for `null` values.
|
||
|
||
Currently, values of function type only have "call" methods, and null doesn't
|
||
have any methods. *)
|
||
Inductive method_accepts :
|
||
option dart_type -> string -> option dart_type -> Prop :=
|
||
|
||
| MA_Non_Null :
|
||
forall name intf desc rcvr_type arg_type par_type ret_type,
|
||
method_exists (Some rcvr_type) name ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some rcvr_type)) intf (Some rcvr_type) ->
|
||
List.In desc (procedures intf) ->
|
||
((pr_name desc) = name)%string ->
|
||
(pr_type desc) = Function_Type par_type ret_type ->
|
||
arg_type <: par_type ->
|
||
method_accepts (Some rcvr_type) name (Some arg_type)
|
||
|
||
| MA_Null :
|
||
forall rcvr_type_opt name,
|
||
method_exists rcvr_type_opt name ->
|
||
method_accepts rcvr_type_opt name None.
|
||
|
||
|
||
(** Describes that the method with the given name of the given dart type
|
||
returns a value of the given type. The predicate can be applied to runtime
|
||
types of values, so it should accept None as the first parameter to account
|
||
for `null` values.
|
||
|
||
Currently, values of function type only have "call" methods, and null doesn't
|
||
have any methods. *)
|
||
Inductive method_returns :
|
||
option dart_type -> string -> dart_type -> Prop :=
|
||
|
||
| Method_Returns :
|
||
forall name intf desc rcvr_type par_type ret_type,
|
||
method_exists (Some rcvr_type) name ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some rcvr_type)) intf (Some rcvr_type) ->
|
||
List.In desc (procedures intf) ->
|
||
((pr_name desc) = name)%string ->
|
||
(pr_type desc) = Function_Type par_type ret_type ->
|
||
method_returns (Some rcvr_type) name ret_type.
|
||
|
||
|
||
(** Describes that the given dart type has a getter with the given name. The
|
||
predicate can be applied to runtime types of values, so it should accept None
|
||
as the first parameter to account for `null` values.
|
||
|
||
Currently, values of function type only have "call" getters, and null doesn't
|
||
have any getters. *)
|
||
Inductive getter_exists : option dart_type -> string -> Prop :=
|
||
|
||
| GE_Interface_Type :
|
||
forall name intf desc class_id type,
|
||
type = (DT_Interface_Type (Interface_Type class_id)) ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some type)) intf (Some type) ->
|
||
List.In desc (getters intf) ->
|
||
((gt_name desc) = name)%string ->
|
||
getter_exists (Some type) name
|
||
|
||
| GE_Function_Type :
|
||
forall type intf desc ftype,
|
||
type = (DT_Function_Type ftype) ->
|
||
(* TODO(dmitryas): Replace `value_of_type` here with a relation that binds
|
||
together the interface and the type, avoiding the construction of the
|
||
value. *)
|
||
value_of_type (mk_runtime_value (Some type)) intf (Some type) ->
|
||
List.In desc (getters intf) ->
|
||
((gt_name desc) = "call")%string ->
|
||
getter_exists (Some type) "call".
|
||
|
||
|
||
(** Describes that the getter with the given name of the given dart type
|
||
returns a value of the given type. The predicate can be applied to runtime
|
||
types of values, so it should accept None as the first parameter to account
|
||
for `null` values.
|
||
|
||
Currently, values of function type only have "call" getters, and null doesn't
|
||
have any getters. *)
|
||
Inductive getter_returns :
|
||
option dart_type -> string -> dart_type -> Prop :=
|
||
|
||
| Getter_Returns :
|
||
forall name intf desc rcvr_type,
|
||
getter_exists (Some rcvr_type) name ->
|
||
value_of_type (mk_runtime_value (Some rcvr_type)) intf (Some rcvr_type) ->
|
||
List.In desc (getters intf) ->
|
||
((gt_name desc) = name)%string ->
|
||
getter_returns (Some rcvr_type) name (gt_type desc).
|
||
|
||
|
||
(** The environment that is used by the abstract machine to map the currently
|
||
visible set of variables to their types and runtime values is represented as
|
||
a list of records.
|
||
|
||
[var_type] represents the declared type of the variable and may not match
|
||
the runtime type of the [value] in case the latter is Null. This is because
|
||
in the current subset of Kernel Null can't be represented syntactically. *)
|
||
Record env_entry := mk_env_entry {
|
||
var_ref : nat;
|
||
var_type : dart_type;
|
||
value : runtime_value;
|
||
}.
|
||
|
||
Definition environment := list env_entry.
|
||
|
||
Definition env_get
|
||
(var : nat)
|
||
(env : environment)
|
||
: option env_entry :=
|
||
List.find (fun entry => Nat.eqb var (var_ref entry)) env.
|
||
|
||
Definition env_extend
|
||
(var : nat)
|
||
(type : dart_type)
|
||
(val : runtime_value)
|
||
(env : environment)
|
||
: environment :=
|
||
(mk_env_entry var type val) :: env.
|
||
|
||
Definition env_in
|
||
(var : nat)
|
||
(env : environment)
|
||
: Prop :=
|
||
match List.find (fun entry => Nat.eqb var (var_ref entry)) env with
|
||
| None => False
|
||
| Some _ => True
|
||
end.
|
||
|
||
Definition empty_env : environment := nil.
|
||
|
||
Definition env_to_type_env : environment -> type_env :=
|
||
fun env => List.fold_left
|
||
(fun TE entry => NatMap.add (var_ref entry) (var_type entry) TE)
|
||
env
|
||
(NatMap.empty dart_type).
|
||
|
||
|
||
(** TODO(dmitryas): Write descriptive comments.
|
||
|
||
First, [untyped_expression_continuation] is defined. Its only difference
|
||
from [expression_continuation] is that the value expected by the continuation
|
||
is untyped; [expression_continuation] pairs an
|
||
[untyped_expression_continuation] and a [dart_type], giving the expected
|
||
value a type. It is done to simplify the extraction of the type from an
|
||
expression continuation in predicates. *)
|
||
Inductive untyped_expression_continuation : Set :=
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- an [environment]
|
||
- a [expression_continuation]
|
||
- a [statement_continuation] *)
|
||
| Expression_Ek :
|
||
environment
|
||
-> expression_continuation
|
||
-> statement_continuation
|
||
-> untyped_expression_continuation
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a [string]
|
||
- an [expression]
|
||
- an [environment]
|
||
- a [expression_continuation] *)
|
||
| Method_Invocation_Ek :
|
||
string
|
||
-> expression
|
||
-> environment
|
||
-> expression_continuation
|
||
-> untyped_expression_continuation
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a [runtime_value]
|
||
- a [string]
|
||
- an [environment]
|
||
- a [expression_continuation] *)
|
||
| Invocation_Ek :
|
||
runtime_value
|
||
-> string
|
||
-> environment
|
||
-> expression_continuation
|
||
-> untyped_expression_continuation
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a [string]
|
||
- a [expression_continuation] *)
|
||
| Property_Get_Ek :
|
||
string
|
||
-> expression_continuation
|
||
-> untyped_expression_continuation
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a [nat]
|
||
- a [dart_type]
|
||
- an [environment]
|
||
- a [statement_continuation] *)
|
||
| Var_Declaration_Ek :
|
||
nat
|
||
-> dart_type
|
||
-> environment
|
||
-> statement_continuation
|
||
-> untyped_expression_continuation
|
||
|
||
(** [Halt_Ek] represents the end of program execution. The main procedure
|
||
returns a value (or null) to this expression continuation. The value is
|
||
then ignored, and the program execution halts. The constructor doesn't
|
||
receive any parameters. *)
|
||
| Halt_Ek :
|
||
untyped_expression_continuation
|
||
|
||
(** TODO(dmitryas): Write descriptive comments. *)
|
||
with statement_continuation : Set :=
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a [expression_continuation]
|
||
- a [runtime_value] *)
|
||
| Exit_Sk :
|
||
expression_continuation
|
||
-> runtime_value
|
||
-> statement_continuation
|
||
|
||
(** The constructor receives the following parameters:
|
||
|
||
- a list of [statement]s
|
||
- an [environment]
|
||
- a [expression_continuation]
|
||
- a [statement_continuation] *)
|
||
| Block_Sk :
|
||
list statement
|
||
-> environment
|
||
-> expression_continuation
|
||
-> statement_continuation
|
||
-> statement_continuation
|
||
|
||
(** A [expression_continuation] encapsulates a [dart_type] that signifies
|
||
the type of the value expected by the expression continuation as the
|
||
input.
|
||
|
||
In the current subset of Kernel the Null type can't be described
|
||
syntactically, so it can't be a type of a typed expression or statement.
|
||
Therefore, the type of the value expected by the expression continuation
|
||
can't be Null, and it's expressed as [dart_type], not [option dart_type]. *)
|
||
with expression_continuation : Set :=
|
||
|
||
| Expression_Continuation :
|
||
untyped_expression_continuation
|
||
-> dart_type
|
||
-> expression_continuation.
|
||
|
||
|
||
(** [configuration] represents configurations of the CESK abstract machine that
|
||
is used for defining the operational semantics. A transition of the machine
|
||
represents a small step of the small-step operational semantics. There are
|
||
the following types of configurations:
|
||
|
||
- [Eval_Configuration] — encapsulates a syntactic expression and an
|
||
expression continuation. After evaluation of the expression the resulting
|
||
value is passed to the expression configuration.
|
||
- [Exec_Configuration] — encapsulates a syntactic statement. Represents the
|
||
execution of the statement.
|
||
- [Value_Passing_Configuration] — encapsulates a value and an expression
|
||
continuation. The value is passed to the expression continuation.
|
||
- [Forward_Configuration] — encapsulates a statement continuation.
|
||
The execution of the program proceeds to the associated statement. *)
|
||
Inductive configuration : Set :=
|
||
|
||
(** [Eval_Configuration] represents the beginning of an expression
|
||
evaluation. The constructor receives the following parameters:
|
||
|
||
- an [expression] — the expression to be evaluated;
|
||
- an [environment] — the mapping from variables to values that is to be
|
||
used during the expression evaluation;
|
||
- a [expression_continuation] — the continuation that will receive
|
||
the value of the expression after its evaluation. *)
|
||
| Eval_Configuration :
|
||
expression
|
||
-> environment
|
||
-> expression_continuation
|
||
-> configuration
|
||
|
||
(** [Exec_Configuration] represents the beginning of a statement execution.
|
||
The constructor receives the following parameters:
|
||
|
||
- a [statement] — the statement to be executed;
|
||
- an [environment] — the mapping from variables to values that is to be
|
||
used during the statement execution;
|
||
- a [expression_continuation] — in case the executed statement
|
||
returns a value, this continuation will receive this value;
|
||
- a [statement_continuation] — in case the executed statement
|
||
doesn't return a value, this continuation represents the rest of the
|
||
program execution. *)
|
||
| Exec_Configuration :
|
||
statement
|
||
-> environment
|
||
-> expression_continuation
|
||
-> statement_continuation
|
||
-> configuration
|
||
|
||
(** [Value_Passing_Configuration] represents the end of an expression
|
||
evaluation. The constructor receives the following parameters:
|
||
|
||
- a [expression_continuation] — the continuation that receives the
|
||
value which is the result of the expression evaluation;
|
||
- a [value] — the result of the expression evaluation. *)
|
||
| Value_Passing_Configuration :
|
||
expression_continuation
|
||
-> runtime_value
|
||
-> configuration
|
||
|
||
(** [Forward_Configuration] represents the rest of the program execution.
|
||
The constructor receives the following parameters:
|
||
|
||
- a [statement_continuation] — represents the rest of the program
|
||
execution;
|
||
- an [environment] — the mapping from variables to values that is to be
|
||
used during the execution of the rest of the program. *)
|
||
| Forward_Configuration :
|
||
statement_continuation
|
||
-> environment
|
||
-> configuration.
|
||
|
||
|
||
(** Represents steps (a.k.a. transitions) of the abstract machine. *)
|
||
Inductive step : configuration -> configuration -> Prop :=
|
||
|
||
(** <Block(stmt :: stmts), ρ, κE, κS>exec ==>
|
||
<stmt, ρ, κE, BlockSK(stmts, ρ, κE, κS)>exec *)
|
||
| Exec_Block :
|
||
forall stmt stmts env ret_cont next_cont,
|
||
step (Exec_Configuration
|
||
(S_Block (Block (stmt :: stmts)))
|
||
env ret_cont next_cont)
|
||
(Exec_Configuration
|
||
stmt env ret_cont
|
||
(Block_Sk stmts env ret_cont next_cont))
|
||
|
||
(** <Block(#[]#), ρ, κE, κS>exec ==> <κS, ρ>forward *)
|
||
| Exec_Block_Empty :
|
||
forall env ret_cont next_cont,
|
||
step (Exec_Configuration
|
||
(S_Block (Block nil)) env ret_cont next_cont)
|
||
(Forward_Configuration next_cont env)
|
||
|
||
(** <BlockSK(stmt :: stmts, ρ, κE, κS), ρ'>forward ==>
|
||
<stmt, ρ', κE, BlockSK(stmts, ρ, κE, κS)>exec *)
|
||
| Forward_Block_Sk :
|
||
forall stmt stmts env ret_cont next_cont env',
|
||
step (Forward_Configuration
|
||
(Block_Sk (stmt :: stmts) env ret_cont next_cont)
|
||
env')
|
||
(Exec_Configuration
|
||
stmt env' ret_cont
|
||
(Block_Sk stmts env ret_cont next_cont))
|
||
|
||
(** <BlockSK(#[]#, ρ, κE, κS), ρ'>forward ==> <κS, ρ>forward *)
|
||
| Forward_Block_Sk_Empty :
|
||
forall env ret_cont next_cont env',
|
||
step (Forward_Configuration
|
||
(Block_Sk nil env ret_cont next_cont)
|
||
env')
|
||
(Forward_Configuration next_cont env)
|
||
|
||
(** <ExpressionStatement(expr), ρ, κE, κS>exec ==>
|
||
<expr, ρ, ExpressionEK(ρ, κE, κS)>eval *)
|
||
| Exec_Expression_Statement :
|
||
forall expr env ret_cont next_cont ret_type,
|
||
expression_type CE (env_to_type_env env) expr = Some ret_type ->
|
||
step (Exec_Configuration
|
||
(S_Expression_Statement (Expression_Statement expr))
|
||
env ret_cont next_cont)
|
||
(Eval_Configuration
|
||
expr env
|
||
(Expression_Continuation
|
||
(Expression_Ek env ret_cont next_cont)
|
||
ret_type))
|
||
|
||
(** <ReturnStatement(expr), ρ, κE, κS>exec ==> <expr, ρ, κE>eval *)
|
||
| Exec_Return_Statement :
|
||
forall expr env ret_cont next_cont,
|
||
step (Exec_Configuration
|
||
(S_Return_Statement (Return_Statement expr))
|
||
env ret_cont next_cont)
|
||
(Eval_Configuration expr env ret_cont)
|
||
|
||
(** <VariableGet(var), ρ, κE>eval ==> <κE, ρ(var)>pass *)
|
||
| Eval_Variable_Get :
|
||
forall var_id env ret_cont entry,
|
||
env_get var_id env = Some entry ->
|
||
step (Eval_Configuration
|
||
(E_Variable_Get (Variable_Get var_id)) env ret_cont)
|
||
(Value_Passing_Configuration
|
||
ret_cont (value entry))
|
||
|
||
(** <MethodInvocation(rcvr, name, arg), ρ, κE>eval ==>
|
||
<rcvr, ρ, MethodInvocationEK(name, arg, ρ, κE)>eval *)
|
||
| Eval_Method_Invocation :
|
||
(* TODO(dmitryas): Remove [ref] after interfaceTargetReference is removed
|
||
from constructor [Method_Invocation]. *)
|
||
forall rcvr_expr rcvr_type name arg env ret_cont ref,
|
||
expression_type CE (env_to_type_env env) rcvr_expr = Some rcvr_type ->
|
||
step (Eval_Configuration
|
||
(E_Invocation_Expression (IE_Method_Invocation
|
||
(Method_Invocation rcvr_expr (Name name) (Arguments arg) ref)))
|
||
env ret_cont)
|
||
(Eval_Configuration rcvr_expr env
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg env ret_cont)
|
||
rcvr_type))
|
||
|
||
(** <MethodInvocationEK(name, arg, ρ, κE), rcvrVal)pass ==>
|
||
<arg, ρ, InvocationEK(rcvrVal, name, ρ, κE)>eval,
|
||
rcvrVall != null *)
|
||
| Pass_Method_Invocation_Ek_Non_Null :
|
||
forall name arg_expr arg_type env ret_cont
|
||
rcvr_val rcvr_type expected_rcvr_type,
|
||
runtime_type rcvr_val = Some rcvr_type ->
|
||
expression_type CE (env_to_type_env env) arg_expr = Some arg_type ->
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg_expr env ret_cont)
|
||
expected_rcvr_type)
|
||
rcvr_val)
|
||
(Eval_Configuration arg_expr env
|
||
(Expression_Continuation
|
||
(Invocation_Ek rcvr_val name env ret_cont)
|
||
arg_type))
|
||
|
||
(** <InvocationEK(rcvrVal, name, ρ, κE), argVal>pass ==>
|
||
<block, ρ', κE, κS>exec,
|
||
where ρ' = ρ0#[#this = rcvrVal#][#arg(f) = argVal#]#,
|
||
block = body(f),
|
||
κS = ExitSK(κE, nullVal),
|
||
f = methods(class(rcvrVal))(name),
|
||
ρ0 — empty environment *)
|
||
| Pass_Invocation_Ek :
|
||
forall rcvr_val rcvr_intf rcvr_type_opt
|
||
proc_desc memb_data named_data func_node
|
||
var_id var_type var_init ret_type body
|
||
name arg_val arg_type env env'
|
||
ret_cont next_cont null_val,
|
||
(* TODO(dmitryas): Add the mapping: this -> rcvr_val to env'. *)
|
||
value_of_type rcvr_val rcvr_intf rcvr_type_opt ->
|
||
List.In proc_desc (procedures rcvr_intf) ->
|
||
NatMap.MapsTo
|
||
(pr_ref proc_desc)
|
||
(M_Procedure (Procedure memb_data named_data func_node))
|
||
ME ->
|
||
func_node =
|
||
Function_Node
|
||
(Variable_Declaration var_id var_type var_init)
|
||
ret_type
|
||
body ->
|
||
env' = env_extend var_id var_type arg_val empty_env ->
|
||
next_cont = Exit_Sk ret_cont null_val ->
|
||
value_of_type null_val (mk_interface nil nil) None ->
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Invocation_Ek rcvr_val name env ret_cont)
|
||
arg_type)
|
||
arg_val)
|
||
(Exec_Configuration body env' ret_cont next_cont)
|
||
|
||
(** <PropertyGet(rcvr, name), ρ, κE>eval ==>
|
||
<rcvr, ρ, PropertyGetEK(name, κE)>eval *)
|
||
| Eval_Property_Get :
|
||
forall rcvr_expr rcvr_type name env ret_cont,
|
||
expression_type CE (env_to_type_env env) rcvr_expr = Some rcvr_type ->
|
||
step (Eval_Configuration
|
||
(E_Property_Get (Property_Get rcvr_expr (Name name)))
|
||
env ret_cont)
|
||
(Eval_Configuration
|
||
rcvr_expr env
|
||
(Expression_Continuation
|
||
(Property_Get_Ek name ret_cont)
|
||
rcvr_type))
|
||
|
||
(** <PropertyGetEK(name, κE), rcvrVal)pass ==> <κE, f>pass,
|
||
where f = methods(class(rcvrVal))(name) *)
|
||
| Pass_Property_Get_Ek :
|
||
forall rcvr_val rcvr_intf rcvr_type_opt expected_rcvr_type
|
||
name memb_id ret_type
|
||
ret_val ret_intf
|
||
ret_cont,
|
||
value_of_type rcvr_val rcvr_intf rcvr_type_opt ->
|
||
List.In (mk_getter_desc name memb_id ret_type) (getters rcvr_intf) ->
|
||
value_of_type ret_val ret_intf (Some ret_type) ->
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Property_Get_Ek name ret_cont)
|
||
expected_rcvr_type)
|
||
rcvr_val)
|
||
(Value_Passing_Configuration
|
||
ret_cont ret_val)
|
||
|
||
(** <ExitSK(κE, val), ρ>forward ==> <κE, val>pass *)
|
||
| Forward_Exit_Sk :
|
||
forall ret_cont val env,
|
||
step (Forward_Configuration (Exit_Sk ret_cont val) env)
|
||
(Value_Passing_Configuration ret_cont val)
|
||
|
||
(** <ConstructorInvocation(cls), ρ, κE>eval ==> <κE, newVal>pass,
|
||
where newVal = new runtime value of syntactic type cls *)
|
||
| Eval_Constructor_Invocation :
|
||
forall env ret_cont new_val intf type_opt class_id,
|
||
NatMap.MapsTo class_id intf CE ->
|
||
value_of_type new_val intf type_opt ->
|
||
step (Eval_Configuration
|
||
(E_Invocation_Expression (IE_Constructor_Invocation
|
||
(Constructor_Invocation class_id)))
|
||
env ret_cont)
|
||
(Value_Passing_Configuration ret_cont new_val)
|
||
|
||
(** <VariableDeclaration(var, type, NONE), ρ, κE, κS>exec ==>
|
||
<κS, ρ'>forward,
|
||
where ρ' = ρ#[#var = nullVal#]# *)
|
||
| Exec_Variable_Declaration_Non_Init :
|
||
forall var type env ret_cont next_cont null_val env',
|
||
value_of_type null_val (mk_interface nil nil) None ->
|
||
env' = env_extend var type null_val env ->
|
||
step (Exec_Configuration
|
||
(S_Variable_Declaration (Variable_Declaration var type None))
|
||
env ret_cont next_cont)
|
||
(Forward_Configuration next_cont env')
|
||
|
||
(** <VariableDeclaration(var, type, expr), ρ, κE, κS>exec ==>
|
||
<expr, ρ, VarDeclarationEK(var, ρ, κS)>eval *)
|
||
| Exec_Variable_Declaration_Init :
|
||
forall var var_type init_type expr env ret_cont next_cont,
|
||
expression_type CE (env_to_type_env env) expr = Some init_type ->
|
||
step (Exec_Configuration
|
||
(S_Variable_Declaration
|
||
(Variable_Declaration var var_type (Some expr)))
|
||
env ret_cont next_cont)
|
||
(Eval_Configuration expr env
|
||
(Expression_Continuation
|
||
(Var_Declaration_Ek var var_type env next_cont)
|
||
init_type))
|
||
|
||
(** <VarDeclarationEK(var, ρ, κS), val>pass ==> <κS, ρ'>forward,
|
||
where ρ' = ρ#[#var = val#]# *)
|
||
| Pass_Var_Declaration_Ek :
|
||
forall var var_type init_type env next_cont val env',
|
||
env' = env_extend var var_type val env ->
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Var_Declaration_Ek var var_type env next_cont)
|
||
init_type)
|
||
val)
|
||
(Forward_Configuration next_cont env')
|
||
|
||
(** <ExpressionEK(ρ, κE, κS), val>pass ==> <κS, ρ>forward *)
|
||
| Pass_Expression_Ek :
|
||
forall env ret_cont next_cont val val_type,
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Expression_Ek env ret_cont next_cont)
|
||
val_type)
|
||
val)
|
||
(Forward_Configuration next_cont env)
|
||
|
||
(** <MethodInvocationEK(name, arg, ρ, κE), null)pass ==>
|
||
<HaltEK, null>pass *)
|
||
| Pass_Method_Invocation_Ek_Null :
|
||
forall name arg_expr arg_type env ret_cont expected_rcvr_type,
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg_expr env ret_cont)
|
||
expected_rcvr_type)
|
||
(mk_runtime_value None))
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
Halt_Ek
|
||
arg_type)
|
||
(mk_runtime_value None))
|
||
|
||
(** <PropertyGetEK(name, κE), null)pass ==> <HaltEK, null>pass *)
|
||
| Pass_Property_Get_Ek_Null :
|
||
forall name ret_cont expected_rcvr_type,
|
||
step (Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Property_Get_Ek name ret_cont)
|
||
expected_rcvr_type)
|
||
(mk_runtime_value None))
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
Halt_Ek
|
||
expected_rcvr_type)
|
||
(mk_runtime_value None)).
|
||
|
||
(* TODO(dmitryas): Add transitions to final states. *)
|
||
|
||
|
||
(** Well-formedness property over configurations is understood as the property
|
||
of being a valid l.h.s. to the [step] relation. The abstract machine may or
|
||
may not end up in a well-formed configuration several steps after its
|
||
configuration was well-formed. *)
|
||
Inductive configuration_wf : configuration -> Prop :=
|
||
|
||
(** Well-formed variable-gets should have the variable in the environment. *)
|
||
| Eval_Variable_Get_Configuration_Wf :
|
||
forall var env ret_cont,
|
||
env_in var env ->
|
||
configuration_wf
|
||
(Eval_Configuration
|
||
(E_Variable_Get (Variable_Get var))
|
||
env ret_cont)
|
||
|
||
(** Configurations that are the beginning of a method-invocation evaluation
|
||
are well-formed if the expression that represents the receiver is
|
||
well-typed, because the machine proceed to evaluation of the receiver, and
|
||
the continuation that awaits for the receiver value should be typed. *)
|
||
| Eval_Method_Invocation_Configuration_Wf :
|
||
forall rcvr_expr rcvr_type name arg_expr ref env ret_cont,
|
||
expression_type CE (env_to_type_env env) rcvr_expr = Some rcvr_type ->
|
||
configuration_wf
|
||
(Eval_Configuration
|
||
(E_Invocation_Expression (IE_Method_Invocation
|
||
(Method_Invocation rcvr_expr (Name name) (Arguments arg_expr) ref)))
|
||
env ret_cont)
|
||
|
||
(** Configurations that are the beginning of a property-get evaluation are
|
||
well-formed if the receiver expression is well-typed, because the machine
|
||
always proceed to evaluation of the receiver, and the continuation that
|
||
awaits for the receiver value should be typed. *)
|
||
| Eval_Property_Get_Configuration_Wf :
|
||
forall rcvr_expr rcvr_type name env ret_cont,
|
||
expression_type CE (env_to_type_env env) rcvr_expr = Some rcvr_type ->
|
||
configuration_wf
|
||
(Eval_Configuration
|
||
(E_Property_Get (Property_Get rcvr_expr (Name name)))
|
||
env ret_cont)
|
||
|
||
(** A constructor invocation is well-formed if the referred class exists in
|
||
the class environment. *)
|
||
| Eval_Constructor_Invocation_Configuration_Wf :
|
||
forall class_id env ret_cont,
|
||
NatMap.In class_id CE ->
|
||
configuration_wf
|
||
(Eval_Configuration
|
||
(E_Invocation_Expression (IE_Constructor_Invocation
|
||
(Constructor_Invocation class_id)))
|
||
env ret_cont)
|
||
|
||
(** TODO(dmitryas): Write descriptive comment here. *)
|
||
| Exec_Variable_Declaration_Init_Wf :
|
||
forall var var_type init_expr init_type env ret_cont next_cont,
|
||
expression_type CE (env_to_type_env env) init_expr = Some init_type ->
|
||
configuration_wf
|
||
(Exec_Configuration
|
||
(S_Variable_Declaration
|
||
(Variable_Declaration var var_type (Some init_expr)))
|
||
env ret_cont next_cont)
|
||
|
||
(** TODO(dmitryas): Write descriptive comment here. *)
|
||
| Exec_Variable_Declaration_Non_Init_Wf :
|
||
forall var var_type env ret_cont next_cont,
|
||
configuration_wf
|
||
(Exec_Configuration
|
||
(S_Variable_Declaration
|
||
(Variable_Declaration var var_type None))
|
||
env ret_cont next_cont)
|
||
|
||
(** TODO(dmitryas): Write descriptive comment here. *)
|
||
| Exec_Return_Statement_Wf :
|
||
forall expr env ret_cont next_cont,
|
||
configuration_wf
|
||
(Exec_Configuration
|
||
(S_Return_Statement (Return_Statement expr))
|
||
env ret_cont next_cont)
|
||
|
||
(** TODO(dmitryas): Write descriptive comment here. *)
|
||
| Exec_Expression_Statement_Wf :
|
||
forall expr expr_type env ret_cont next_cont,
|
||
expression_type CE (env_to_type_env env) expr = Some expr_type ->
|
||
configuration_wf
|
||
(Exec_Configuration
|
||
(S_Expression_Statement (Expression_Statement expr))
|
||
env ret_cont next_cont)
|
||
|
||
(** TODO(dmitryas): Write descriptive comment here. *)
|
||
| Exec_Block_Wf :
|
||
forall stmts env ret_cont next_cont,
|
||
configuration_wf
|
||
(Exec_Configuration (S_Block (Block stmts)) env ret_cont next_cont)
|
||
|
||
(** These configurations pass the receiver to the continuation that is the
|
||
rest of the method invocation. These configurations are well-formed if the
|
||
argument expression is well-typed, because the machine procedes to the
|
||
evaluation of the argument, and the expression continuation that awaits for
|
||
the argument value needs to be typed. *)
|
||
| Pass_Method_Invocation_Ek_Non_Null_Configuration_Wf :
|
||
forall name arg_expr arg_type env ret_cont
|
||
expected_rcvr_type rcvr_type rcvr_val,
|
||
runtime_type rcvr_val = Some rcvr_type ->
|
||
expression_type CE (env_to_type_env env) arg_expr = Some arg_type ->
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg_expr env ret_cont)
|
||
expected_rcvr_type)
|
||
rcvr_val)
|
||
|
||
(** These configurations pass the evaluated argument to the rest of the
|
||
method invocation. The precondition is that the method with such name
|
||
exists. *)
|
||
| Pass_Invocation_Ek_Configuration_Wf :
|
||
forall rcvr_val name ret_cont arg_val arg_type env,
|
||
method_exists (runtime_type rcvr_val) name ->
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Invocation_Ek rcvr_val name env ret_cont)
|
||
arg_type)
|
||
arg_val)
|
||
|
||
(** These configurations pass the evaluated receiver to the rest of the
|
||
property get. The preconditions is that the getter with such name
|
||
exists. *)
|
||
| Pass_Property_Get_Ek_Non_Null_Configuration_Wf :
|
||
forall name ret_cont expected_rcvr_type rcvr_type rcvr_val,
|
||
runtime_type rcvr_val = Some rcvr_type ->
|
||
getter_exists (runtime_type rcvr_val) name ->
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Property_Get_Ek name ret_cont)
|
||
expected_rcvr_type)
|
||
rcvr_val)
|
||
|
||
(** In the currently formalized subset of Kernel all forward configurations
|
||
are well-formed. The machine either proceeds to the execution of a
|
||
a statement or proceeds to the next continuation. *)
|
||
| Forward_Configuration_Wf :
|
||
forall next_cont env,
|
||
configuration_wf (Forward_Configuration next_cont env)
|
||
|
||
(** TODO(dmitryas): Write descriptive comments. *)
|
||
| Pass_Expression_Ek_Configuration_Wf :
|
||
forall env ret_cont next_cont val val_type,
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Expression_Ek env ret_cont next_cont)
|
||
val_type)
|
||
val)
|
||
|
||
(** TODO(dmitryas): Write descriptive comments. *)
|
||
| Pass_Var_Declaration_Ek_Configuration_Wf :
|
||
forall var var_type env next_cont init_type val,
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Var_Declaration_Ek var var_type env next_cont)
|
||
init_type)
|
||
val)
|
||
|
||
(** Invoking a method on `null` always puts the abstract machine in a final
|
||
state, so passing `null` to MethodInvocationEK is always well-formed. *)
|
||
| Pass_Method_Invocation_Ek_Null_Configuration_Wf :
|
||
forall name arg_expr env ret_cont rcvr_type rcvr_val,
|
||
runtime_type rcvr_val = None ->
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg_expr env ret_cont)
|
||
rcvr_type)
|
||
rcvr_val)
|
||
|
||
(** Getting a property of `null` always puts the abstract machine in a final
|
||
state, so passing `null` to propertyGetEK is always well-formed. *)
|
||
| Pass_Property_Get_Ek_Null_Configuration_Wf :
|
||
forall name ret_cont rcvr_type rcvr_val,
|
||
runtime_type rcvr_val = None ->
|
||
configuration_wf
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation (Property_Get_Ek name ret_cont) rcvr_type)
|
||
rcvr_val).
|
||
|
||
|
||
Inductive configuration_final : configuration -> Prop :=
|
||
|
||
| Configuration_Final :
|
||
forall val ret_type,
|
||
configuration_final
|
||
(Value_Passing_Configuration
|
||
(Expression_Continuation Halt_Ek ret_type)
|
||
val).
|
||
|
||
|
||
Inductive ref_in_dart_type : nat -> dart_type -> Prop :=
|
||
|
||
| RDT_Interface_Type :
|
||
forall ref,
|
||
ref_in_dart_type ref (DT_Interface_Type (Interface_Type ref))
|
||
|
||
| RDT_Function_Type :
|
||
forall ref param_type ret_type,
|
||
(ref_in_dart_type ref param_type \/
|
||
ref_in_dart_type ref ret_type) ->
|
||
ref_in_dart_type ref (DT_Function_Type
|
||
(Function_Type param_type ret_type)).
|
||
|
||
|
||
Inductive dart_type_valid : option dart_type -> Prop :=
|
||
|
||
| DTV_Null :
|
||
dart_type_valid None
|
||
|
||
| DTV_Non_Null :
|
||
forall class_id type,
|
||
ref_in_dart_type class_id type ->
|
||
NatMap.In class_id CE ->
|
||
dart_type_valid (Some type).
|
||
|
||
|
||
Inductive runtime_value_valid (val : runtime_value) : Prop :=
|
||
|
||
| RTV_Not_Null :
|
||
forall intf type,
|
||
(runtime_type val) = Some type ->
|
||
dart_type_valid (Some type) ->
|
||
value_of_type val intf (runtime_type val) ->
|
||
runtime_value_valid val
|
||
|
||
| RTV_Null :
|
||
value_of_type val (mk_interface nil nil) None ->
|
||
runtime_value_valid val.
|
||
|
||
|
||
(** [expression_wf] is a well-formedness condition for expression w.r.t. the
|
||
class and member environments. It requires that all class and member
|
||
references in the expression are present in [CE] and [ME] respectively. *)
|
||
Inductive expression_wf : expression -> Prop :=
|
||
|
||
| EXPWF_Variable_Get :
|
||
forall var_get_expr,
|
||
expression_wf (E_Variable_Get var_get_expr)
|
||
|
||
| EXPWF_Property_Get :
|
||
forall rcvr_expr name,
|
||
expression_wf rcvr_expr ->
|
||
expression_wf (E_Property_Get (Property_Get rcvr_expr name))
|
||
|
||
| EXPWF_Method_Invocation :
|
||
(* TODO(dmitryas): Remove [ref] when the corresponding element is removed
|
||
from the AST. *)
|
||
forall rcvr_expr name arg_expr ref,
|
||
expression_wf rcvr_expr ->
|
||
expression_wf arg_expr ->
|
||
expression_wf (E_Invocation_Expression (IE_Method_Invocation
|
||
(Method_Invocation rcvr_expr name (Arguments arg_expr) ref)))
|
||
|
||
| EXPWF_Constructor_Invocation :
|
||
forall ref,
|
||
NatMap.In ref CE ->
|
||
expression_wf (E_Invocation_Expression (IE_Constructor_Invocation
|
||
(Constructor_Invocation ref))).
|
||
|
||
|
||
(** [statement_wf] is a property that is analogous to [expression_wf], but is
|
||
defined for statements. *)
|
||
Inductive statement_wf : statement -> Prop :=
|
||
|
||
| STWF_Expression_Statement :
|
||
forall expr,
|
||
expression_wf expr ->
|
||
statement_wf (S_Expression_Statement (Expression_Statement expr))
|
||
|
||
| STWF_Block_Empty :
|
||
statement_wf (S_Block (Block nil))
|
||
|
||
| STWF_Block_Non_Empty :
|
||
forall stmt stmts,
|
||
statement_wf stmt ->
|
||
statement_wf (S_Block (Block stmts)) ->
|
||
statement_wf (S_Block (Block (stmt :: stmts)))
|
||
|
||
| STWF_Return_Statement :
|
||
forall expr,
|
||
expression_wf expr ->
|
||
statement_wf (S_Return_Statement (Return_Statement expr))
|
||
|
||
| STWF_Variable_Declaration_Non_Init :
|
||
forall var_id type,
|
||
(forall class_id,
|
||
ref_in_dart_type class_id type -> NatMap.In class_id CE) ->
|
||
statement_wf (S_Variable_Declaration
|
||
(Variable_Declaration var_id type None))
|
||
|
||
| STWF_Variable_Declaration_Init :
|
||
forall var_id type init_expr,
|
||
dart_type_valid (Some type) ->
|
||
expression_wf init_expr ->
|
||
statement_wf (S_Variable_Declaration
|
||
(Variable_Declaration var_id type (Some init_expr))).
|
||
|
||
|
||
(** [environment_valid] is a property of environment validity with respect
|
||
to the class and method environments. For each variable in the environment
|
||
there should be a valid interface, so that [value_of_type] predicate for the
|
||
variable is true. *)
|
||
Inductive environment_valid : environment -> Prop :=
|
||
|
||
| EV_Empty :
|
||
environment_valid nil
|
||
|
||
| EV_Non_Empty_Null :
|
||
forall entry env,
|
||
dart_type_valid (Some (var_type entry)) ->
|
||
(runtime_type (value entry)) = None ->
|
||
environment_valid env ->
|
||
environment_valid (entry :: env)
|
||
|
||
| EV_Non_Empty_Non_Null :
|
||
forall entry env,
|
||
dart_type_valid (Some (var_type entry)) ->
|
||
(runtime_type (value entry)) = Some (var_type entry) ->
|
||
environment_valid env ->
|
||
environment_valid (entry :: env).
|
||
|
||
|
||
(** The given syntactic type is accepted by the given expression continuation.
|
||
|
||
None is accepted as the second argument, because runtime type of values can
|
||
be checkec agains the expression continuation. *)
|
||
Inductive econt_accepts :
|
||
expression_continuation -> option dart_type -> Prop :=
|
||
|
||
| EA_Null :
|
||
forall econt,
|
||
econt_accepts econt None
|
||
|
||
| EA_Non_Null :
|
||
forall cont expected_type type,
|
||
type <: expected_type ->
|
||
econt_accepts
|
||
(Expression_Continuation cont expected_type)
|
||
(Some type).
|
||
|
||
|
||
(** The syntactic type of the expression matches the syntactic type of the
|
||
value expected by the expression continuation. *)
|
||
Inductive econt_accepts_expr :
|
||
expression_continuation -> expression -> environment -> Prop :=
|
||
|
||
| Econt_Accepts_Expr :
|
||
forall econt expr env expr_type,
|
||
expression_type CE (env_to_type_env env) expr = Some expr_type ->
|
||
econt_accepts econt (Some expr_type) ->
|
||
econt_accepts_expr econt expr env.
|
||
|
||
|
||
(** The syntactic type returned by the statement (if any) matches the syntactic
|
||
type of the value expected by the expression continuation. *)
|
||
Inductive econt_accepts_stmt :
|
||
expression_continuation -> statement -> environment -> Prop :=
|
||
|
||
| Econt_Accepts_Stmt :
|
||
forall econt stmt env ret_type te,
|
||
statement_type CE (env_to_type_env env) stmt ret_type = Some te ->
|
||
econt_accepts econt (Some ret_type) ->
|
||
econt_accepts_stmt econt stmt env.
|
||
|
||
|
||
(** The syntactic type of the value matches the syntactic type of the value
|
||
expected by the expression continuation. *)
|
||
Definition econt_accepts_val :
|
||
expression_continuation -> runtime_value -> Prop :=
|
||
fun econt val => econt_accepts econt (runtime_type val).
|
||
|
||
|
||
(** Each free variable referenced from the expression is present in the
|
||
environment. *)
|
||
Inductive eval_environment_sufficient : environment -> expression -> Prop :=
|
||
|
||
| EES_Variable_Get :
|
||
forall var env,
|
||
env_in var env ->
|
||
eval_environment_sufficient env (E_Variable_Get (Variable_Get var))
|
||
|
||
| EES_Property_Get :
|
||
forall expr name env,
|
||
eval_environment_sufficient env expr ->
|
||
eval_environment_sufficient env (E_Property_Get (Property_Get expr name))
|
||
|
||
| EES_Constructor_Invocation :
|
||
forall class_id env,
|
||
eval_environment_sufficient
|
||
env
|
||
(E_Invocation_Expression
|
||
(IE_Constructor_Invocation
|
||
(Constructor_Invocation class_id)))
|
||
|
||
| EES_Method_Invocation :
|
||
(* TODO(dmitryas): Remove ref when it's removed from the AST. *)
|
||
forall rcvr_expr arg_expr name ref env,
|
||
eval_environment_sufficient env rcvr_expr ->
|
||
eval_environment_sufficient env arg_expr ->
|
||
eval_environment_sufficient
|
||
env
|
||
(E_Invocation_Expression
|
||
(IE_Method_Invocation
|
||
(Method_Invocation rcvr_expr name (Arguments arg_expr) ref))).
|
||
|
||
|
||
(** [exec_environment_sufficient] represents the property of the environment
|
||
w.r.t. the given statement. The property shows if the given environment is
|
||
sufficient to evaluate all expressions in the given statement. *)
|
||
Inductive exec_environment_sufficient : environment -> statement -> Prop :=
|
||
|
||
| EES_Expression_Statement :
|
||
forall env expr,
|
||
eval_environment_sufficient env expr ->
|
||
exec_environment_sufficient
|
||
env
|
||
(S_Expression_Statement (Expression_Statement expr))
|
||
|
||
| EES_Block_Empty :
|
||
forall env,
|
||
exec_environment_sufficient env (S_Block (Block nil))
|
||
|
||
| EES_Block_Non_Empty :
|
||
forall env stmt stmts,
|
||
exec_environment_sufficient env stmt ->
|
||
exec_environment_sufficient env (S_Block (Block stmts)) ->
|
||
exec_environment_sufficient env (S_Block (Block (stmt :: stmts)))
|
||
|
||
| EES_Return_Statement :
|
||
forall env expr,
|
||
eval_environment_sufficient env expr ->
|
||
exec_environment_sufficient
|
||
env
|
||
(S_Return_Statement (Return_Statement expr))
|
||
|
||
| EES_Variable_Declaration_Non_Init :
|
||
forall env var type,
|
||
exec_environment_sufficient
|
||
env
|
||
(S_Variable_Declaration (Variable_Declaration var type None))
|
||
|
||
| EES_Variable_Declaration_Init :
|
||
forall env var type init_expr,
|
||
eval_environment_sufficient env init_expr ->
|
||
exec_environment_sufficient
|
||
env
|
||
(S_Variable_Declaration
|
||
(Variable_Declaration var type (Some init_expr))).
|
||
|
||
|
||
(** Validity property for expression continuations [econt_valid] and statement
|
||
continuations [scont_valid] is mutually inductive, because instances of one
|
||
may refer to instances of the other. *)
|
||
Inductive econt_valid : expression_continuation -> Prop :=
|
||
|
||
| CV_Expression_Ek :
|
||
forall expr_type env ret_cont next_cont,
|
||
environment_valid env ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
dart_type_valid (Some expr_type) ->
|
||
econt_valid
|
||
(Expression_Continuation
|
||
(Expression_Ek env ret_cont next_cont)
|
||
expr_type)
|
||
|
||
| CV_Method_Invocation_Ek :
|
||
forall rcvr_type name arg_exp arg_type ret_type env ret_cont,
|
||
environment_valid env ->
|
||
dart_type_valid (Some rcvr_type) ->
|
||
method_accepts (Some rcvr_type) name (Some arg_type) ->
|
||
method_returns (Some rcvr_type) name ret_type ->
|
||
expression_wf arg_exp ->
|
||
eval_environment_sufficient env arg_exp ->
|
||
expression_type CE (env_to_type_env env) arg_exp = Some arg_type ->
|
||
dart_type_valid (Some arg_type) ->
|
||
econt_valid ret_cont ->
|
||
dart_type_valid (Some ret_type) ->
|
||
econt_accepts ret_cont (Some ret_type) ->
|
||
econt_valid
|
||
(Expression_Continuation
|
||
(Method_Invocation_Ek name arg_exp env ret_cont)
|
||
rcvr_type)
|
||
|
||
| CV_Invocation_Ek :
|
||
forall rcvr_val name env ret_cont arg_type ret_type,
|
||
environment_valid env ->
|
||
runtime_value_valid rcvr_val ->
|
||
method_accepts (runtime_type rcvr_val) name (Some arg_type) ->
|
||
method_returns (runtime_type rcvr_val) name ret_type ->
|
||
dart_type_valid (Some arg_type) ->
|
||
econt_valid ret_cont ->
|
||
dart_type_valid (Some ret_type) ->
|
||
econt_accepts ret_cont (Some ret_type) ->
|
||
econt_valid
|
||
(Expression_Continuation
|
||
(Invocation_Ek rcvr_val name env ret_cont)
|
||
arg_type)
|
||
|
||
| CV_Property_Get_Ek :
|
||
forall name ret_cont rcvr_type ret_type,
|
||
dart_type_valid (Some rcvr_type) ->
|
||
getter_returns (Some rcvr_type) name ret_type ->
|
||
econt_valid ret_cont ->
|
||
dart_type_valid (Some ret_type) ->
|
||
econt_accepts ret_cont (Some ret_type) ->
|
||
econt_valid
|
||
(Expression_Continuation
|
||
(Property_Get_Ek name ret_cont)
|
||
rcvr_type)
|
||
|
||
| CV_Var_Declaration_Ek :
|
||
forall var var_type env next_cont init_type,
|
||
environment_valid env ->
|
||
dart_type_valid (Some var_type) ->
|
||
dart_type_valid (Some init_type) ->
|
||
init_type <: var_type ->
|
||
scont_valid next_cont ->
|
||
econt_valid
|
||
(Expression_Continuation
|
||
(Var_Declaration_Ek var var_type env next_cont)
|
||
init_type)
|
||
|
||
with scont_valid : statement_continuation -> Prop :=
|
||
|
||
| CV_Exit_Sk :
|
||
forall ret_cont val,
|
||
econt_valid ret_cont ->
|
||
runtime_value_valid val ->
|
||
econt_accepts_val ret_cont val ->
|
||
scont_valid (Exit_Sk ret_cont val)
|
||
|
||
| CV_Block_Sk_Empty :
|
||
forall env ret_cont next_cont,
|
||
environment_valid env ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk nil env ret_cont next_cont)
|
||
|
||
| CV_Block_Sk_Expression_Statement :
|
||
forall stmt expr expr_type stmts env ret_cont next_cont,
|
||
environment_valid env ->
|
||
stmt = S_Expression_Statement (Expression_Statement expr) ->
|
||
statement_wf stmt ->
|
||
expression_type CE (env_to_type_env env) expr = Some expr_type ->
|
||
scont_valid (Block_Sk stmts env ret_cont next_cont) ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk (stmt :: stmts) env ret_cont next_cont)
|
||
|
||
| CV_Block_Sk_Block :
|
||
forall stmt block_stmts stmts env ret_cont next_cont,
|
||
environment_valid env ->
|
||
stmt = S_Block (Block block_stmts) ->
|
||
statement_wf stmt ->
|
||
scont_valid (Block_Sk stmts env ret_cont next_cont) ->
|
||
scont_valid
|
||
(Block_Sk block_stmts env ret_cont
|
||
(Block_Sk stmts env ret_cont next_cont)) ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk (stmt :: stmts) env ret_cont next_cont)
|
||
|
||
| CV_Block_Sk_Return_Statement :
|
||
forall stmt expr expr_type stmts env ret_cont next_cont,
|
||
environment_valid env ->
|
||
stmt = S_Return_Statement (Return_Statement expr) ->
|
||
statement_wf stmt ->
|
||
expression_type CE (env_to_type_env env) expr = Some expr_type ->
|
||
dart_type_valid (Some expr_type) ->
|
||
econt_valid ret_cont ->
|
||
econt_accepts ret_cont (Some expr_type) ->
|
||
(* TODO(dmitryas): Do we really need the validity of the dead code? *)
|
||
scont_valid (Block_Sk stmts env ret_cont next_cont) ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk (stmt :: stmts) env ret_cont next_cont)
|
||
|
||
| CV_Block_Sk_Variable_Declaration_Init :
|
||
forall stmt var var_type init_expr init_expr_type
|
||
stmts env env' ret_cont next_cont,
|
||
environment_valid env ->
|
||
stmt = S_Variable_Declaration
|
||
(Variable_Declaration var var_type (Some init_expr)) ->
|
||
statement_wf stmt ->
|
||
expression_type CE (env_to_type_env env) init_expr = Some init_expr_type ->
|
||
init_expr_type <: var_type ->
|
||
env' = env_extend var var_type (mk_runtime_value (Some var_type)) env ->
|
||
scont_valid (Block_Sk stmts env' ret_cont next_cont) ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk (stmt :: stmts) env ret_cont next_cont)
|
||
|
||
| CV_Block_Sk_Variable_Declaration_Non_Init :
|
||
forall stmt var var_type stmts env env' ret_cont next_cont,
|
||
environment_valid env ->
|
||
stmt = S_Variable_Declaration
|
||
(Variable_Declaration var var_type None) ->
|
||
statement_wf stmt ->
|
||
env' = env_extend var var_type (mk_runtime_value None) env ->
|
||
scont_valid (Block_Sk stmts env' ret_cont next_cont) ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
scont_valid (Block_Sk (stmt :: stmts) env ret_cont next_cont).
|
||
|
||
|
||
Inductive configuration_valid : configuration -> Prop :=
|
||
|
||
| Eval_Configuration_Valid :
|
||
forall exp env cont,
|
||
expression_wf exp ->
|
||
environment_valid env ->
|
||
econt_valid cont ->
|
||
eval_environment_sufficient env exp ->
|
||
econt_accepts_expr cont exp env ->
|
||
configuration_valid (Eval_Configuration exp env cont)
|
||
|
||
| Exec_Configuration_Valid :
|
||
forall stmt env ret_cont next_cont,
|
||
statement_wf stmt ->
|
||
environment_valid env ->
|
||
econt_valid ret_cont ->
|
||
scont_valid next_cont ->
|
||
exec_environment_sufficient env stmt ->
|
||
econt_accepts_stmt ret_cont stmt env ->
|
||
configuration_valid (Exec_Configuration stmt env ret_cont next_cont)
|
||
|
||
| Value_Passing_Configuration_Valid :
|
||
forall cont val,
|
||
econt_valid cont ->
|
||
runtime_value_valid val ->
|
||
econt_accepts_val cont val ->
|
||
configuration_valid (Value_Passing_Configuration cont val)
|
||
|
||
| Forward_Configuration_Valid :
|
||
forall cont env,
|
||
scont_valid cont ->
|
||
environment_valid env ->
|
||
configuration_valid (Forward_Configuration cont env).
|
||
|
||
|
||
Inductive steps : configuration -> configuration -> Prop :=
|
||
|
||
| steps_zero :
|
||
forall conf,
|
||
steps conf conf
|
||
|
||
| steps_trans_right :
|
||
forall conf1 conf2 conf3,
|
||
steps conf1 conf2 ->
|
||
step conf2 conf3 ->
|
||
steps conf1 conf3.
|
||
|
||
|
||
End OperationalSemantics.
|