Module ErgoSpec.Common.Utils.NamespaceContext


Ergo is a language for expressing contract logic.

Abstract Syntax


Require Import String.
Require Import List.
Require Import ErgoSpec.Backend.ErgoBackend.
Require Import ErgoSpec.Common.Utils.Provenance.
Require Import ErgoSpec.Common.Utils.Names.
Require Import ErgoSpec.Common.Utils.Result.

Section NamespaceContext.

  Section NameTable.
Maps local names to absolute names for a given ErgoType module
    Definition name_table : Set := list (local_name * absolute_name).

Maps namespaces to the names tables for that namespace
    Record namespace_table : Set :=
      mkNamespaceTable
        { namespace_table_types : name_table;
          namespace_table_constants : name_table;
          namespace_table_functions : name_table;
          namespace_table_contracts : name_table; }.

    Definition empty_namespace_table : namespace_table :=
      mkNamespaceTable nil nil nil nil.

    Definition one_type_to_namespace_table (ln:local_name) (an:absolute_name) : namespace_table :=
      mkNamespaceTable ((ln,an)::nil) nil nil nil.
    Definition one_constant_to_namespace_table (ln:local_name) (an:absolute_name) : namespace_table :=
      mkNamespaceTable nil ((ln,an)::nil) nil nil.
    Definition one_function_to_namespace_table (ln:local_name) (an:absolute_name) : namespace_table :=
      mkNamespaceTable nil nil ((ln,an)::nil) nil.
    Definition one_contract_to_namespace_table (ln:local_name) (an:absolute_name) : namespace_table :=
      mkNamespaceTable nil nil nil ((ln,an)::nil).

    Definition namespace_table_app (tbl1 tbl2:namespace_table) : namespace_table :=
      mkNamespaceTable
        (app tbl1.(namespace_table_types) tbl2.(namespace_table_types))
        (app tbl1.(namespace_table_constants) tbl2.(namespace_table_constants))
        (app tbl1.(namespace_table_functions) tbl2.(namespace_table_functions))
        (app tbl1.(namespace_table_contracts) tbl2.(namespace_table_contracts)).

    Definition lookup_type_name (prov:provenance) (tbl:namespace_table) (ln:local_name) : eresult absolute_name :=
      match lookup string_dec tbl.(namespace_table_types) ln with
      | None => type_name_not_found_error prov ln
      | Some an => esuccess an
      end.
    Definition lookup_constant_name (prov:provenance) (tbl:namespace_table) (ln:local_name) : eresult absolute_name :=
      match lookup string_dec tbl.(namespace_table_constants) ln with
      | None => variable_name_not_found_error prov ln
      | Some an => esuccess an
      end.
    Definition lookup_function_name (prov:provenance) (tbl:namespace_table) (ln:local_name) : eresult absolute_name :=
      match lookup string_dec tbl.(namespace_table_functions) ln with
      | None => function_name_not_found_error prov ln
      | Some an => esuccess an
      end.
    Definition lookup_contract_name (prov:provenance) (tbl:namespace_table) (ln:local_name) : eresult absolute_name :=
      match lookup string_dec tbl.(namespace_table_contracts) ln with
      | None => contract_name_not_found_error prov ln
      | Some an => esuccess an
      end.

    Definition resolve_type_name (prov:provenance) (tbl:namespace_table) (rn:relative_name) :=
      match fst rn with
      | None => lookup_type_name prov tbl (snd rn)
      | Some ns => esuccess (absolute_name_of_local_name ns (snd rn))
      end.
    Definition resolve_constant_name (prov:provenance) (tbl:namespace_table) (rn:relative_name) :=
      match fst rn with
      | None => lookup_constant_name prov tbl (snd rn)
      | Some ns => esuccess (absolute_name_of_local_name ns (snd rn))
      end.
    Definition resolve_function_name (prov:provenance) (tbl:namespace_table) (rn:relative_name) :=
      match fst rn with
      | None => lookup_function_name prov tbl (snd rn)
      | Some ns => esuccess (absolute_name_of_local_name ns (snd rn))
      end.
    Definition resolve_contract_name (prov:provenance) (tbl:namespace_table) (rn:relative_name) :=
      match fst rn with
      | None => lookup_contract_name prov tbl (snd rn)
      | Some ns => esuccess (absolute_name_of_local_name ns (snd rn))
      end.

    Definition add_type_to_namespace_table (ln:local_name) (an:absolute_name) (tbl:namespace_table) :=
      mkNamespaceTable
        ((ln,an)::tbl.(namespace_table_types))
        tbl.(namespace_table_constants)
        tbl.(namespace_table_functions)
        tbl.(namespace_table_contracts).
    Definition add_constant_to_namespace_table (ln:local_name) (an:absolute_name) (tbl:namespace_table) :=
      mkNamespaceTable
        tbl.(namespace_table_types)
        ((ln,an)::tbl.(namespace_table_constants))
        tbl.(namespace_table_functions)
        tbl.(namespace_table_contracts).
    Definition add_function_to_namespace_table (ln:local_name) (an:absolute_name) (tbl:namespace_table) :=
      mkNamespaceTable
        tbl.(namespace_table_types)
        tbl.(namespace_table_constants)
        ((ln,an)::tbl.(namespace_table_functions))
        tbl.(namespace_table_contracts).
    Definition add_contract_to_namespace_table (ln:local_name) (an:absolute_name) (tbl:namespace_table) :=
      mkNamespaceTable
        tbl.(namespace_table_types)
        tbl.(namespace_table_constants)
        tbl.(namespace_table_functions)
        ((ln,an)::tbl.(namespace_table_contracts)).
  End NameTable.

  Definition enum_ctxt : Set := list string.
  Definition abstract_ctxt : Set := list string.
  Record namespace_ctxt : Set :=
    mkNamespaceCtxt {
        namespace_ctxt_modules : list (namespace_name * namespace_table);
        namespace_ctxt_namespace : namespace_name;
        namespace_ctxt_current_module : namespace_table;
        namespace_ctxt_current_in_scope : namespace_table;
        namespace_ctxt_enums : enum_ctxt;
        namespace_ctxt_abstract : abstract_ctxt;
      }.

  Definition empty_namespace_ctxt (ns:namespace_name) : namespace_ctxt :=
    mkNamespaceCtxt nil ns empty_namespace_table empty_namespace_table nil nil.

  Definition update_namespace_context_modules
             (ctxt:namespace_ctxt)
             (ns:namespace_name)
             (update:namespace_table -> namespace_table) : namespace_ctxt :=
    match lookup string_dec ctxt.(namespace_ctxt_modules) ns with
    | Some t =>
      mkNamespaceCtxt (update_first string_dec ctxt.(namespace_ctxt_modules) ns (update t))
                      ctxt.(namespace_ctxt_namespace)
                      ctxt.(namespace_ctxt_current_module)
                      ctxt.(namespace_ctxt_current_in_scope)
                      ctxt.(namespace_ctxt_enums)
                      ctxt.(namespace_ctxt_abstract)
    | None =>
      mkNamespaceCtxt ((ns, update empty_namespace_table) :: ctxt.(namespace_ctxt_modules))
                      ctxt.(namespace_ctxt_namespace)
                      ctxt.(namespace_ctxt_current_module)
                      ctxt.(namespace_ctxt_current_in_scope)
                      ctxt.(namespace_ctxt_enums)
                      ctxt.(namespace_ctxt_abstract)
    end.

  Definition update_namespace_context_current_module
             (ctxt:namespace_ctxt)
             (update:namespace_table -> namespace_table) : namespace_ctxt :=
    mkNamespaceCtxt ctxt.(namespace_ctxt_modules)
                    ctxt.(namespace_ctxt_namespace)
                    (update ctxt.(namespace_ctxt_current_module))
                    ctxt.(namespace_ctxt_current_in_scope)
                    ctxt.(namespace_ctxt_enums)
                    ctxt.(namespace_ctxt_abstract).
  
  Definition update_namespace_context_current_in_scope
             (ctxt:namespace_ctxt)
             (update:namespace_table -> namespace_table) : namespace_ctxt :=
    mkNamespaceCtxt ctxt.(namespace_ctxt_modules)
                    ctxt.(namespace_ctxt_namespace)
                    ctxt.(namespace_ctxt_current_module)
                    (update ctxt.(namespace_ctxt_current_in_scope))
                    ctxt.(namespace_ctxt_enums)
                    ctxt.(namespace_ctxt_abstract).
  
  Definition update_namespace_context_current_both
             (ctxt:namespace_ctxt)
             (update:namespace_table -> namespace_table) : namespace_ctxt :=
    mkNamespaceCtxt ctxt.(namespace_ctxt_modules)
                    ctxt.(namespace_ctxt_namespace)
                    (update ctxt.(namespace_ctxt_current_module))
                    (update ctxt.(namespace_ctxt_current_in_scope))
                    ctxt.(namespace_ctxt_enums)
                    ctxt.(namespace_ctxt_abstract).
  
  Definition update_namespace_context_enums
             (ctxt:namespace_ctxt)
             (ectxt:enum_ctxt) : namespace_ctxt :=
    mkNamespaceCtxt ctxt.(namespace_ctxt_modules)
                    ctxt.(namespace_ctxt_namespace)
                    ctxt.(namespace_ctxt_current_module)
                    ctxt.(namespace_ctxt_current_in_scope)
                    ectxt
                    ctxt.(namespace_ctxt_abstract).
    
  Definition update_namespace_context_abstract
             (ctxt:namespace_ctxt)
             (actxt:abstract_ctxt) : namespace_ctxt :=
    mkNamespaceCtxt ctxt.(namespace_ctxt_modules)
                    ctxt.(namespace_ctxt_namespace)
                    ctxt.(namespace_ctxt_current_module)
                    ctxt.(namespace_ctxt_current_in_scope)
                    ctxt.(namespace_ctxt_enums)
                    actxt.
    
  Definition add_type_to_namespace_ctxt
             (ctxt:namespace_ctxt) (ns:namespace_name) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_modules ctxt ns (add_type_to_namespace_table ln an).
  
  Definition add_constant_to_namespace_ctxt
             (ctxt:namespace_ctxt) (ns:namespace_name) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_modules ctxt ns (add_constant_to_namespace_table ln an).
  
  Definition add_function_to_namespace_ctxt
             (ctxt:namespace_ctxt) (ns:namespace_name) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_modules ctxt ns (add_function_to_namespace_table ln an).

  Definition add_contract_to_namespace_ctxt
             (ctxt:namespace_ctxt) (ns:namespace_name) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_modules ctxt ns (add_contract_to_namespace_table ln an).

  Definition add_type_to_namespace_ctxt_current
             (ctxt:namespace_ctxt) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_current_both ctxt (add_type_to_namespace_table ln an).
    
  Definition add_constant_to_namespace_ctxt_current
             (ctxt:namespace_ctxt) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_current_both ctxt (add_constant_to_namespace_table ln an).
  
  Definition add_function_to_namespace_ctxt_current
             (ctxt:namespace_ctxt) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_current_both ctxt (add_function_to_namespace_table ln an).

  Definition add_contract_to_namespace_ctxt_current
             (ctxt:namespace_ctxt) (ln:local_name) (an:absolute_name) :=
    update_namespace_context_current_both ctxt (add_contract_to_namespace_table ln an).

  Definition new_namespace_scope (ctxt:namespace_ctxt) (ns:namespace_name) : namespace_ctxt :=
    let prev_ns := ctxt.(namespace_ctxt_namespace) in
    let prev_tbl_current_module := ctxt.(namespace_ctxt_current_module) in
    let prev_modules := ctxt.(namespace_ctxt_modules) in
    let prev_enums := ctxt.(namespace_ctxt_enums) in
    let prev_abstract := ctxt.(namespace_ctxt_abstract) in
    if string_dec prev_ns no_namespace
    then
      mkNamespaceCtxt
        prev_modules
        ns
        empty_namespace_table
        empty_namespace_table
        prev_enums
        prev_abstract
    else
      match lookup string_dec prev_modules prev_ns with
      | Some t =>
        mkNamespaceCtxt
          (update_first string_dec prev_modules prev_ns (namespace_table_app prev_tbl_current_module t))
          ns
          empty_namespace_table
          empty_namespace_table
          prev_enums
          prev_abstract
      | None =>
        mkNamespaceCtxt
          ((prev_ns, prev_tbl_current_module) :: prev_modules)
          ns
          empty_namespace_table
          empty_namespace_table
          prev_enums
          prev_abstract
      end.

  Definition local_namespace_scope (ctxt:namespace_ctxt) (ns:namespace_name) : namespace_ctxt :=
    let prev_ns := ctxt.(namespace_ctxt_namespace) in
    let prev_tbl_current_module := ctxt.(namespace_ctxt_current_module) in
    let prev_tbl_current_in_scope := ctxt.(namespace_ctxt_current_in_scope) in
    let prev_modules := ctxt.(namespace_ctxt_modules) in
    let prev_enums := ctxt.(namespace_ctxt_enums) in
    let prev_abstract := ctxt.(namespace_ctxt_abstract) in
    mkNamespaceCtxt
      prev_modules
      ns
      prev_tbl_current_module
      prev_tbl_current_in_scope
      prev_enums
      prev_abstract.

End NamespaceContext.