2015-06-12 20:38:57 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#include "library/replace_visitor.h"
|
2015-12-18 06:19:55 +00:00
|
|
|
#include "library/attribute_manager.h"
|
2015-11-24 23:22:21 +00:00
|
|
|
#include "library/blast/forward/pattern.h"
|
2015-06-12 20:38:57 +00:00
|
|
|
#include "frontends/lean/decl_attributes.h"
|
|
|
|
#include "frontends/lean/parser.h"
|
|
|
|
#include "frontends/lean/tokens.h"
|
|
|
|
#include "frontends/lean/util.h"
|
|
|
|
|
|
|
|
namespace lean {
|
2015-12-18 06:19:55 +00:00
|
|
|
decl_attributes::decl_attributes(bool is_abbrev, bool persistent) {
|
2015-06-12 20:38:57 +00:00
|
|
|
m_is_abbrev = is_abbrev;
|
|
|
|
m_persistent = persistent;
|
2015-12-18 06:19:55 +00:00
|
|
|
m_parsing_only = false;
|
|
|
|
if (is_abbrev)
|
|
|
|
m_entries = to_list(entry("reducible"));
|
2015-06-12 20:38:57 +00:00
|
|
|
}
|
|
|
|
|
2015-11-17 06:34:06 +00:00
|
|
|
void decl_attributes::parse(parser & p) {
|
2015-12-18 06:19:55 +00:00
|
|
|
buffer<char const *> attr_tokens;
|
|
|
|
get_attribute_tokens(attr_tokens);
|
2015-06-12 20:38:57 +00:00
|
|
|
while (true) {
|
2015-12-18 06:19:55 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
if (auto it = parse_priority(p)) {
|
|
|
|
m_prio = *it;
|
|
|
|
bool has_prio_attr = false;
|
|
|
|
for (auto const & entry : m_entries) {
|
|
|
|
if (get_attribute_kind(entry.m_attr.c_str()) == attribute_kind::Prioritized) {
|
|
|
|
has_prio_attr = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!has_prio_attr) {
|
|
|
|
throw parser_error("invalid '[priority]' attribute, declaration has not been marked with a prioritized attribute", pos);
|
2015-06-12 20:38:57 +00:00
|
|
|
}
|
|
|
|
} else if (p.curr_is_token(get_parsing_only_tk())) {
|
|
|
|
if (!m_is_abbrev)
|
2015-10-09 20:21:03 +00:00
|
|
|
throw parser_error("invalid '[parsing_only]' attribute, only abbreviations can be "
|
|
|
|
"marked as '[parsing_only]'", pos);
|
2015-12-18 06:19:55 +00:00
|
|
|
m_parsing_only = true;
|
2015-06-12 20:38:57 +00:00
|
|
|
p.next();
|
2015-12-18 06:19:55 +00:00
|
|
|
} else {
|
|
|
|
bool found = false;
|
|
|
|
for (char const * tk : attr_tokens) {
|
|
|
|
if (p.curr_is_token(tk)) {
|
|
|
|
p.next();
|
|
|
|
char const * attr = get_attribute_from_token(tk);
|
|
|
|
for (auto const & entry : m_entries) {
|
|
|
|
if (are_incompatible(entry.m_attr.c_str(), attr)) {
|
|
|
|
throw parser_error(sstream() << "invalid attribute [" << attr
|
|
|
|
<< "], declaration was already marked with [" << entry.m_attr << "]", pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (get_attribute_kind(attr)) {
|
|
|
|
case attribute_kind::Default:
|
|
|
|
case attribute_kind::Prioritized:
|
|
|
|
m_entries = cons(entry(attr), m_entries);
|
|
|
|
break;
|
|
|
|
case attribute_kind::Parametric: {
|
|
|
|
unsigned v = p.parse_small_nat();
|
|
|
|
if (v == 0)
|
|
|
|
throw parser_error("invalid attribute parameter, value must be positive", pos);
|
|
|
|
p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
|
|
|
|
m_entries = cons(entry(attr, v-1), m_entries);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute_kind::OptParametric:
|
|
|
|
if (!p.curr_is_token(get_rbracket_tk())) {
|
|
|
|
unsigned v = p.parse_small_nat();
|
|
|
|
if (v == 0)
|
|
|
|
throw parser_error("invalid attribute parameter, value must be positive", pos);
|
|
|
|
p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
|
|
|
|
m_entries = cons(entry(attr, v-1), m_entries);
|
|
|
|
} else {
|
|
|
|
p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
|
|
|
|
m_entries = cons(entry(attr), m_entries);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case attribute_kind::MultiParametric: {
|
|
|
|
buffer<unsigned> vs;
|
|
|
|
while (true) {
|
|
|
|
unsigned v = p.parse_small_nat();
|
|
|
|
if (v == 0)
|
|
|
|
throw parser_error("invalid attribute parameter, value must be positive", pos);
|
|
|
|
vs.push_back(v-1);
|
|
|
|
if (p.curr_is_token(get_rbracket_tk()))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p.next();
|
|
|
|
m_entries = cons(entry(attr, to_list(vs)), m_entries);
|
|
|
|
break;
|
|
|
|
}}
|
|
|
|
found = true;
|
2015-07-08 01:01:57 +00:00
|
|
|
break;
|
2015-12-18 06:19:55 +00:00
|
|
|
}
|
2015-07-08 01:01:57 +00:00
|
|
|
}
|
2015-12-18 06:19:55 +00:00
|
|
|
if (!found)
|
|
|
|
break;
|
2015-06-12 20:38:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-05 18:28:01 +00:00
|
|
|
environment decl_attributes::apply(environment env, io_state const & ios, name const & d, name const & ns) const {
|
2015-12-18 06:19:55 +00:00
|
|
|
buffer<entry> entries;
|
|
|
|
to_buffer(m_entries, entries);
|
2015-11-26 19:41:56 +00:00
|
|
|
if (has_pattern_hints(env.get(d).get_type())) {
|
|
|
|
// turn on [forward] if patterns hints have been used in the type.
|
2015-12-18 06:19:55 +00:00
|
|
|
entries.push_back(entry("forward"));
|
2015-06-12 20:38:57 +00:00
|
|
|
}
|
2015-12-18 06:19:55 +00:00
|
|
|
unsigned i = entries.size();
|
|
|
|
while (i > 0) {
|
|
|
|
--i;
|
|
|
|
auto const & entry = entries[i];
|
|
|
|
char const * attr = entry.m_attr.c_str();
|
|
|
|
switch (get_attribute_kind(attr)) {
|
|
|
|
case attribute_kind::Default:
|
|
|
|
env = set_attribute(env, ios, attr, d, ns, m_persistent);
|
|
|
|
break;
|
|
|
|
case attribute_kind::Prioritized:
|
|
|
|
if (m_prio)
|
|
|
|
env = set_prio_attribute(env, ios, attr, d, *m_prio, ns, m_persistent);
|
|
|
|
else
|
|
|
|
env = set_prio_attribute(env, ios, attr, d, LEAN_DEFAULT_PRIORITY, ns, m_persistent);
|
|
|
|
break;
|
|
|
|
case attribute_kind::Parametric:
|
|
|
|
env = set_param_attribute(env, ios, attr, d, head(entry.m_params), ns, m_persistent);
|
|
|
|
break;
|
|
|
|
case attribute_kind::OptParametric:
|
|
|
|
if (entry.m_params)
|
|
|
|
env = set_opt_param_attribute(env, ios, attr, d, optional<unsigned>(head(entry.m_params)), ns, m_persistent);
|
|
|
|
else
|
|
|
|
env = set_opt_param_attribute(env, ios, attr, d, optional<unsigned>(), ns, m_persistent);
|
|
|
|
break;
|
|
|
|
case attribute_kind::MultiParametric:
|
|
|
|
env = set_params_attribute(env, ios, attr, d, entry.m_params, ns, m_persistent);
|
|
|
|
break;
|
2015-06-21 19:36:43 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-12 20:38:57 +00:00
|
|
|
return env;
|
|
|
|
}
|
2015-06-13 00:32:18 +00:00
|
|
|
|
2015-12-18 06:19:55 +00:00
|
|
|
serializer & operator<<(serializer & s, decl_attributes::entry const & e) {
|
|
|
|
s << e.m_attr;
|
|
|
|
write_list(s, e.m_params);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
deserializer & operator>>(deserializer & d, decl_attributes::entry & e) {
|
|
|
|
d >> e.m_attr;
|
|
|
|
e.m_params = read_list<unsigned>(d);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2015-06-13 00:32:18 +00:00
|
|
|
void decl_attributes::write(serializer & s) const {
|
2015-12-18 06:19:55 +00:00
|
|
|
s << m_is_abbrev << m_persistent << m_prio << m_parsing_only;
|
|
|
|
write_list(s, m_entries);
|
2015-06-13 00:32:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void decl_attributes::read(deserializer & d) {
|
2015-12-18 06:19:55 +00:00
|
|
|
d >> m_is_abbrev >> m_persistent >> m_prio >> m_parsing_only;
|
|
|
|
m_entries = read_list<decl_attributes::entry>(d);
|
2015-06-13 00:32:18 +00:00
|
|
|
}
|
2015-12-14 02:22:51 +00:00
|
|
|
|
|
|
|
bool operator==(decl_attributes const & d1, decl_attributes const & d2) {
|
|
|
|
return
|
2015-12-18 06:19:55 +00:00
|
|
|
d1.m_is_abbrev == d2.m_is_abbrev ||
|
|
|
|
d1.m_persistent == d2.m_persistent ||
|
|
|
|
d1.m_parsing_only == d2.m_parsing_only ||
|
|
|
|
d1.m_entries == d2.m_entries ||
|
|
|
|
d1.m_prio == d2.m_prio;
|
2015-12-14 02:22:51 +00:00
|
|
|
}
|
2015-06-12 20:38:57 +00:00
|
|
|
}
|