Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleanup parsing ptrns: #281

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions docs/langref.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,12 @@ Tuple patterns allow for _groups_:
- `(a b c: Nat, d e: Bool)` means `(a: Nat, b: Nat, c: Nat, d: Bool, e: Bool)`.
- `[a b c: Nat, d e: Bool]` means `[a: Nat, b: Nat, c: Nat, d: Bool, e: Bool]`.

You can introduce an optional name for the whole tuple pattern:
#### Alias Pattern

You can wrap a pattern into an *alias pattern*:

```rust
let abc::(a, b, c) = (1, 2, 3);
let (a, b, c) as abc = (1, 2, 3);
```

This will bind
Expand All @@ -236,18 +238,18 @@ This will bind
Here is another example:

```rust
{T: *, as: Nat}::Tas [%mem.M, %mem.Ptr Tas] → [%mem.M, T]
{T: *, a: Nat} as Ts [%mem.M, %mem.Ptr Ts] → [%mem.M, T]
```

#### Rebind

Finally, you can put a <tt>\`</tt> in front of an identifier of a `()`-style pattern to (potentially) rebind a name to a different value.
A `let` and `ret` expression allows you to rebind the same name to a different value:
This is particularly useful, when dealing with memory:

```rust
let (`mem, ptr) = %mem.alloc (I32, 0) mem;
let `mem = %mem.store (mem, ptr, 23:I32);
let (`mem, val) = %mem.load (mem, ptr);
let (mem, ptr) = %mem.alloc (I32, 0) mem;
let mem = %mem.store (mem, ptr, 23:I32);
let (mem, val) = %mem.load (mem, ptr);
```

### Expressions {#expr}
Expand Down
111 changes: 74 additions & 37 deletions include/mim/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,22 @@ class Expr : public Node {
: Node(loc) {}

public:
/// @name Precedence
///@{
enum class Prec {
Err,
Bot,
Where,
Arrow,
Pi,
App,
Extract,
Lit,
};

static constexpr bool is_rassoc(Prec p) { return p == Prec::Arrow; }
///@}

Ref emit(Emitter&) const;
virtual void bind(Scopes&) const = 0;
virtual Ref emit_decl(Emitter&, Ref /*type*/) const { fe::unreachable(); }
Expand Down Expand Up @@ -170,107 +186,129 @@ class ValDecl : public Decl {

class Ptrn : public Decl {
public:
Ptrn(Loc loc, bool rebind, Dbg dbg)
: Decl(loc)
, dbg_(dbg)
, rebind_(rebind) {}
Ptrn(Loc loc)
: Decl(loc) {}

bool rebind() const { return rebind_; }
Dbg dbg() const { return dbg_; }
virtual bool implicit() const { return false; }

virtual void bind(Scopes&, bool quiet = false) const = 0;
Ref emit_value(Emitter&, Ref) const;
virtual Ref emit_type(Emitter&) const = 0;
virtual void bind(Scopes&, bool rebind, bool quiet) const = 0;
virtual Ref emit_value(Emitter&, Ref) const = 0;
virtual Ref emit_type(Emitter&) const = 0;

[[nodiscard]] static Ptr<Expr> to_expr(AST&, Ptr<Ptrn>&&);
[[nodiscard]] static Ptr<Ptrn> to_ptrn(Ptr<Expr>&&);

private:
virtual void emit_value_(Emitter&, Ref) const {}

Dbg dbg_;
bool rebind_;
};

class ErrorPtrn : public Ptrn {
public:
ErrorPtrn(Loc loc)
: Ptrn(loc, false, Dbg()) {}
: Ptrn(loc) {}

void bind(Scopes&, bool quiet = false) const override;
void bind(Scopes&, bool rebind, bool quiet) const override;
Ref emit_value(Emitter&, Ref) const override;
Ref emit_type(Emitter&) const override;
std::ostream& stream(Tab&, std::ostream&) const override;
};

/// `dbg: type`
class IdPtrn : public Ptrn {
public:
IdPtrn(Loc loc, bool rebind, Dbg dbg, Ptr<Expr>&& type)
: Ptrn(loc, rebind, dbg)
IdPtrn(Loc loc, Dbg dbg, Ptr<Expr>&& type)
: Ptrn(loc)
, dbg_(dbg)
, type_(std::move(type)) {}

Dbg dbg() const { return dbg_; }
const Expr* type() const { return type_.get(); }

static Ptr<IdPtrn> mk_type(AST& ast, Ptr<Expr>&& type) {
auto loc = type->loc();
return ast.ptr<IdPtrn>(loc, false, Dbg(loc, ast.sym_anon()), std::move(type));
return ast.ptr<IdPtrn>(loc, Dbg(loc, ast.sym_anon()), std::move(type));
}
static Ptr<IdPtrn> mk_id(AST& ast, Dbg dbg, Ptr<Expr>&& type) {
auto loc = (type && dbg) ? dbg.loc() + type->loc() : type ? type->loc() : dbg.loc();
return ast.ptr<IdPtrn>(loc, false, dbg, std::move(type));
return ast.ptr<IdPtrn>(loc, dbg, std::move(type));
}

void bind(Scopes&, bool quiet = false) const override;
void bind(Scopes&, bool rebind, bool quiet) const override;
Ref emit_value(Emitter&, Ref) const override;
Ref emit_type(Emitter&) const override;
std::ostream& stream(Tab&, std::ostream&) const override;

private:
Dbg dbg_;
Ptr<Expr> type_;
};

/// `dbg_0 ... dbg_n-2 id` where `id` = `dbg_n-1: type`
class GrpPtrn : public Ptrn {
public:
GrpPtrn(Dbg dbg, const IdPtrn* id)
: Ptrn(dbg.loc(), false, dbg)
: Ptrn(dbg.loc())
, dbg_(dbg)
, id_(id) {}

Dbg dbg() const { return dbg_; }
const IdPtrn* id() const { return id_; }

void bind(Scopes&, bool quiet = false) const override;
void bind(Scopes&, bool rebind, bool quiet) const override;
Ref emit_value(Emitter&, Ref) const override;
Ref emit_type(Emitter&) const override;
std::ostream& stream(Tab&, std::ostream&) const override;

private:
Dbg dbg_;
const IdPtrn* id_;
};

/// `dbg::(ptrn_0, ..., ptrn_n-1)` or `dbg::[ptrn_0, ..., ptrn_n-1]`
/// `ptrn as id`
class AliasPtrn : public Ptrn {
public:
AliasPtrn(Loc loc, Ptr<Ptrn>&& ptrn, Dbg dbg)
: Ptrn(loc)
, ptrn_(std::move(ptrn))
, dbg_(dbg) {}

const Ptrn* ptrn() const { return ptrn_.get(); }
Dbg dbg() const { return dbg_; }
bool implicit() const override { return ptrn()->implicit(); }

void bind(Scopes&, bool rebind, bool quiet) const override;
Ref emit_value(Emitter&, Ref) const override;
Ref emit_type(Emitter&) const override;
std::ostream& stream(Tab&, std::ostream&) const override;

private:
Ptr<Ptrn> ptrn_;
Dbg dbg_;
};

/// `(ptrn_0, ..., ptrn_n-1)`, `[ptrn_0, ..., ptrn_n-1]`, or `{ptrn_0, ..., ptrn_n-1}`
class TuplePtrn : public Ptrn {
public:
TuplePtrn(Loc loc, Tok::Tag delim_l, Ptrs<Ptrn>&& ptrns, bool rebind, Dbg dbg)
: Ptrn(loc, rebind, dbg)
TuplePtrn(Loc loc, Tok::Tag delim_l, Ptrs<Ptrn>&& ptrns)
: Ptrn(loc)
, delim_l_(delim_l)
, ptrns_(std::move(ptrns)) {}

Tok::Tag delim_l() const { return delim_l_; }
Tok::Tag delim_r() const { return Tok::delim_l2r(delim_l()); }
bool is_paren() const { return delim_l() == Tok::Tag::D_paren_l; }
bool is_brckt() const { return delim_l() == Tok::Tag::D_brckt_l; }
bool implicit() const override { return delim_l_ == Tok::Tag::D_brace_l; }

const auto& ptrns() const { return ptrns_; }
const Ptrn* ptrn(size_t i) const { return ptrns_[i].get(); }
size_t num_ptrns() const { return ptrns().size(); }

void bind(Scopes&, bool quiet = false) const override;
void bind(Scopes&, bool rebind, bool quiet) const override;
Ref emit_value(Emitter&, Ref) const override;
Ref emit_type(Emitter&) const override;
Ref emit_decl(Emitter&, Ref type) const;
Ref emit_body(Emitter&, Ref decl) const;
std::ostream& stream(Tab&, std::ostream&) const override;

private:
void emit_value_(Emitter&, Ref) const override;

Tok::Tag delim_l_;
Ptrs<Ptrn> ptrns_;
};
Expand Down Expand Up @@ -442,18 +480,17 @@ class PiExpr : public Expr {
public:
class Dom : public Node {
public:
Dom(Loc loc, bool is_implicit, Ptr<Ptrn>&& ptrn)
Dom(Loc loc, Ptr<Ptrn>&& ptrn)
: Node(loc)
, is_implicit_(is_implicit)
, ptrn_(std::move(ptrn)) {}

bool is_implicit() const { return is_implicit_; }
bool implicit() const { return ptrn_->implicit(); }
const Ptrn* ptrn() const { return ptrn_.get(); }
const IdPtrn* ret() const { return ret_.get(); }

void add_ret(AST& ast, Ptr<Expr>&& type) const {
auto loc = type->loc();
ret_ = ast.ptr<IdPtrn>(loc, false, Dbg(loc, ast.sym_return()), std::move(type));
ret_ = ast.ptr<IdPtrn>(loc, Dbg(loc, ast.sym_return()), std::move(type));
}

virtual void bind(Scopes& scopes, bool quiet = false) const;
Expand All @@ -465,7 +502,6 @@ class PiExpr : public Expr {
mutable Pi* decl_ = nullptr;

private:
bool is_implicit_;
Ptr<Ptrn> ptrn_;
mutable Ptr<IdPtrn> ret_;

Expand Down Expand Up @@ -811,10 +847,11 @@ class LamDecl : public RecDecl {
public:
class Dom : public PiExpr::Dom {
public:
Dom(Loc loc, bool is_implicit, Ptr<Ptrn>&& ptrn, Ptr<Expr>&& filter)
: PiExpr::Dom(loc, is_implicit, std::move(ptrn))
Dom(Loc loc, Ptr<Ptrn>&& ptrn, Ptr<Expr>&& filter)
: PiExpr::Dom(loc, std::move(ptrn))
, filter_(std::move(filter)) {}

bool implicit() const { return ptrn()->implicit(); }
const Expr* filter() const { return filter_.get(); }

void bind(Scopes& scopes, bool quiet = false) const override;
Expand Down
18 changes: 13 additions & 5 deletions include/mim/ast/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ class Parser : public fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser> {

/// @name parse exprs
///@{
Ptr<Expr> parse_expr(std::string_view ctxt, Prec = Prec::Bot);
Ptr<Expr> parse_expr(std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
Ptr<Expr> parse_primary_expr(std::string_view ctxt);
Ptr<Expr> parse_infix_expr(Tracker, Ptr<Expr>&& lhs, Prec = Prec::Bot);
Ptr<Expr> parse_infix_expr(Tracker, Ptr<Expr>&& lhs, Expr::Prec = Expr::Prec::Bot);
///@}

/// @name parse primary exprs
Expand All @@ -94,11 +94,19 @@ class Parser : public fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser> {
Ptr<Expr> parse_insert_expr();
///@}

enum PtrnStyle {
Style_Bit = 0b001,
Brckt_Style = 0b001,
Paren_Style = 0b000,
Implicit = 0b010,
};

/// @name parse ptrns
///@{
/// Depending on @p tag, this parses a `()`-style (Tok::Tag::D_paren_l) or `[]`-style (Tok::Tag::D_brckt_l) Ptrn.
Ptr<Ptrn> parse_ptrn(Tok::Tag tag, std::string_view ctxt, Prec = Prec::Bot, bool allow_annex = false);
Ptr<TuplePtrn> parse_tuple_ptrn();
/// Depending on @p style, this parses a `()`-style (Tok::Tag::D_paren_l) or `[]`-style (Tok::Tag::D_brckt_l) Ptrn.
Ptr<Ptrn> parse_ptrn(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
Ptr<Ptrn> parse_ptrn_(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
Ptr<TuplePtrn> parse_tuple_ptrn(int style);
///@}

/// @name parse decls
Expand Down
23 changes: 3 additions & 20 deletions include/mim/ast/tok.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ class Lit;
namespace ast {

// clang-format off
#define MIM_KEY(m) \
#define MIM_KEY(m) \
m(K_module, "module") \
m(K_import, "import") \
m(K_plugin, "plugin") \
m(K_and, "and" ) \
m(K_ax, "axm" ) \
m(K_as, "as" ) \
m(K_axm, "axm" ) \
m(K_let, "let" ) \
m(K_rec, "rec" ) \
m(K_ret, "ret" ) \
Expand Down Expand Up @@ -81,12 +82,10 @@ constexpr auto Num_Keys = size_t(0) MIM_KEY(CODE);
m(T_arrow, "→") \
m(T_assign, "=") \
m(T_at, "@") \
m(T_backtick, "`") \
m(T_bot, "⊥") \
m(T_top, "⊤") \
m(T_box, "□") \
m(T_colon, ":") \
m(T_colon_colon,"::") \
m(T_comma, ",") \
m(T_dollar, "$") \
m(T_dot, ".") \
Expand All @@ -101,22 +100,6 @@ constexpr auto Num_Keys = size_t(0) MIM_KEY(CODE);
m("top", T_top ) \
m("insert", K_ins ) \

/// @name Precedence
///@{
enum class Prec {
Err,
Bot,
Where,
Arrow,
Pi,
App,
Extract,
Lit,
};

inline constexpr bool is_rassoc(Prec p) { return p == Prec::Arrow; }
///@}

class Tok {
public:
/// @name Tag
Expand Down
4 changes: 2 additions & 2 deletions include/mim/plug/affine/pass/lower_for.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace mim::plug::affine {
/// con %affine.For_impl
/// (m: Nat , n: Nat , Ts: «n; *»)
/// (begin: Idx m, end: Idx m, step: Idx m, init: «i: n; Ts#i»,
/// body: Cn [iter: Idx m, acc: «i: n; Ts#i», yield: Cn [«i: n; Ts#i»]],
/// exit: Cn [«i: n; Ts#i»]
/// body: Cn [iter: Idx m, acc: «i: n; Ts#i», yield: Cn «i: n; Ts#i»],
/// exit: Cn «i: n; Ts#i»
/// ) =
/// con head(iter: Idx m, acc: «i: n; Ts#i») =
/// con new_body() = body (iter, acc, cn acc: «i: n; Ts#i» =
Expand Down
14 changes: 7 additions & 7 deletions lit/affine/for_over_mem.mim
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ let arr_size = ⊤:Nat;
// let arr_size = 16;

con extern main [mem: %mem.M, argc: I32, argv: %mem.Ptr (%mem.Ptr (I32, 0), 0), return: Cn [%mem.M, I32]] =
let (`mem, ptr) = %mem.alloc (<<%core.bitcast Nat argc; I32>>, 0) (mem);
let (mem, ptr) = %mem.alloc (<<%core.bitcast Nat argc; I32>>, 0) (mem);
%affine.For (i32, 3, (%mem.M, I32, I32)) (0I32, argc, 1I32, (mem, 0I32, 0I32), for_body, for_exit)
where
con for_body [i: I32, [mem: %mem.M, acc_a: I32, acc_b: I32], continue: Cn [%mem.M, I32, I32]] =
let a = %core.wrap.add 0 (i, acc_a);
let b = %core.wrap.sub 0 (i, acc_b);
let lea = %mem.lea (arr_size, <arr_size; I32>, 0) (ptr, %core.conv.u arr_size i);
let `mem = %mem.store (mem, lea, a);
let a = %core.wrap.add 0 (i, acc_a);
let b = %core.wrap.sub 0 (i, acc_b);
let lea = %mem.lea (arr_size, <arr_size; I32>, 0) (ptr, %core.conv.u arr_size i);
let mem = %mem.store (mem, lea, a);
continue (mem, a, b);

con for_exit [mem: %mem.M, I32, I32]::acc =
con for_exit [mem: %mem.M, I32, I32] =
let lea = %mem.lea (arr_size, <arr_size; I32>, 0) (ptr, %core.conv.u arr_size (%core.wrap.sub 0 (argc, 4I32)));
let (`mem, val)::ld = %mem.load (mem, lea);
let ld = %mem.load (mem, lea);
return ld;
end;

Expand Down
Loading
Loading