diff --git a/library/init/default.lean b/library/init/default.lean index 1f1ea1bd72..c8d58969df 100644 --- a/library/init/default.lean +++ b/library/init/default.lean @@ -12,4 +12,5 @@ import init.monad init.option init.state init.fin init.list init.char init.strin import init.monad_combinators init.set import init.timeit init.trace init.unsigned init.ordering init.list_classes init.coe import init.wf init.nat_div init.meta init.instances init.breakpoint -import init.sigma_lex init.id_locked init.order init.algebra init.nat_lemmas init.char_lemmas +import init.sigma_lex init.id_locked init.order init.algebra +import init.nat_lemmas init.char_lemmas init.string_lemmas diff --git a/library/init/string_lemmas.lean b/library/init/string_lemmas.lean new file mode 100644 index 0000000000..5cac68a026 --- /dev/null +++ b/library/init/string_lemmas.lean @@ -0,0 +1,21 @@ +/- +Copyright (c) 2016 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Author: Leonardo de Moura +-/ +prelude +import init.meta + +namespace string +lemma empty_ne_str (c : char) (s : string) : empty ≠ str c s := +begin intro h, contradiction end + +lemma str_ne_empty (c : char) (s : string) : str c s ≠ empty := +begin intro h, contradiction end + +lemma str_ne_str_left {c₁ c₂ : char} (s₁ s₂ : string) : c₁ ≠ c₂ → str c₁ s₁ ≠ str c₂ s₂ := +begin intros h₁ h₂, unfold str at h₂, injection h₂, contradiction end + +lemma str_ne_str_right (c₁ c₂ : char) {s₁ s₂ : string} : s₁ ≠ s₂ → str c₁ s₁ ≠ str c₂ s₂ := +begin intros h₁ h₂, unfold str at h₂, injection h₂, contradiction end +end string diff --git a/src/library/comp_val.cpp b/src/library/comp_val.cpp index 086a6e378c..123623cae9 100644 --- a/src/library/comp_val.cpp +++ b/src/library/comp_val.cpp @@ -5,6 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #include "library/num.h" +#include "library/string.h" #include "library/util.h" #include "library/constants.h" @@ -113,7 +114,7 @@ optional mk_fin_val_ne_proof(expr const & a, expr const & b) { expr const & n = app_arg(app_fn(app_fn(a))); expr const & v_a = app_arg(app_fn(a)); expr const & v_b = app_arg(app_fn(b)); - auto pr = mk_nat_val_lt_proof(v_a, v_b); + auto pr = mk_nat_val_ne_proof(v_a, v_b); if (!pr) return none_expr(); return some_expr(mk_app(mk_constant(get_fin_ne_of_vne_name()), n, a, b, *pr)); } @@ -134,8 +135,51 @@ optional mk_char_val_ne_proof(expr const & a, expr const & b) { return mk_fin_val_ne_proof(a, b); } +/* Remark: this function assumes 'e' has type string */ +static bool is_string_str(expr const & e, expr & c, expr & s) { + if (is_app_of(e, get_string_str_name(), 2) || + is_app_of(e, get_list_cons_name(), 3)) { + c = app_arg(app_fn(e)); + s = app_arg(e); + return true; + } + return false; +} + +/* Remark: this function assumes 'e' has type string */ +static bool is_string_empty(expr const & e) { + return + is_constant(e, get_string_empty_name()) || + is_app_of(e, get_list_nil_name(), 1); +} + +optional mk_string_val_ne_proof(expr a, expr b) { + if (auto new_a = expand_string_macro(a)) + a = *new_a; + if (auto new_b = expand_string_macro(b)) + b = *new_b; + expr c_a, s_a; + expr c_b, s_b; + if (is_string_str(a, c_a, s_a)) { + if (is_string_str(b, c_b, s_b)) { + if (auto pr = mk_char_val_ne_proof(c_a, c_b)) { + return some_expr(mk_app({mk_constant(get_string_str_ne_str_left_name()), c_a, c_b, s_a, s_b, *pr})); + } else if (auto pr = mk_string_val_ne_proof(s_a, s_b)) { + return some_expr(mk_app({mk_constant(get_string_str_ne_str_right_name()), c_a, c_b, s_a, s_b, *pr})); + } + } else if (is_string_empty(b)) { + return some_expr(mk_app(mk_constant(get_string_str_ne_empty_name()), c_a, s_a)); + } + } else if (is_string_empty(a)) { + if (is_string_str(b, c_b, s_b)) { + return some_expr(mk_app(mk_constant(get_string_empty_ne_str_name()), c_b, s_b)); + } + } + return none_expr(); +} + void initialize_comp_val() { - g_char_sz = new expr(to_nat_expr(mpz(255))); + g_char_sz = new expr(to_nat_expr(mpz(256))); } void finalize_comp_val() { diff --git a/src/library/comp_val.h b/src/library/comp_val.h index d84b25b198..5f79fc3e71 100644 --- a/src/library/comp_val.h +++ b/src/library/comp_val.h @@ -34,6 +34,9 @@ optional mk_fin_val_ne_proof(expr const & a, expr const & b); /* Similar to mk_char_val_ne_proof, but for char type */ optional mk_char_val_ne_proof(expr const & a, expr const & b); +/* Similar to mk_char_val_ne_proof, but for string type */ +optional mk_string_val_ne_proof(expr a, expr b); + void initialize_comp_val(); void finalize_comp_val(); } diff --git a/src/library/constants.cpp b/src/library/constants.cpp index 09206c0fdb..72ef950770 100644 --- a/src/library/constants.cpp +++ b/src/library/constants.cpp @@ -359,6 +359,10 @@ name const * g_store = nullptr; name const * g_string = nullptr; name const * g_string_empty = nullptr; name const * g_string_str = nullptr; +name const * g_string_empty_ne_str = nullptr; +name const * g_string_str_ne_empty = nullptr; +name const * g_string_str_ne_str_left = nullptr; +name const * g_string_str_ne_str_right = nullptr; name const * g_sub = nullptr; name const * g_subsingleton = nullptr; name const * g_subsingleton_elim = nullptr; @@ -778,6 +782,10 @@ void initialize_constants() { g_string = new name{"string"}; g_string_empty = new name{"string", "empty"}; g_string_str = new name{"string", "str"}; + g_string_empty_ne_str = new name{"string", "empty_ne_str"}; + g_string_str_ne_empty = new name{"string", "str_ne_empty"}; + g_string_str_ne_str_left = new name{"string", "str_ne_str_left"}; + g_string_str_ne_str_right = new name{"string", "str_ne_str_right"}; g_sub = new name{"sub"}; g_subsingleton = new name{"subsingleton"}; g_subsingleton_elim = new name{"subsingleton", "elim"}; @@ -1198,6 +1206,10 @@ void finalize_constants() { delete g_string; delete g_string_empty; delete g_string_str; + delete g_string_empty_ne_str; + delete g_string_str_ne_empty; + delete g_string_str_ne_str_left; + delete g_string_str_ne_str_right; delete g_sub; delete g_subsingleton; delete g_subsingleton_elim; @@ -1617,6 +1629,10 @@ name const & get_store_name() { return *g_store; } name const & get_string_name() { return *g_string; } name const & get_string_empty_name() { return *g_string_empty; } name const & get_string_str_name() { return *g_string_str; } +name const & get_string_empty_ne_str_name() { return *g_string_empty_ne_str; } +name const & get_string_str_ne_empty_name() { return *g_string_str_ne_empty; } +name const & get_string_str_ne_str_left_name() { return *g_string_str_ne_str_left; } +name const & get_string_str_ne_str_right_name() { return *g_string_str_ne_str_right; } name const & get_sub_name() { return *g_sub; } name const & get_subsingleton_name() { return *g_subsingleton; } name const & get_subsingleton_elim_name() { return *g_subsingleton_elim; } diff --git a/src/library/constants.h b/src/library/constants.h index 5ba90e9cdb..15e9dd37a6 100644 --- a/src/library/constants.h +++ b/src/library/constants.h @@ -361,6 +361,10 @@ name const & get_store_name(); name const & get_string_name(); name const & get_string_empty_name(); name const & get_string_str_name(); +name const & get_string_empty_ne_str_name(); +name const & get_string_str_ne_empty_name(); +name const & get_string_str_ne_str_left_name(); +name const & get_string_str_ne_str_right_name(); name const & get_sub_name(); name const & get_subsingleton_name(); name const & get_subsingleton_elim_name(); diff --git a/src/library/constants.txt b/src/library/constants.txt index cf60936215..7f4a93d73b 100644 --- a/src/library/constants.txt +++ b/src/library/constants.txt @@ -354,6 +354,10 @@ store string string.empty string.str +string.empty_ne_str +string.str_ne_empty +string.str_ne_str_left +string.str_ne_str_right sub subsingleton subsingleton.elim diff --git a/src/library/string.cpp b/src/library/string.cpp index ffcbf4b815..52cb993191 100644 --- a/src/library/string.cpp +++ b/src/library/string.cpp @@ -139,6 +139,11 @@ void initialize_string() { }); } +optional expand_string_macro(expr const & e) { + if (!is_string_macro(e)) return none_expr(); + return some_expr(from_string_core(to_string_macro(e).get_value())); +} + void finalize_string() { delete g_nat; delete g_str; diff --git a/src/library/string.h b/src/library/string.h index 70743be21e..7c466f6925 100644 --- a/src/library/string.h +++ b/src/library/string.h @@ -18,6 +18,8 @@ expr from_string(std::string const & s); optional to_string(expr const & e); bool is_string_macro(expr const & e); +/** \brief Expand string macro if 'e' is a string macro */ +optional expand_string_macro(expr const & e); optional to_char(expr const & e);