15 if (
s->isa<Nat>())
return true;
16 if (
auto arr =
s->isa<Arr>())
return arr->body()->isa<
Nat>();
17 if (
auto sig =
s->isa_imm<Sigma>())
return std::ranges::all_of(sig->ops(), [](Ref op) { return op->isa<Nat>(); });
22const Def* infer_sigma(World& world,
Defs ops) {
24 for (
size_t i = 0, e = ops.size(); i != e; ++i) elems[i] = ops[i]->type();
25 return world.sigma(elems);
33#if (!defined(_MSC_VER) && defined(NDEBUG))
34bool World::Lock::guard_ =
false;
56 data_.lit_bool[0] =
lit_idx(2, 0_u64);
57 data_.lit_bool[1] =
lit_idx(2, 1_u64);
66 for (
auto def : move_.defs) def->~Def();
84 if (
driver().is_loaded(plugin)) {
96 error(level->
loc(),
"argument `{}` to `Type` must be of type `Univ` but is of type `{}`", level, level->
type());
98 return unify<Type>(1, level)->as<
Type>();
103 error(op->
loc(),
"operand '{}' of a universe increment must be of type `Univ` but is of type `{}`", op,
107 return unify<UInc>(1, op, offset);
114 if (
auto um = op->isa<
UMax>())
115 ops.insert(ops.end(), um->ops().begin(), um->ops().end());
117 ops.emplace_back(op);
120 for (
auto& op : ops) {
128 error(r->loc(),
"operand '{}' must be a Type of some level", r);
131 if (!r->type()->isa<
Univ>())
132 error(r->loc(),
"operand '{}' of a universe max must be of type 'Univ' but is of type '{}'", r, r->type());
137 lvl = std::max(lvl, *l);
146 std::ranges::sort(ops, [](
auto op1,
auto op2) {
return op1->gid() < op2->gid(); });
147 ops.erase(std::unique(ops.begin(), ops.end()), ops.end());
148 ldef = unify<UMax>(ops.size(), *
this, ops);
161 if (
auto var = mut->var_)
return var;
162 return mut->var_ = unify<Var>(1,
type, mut);
166 while (
auto pi = callee->
type()->isa<
Pi>()) {
169 auto a =
app(callee, infer);
173 if (
auto app = callee->isa<
App>();
app &&
app->curry() == 1) {
176 callee = apps.front()->callee();
183 return app(callee, arg);
188 auto pi = callee->
type()->isa<
Pi>();
192 .
error(callee->
loc(),
"called expression not of function type")
193 .
error(callee->
loc(),
"'{}' <--- callee type", callee->
type());
197 .
error(arg->
loc(),
"cannot apply argument to callee")
198 .
note(callee->
loc(),
"callee: '{}'", callee)
199 .
note(arg->
loc(),
"argument: '{}'", arg)
200 .
note(callee->
loc(),
"vvv domain type vvv\n'{}'\n'{}'",
pi->
dom(), arg->
type())
201 .
note(arg->
loc(),
"^^^ argument type ^^^");
204 if (
auto imm = callee->
isa_imm<
Lam>())
return imm->body();
208 DLOG(
"partial evaluate: {} ({})",
lam, arg);
220 curry = curry == 0 ? trip : curry;
223 if (
auto normalize =
axiom->
normalizer(); Normalize && normalize && curry == 0)
224 return normalize(
type, callee, arg);
227 return unify<App>(2,
axiom, curry, trip,
type, callee, arg);
232 if (n == 0)
return sigma();
233 if (n == 1)
return ops[0];
235 return unify<Sigma>(ops.size(),
Sigma::infer(*
this, ops), ops);
239 if (ops.size() == 1)
return ops[0];
241 auto sigma = infer_sigma(*
this, ops);
244 error(t->loc(),
"cannot assign tuple '{}' of type '{}' to incompatible tuple type '{}'", t, t->type(),
sigma);
254 if (n == 0)
return tuple();
255 if (n == 1)
return ops[0];
262 if (
auto extract = ops[0]->isa<Extract>()) {
265 for (
size_t i = 0; i != n && eta; ++i) {
266 if (
auto extract = ops[i]->isa<Extract>()) {
268 if (eta &=
u64(i) == *index) {
269 eta &=
extract->tuple() == tup;
281 return unify<Tuple>(ops.size(),
type, ops);
286 std::ranges::transform(
sym, std::back_inserter(defs), [
this](
auto c) {
return lit_i8(c); });
292 if (index->isa<
Tuple>()) {
294 auto idx =
DefVec(n, [&](
size_t i) {
return index->
op(i); });
295 auto ops =
DefVec(n, [&](
size_t i) {
return d->proj(n,
Lit::as(idx[i])); });
297 }
else if (index->isa<
Pack>()) {
298 auto ops =
DefVec(index->
as_lit_arity(), [&](
size_t) { return extract(d, index->ops().back()); });
305 if (
auto l =
Lit::isa(size); l && *l == 1) {
306 if (
auto l =
Lit::isa(index); !l || *l != 0)
WLOG(
"unknown Idx of size 1: {}", index);
314 if (
auto pack = d->isa_imm<
Pack>())
return pack->body();
317 error(index->
loc(),
"index '{}' does not fit within arity '{}'", index,
type->
arity());
335 return unify<Extract>(2, t, d, index);
338 return unify<Extract>(2,
sigma->
op(*i), d, index);
349 return unify<Extract>(2, elem_t, d, index);
353 auto type = d->unfold_type();
358 error(index->
loc(),
"index '{}' does not fit within arity '{}'", index,
type->
arity());
364 .
error(val->
loc(),
"value to be inserted not assignable to element")
365 .
note(val->
loc(),
"vvv value type vvv \n'{}'\n'{}'", val->
type(), elem_type)
366 .
note(val->
loc(),
"^^^ element type ^^^", elem_type);
370 if (
auto l =
Lit::isa(size); l && *l == 1)
371 return tuple(d, {val});
374 if (
auto t = d->isa<
Tuple>(); t && lidx)
return t->refine(*lidx, val);
380 new_ops[*lidx] = val;
390 return unify<Insert>(3, d, index, val);
395 if (!is_shape(shape->type()))
error(shape->loc(),
"expected shape but got '{}' of type '{}'", shape, shape->type());
398 if (*a == 0)
return sigma();
399 if (*a == 1)
return body;
403 if (
auto ex = shape->isa<
Extract>()) {
404 if (
auto tup = ex->tuple()->isa<
Tuple>()) {
405 auto arrs =
DefVec(tup->num_ops(), [&](
size_t i) { return arr(tup->op(i), body); });
414 if (
auto p = shape->isa<
Pack>()) {
415 if (
auto s =
Lit::isa(p->shape()))
return arr(*s,
arr(
pack(*s - 1, p->body()), body));
418 return unify<Arr>(2, body->
unfold_type(), shape, body);
422 if (!is_shape(shape->type()))
error(shape->loc(),
"expected shape but got '{}' of type '{}'", shape, shape->type());
425 if (*a == 0)
return tuple();
426 if (*a == 1)
return body;
433 if (
auto p = shape->isa<
Pack>()) {
438 return unify<Pack>(1,
type, body);
442 if (shape.empty())
return body;
443 return arr(shape.rsubspan(1),
arr(shape.back(), body));
447 if (shape.empty())
return body;
448 return pack(shape.rsubspan(1),
pack(shape.back(), body));
454 if (*s != 0 && val >= *s)
error(
type->
loc(),
"index '{}' does not fit within arity '{}'", size, val);
455 }
else if (val != 0) {
456 error(
type->
loc(),
"cannot create literal '{}' of 'Idx {}' as size is unknown", val, size);
460 return unify<Lit>(0,
type, val);
471 return unify<TExt<Up>>(0,
type);
478 if (std::ranges::any_of(ops, [&](
Ref op) {
return Up ? bool(op->isa<
Top>()) : bool(op->isa<
Bot>()); }))
482 DefVec cpy(ops.begin(), ops.end());
483 auto [_, end] = std::ranges::copy_if(ops, cpy.begin(), [&](
Ref op) { return !op->isa<Ext>(); });
487 end = std::unique(cpy.begin(), end);
488 cpy.resize(std::distance(cpy.begin(), end));
490 if (cpy.size() == 0)
return ext<!Up>(kind);
491 if (cpy.size() == 1)
return cpy[0];
495 return unify<TBound<Up>>(cpy.size(), kind, cpy);
500 auto types =
DefVec(ops.size(), [&](
size_t i) { return ops[i]->type(); });
501 return unify<Ac>(ops.size(),
meet(types), ops);
504 assert(ops.size() == 1);
511 if (
type->isa<
Join>())
return unify<Vel>(1,
type, value);
519 auto c_pi = clash->
type()->isa<
Pi>();
522 assert(m_pi && c_pi);
523 auto a = m_pi->dom()->isa_lit_arity();
524 assert_unused(a && *a == 2);
527 auto codom =
join({m_pi->codom(), c_pi->
codom()});
528 return unify<Test>(4,
pi(c_pi->
dom(), codom), value, probe,
match, clash);
534 auto name = symbol.str();
536 auto pos =
name.find(suffix);
537 if (pos != std::string::npos) {
538 auto num =
name.substr(pos + suffix.size());
543 num = std::to_string(std::stoi(num) + 1);
544 name =
name.substr(0, pos + suffix.size()) +
"_" + num;
557#ifdef MIM_ENABLE_CHECKS
562 auto i = std::ranges::find_if(move_.defs, [=](
auto def) { return def->gid() == gid; });
563 if (i == move_.defs.end())
return nullptr;
568 for (
auto [_, mut] :
externals()) assert(mut->is_closed() && mut->is_set());
A (possibly paramterized) Array.
NormalizeFn normalizer() const
static std::tuple< const Axiom *, u8, u8 > get(const Def *def)
Yields currying counter of def.
static constexpr u8 Trip_End
static bool alpha(Ref d1, Ref d2)
Are d1 and d2 α-equivalent?
static bool assignable(Ref type, Ref value)
Can value be assigned to sth of type?
static Ref is_uniform(Defs defs)
Yields defs.front(), if all defs are Check::alpha-equivalent (infer = false) and nullptr otherwise.
bool is_set() const
Yields true if empty or the last op is set.
const Def * proj(nat_t a, nat_t i) const
Similar to World::extract while assuming an arity of a, but also works on Sigmas and Arrays.
const Def * op(size_t i) const
nat_t as_lit_arity() const
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
DefVec reduce(const Def *arg) const
Rewrites Def::ops by substituting this mutable's Var with arg.
const Def * unfold_type() const
Yields the type of this Def and builds a new Type (UInc n) if necessary.
Ref var(nat_t a, nat_t i)
std::optional< nat_t > isa_lit_arity() const
const T * isa_imm() const
bool is_closed() const
Has no free_vars()?
Some "global" variables needed all over the place.
Error & error(Loc loc, const char *s, Args &&... args)
Error & note(Loc loc, const char *s, Args &&... args)
static Ref size(Ref def)
Checks if def is a Idx s and returns s or nullptr otherwise.
static bool eliminate(Vector< Ref * >)
Eliminate Infers that may have been resolved in the meantime by rebuilding.
Creates a new Tuple / Pack by inserting Insert::value at position Insert::index into Insert::tuple.
Lam * set(Filter filter, const Def *body)
static std::optional< T > isa(Ref def)
Facility to log what you are doing.
A (possibly paramterized) Tuple.
A dependent function type.
Helper class to retrieve Infer::arg if present.
static const Def * refer(const Def *def)
Retrieves Infer::arg from def.
static Ref infer(World &, Defs)
This is a thin wrapper for std::span<T, N> with the following additional features:
Specific Bound depending on Up.
Extremum. Either Top (Up) or Bottom.
Data constructor for a Sigma.
const Def * level() const
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Lit * lit_idx(nat_t size, u64 val)
Constructs a Lit of type Idx of size size.
Infer * mut_infer(Ref type)
Ref gid2def(u32 gid)
Lookup Def by gid.
const Driver & driver() const
World(Driver *)
Inherits the state into the new World.
const auto & annexes() const
Ref iapp(Ref callee, Ref arg)
Ref test(Ref value, Ref probe, Ref match, Ref clash)
World & verify()
Verifies that all externals() and annexes() are Def::is_closed(), if MIM_ENABLE_CHECKS.
const auto & externals() const
Ref insert(Ref d, Ref i, Ref val)
Sigma * mut_sigma(Ref type, size_t size)
Ref var(Ref type, Def *mut)
Ref arr(Ref shape, Ref body)
Flags & flags()
Retrive compile Flags.
Ref app(Ref callee, Ref arg)
Ref ac(Ref type, Defs ops)
Sym sym(std::string_view)
const Pi * pi(Ref dom, Ref codom, bool implicit=false)
Sym append_suffix(Sym name, std::string suffix)
Appends a suffix or an increasing number if the suffix already exists.
Ref pack(Ref arity, Ref body)
const Lit * lit_univ(u64 level)
Ref pick(Ref type, Ref value)
const Tuple * tuple()
the unit value of type []
Ref extract(Ref d, Ref i)
const Lit * lit(Ref type, u64 val)
Ref vel(Ref type, Ref value)
const Sigma * sigma()
The unit type within Type 0.
const Lit * lit_nat(nat_t a)
const Axiom * axiom(NormalizeFn n, u8 curry, u8 trip, Ref type, plugin_t p, tag_t t, sub_t s)
const Def * register_annex(flags_t f, const Def *)
Ref raw_app(Ref type, Ref callee, Ref arg)
void breakpoint(u32 gid)
Trigger breakpoint in your debugger when creating Def with Def::gid gid.
Ref uinc(Ref op, level_t offset=1)
Ref singleton(Ref inner_type)
const Lam * lam(const Pi *pi, Lam::Filter f, Ref body)
Lam * mut_lam(const Pi *pi)
const Def * annex()
Get Axiom from a plugin.
#define DLOG(...)
Vaporizes to nothingness in Debug build.
Vector< const Def * > DefVec
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
void error(Loc loc, const char *f, Args &&... args)
std::deque< const App * > decurry(const Def *)
Yields curried Apps in a flat std::deque<const App*>.
Compiler switches that must be saved and looked up in later phases of compilation.
static Sym demangle(Driver &, plugin_t plugin)
Reverts an Axiom::mangled string to a Sym.
absl::flat_hash_set< uint32_t > breakpoints