Пример #1
0
environment coercion_cmd(parser & p) {
    auto pos = p.pos();
    expr f   = p.parse_expr();
    if (!is_constant(f))
        throw parser_error("invalid 'coercion' command, constant expected", pos);
    if (p.curr_is_token(g_colon)) {
        p.next();
        pos = p.pos();
        expr C = p.parse_expr();
        if (!is_constant(C))
            throw parser_error("invalid 'coercion' command, constant expected", pos);
        return add_coercion(p.env(), const_name(f), const_name(C), p.ios());
    } else {
        return add_coercion(p.env(), const_name(f), p.ios());
    }
}
Пример #2
0
static expr parse_struct_expr_core(parser & p, pos_info const & pos, bool curly_bar) {
    expr t = p.parse_expr();
    buffer<name> field_names;
    buffer<expr> field_values;
    buffer<expr> using_exprs;
    while (p.curr_is_token(get_comma_tk())) {
        p.next();
        pair<optional<name>, expr> id_e = p.parse_optional_assignment();
        if (id_e.first) {
            field_names.push_back(*id_e.first);
            field_values.push_back(id_e.second);
        } else {
            using_exprs.push_back(id_e.second);
        }
    }
    if (curly_bar)
        p.check_token_next(get_rcurlybar_tk(), "invalid structure expression, '|}' expected");
    else
        p.check_token_next(get_rdcurly_tk(), "invalid structure expression, '⦄' expected");
    buffer<expr> args;
    args.push_back(t);
    args.append(field_values);
    args.append(using_exprs);
    return p.save_pos(mk_structure_instance(to_list(field_names), args.size(), args.data()), pos);
}
Пример #3
0
static expr parse_notation_expr(parser & p, buffer<expr> const & locals) {
    auto pos = p.pos();
    expr r = p.parse_expr();
    r = abstract(r, locals.size(), locals.data());
    check_notation_expr(r, pos);
    return r;
}
Пример #4
0
environment check_cmd(parser & p) {
    expr e   = p.parse_expr();
    list<expr> ctx = locals_to_context(e, p);
    level_param_names ls = to_level_param_names(collect_univ_params(e));
    level_param_names new_ls;
    std::tie(e, new_ls) = p.elaborate_relaxed(e, ctx);
    auto tc = mk_type_checker_with_hints(p.env(), p.mk_ngen(), true);
    expr type = tc->check(e, append(ls, new_ls));
    auto reg              = p.regular_stream();
    formatter const & fmt = reg.get_formatter();
    options opts          = p.ios().get_options();
    unsigned indent       = get_pp_indent(opts);
    format r = group(format{fmt(e), space(), colon(), nest(indent, compose(line(), fmt(type)))});
    reg << mk_pair(r, opts) << endl;
    return p.env();
}
Пример #5
0
environment print_cmd(parser & p) {
    if (p.curr() == scanner::token_kind::String) {
        p.regular_stream() << p.get_str_val() << endl;
        p.next();
    } else if (p.curr_is_token_or_id(g_raw)) {
        p.next();
        expr e = p.parse_expr();
        p.regular_stream() << e << endl;
    } else if (p.curr_is_token_or_id(g_options)) {
        p.next();
        p.regular_stream() << p.ios().get_options() << endl;
    } else {
        throw parser_error("invalid print command", p.pos());
    }
    return p.env();
}
Пример #6
0
expr parse_nested_declaration(parser & p, unsigned, expr const *, pos_info const & pos) {
    try {
        optional<name> n;
        decl_attributes attrs;
        if (!g_allow_nested_declarations)
            throw parser_error("invalid 'abstract' expression, it is only allowed inside definitions", pos);
        if (p.curr_is_token(get_as_tk())) {
            p.next();
            n = p.check_id_next("invalid 'abstract' expression, identifier expected");
        }
        attrs.parse(p);
        expr e = p.parse_expr();
        p.check_token_next(get_end_tk(), "invalid 'abstract' expression, 'end' expected");
        return p.save_pos(mk_nested_declaration(n, attrs, e), pos);
    } catch (exception & ex) {
        consume_until_end(p);
        ex.rethrow();
        lean_unreachable();
    }
}
Пример #7
0
static unsigned parse_precedence_core(parser & p) {
    auto pos = p.pos();
    if (p.curr_is_numeral()) {
        return p.parse_small_nat();
    } else {
        environment env = p.env();
        env = open_prec_aliases(env);
        parser::local_scope scope(p, env);
        expr pre_val = p.parse_expr(get_max_prec());
        pre_val  = mk_typed_expr(mk_constant(get_num_name()), pre_val);
        expr val = std::get<0>(p.elaborate(pre_val, list<expr>()));
        val = normalize(p.env(), val);
        if (optional<mpz> mpz_val = to_num_core(val)) {
            if (!mpz_val->is_unsigned_int())
                throw parser_error("invalid 'precedence', argument does not fit in a machine integer", pos);
            return mpz_val->get_unsigned_int();
        } else {
            throw parser_error("invalid 'precedence', argument does not evaluate to a numeral", pos);
        }
    }
}
Пример #8
0
static notation_entry parse_notation_core(parser & p, bool overload, notation_entry_group grp, buffer<token_entry> & new_tokens, bool parse_only,
                                          unsigned priority) {
    buffer<expr>       locals;
    buffer<transition> ts;
    parser::local_scope scope(p);
    bool is_nud = true;
    optional<parse_table> pt;
    optional<parse_table> reserved_pt;
    if (p.curr_is_numeral()) {
        lean_assert(p.curr_is_numeral());
        mpz num = p.get_num_val().get_numerator();
        p.next();
        p.check_token_next(get_assign_tk(), "invalid numeral notation, `:=` expected");
        auto e_pos = p.pos();
        expr e     = p.parse_expr();
        check_notation_expr(e, e_pos);
        return notation_entry(num, e, overload, parse_only);
    } else if (p.curr_is_identifier()) {
        parse_notation_local(p, locals);
        is_nud = false;
        pt = get_led_table(p.env());
        if (grp != notation_entry_group::Reserve)
            reserved_pt = get_reserved_led_table(p.env());
    } else {
        pt = get_nud_table(p.env());
        if (grp != notation_entry_group::Reserve)
            reserved_pt = get_reserved_nud_table(p.env());
    }
    bool used_default = false;
    while ((grp != notation_entry_group::Reserve && !p.curr_is_token(get_assign_tk())) ||
           (grp == notation_entry_group::Reserve && !p.curr_is_command() && !p.curr_is_eof())) {
        name pp_tk = parse_quoted_symbol_or_token(p, new_tokens, used_default, grp).to_string();
        name tk = utf8_trim(pp_tk.to_string());
        if (auto at = find_next(reserved_pt, tk)) {
            // Remark: we are ignoring multiple actions in the reserved notation table
            transition const & trans = head(at).first;
            action const & a = trans.get_action();
            reserved_pt      = head(at).second;
            if (!p.curr_is_quoted_symbol())
                pp_tk = trans.get_pp_token();
            switch (a.kind()) {
            case notation::action_kind::Skip:
                if (!p.curr_is_quoted_symbol() && !p.curr_is_keyword() && !p.curr_is_token(get_assign_tk())) {
                    if (g_allow_local && !p.curr_is_token_or_id(get_binders_tk())) {
                        ts.push_back(parse_transition(p, pt, tk, locals, new_tokens, grp, pp_tk));
                        break;
                    }
                    p.check_token_or_id_next(get_binders_tk(),
                                             "invalid notation declaration, quoted-symbol, keyword or `:=` expected "
                                             "(declaration prefix matches reserved notation)");
                }
                ts.push_back(transition(tk, a, pp_tk));
                break;
            case notation::action_kind::Binder:
                if (g_allow_local && !p.curr_is_token_or_id(get_binder_tk())) {
                    ts.push_back(parse_transition(p, pt, tk, locals, new_tokens, grp, pp_tk));
                    break;
                }
                p.check_token_or_id_next(get_binder_tk(),
                                         "invalid notation declaration, 'binder' expected "
                                         "(declaration prefix matches reserved notation)");
                ts.push_back(transition(tk, a, pp_tk));
                break;
            case notation::action_kind::Binders:
                if (g_allow_local && !p.curr_is_token_or_id(get_binders_tk())) {
                    ts.push_back(parse_transition(p, pt, tk, locals, new_tokens, grp, pp_tk));
                    break;
                }
                p.check_token_or_id_next(get_binders_tk(),
                                         "invalid notation declaration, 'binders' expected "
                                         "(declaration prefix matches reserved notation)");
                ts.push_back(transition(tk, a, pp_tk));
                break;
            case notation::action_kind::Expr: case notation::action_kind::Exprs: case notation::action_kind::ScopedExpr:
            case notation::action_kind::Ext:  {
                if (g_allow_local && !p.curr_is_identifier()) {
                    ts.push_back(parse_transition(p, pt, tk, locals, new_tokens, grp, pp_tk));
                    break;
                }
                name n = p.check_id_next("invalid notation declaration, identifier expected "
                                         "(declaration prefix matches reserved notation)");
                if (p.curr_is_token(get_colon_tk())) {
                    if (g_allow_local) {
                        unsigned default_prec = get_default_prec(pt, tk);
                        action a = parse_action(p, tk, default_prec, locals, new_tokens, grp);
                        expr local_type = mk_Prop(); // type used in notation local declarations, it is irrelevant
                        expr l = mk_local(n, local_type);
                        p.add_local(l);
                        locals.push_back(l);
                        ts.push_back(transition(tk, a, pp_tk));
                        break;
                    } else {
                        throw parser_error("invalid notation declaration, invalid ':' occurrence "
                                           "(declaration prefix matches reserved notation)", p.pos());
                    }
                } else {
                    expr local_type = mk_Prop(); // type used in notation local declarations, it is irrelevant
                    expr l = mk_local(n, local_type);
                    p.add_local(l);
                    locals.push_back(l);
                    ts.push_back(transition(tk, a, pp_tk));
                    break;
                }
            }}
        } else {
            reserved_pt = optional<parse_table>();
            ts.push_back(parse_transition(p, pt, tk, locals, new_tokens, grp, pp_tk));
        }
        pt = find_match(pt, ts.back());
    }
    // for atomic notation where binding power was not set, we set it to max
    if (used_default && ts.size() == 1 && ts.back().get_action().kind() == notation::action_kind::Skip) {
        lean_assert(!new_tokens.empty());
        new_tokens.back().m_prec = get_max_prec();
    }
    expr n;
    if (grp == notation_entry_group::Reserve) {
        // reserve notation commands do not have a denotation
        lean_assert(p.curr_is_command() || p.curr_is_eof());
        expr dummy = mk_Prop(); // any expression without free variables will do
        n = dummy;
    } else {
        lean_assert(p.curr_is_token(get_assign_tk()));
        p.next();
        if (ts.empty())
            throw parser_error("invalid notation declaration, empty notation is not allowed", p.pos());
        n = parse_notation_expr(p, locals);
    }
    return notation_entry(is_nud, to_list(ts.begin(), ts.end()), n, overload, priority, grp, parse_only);
}