/* Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #include "library/vm/vm_name.h" #include "library/vm/vm_nat.h" #include "library/vm/vm_level.h" #include "library/vm/vm_expr.h" #include "library/vm/vm_list.h" namespace lean { template struct vm_list : public vm_external { list m_val; vm_list(list const & v):m_val(v) {} virtual ~vm_list() {} virtual void dealloc() override { this->~vm_list(); get_vm_allocator().deallocate(sizeof(vm_list), this); } virtual vm_external * ts_clone(vm_clone_fn const &) override { return new vm_list(m_val); } virtual vm_external * clone(vm_clone_fn const &) override { return new (get_vm_allocator().allocate(sizeof(vm_list))) vm_list(m_val); } }; template vm_obj list_to_obj(list const & l) { return mk_vm_external(new (get_vm_allocator().allocate(sizeof(vm_list))) vm_list(l)); } vm_obj to_obj(list const & ls) { return list_to_obj(ls); } vm_obj to_obj(list const & ls) { return list_to_obj(ls); } vm_obj to_obj(list const & ls) { return list_to_obj(ls); } vm_obj to_obj(list> const & ls) { return list_to_obj(ls); } vm_obj to_obj(buffer const & ls) { return to_obj(to_list(ls)); } vm_obj to_obj(buffer const & ls) { return to_obj(to_list(ls)); } vm_obj to_obj(buffer const & ls) { return to_obj(to_list(ls)); } #define MK_TO_LIST(A, ToA) \ list to_list_ ## A(vm_obj const & o) { \ if (is_simple(o)) { \ return list(); \ } else if (is_constructor(o)) { \ return list(ToA(cfield(o, 0)), to_list_ ## A(cfield(o, 1))); \ } else { \ lean_vm_check(dynamic_cast*>(to_external(o))); \ return static_cast*>(to_external(o))->m_val; \ } \ } MK_TO_LIST(name, to_name) MK_TO_LIST(level, to_level) MK_TO_LIST(expr, to_expr) #define MK_TO_BUFFER(A, ToA) \ void to_buffer_ ## A(vm_obj const & o, buffer & r) { \ if (is_simple(o)) { \ return; \ } else if (is_constructor(o)) { \ r.push_back(ToA(cfield(o, 0))); \ to_buffer_ ## A(cfield(o, 1), r); \ } else { \ lean_vm_check(dynamic_cast*>(to_external(o))); \ to_buffer(static_cast*>(to_external(o))->m_val, r); \ } \ } MK_TO_BUFFER(name, to_name) MK_TO_BUFFER(level, to_level) MK_TO_BUFFER(expr, to_expr) template unsigned list_cases_on_core(list const & l, buffer & data) { if (empty(l)) { return 0; } else { data.push_back(to_obj(head(l))); data.push_back(list_to_obj(tail(l))); return 1; } } unsigned list_cases_on(vm_obj const & o, buffer & data) { if (is_simple(o)) { return 0; } else if (is_constructor(o)) { data.append(csize(o), cfields(o)); return 1; } else { if (auto l = dynamic_cast*>(to_external(o))) { return list_cases_on_core(l->m_val, data); } else if (auto l = dynamic_cast*>(to_external(o))) { return list_cases_on_core(l->m_val, data); } else if (auto l = dynamic_cast*>(to_external(o))) { return list_cases_on_core(l->m_val, data); } else { lean_unreachable(); } } } vm_obj to_obj(list const & ls) { return to_vm_list(ls, [&](unsigned n) { return mk_vm_nat(n); }); } vm_obj to_obj(buffer const & ls) { vm_obj obj = mk_vm_nil(); for (unsigned i = ls.size(); i > 0; i--) obj = mk_vm_cons(ls[i - 1], obj); return obj; } void initialize_vm_list() { DECLARE_VM_CASES_BUILTIN(name({"list", "cases_on"}), list_cases_on); } void finalize_vm_list() { } }