474c075794
Details to come in discussions. Bug: Change-Id: Ia50d85dd27cde83e25086f64dc6746cc52036128 Reviewed-on: https://dart-review.googlesource.com/4941 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
142 lines
5.0 KiB
V
142 lines
5.0 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 Common.
|
|
Require Import Syntax.
|
|
Import Common.OptionMonad.
|
|
Module L := Common.ListExtensions.
|
|
Require Import Coq.Strings.String.
|
|
|
|
Fixpoint type_equiv (s : dart_type) (t : dart_type) : bool :=
|
|
match (s, t) with
|
|
| (DT_Interface_Type (Interface_Type s_class),
|
|
DT_Interface_Type (Interface_Type t_class)) =>
|
|
Nat.eqb s_class t_class
|
|
| (DT_Function_Type (Function_Type s_param s_ret),
|
|
DT_Function_Type (Function_Type t_param t_ret)) =>
|
|
type_equiv s_param t_param && type_equiv s_ret t_ret
|
|
| _ => false
|
|
end.
|
|
|
|
Notation "s ≡ t" := (type_equiv s t = true) (at level 70, no associativity).
|
|
|
|
Lemma type_equiv_trans : forall s t r, s ≡ t /\ t ≡ r -> s ≡ r.
|
|
Admitted.
|
|
|
|
(* Semantic Types *)
|
|
Record procedure_desc : Type := mk_procedure_desc {
|
|
pr_name : string;
|
|
pr_ref : nat;
|
|
pr_type : function_type;
|
|
}.
|
|
|
|
Definition procedure_dissect (p : procedure) : procedure_desc :=
|
|
let (memb, _, fn) := p in
|
|
let (nn, _, name) := memb in
|
|
let (name_str) := name in
|
|
let (ref) := nn in
|
|
let (id) := ref in
|
|
let (param, ret_type, _) := fn in
|
|
let (_, param_type, _) := param in
|
|
mk_procedure_desc name_str id (Function_Type param_type ret_type).
|
|
|
|
Record interface : Type := mk_interface {
|
|
procedures : list procedure_desc;
|
|
}.
|
|
|
|
(** Type envronment maps class IDs to their interface type. *)
|
|
Definition class_env : Type := NatMap.t interface.
|
|
Definition type_env : Type := NatMap.t dart_type.
|
|
|
|
Fixpoint class_type (CE : class_env) (c : class) : option class_env :=
|
|
let (nn_data, _, procedures) := c in
|
|
let (ref) := nn_data in
|
|
let (class_id) := ref in
|
|
let class_interface := mk_interface (map procedure_dissect procedures) in
|
|
let CE' := NatMap.add class_id class_interface CE in
|
|
if forallb (procedure_type CE') procedures then Some CE' else None
|
|
|
|
with procedure_type (CE : class_env) (p : procedure) : bool :=
|
|
let (_, _, fn) := p in
|
|
let (param, ret_type, body) := fn in
|
|
let (param_var, param_type, _) := param in
|
|
let TE := NatMap.add param_var param_type (NatMap.empty _) in
|
|
match statement_type CE TE body with
|
|
| Some (_, Some t) => type_equiv t ret_type
|
|
| _ => false
|
|
end
|
|
|
|
with statement_type (CE : class_env) (TE : type_env) (s : statement) :
|
|
option (type_env * option dart_type) :=
|
|
match s with
|
|
| S_Expression_Statement (Expression_Statement e) =>
|
|
_ <- expression_type CE TE e; [(TE, None)]
|
|
| S_Return_Statement (Return_Statement re) =>
|
|
rt <- expression_type CE TE re; [(TE, Some rt)]
|
|
| S_Variable_Declaration (Variable_Declaration _ _ None) => None
|
|
| S_Variable_Declaration (Variable_Declaration var type (Some init)) =>
|
|
init_type <- expression_type CE TE init;
|
|
if type_equiv init_type type then
|
|
[(NatMap.add var type TE, None)]
|
|
else
|
|
None
|
|
| S_Block (Block stmts) =>
|
|
let process_statements := fix process_statements TE stmts :=
|
|
match stmts with
|
|
| nil => [(TE, None)]
|
|
| (s::ss) =>
|
|
st <- statement_type CE TE s;
|
|
let (TE', s_rt) := st in
|
|
sst <- process_statements TE' ss;
|
|
let (TE'', ss_rt) := sst in
|
|
match (s_rt, ss_rt) with
|
|
| (None, ss_rt) => [(TE'', ss_rt)]
|
|
| (Some rt, None) => [(TE'', Some rt)]
|
|
| (Some rt, Some rt') =>
|
|
if type_equiv rt rt' then [(TE'', Some rt)] else None
|
|
end
|
|
end in
|
|
process_statements TE stmts
|
|
end
|
|
|
|
with expression_type (CE : class_env) (TE : type_env) (e : expression) : option dart_type :=
|
|
match e with
|
|
| E_Variable_Get (Variable_Get v) => NatMap.find v TE
|
|
| E_Property_Get (Property_Get rec prop) =>
|
|
rec_type <- expression_type CE TE rec;
|
|
let (prop_name) := prop in
|
|
match rec_type with
|
|
| DT_Function_Type _ => None
|
|
| DT_Interface_Type (Interface_Type class) =>
|
|
interface <- NatMap.find class CE;
|
|
proc_desc <- List.find (fun P =>
|
|
if string_dec (pr_name P) prop_name then true else false)
|
|
(procedures interface);
|
|
[DT_Function_Type (pr_type proc_desc)]
|
|
end
|
|
| E_Invocation_Expression (IE_Constructor_Invocation (Constructor_Invocation class _)) =>
|
|
_ <- NatMap.find class CE;
|
|
[DT_Interface_Type (Interface_Type class)]
|
|
| E_Invocation_Expression (IE_Method_Invocation (Method_Invocation rec method args _)) =>
|
|
rec_type <- expression_type CE TE rec;
|
|
let (method_name) := method in
|
|
match rec_type with
|
|
| DT_Function_Type fn_type =>
|
|
if string_dec "call" method_name then [rec_type] else None
|
|
| DT_Interface_Type (Interface_Type class) =>
|
|
interface <- NatMap.find class CE;
|
|
proc_desc <- List.find (fun P =>
|
|
if string_dec (pr_name P) method_name then true else false)
|
|
(procedures interface);
|
|
[DT_Function_Type (pr_type proc_desc)]
|
|
end
|
|
end
|
|
.
|
|
|
|
Lemma type_equiv_sanity1 :
|
|
forall CE TE e v s t et,
|
|
expression_type CE (NatMap.add v s TE) e = Some et /\ s ≡ t ->
|
|
exists es, expression_type CE (NatMap.add v t TE) e = Some es /\ et ≡ es.
|
|
Admitted.
|