#+property: tangle jojo.cpp
#+title: jojo
* [note]
*** improving point
- no data_cons -- null fields
- non-full type name in method definition -- misleading
- no (.method obj) syntax
- no class method
- no letrec
* prolog
*** include
#+begin_src cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <functional>
#include <cassert>
#include <memory>
#include <vector>
#include <array>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <filesystem>
#+end_src
*** about namespace
#+begin_src cpp
using namespace std;
namespace fs = filesystem;
#+end_src
* datatype
*** forward declaration
#+begin_src cpp
struct obj_t;
struct jo_t;
struct env_t;
struct box_t;
struct jojo_t;
struct frame_t;
#+end_src
*** datatype
#+begin_src cpp
using name_t = string;
using tag_t = size_t;
using tag_vector_t = vector <tag_t>;
using name_vector_t = vector <name_t>;
using name_stack_t = stack <name_t>;
using bind_t = pair <name_t, shared_ptr <obj_t>>;
using bind_vector_t = vector <bind_t>; // index from end
using scope_t = vector <bind_vector_t>; // index from end
using jo_vector_t = vector <jo_t *>;
using obj_map_t = map <name_t, shared_ptr <obj_t>>;
using obj_vector_t = vector <shared_ptr <obj_t>>;
using box_map_t = map <name_t, box_t *>;
using obj_stack_t = stack <shared_ptr <obj_t>>;
using frame_stack_t = stack <shared_ptr <frame_t>>;
using jojo_map_t = map <tag_t, shared_ptr <jojo_t>>;
using string_vector_t = vector <string> ;
using local_ref_t = pair <size_t, size_t>;
using static_scope_t = map <name_t, local_ref_t>;
using path_t = fs::path;
using num_t = double;
using tagged_box_t = pair <name_t, box_t *>;
using tagged_box_vector_t = vector <tagged_box_t>;
using tag_map_t = map <name_t, tag_t>;
using symbol = string;
#+end_src
*** obj_t
#+begin_src cpp
struct obj_t
{
tag_t tag;
obj_map_t obj_map;
virtual ~obj_t ();
virtual string repr (env_t &env);
virtual void print (env_t &env);
virtual bool eq (shared_ptr <obj_t> obj);
virtual void apply (env_t &env, size_t arity);
virtual void apply_to_arg_dict (env_t &env);
};
#+end_src
*** jo_t
#+begin_src cpp
struct jo_t
{
virtual jo_t * copy ();
virtual ~jo_t ();
virtual void exe (env_t &env, scope_t &scope);
virtual string repr (env_t &env);
};
#+end_src
*** env_t
#+begin_src cpp
struct env_t
{
box_map_t box_map;
obj_stack_t obj_stack;
frame_stack_t frame_stack;
tagged_box_vector_t tagged_box_vector;
tag_map_t tag_map;
path_t current_dir;
path_t module_path;
env_t ();
void step ();
void run ();
void box_map_report ();
void frame_stack_report ();
void obj_stack_report ();
void report ();
void run_with_base (size_t base);
void double_report ();
void step_and_report ();
};
#+end_src
*** box_t
- box will be used as shared raw pointer.
- the consequence is module reload is not allowed.
#+begin_src cpp
struct box_t
{
shared_ptr <obj_t> obj;
bool empty_p;
box_t ();
};
#+end_src
*** jojo_t
#+begin_src cpp
struct jojo_t
{
jo_vector_t jo_vector;
jojo_t (jo_vector_t jo_vector);
~jojo_t ();
};
#+end_src
*** frame_t
#+begin_src cpp
struct frame_t
{
size_t index;
shared_ptr <jojo_t> jojo;
scope_t scope;
frame_t (shared_ptr <jojo_t> jojo, scope_t scope);
};
#+end_src
* utility
*** string
***** string_split
#+begin_src cpp
template <typename Out>
void
string_split (const string &s, char delim, Out result)
{
stringstream ss (s);
string item;
while (getline (ss, item, delim)) {
*(result++) = item;
}
}
vector <string>
string_split (const string &s, char delim)
{
vector <string> elems;
string_split (s, delim, back_inserter (elems));
return elems;
}
#+end_src
***** string_vector_join
#+begin_src cpp
string
string_vector_join (string_vector_t string_vector, char c)
{
string str = "";
for (auto s: string_vector) {
str += s;
str += c;
}
if (! str.empty ()) str.pop_back ();
return str;
}
#+end_src
*** vector
***** vector_rest
#+begin_src cpp
template <typename T>
vector <T>
vector_rest (vector <T> v)
{
auto size = v.size ();
assert (size >= 1);
vector <T> result = {};
for (auto it = v.begin () + 1;
it != v.end ();
it++) {
auto obj = *it;
result.push_back (obj);
}
return result;
}
#+end_src
*** name_vector
***** name_vector_repr
#+begin_src cpp
string
name_vector_repr (name_vector_t &name_vector)
{
if (name_vector.size () == 0) {
string repr = "[";
repr += "]";
return repr;
} else {
string repr = "[";
for (auto name: name_vector) {
repr += name;
repr += " ";
}
if (! repr.empty ()) repr.pop_back ();
repr += "]";
return repr;
}
}
#+end_src
*** bind
***** bind_eq
#+begin_src cpp
bool
bind_eq (
bind_t &lhs,
bind_t &rhs)
{
if (lhs.first != rhs.first) return false;
return lhs.second->eq (rhs.second);
}
#+end_src
*** bind_vector
***** bind_vector_repr
#+begin_src cpp
string
bind_vector_repr (
env_t &env,
bind_vector_t bind_vector)
{
string repr = "";
for (auto it = bind_vector.rbegin ();
it != bind_vector.rend ();
it++) {
repr += "(";
repr += to_string (distance (bind_vector.rbegin (), it));
repr += " ";
repr += it->first;
repr += " = ";
auto obj = it->second;
if (obj == nullptr) {
repr += "_";
} else {
repr += obj->repr (env);
}
repr += ") ";
}
return repr;
}
#+end_src
***** number_of_obj_in_bind_vector
#+begin_src cpp
size_t
number_of_obj_in_bind_vector (bind_vector_t &bind_vector)
{
size_t sum = 0;
auto begin = bind_vector.begin ();
auto end = bind_vector.end ();
for (auto it = begin; it != end; it++)
if (it->second)
sum++;
return sum;
}
#+end_src
***** bind_vector_insert_obj
#+begin_src cpp
void
bind_vector_insert_obj (
env_t &env,
bind_vector_t &bind_vector,
shared_ptr <obj_t> obj)
{
auto begin = bind_vector.rbegin ();
auto end = bind_vector.rend ();
for (auto it = begin; it != end; it++) {
if (it->second == nullptr) {
it->second = obj;
return;
}
}
cout << "- fatal error : bind_vector_insert_obj" << "\n";
cout << " the bind_vector is filled" << "\n";
exit (1);
}
#+end_src
***** bind_vector_merge_obj_vector
#+begin_src cpp
bind_vector_t
bind_vector_merge_obj_vector (
env_t &env,
bind_vector_t &old_bind_vector,
obj_vector_t &obj_vector)
{
auto bind_vector = old_bind_vector;
for (auto obj: obj_vector)
bind_vector_insert_obj (env, bind_vector, obj);
return bind_vector;
}
#+end_src
***** bind_vector_insert_obj_with_name
#+begin_src cpp
void
bind_vector_insert_obj_with_name (
env_t &env,
bind_vector_t &bind_vector,
shared_ptr <obj_t> obj,
name_t name)
{
auto begin = bind_vector.rbegin ();
auto end = bind_vector.rend ();
for (auto it = begin; it != end; it++) {
if (it->first == name) {
it->second = obj;
return;
}
}
cout << "- fatal error : bind_vector_insert_obj_with_name" << "\n";
cout << " name not found in the bind_vector" << "\n";
cout << " name : " << name << "\n";
cout << " bind_vector : "
<< bind_vector_repr (env, bind_vector) << "\n";
exit (1);
}
#+end_src
***** bind_vector_merge_obj_map
#+begin_src cpp
bind_vector_t
bind_vector_merge_obj_map (
env_t &env,
bind_vector_t &old_bind_vector,
obj_map_t &obj_map)
{
auto bind_vector = old_bind_vector;
for (auto &kv: obj_map) {
auto name = kv.first;
auto obj = kv.second;
bind_vector_insert_obj_with_name (
env,
bind_vector,
obj,
name);
}
return bind_vector;
}
#+end_src
***** bind_vector_from_name_vector
#+begin_src cpp
bind_vector_t
bind_vector_from_name_vector (name_vector_t &name_vector)
{
auto bind_vector = bind_vector_t ();
auto begin = name_vector.rbegin ();
auto end = name_vector.rend ();
for (auto it = begin; it != end; it++)
bind_vector.push_back (make_pair (*it, nullptr));
return bind_vector;
}
#+end_src
***** bind_vector_eq
#+begin_src cpp
bool
bind_vector_eq (
bind_vector_t &lhs,
bind_vector_t &rhs)
{
if (lhs.size () != rhs.size ()) return false;
auto size = lhs.size ();
size_t index = 0;
while (index < size) {
if (! bind_eq (lhs [index], rhs [index]))
return false;
index++;
}
return true;
}
#+end_src
*** obj_vector
***** pick_up_obj_vector
#+begin_src cpp
obj_vector_t
pick_up_obj_vector (env_t &env, size_t counter)
{
auto obj_vector = obj_vector_t ();
while (counter > 0) {
counter--;
auto obj = env.obj_stack.top ();
obj_vector.push_back (obj);
env.obj_stack.pop ();
}
reverse (obj_vector.begin (),
obj_vector.end ());
return obj_vector;
}
#+end_src
*** scope
***** scope_eq
#+begin_src cpp
bool
scope_eq (
scope_t &lhs,
scope_t &rhs)
{
if (lhs.size () != rhs.size ()) return false;
auto size = lhs.size ();
size_t index = 0;
while (index < size) {
if (! bind_vector_eq (lhs [index], rhs [index]))
return false;
index++;
}
return true;
}
#+end_src
***** scope_extend
#+begin_src cpp
scope_t
scope_extend (
scope_t old_scope,
bind_vector_t bind_vector)
{
auto scope = old_scope;
scope.push_back (bind_vector);
return scope;
}
#+end_src
***** scope_repr
#+begin_src cpp
string
scope_repr (env_t &env, scope_t scope)
{
string repr = "";
repr += " - [";
repr += to_string (scope.size ());
repr += "] ";
repr += "scope - ";
repr += "\n";
for (auto it = scope.rbegin ();
it != scope.rend ();
it++) {
repr += " ";
repr += to_string (distance (scope.rbegin (), it));
repr += " ";
repr += bind_vector_repr (env, *it);
repr += "\n";
}
return repr;
}
#+end_src
*** obj_map
***** obj_map_eq
#+begin_src cpp
bool
obj_map_eq (obj_map_t &lhs, obj_map_t &rhs)
{
if (lhs.size () != rhs.size ()) return false;
for (auto &kv: lhs) {
auto name = kv.first;
auto it = rhs.find (name);
if (it == rhs.end ()) return false;
if (! kv.second->eq (it->second)) return false;
}
return true;
}
#+end_src
***** obj_map_repr
#+begin_src cpp
string
obj_map_repr (env_t &env, obj_map_t &obj_map)
{
string repr = "";
for (auto &kv: obj_map) {
auto name = kv.first;
repr += name;
repr += " = ";
auto obj = kv.second;
repr += obj->repr (env);
repr += " ";
}
if (! repr.empty ()) repr.pop_back ();
return repr;
}
#+end_src
***** name_vector_obj_map_lack
#+begin_src cpp
name_vector_t
name_vector_obj_map_lack (
name_vector_t &old_name_vector,
obj_map_t &obj_map)
{
auto name_vector = name_vector_t ();
for (auto name: old_name_vector) {
auto it = obj_map.find (name);
// not found == lack
if (it == obj_map.end ())
name_vector.push_back (name);
}
return name_vector;
}
#+end_src
***** name_vector_obj_map_arity_lack
#+begin_src cpp
name_vector_t
name_vector_obj_map_arity_lack (
name_vector_t &old_name_vector,
obj_map_t &obj_map,
size_t arity)
{
auto name_vector = name_vector_obj_map_lack
(old_name_vector, obj_map);
auto lack = name_vector.size ();
auto counter = lack - arity;
while (counter > 0) {
counter--;
name_vector.pop_back ();
}
return name_vector;
}
#+end_src
***** pick_up_obj_map_and_merge
#+begin_src cpp
obj_map_t
pick_up_obj_map_and_merge (
env_t &env,
name_vector_t &lack_name_vector,
obj_map_t &old_obj_map)
{
auto obj_map = old_obj_map;
auto begin = lack_name_vector.rbegin ();
auto end = lack_name_vector.rend ();
for (auto it = begin; it != end; it++) {
name_t name = *it;
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
obj_map [name] = obj;
}
return obj_map;
}
#+end_src
***** name_vector_and_obj_map_repr
#+begin_src cpp
string
name_vector_and_obj_map_repr (
env_t &env,
name_vector_t &name_vector,
obj_map_t &obj_map)
{
string repr = "";
for (auto &name: name_vector) {
auto it = obj_map.find (name);
if (it == obj_map.end ()) {
repr += name;
repr += " = _ ";
}
}
for (auto &kv: obj_map) {
auto name = kv.first;
repr += name;
repr += " = ";
auto obj = kv.second;
repr += obj->repr (env);
repr += " ";
}
if (! repr.empty ()) repr.pop_back ();
return repr;
}
#+end_src
***** obj_map_merge
#+begin_src cpp
obj_map_t
obj_map_merge (
env_t &env,
obj_map_t &ante,
obj_map_t &succ)
{
auto obj_map = obj_map_t ();
for (auto &kv: ante) {
auto name = kv.first;
auto obj = kv.second;
obj_map [name] = obj;
}
for (auto &kv: succ) {
auto name = kv.first;
auto obj = kv.second;
obj_map [name] = obj;
}
return obj_map;
}
#+end_src
*** name
***** name_t2c
#+begin_src cpp
name_t
name_t2c (name_t type_name)
{
auto name = type_name;
auto size = name.size ();
assert (size > 2);
assert (name [size - 1] == 't');
assert (name [size - 2] == '-');
name.pop_back ();
name += 'c';
return name;
}
#+end_src
***** name_t2p
#+begin_src cpp
name_t
name_t2p (name_t type_name)
{
auto name = type_name;
auto size = name.size ();
assert (size > 2);
assert (name [size - 1] == 't');
assert (name [size - 2] == '-');
name.pop_back ();
name += 'p';
return name;
}
#+end_src
***** name_c2t
#+begin_src cpp
name_t
name_c2t (name_t data_name)
{
auto name = data_name;
auto size = name.size ();
assert (size > 2);
assert (name [size - 1] == 'c');
assert (name [size - 2] == '-');
name.pop_back ();
name += 't';
return name;
}
#+end_src
***** name_p2t
#+begin_src cpp
name_t
name_p2t (name_t pred_name)
{
auto name = pred_name;
auto size = name.size ();
assert (size > 2);
assert (name [size - 1] == 'p');
assert (name [size - 2] == '-');
name.pop_back ();
name += 't';
return name;
}
#+end_src
*** frame
***** new_frame_from_jojo
#+begin_src cpp
shared_ptr <frame_t>
new_frame_from_jojo (shared_ptr <jojo_t> jojo)
{
return make_shared <frame_t>
(jojo, scope_t ());
}
#+end_src
***** new_frame_from_jo_vector
#+begin_src cpp
shared_ptr <frame_t>
new_frame_from_jo_vector (jo_vector_t jo_vector)
{
auto jojo = make_shared <jojo_t> (jo_vector);
return make_shared <frame_t>
(jojo, scope_t ());
}
#+end_src
*** local_ref
***** static_scope_extend
#+begin_src cpp
static_scope_t
static_scope_extend (
env_t &env,
static_scope_t &old_static_scope,
name_vector_t &name_vector)
{
auto static_scope = static_scope_t ();
for (auto &kv: old_static_scope) {
auto name = kv.first;
auto old_local_ref = kv.second;
auto local_ref = local_ref_t ();
local_ref.first = old_local_ref.first + 1;
local_ref.second = old_local_ref.second;
static_scope [name] = local_ref;
}
size_t index = 0;
auto size = name_vector.size ();
while (index < size) {
auto name = name_vector [index];
auto local_ref = local_ref_t ();
local_ref.first = 0;
local_ref.second = index;
static_scope [name] = local_ref;
index++;
}
return static_scope;
}
#+end_src
*** assert
***** assert_pop_eq
#+begin_src cpp
void
assert_pop_eq (env_t &env, shared_ptr <obj_t> obj)
{
auto that = env.obj_stack.top ();
assert (obj->eq (that));
env.obj_stack.pop ();
}
#+end_src
***** assert_tos_eq
#+begin_src cpp
void
assert_tos_eq (env_t &env, shared_ptr <obj_t> obj)
{
auto that = env.obj_stack.top ();
assert (obj->eq (that));
}
#+end_src
***** assert_stack_size
#+begin_src cpp
void
assert_stack_size (env_t &env, size_t size)
{
assert (env.obj_stack.size () == size);
}
#+end_src
*** num
***** s2n
#+begin_src cpp
num_t s2n (string s)
{
return stod (s);
}
#+end_src
* obj
*** obj_t::~obj_t
#+begin_src cpp
obj_t::~obj_t ()
{
// all classes that will be derived from
// should have a virtual or protected destructor,
// otherwise deleting an instance via a pointer
// to a base class results in undefined behavior.
}
#+end_src
*** obj_t::repr
#+begin_src cpp
name_t
name_of_tag (env_t &env, tag_t tag);
string
obj_t::repr (env_t &env)
{
return "#<" + name_of_tag (env, this->tag) + ">";
}
#+end_src
*** obj_t::print
#+begin_src cpp
void
obj_t::print (env_t &env)
{
cout << this->repr (env) << flush;
}
#+end_src
*** obj_t::eq
#+begin_src cpp
bool
obj_t::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) {
return false;
} else {
cout << "- fatal error : obj_t::eq" << "\n";
cout << " eq is not implemented for : ";
cout << obj->tag << "\n";
exit (1);
}
}
#+end_src
*** obj_t::apply
#+begin_src cpp
void
obj_t::apply (env_t &env, size_t arity)
{
cout << "- fatal error : obj_t::apply" << "\n";
cout << " applying non applicable object" << "\n";
cout << " tag : " << name_of_tag (env, this->tag) << "\n";
cout << " obj : " << this->repr (env) << "\n";
exit (1);
}
#+end_src
*** obj_t::apply_to_arg_dict
#+begin_src cpp
void
obj_t::apply_to_arg_dict (env_t &env)
{
cout << "- fatal error : obj_t::apply_to_arg_dict" << "\n";
cout << " applying non applicable object" << "\n";
cout << " tag : " << name_of_tag (env, this->tag) << "\n";
cout << " obj : " << this->repr (env) << "\n";
exit (1);
}
#+end_src
*** define
#+begin_src cpp
box_t *
boxing (env_t &env, name_t name);
void
define (
env_t &env,
name_t name,
shared_ptr <obj_t> obj)
{
auto box = boxing (env, name);
box->obj = obj;
box->empty_p = false;
}
#+end_src
*** obj_eq
#+begin_src cpp
bool
obj_eq (
shared_ptr <obj_t> &lhs,
shared_ptr <obj_t> &rhs)
{
return lhs->eq (rhs);
}
#+end_src
*** find_obj_from_name
#+begin_src cpp
shared_ptr <obj_t>
find_obj_from_name (env_t &env, name_t name)
{
auto string_vector = string_split (name, '.');
assert (string_vector.size () > 0);
auto first_name = string_vector [0];
auto it = env.box_map.find (first_name);
if (it != env.box_map.end ()) {
auto box = it->second;
auto obj = box->obj;
for (auto sub_name: vector_rest (string_vector)) {
auto it = obj->obj_map.find (sub_name);
if (it != obj->obj_map.end ()) {
obj = it->second;
} else {
return nullptr;
}
}
return obj;
} else {
return nullptr;
}
}
#+end_src
* jo
*** jo_t::copy
#+begin_src cpp
jo_t *
jo_t::copy ()
{
cout << "- fatal error : jo_t::copy unknown jo" << "\n";
exit (1);
}
#+end_src
*** jo_t::~jo_t
#+begin_src cpp
jo_t::~jo_t ()
{
// all classes that will be derived from
// should have a virtual or protected destructor,
// otherwise deleting an instance via a pointer
// to a base class results in undefined behavior.
}
#+end_src
*** jo_t::exe
#+begin_src cpp
void
jo_t::exe (env_t &env, scope_t &scope)
{
cout << "- fatal error : unknown jo" << "\n";
exit (1);
}
#+end_src
*** jo_t::repr
#+begin_src cpp
string
jo_t::repr (env_t &env)
{
return "#<unknown-jo>";
}
#+end_src
* env
*** box
***** box_t::box_t
#+begin_src cpp
box_t::box_t ()
{
this->empty_p = true;
}
#+end_src
***** boxing
#+begin_src cpp
box_t *
boxing (env_t &env, name_t name)
{
auto it = env.box_map.find (name);
if (it != env.box_map.end ()) {
auto box = it->second;
return box;
} else {
auto box = new box_t ();
env.box_map [name] = box;
return box;
}
}
#+end_src
***** name_of_box
#+begin_src cpp
name_t
name_of_box (env_t &env, box_t *box)
{
for (auto &kv: env.box_map) {
auto name = kv.first;
if (kv.second == box) {
return name;
}
}
return "#non-name";
}
#+end_src
*** jojo
***** jojo_t::jojo_t
#+begin_src cpp
jojo_t::
jojo_t (jo_vector_t jo_vector)
{
this->jo_vector = jo_vector;
}
#+end_src
***** jojo_t::~jojo_t
#+begin_src cpp
jojo_t::
~jojo_t ()
{
for (jo_t *jo_ptr: this->jo_vector)
delete jo_ptr;
}
#+end_src
***** jojo_append
#+begin_src cpp
shared_ptr <jojo_t>
jojo_append (
shared_ptr <jojo_t> ante,
shared_ptr <jojo_t> succ)
{
auto jo_vector = jo_vector_t ();
for (auto x: ante->jo_vector) jo_vector.push_back (x->copy ());
for (auto x: succ->jo_vector) jo_vector.push_back (x->copy ());
return make_shared <jojo_t> (jo_vector);
}
#+end_src
***** jojo_repr
#+begin_src cpp
string
jojo_repr (
env_t &env,
shared_ptr <jojo_t> jojo)
{
assert (jojo->jo_vector.size () != 0);
string repr = "";
for (auto &jo: jojo->jo_vector) {
repr += jo->repr (env);
repr += " ";
}
repr.pop_back ();
return repr;
}
#+end_src
*** frame
***** frame_t::frame_t
#+begin_src cpp
frame_t::
frame_t (
shared_ptr <jojo_t> jojo,
scope_t scope)
{
this->index = 0;
this->jojo = jojo;
this->scope = scope;
}
#+end_src
***** jojo_print
#+begin_src cpp
void
jojo_print (env_t &env, shared_ptr <jojo_t> jojo)
{
for (auto &jo: jojo->jo_vector) {
cout << jo->repr (env) << " ";
}
}
#+end_src
***** jojo_print_with_index
#+begin_src cpp
void
jojo_print_with_index (
env_t &env,
shared_ptr <jojo_t> jojo,
size_t index)
{
for (auto it = jojo->jo_vector.begin ();
it != jojo->jo_vector.end ();
it++) {
size_t it_index = it - jojo->jo_vector.begin ();
jo_t *jo = *it;
if (index == it_index) {
cout << "->> " << jo->repr (env) << " ";
} else {
cout << jo->repr (env) << " ";
}
}
}
#+end_src
***** frame_report
#+begin_src cpp
void
frame_report (env_t &env, shared_ptr <frame_t> frame)
{
cout << " - [" << frame->index+1
<< "/" << frame->jojo->jo_vector.size ()
<< "] ";
jojo_print_with_index (env, frame->jojo, frame->index);
cout << "\n";
cout << scope_repr (env, frame->scope);
}
#+end_src
*** tag
***** tag_name_p
#+begin_src cpp
bool
tag_name_p (name_t name)
{
auto size = name.size ();
if (size < 3) return false;
if (name [size - 1] != 't') return false;
if (name [size - 2] != '-') return false;
return true;
}
#+end_src
***** tagging
#+begin_src cpp
tag_t
tagging (env_t &env, name_t name)
{
assert (tag_name_p (name));
auto it = env.tag_map.find (name);
if (it != env.tag_map.end ()) {
auto tag = it->second;
return tag;
} else {
auto tag = env.tagged_box_vector.size ();
env.tag_map [name] = tag;
auto box = boxing (env, name);
env.tagged_box_vector.push_back (make_pair (name, box));
return tag;
}
}
#+end_src
***** box_of_tag
#+begin_src cpp
box_t *
box_of_tag (env_t &env, tag_t tag)
{
if (tag >= env.tagged_box_vector.size ()) {
cout << "- fatal error : box_of_tag" << "\n"
<< " unknown tag : " << tag << "\n";
exit (1);
} else {
return env.tagged_box_vector [tag] .second;
}
}
#+end_src
***** name_of_tag
#+begin_src cpp
name_t
name_of_tag (env_t &env, tag_t tag)
{
if (tag >= env.tagged_box_vector.size ()) {
return "#<unknown-tag:" + to_string (tag) + ">";
} else {
return env.tagged_box_vector [tag] .first;
}
}
#+end_src
***** null_tagged_box
#+begin_src cpp
tagged_box_t null_tagged_box = make_pair ("", nullptr);
#+end_src
***** make_tagged_box_vector
#+begin_src cpp
tagged_box_vector_t
make_tagged_box_vector ()
{
auto tagged_box_vector = tagged_box_vector_t (64, null_tagged_box);
return tagged_box_vector;
}
#+end_src
***** preserved_tag
#+begin_src cpp
void
define_type (env_t &env, name_t name);
void
preserve_tag (env_t &env, tag_t tag, name_t name)
{
env.tag_map [name] = tag;
auto box = boxing (env, name);
env.tagged_box_vector [tag] = make_pair (name, box);
define_type (env, name);
}
#+end_src
***** about preserved tags
#+begin_src cpp
tag_t closure_tag = 0;
tag_t type_tag = 1;
tag_t true_tag = 2;
tag_t false_tag = 3;
tag_t data_cons_tag = 4;
tag_t prim_tag = 5;
tag_t num_tag = 6;
tag_t str_tag = 7;
tag_t null_tag = 8;
tag_t cons_tag = 9;
tag_t vect_tag = 10;
tag_t dict_tag = 11;
tag_t module_tag = 12;
tag_t keyword_tag = 13;
tag_t macro_tag = 14;
tag_t top_keyword_tag = 15;
tag_t sym_tag = 16;
tag_t nothing_tag = 17;
tag_t just_tag = 18;
#+end_src
***** init_tagged_box_vector
#+begin_src cpp
void
init_tagged_box_vector (env_t &env)
{
preserve_tag (env, closure_tag , "closure-t");
preserve_tag (env, type_tag , "type-t");
preserve_tag (env, true_tag , "true-t");
preserve_tag (env, false_tag , "false-t");
preserve_tag (env, data_cons_tag , "data-cons-t");
preserve_tag (env, prim_tag , "prim-t");
preserve_tag (env, num_tag , "num-t");
preserve_tag (env, str_tag , "str-t");
preserve_tag (env, null_tag , "null-t");
preserve_tag (env, cons_tag , "cons-t");
preserve_tag (env, vect_tag , "vect-t");
preserve_tag (env, dict_tag , "dict-t");
preserve_tag (env, module_tag , "module-t");
preserve_tag (env, keyword_tag , "keyword-t");
preserve_tag (env, macro_tag , "macro-t");
preserve_tag (env, top_keyword_tag , "top-keyword-t");
preserve_tag (env, sym_tag , "sym-t");
preserve_tag (env, nothing_tag , "nothing-t");
preserve_tag (env, just_tag , "just-t");
}
#+end_src
*** env_t::env_t
#+begin_src cpp
env_t::env_t ()
{
this->current_dir = fs::current_path ();
this->tagged_box_vector = make_tagged_box_vector ();
auto &env = *this;
init_tagged_box_vector (env);
}
#+end_src
*** env_t::step
#+begin_src cpp
void
env_t::step ()
{
auto frame = this->frame_stack.top ();
size_t size = frame->jojo->jo_vector.size ();
// it is assumed that jojo in frame are not empty
assert (size != 0);
size_t index = frame->index;
frame->index++;
// handle proper tail call
if (index+1 == size) this->frame_stack.pop ();
// since the last frame might be drop,
// we pass last scope as an extra argument.
frame->jojo->jo_vector[index]->exe (*this, frame->scope);
}
#+end_src
*** env_t::run
#+begin_src cpp
void
env_t::run ()
{
while (!this->frame_stack.empty ()) {
this->step ();
}
}
#+end_src
*** env_t::box_map_report
#+begin_src cpp
void
env_t::box_map_report ()
{
auto &env = *this;
cout << "- [" << env.box_map.size () << "] "
<< "box_map - " << "\n";
for (auto &kv: env.box_map) {
cout << " " << kv.first << " = ";
auto box = kv.second;
if (box->empty_p) {
cout << "_";
} else {
cout << box->obj->repr (env);
}
cout << "\n";
}
}
#+end_src
*** env_t::frame_stack_report
#+begin_src cpp
void
env_t::frame_stack_report ()
{
auto &env = *this;
cout << "- [" << env.frame_stack.size () << "] "
<< "frame_stack - " << "\n";
frame_stack_t frame_stack = env.frame_stack;
while (! frame_stack.empty ()) {
auto frame = frame_stack.top ();
frame_report (env, frame);
frame_stack.pop ();
}
}
#+end_src
*** env_t::obj_stack_report
#+begin_src cpp
void
env_t::obj_stack_report ()
{
auto &env = *this;
cout << "- [" << env.obj_stack.size () << "] "
<< "obj_stack - " << "\n";
auto obj_stack = env.obj_stack;
while (! obj_stack.empty ()) {
auto obj = obj_stack.top ();
cout << " ";
cout << obj->repr (env);
cout << "\n";
obj_stack.pop ();
}
}
#+end_src
*** env_t::report
#+begin_src cpp
void
env_t::report ()
{
this->box_map_report ();
this->frame_stack_report ();
this->obj_stack_report ();
}
#+end_src
*** env_t::run_with_base
#+begin_src cpp
void
env_t::run_with_base (size_t base)
{
while (this->frame_stack.size () > base) {
this->step ();
}
}
#+end_src
*** env_t::double_report
#+begin_src cpp
void
env_t::double_report ()
{
this->report ();
this->run ();
this->report ();
}
#+end_src
*** env_t::step_and_report
#+begin_src cpp
void
env_t::step_and_report ()
{
this->step ();
this->report ();
}
#+end_src
* closure
*** closure_o
#+begin_src cpp
struct closure_o: obj_t
{
name_vector_t name_vector;
shared_ptr <jojo_t> jojo;
bind_vector_t bind_vector;
scope_t scope;
closure_o (name_vector_t name_vector,
shared_ptr <jojo_t> jojo,
bind_vector_t bind_vector,
scope_t scope);
bool eq (shared_ptr <obj_t> obj);
void apply (env_t &env, size_t arity);
void apply_to_arg_dict (env_t &env);
string repr (env_t &env);
};
#+end_src
*** closure_o::closure_o
#+begin_src cpp
closure_o::
closure_o (
name_vector_t name_vector,
shared_ptr <jojo_t> jojo,
bind_vector_t bind_vector,
scope_t scope)
{
this->tag = closure_tag;
this->name_vector = name_vector;
this->jojo = jojo;
this->bind_vector = bind_vector;
this->scope = scope;
}
#+end_src
*** make_closure
#+begin_src cpp
shared_ptr <closure_o>
make_closure (
name_vector_t name_vector,
shared_ptr <jojo_t> jojo,
bind_vector_t bind_vector,
scope_t scope)
{
return make_shared <closure_o> (
name_vector,
jojo,
bind_vector,
scope);
}
#+end_src
*** closure_o::apply
#+begin_src cpp
void
closure_o::apply (env_t &env, size_t arity)
{
auto size = this->name_vector.size ();
auto have = number_of_obj_in_bind_vector (this->bind_vector);
auto lack = size - have;
if (arity > lack) {
cout << "- fatal error : closure_o::apply" << "\n";
cout << " over-arity apply" << "\n";
cout << " arity > lack" << "\n";
cout << " arity : " << arity << "\n";
cout << " lack : " << lack << "\n";
cout << " closure : " << this->repr (env) << "\n";
exit (1);
}
auto obj_vector = pick_up_obj_vector (env, arity);
auto bind_vector = bind_vector_merge_obj_vector (
env, this->bind_vector, obj_vector);
if (lack == arity) {
auto scope = scope_extend (
this->scope, bind_vector);
auto frame = make_shared <frame_t> (
this->jojo, scope);
env.frame_stack.push (frame);
} else {
assert (arity < lack);
auto closure = make_closure (
this->name_vector,
this->jojo,
bind_vector,
this->scope);
env.obj_stack.push (closure);
}
}
#+end_src
*** closure_o::eq
#+begin_src cpp
bool
closure_o::eq (shared_ptr <obj_t> obj)
{
// raw pointers must be eq first
if (this != obj.get ()) {
return false;
}
auto that = static_pointer_cast <closure_o> (obj);
if (scope_eq (this->scope, that->scope)) {
return false;
}
if (bind_vector_eq (
this->bind_vector,
that->bind_vector)) {
return false;
} else {
return true;
}
}
#+end_src
*** closure_p
#+begin_src cpp
bool
closure_p (shared_ptr <obj_t> a)
{
return a->tag == closure_tag;
}
#+end_src
*** closure_o::repr
#+begin_src cpp
string
closure_o::repr (env_t &env)
{
string repr = "(closure ";
repr += name_vector_repr (this->name_vector);
repr += " ";
repr += jojo_repr (env, this->jojo);
repr += "\n";
auto scope = this->scope;
scope.push_back (this->bind_vector);
repr += scope_repr (env, scope);
if (! repr.empty ()) repr.pop_back ();
if (! repr.empty ()) repr.pop_back ();
repr += ")";
return repr;
}
#+end_src
* type
*** type_o
#+begin_src cpp
struct type_o: obj_t
{
tag_t tag_of_type;
tag_vector_t super_tag_vector;
type_o (
tag_t tag_of_type,
tag_vector_t super_tag_vector,
obj_map_t obj_map);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** type_o::type_o
#+begin_src cpp
type_o::type_o (
tag_t tag_of_type,
tag_vector_t super_tag_vector,
obj_map_t obj_map)
{
this->tag = type_tag;
this->tag_of_type = tag_of_type;
this->super_tag_vector = super_tag_vector;
this->obj_map = obj_map;
}
#+end_src
*** make_type
#+begin_src cpp
shared_ptr <type_o>
make_type (
tag_t tag_of_type,
tag_vector_t super_tag_vector,
obj_map_t obj_map)
{
return make_shared <type_o> (
tag_of_type,
super_tag_vector,
obj_map);
}
#+end_src
*** as_type
#+begin_src cpp
shared_ptr <type_o>
as_type (shared_ptr <obj_t> obj)
{
return static_pointer_cast <type_o> (obj);
}
#+end_src
*** type_o::repr
#+begin_src cpp
string
type_o::repr (env_t &env)
{
return name_of_tag (env, this->tag_of_type);
}
#+end_src
*** type_o::eq
#+begin_src cpp
bool
type_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_type (obj);
if (this->tag_of_type != that->tag_of_type) return false;
return true;
}
#+end_src
*** find_type_from_prefix
#+begin_src cpp
shared_ptr <type_o>
find_type_from_prefix (env_t &env, name_t prefix)
{
auto string_vector = string_split (prefix, '.');
assert (string_vector.size () > 0);
auto top = string_vector [0];
auto it = env.box_map.find (top + "-t");
if (it != env.box_map.end ()) {
auto box = it->second;
if (box->empty_p) return nullptr;
auto obj = box->obj;
if (obj->tag != type_tag) return nullptr;
auto type = as_type (obj);
auto begin = string_vector.begin () + 1;
auto end = string_vector.end ();
for (auto it = begin; it != end; it++) {
auto field = *it;
field += "-t";
auto obj = type->obj_map [field];
if (obj->tag != type_tag) return nullptr;
type = as_type (obj);
}
return type;
}
return nullptr;
}
#+end_src
*** assign
#+begin_src cpp
void
assign (
env_t &env,
name_t prefix,
name_t name,
shared_ptr <obj_t> obj)
{
if (prefix == "") {
define (env, name, obj);
return;
}
auto type = find_type_from_prefix (env, prefix);
if (type) {
type->obj_map [name] = obj;
} else {
cout << "- fatal error : assign fail" << "\n";
cout << " unknown prefix : " << prefix << "\n";
exit (1);
}
}
#+end_src
*** assign_type
#+begin_src cpp
void
assign_type (
env_t &env,
name_t prefix,
name_t type_name,
tag_t tag_of_type,
tag_vector_t super_tag_vector)
{
auto type = make_type (
tag_of_type,
super_tag_vector,
obj_map_t ());
auto box = box_of_tag (env, tag_of_type);
box->obj = type;
box->empty_p = false;
assign (env, prefix, type_name, type);
}
#+end_src
*** define_type
#+begin_src cpp
void
define_type (env_t &env, name_t name)
{
auto type_name = name;
auto tag_of_type = tagging (env, name);
assign_type (env, "", type_name, tag_of_type, {});
}
#+end_src
*** type_of
#+begin_src cpp
shared_ptr <type_o>
type_of (env_t &env, shared_ptr <obj_t> obj)
{
auto box = box_of_tag (env, obj->tag);
assert (! box->empty_p);
return as_type (box->obj);
}
#+end_src
* data
*** data_o
#+begin_src cpp
struct data_o: obj_t, enable_shared_from_this <obj_t>
{
name_vector_t name_vector;
data_o (
tag_t tag,
name_vector_t name_vector,
obj_map_t obj_map);
void apply (env_t &env, size_t arity);
void apply_to_arg_dict (env_t &env);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** data_o::data_o
#+begin_src cpp
data_o::
data_o (
tag_t tag,
name_vector_t name_vector,
obj_map_t obj_map)
{
this->tag = tag;
this->name_vector = name_vector;
this->obj_map = obj_map;
}
#+end_src
*** make_data
#+begin_src cpp
shared_ptr <data_o>
make_data (
tag_t tag,
name_vector_t name_vector,
obj_map_t obj_map)
{
return make_shared <data_o> (
tag,
name_vector,
obj_map);
}
#+end_src
*** data_o::eq
#+begin_src cpp
bool
data_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = static_pointer_cast <data_o> (obj);
return obj_map_eq (this->obj_map, that->obj_map);
}
#+end_src
*** data_o::repr
#+begin_src cpp
string
sexp_repr (env_t &env, shared_ptr <obj_t> a);
string
data_o::repr (env_t &env)
{
if (this->tag == null_tag or
this->tag == cons_tag)
{
return sexp_repr (env, shared_from_this ());
} else if (this->obj_map.size () == 0) {
string repr = "";
repr += name_of_tag (env, this->tag);
repr.pop_back ();
repr.pop_back ();
repr += "-c";
return repr;
} else {
string repr = "(";
repr += name_of_tag (env, this->tag);
repr.pop_back ();
repr.pop_back ();
repr += "-c ";
repr += obj_map_repr (env, this->obj_map);
repr += ")";
return repr;
}
}
#+end_src
*** assign_data
#+begin_src cpp
void
assign_data (
env_t &env,
name_t prefix,
name_t data_name,
tag_t tag_of_type,
name_vector_t name_vector)
{
auto data = make_data (
tag_of_type,
name_vector,
obj_map_t ());
assign (env, prefix, data_name, data);
}
#+end_src
*** data_o::apply
#+begin_src cpp
void
data_o::apply (env_t &env, size_t arity)
{
auto size = this->name_vector.size ();
auto have = this->obj_map.size ();
auto lack = size - have;
auto lack_name_vector = name_vector_t ();
if (lack == arity) {
lack_name_vector = name_vector_obj_map_lack (
this->name_vector, this->obj_map);
} else if (arity < lack) {
lack_name_vector = name_vector_obj_map_arity_lack (
this->name_vector, this->obj_map, arity);
} else {
cout << "- fatal error : data_o::apply" << "\n";
cout << " over-arity apply" << "\n";
cout << " arity > lack" << "\n";
cout << " arity : " << arity << "\n";
cout << " lack : " << lack << "\n";
exit (1);
}
auto obj_map = pick_up_obj_map_and_merge (
env, lack_name_vector, this->obj_map);
auto data = make_data (
this->tag,
this->name_vector,
obj_map);
env.obj_stack.push (data);
}
#+end_src
* bool
*** true_c
#+begin_src cpp
shared_ptr <data_o>
true_c ()
{
return make_data (
true_tag,
name_vector_t (),
obj_map_t ());
}
#+end_src
*** true_p
#+begin_src cpp
bool
true_p (shared_ptr <obj_t> a)
{
return a->tag == true_tag;
}
#+end_src
*** false_c
#+begin_src cpp
shared_ptr <data_o>
false_c ()
{
return make_data (
false_tag,
name_vector_t (),
obj_map_t ());
}
#+end_src
*** false_p
#+begin_src cpp
bool
false_p (shared_ptr <obj_t> a)
{
return a->tag == false_tag;
}
#+end_src
*** make_bool
#+begin_src cpp
shared_ptr <data_o>
make_bool (bool b)
{
if (b) {
return true_c ();
} else {
return false_c ();
}
}
#+end_src
*** bool_p
#+begin_src cpp
bool
bool_p (shared_ptr <obj_t> a)
{
return true_p (a)
or false_p (a);
}
#+end_src
* prim
*** prim_fn
#+begin_src cpp
using prim_fn = function
<void (env_t &, obj_map_t &)>;
#+end_src
*** prim_o
#+begin_src cpp
struct prim_o: obj_t
{
name_vector_t name_vector;
prim_fn fn;
prim_o (
name_vector_t name_vector,
prim_fn fn,
obj_map_t obj_map);
bool eq (shared_ptr <obj_t> obj);
void apply (env_t &env, size_t arity);
void apply_to_arg_dict (env_t &env);
string repr (env_t &env);
};
#+end_src
*** prim_o::prim_o
#+begin_src cpp
prim_o::prim_o (
name_vector_t name_vector,
prim_fn fn,
obj_map_t obj_map)
{
this->tag = prim_tag;
this->name_vector = name_vector;
this->fn = fn;
this->obj_map = obj_map;
}
#+end_src
*** make_prim
#+begin_src cpp
shared_ptr <prim_o>
make_prim (
name_vector_t name_vector,
prim_fn fn,
obj_map_t obj_map)
{
return make_shared <prim_o> (
name_vector,
fn,
obj_map);
}
#+end_src
*** prim_p
#+begin_src cpp
bool
prim_p (shared_ptr <obj_t> a)
{
return a->tag == prim_tag;
}
#+end_src
*** prim_o::repr
#+begin_src cpp
string
prim_o::repr (env_t &env)
{
if (this->name_vector.size () == 0) {
string repr = "(prim)";
return repr;
} else {
string repr = "(prim ";
repr += name_vector_and_obj_map_repr
(env, this->name_vector, this->obj_map);
repr += ")";
return repr;
}
}
#+end_src
*** prim_o::eq
#+begin_src cpp
bool prim_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = static_pointer_cast <prim_o> (obj);
if (this != obj.get ()) return false;
return obj_map_eq (this->obj_map, that->obj_map);
}
#+end_src
*** prim_o::apply
#+begin_src cpp
void prim_o::apply (env_t &env, size_t arity)
{
auto size = this->name_vector.size ();
auto have = this->obj_map.size ();
auto lack = size - have;
if (lack == arity) {
auto lack_name_vector = name_vector_obj_map_lack (
this->name_vector, this->obj_map);
auto obj_map = pick_up_obj_map_and_merge (
env, lack_name_vector, this->obj_map);
this->fn (env, obj_map);
} else if (arity < lack) {
auto lack_name_vector = name_vector_obj_map_arity_lack (
this->name_vector, this->obj_map, arity);
auto obj_map = pick_up_obj_map_and_merge (
env, lack_name_vector, this->obj_map);
auto prim = make_prim (
this->name_vector,
this->fn,
obj_map);
env.obj_stack.push (prim);
} else {
cout << "- fatal error : prim_o::apply" << "\n";
cout << " over-arity apply" << "\n";
cout << " arity > lack" << "\n";
cout << " arity : " << arity << "\n";
cout << " lack : " << lack << "\n";
exit (1);
}
}
#+end_src
*** sig_t
#+begin_src cpp
using sig_t = name_vector_t;
#+end_src
*** name_of_sig
#+begin_src cpp
name_t
name_of_sig (sig_t &sig)
{
return sig [0];
}
#+end_src
*** name_vector_of_sig
#+begin_src cpp
name_vector_t
name_vector_of_sig (sig_t &sig)
{
auto name_vector = name_vector_t ();
auto begin = sig.begin () + 1;
auto end = sig.end ();
for (auto it = begin; it != end; it++) {
name_vector.push_back (*it);
}
return name_vector;
}
#+end_src
*** define_prim
#+begin_src cpp
void
define_prim (env_t &env, sig_t sig, prim_fn fn)
{
auto name = name_of_sig (sig);
auto name_vector = name_vector_of_sig (sig);
auto prim = make_prim (
name_vector, fn, obj_map_t ());
define (env, name, prim);
}
#+end_src
* num
*** num_o
#+begin_src cpp
struct num_o: obj_t
{
num_t num;
num_o (num_t num);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** num_o::num_o
#+begin_src cpp
num_o::num_o (num_t num)
{
this->tag = num_tag;
this->num = num;
}
#+end_src
*** make_num
#+begin_src cpp
shared_ptr <num_o>
make_num (num_t num)
{
return make_shared <num_o> (num);
}
#+end_src
*** num_o::repr
#+begin_src cpp
string
num_o::repr (env_t &env)
{
if (this->num == floor (this->num)) {
return to_string (static_cast <long long int> (this->num));
} else {
return to_string (this->num);
}
}
#+end_src
*** as_num
#+begin_src cpp
shared_ptr <num_o>
as_num (shared_ptr <obj_t> obj)
{
assert (obj->tag == num_tag);
return static_pointer_cast <num_o> (obj);
}
#+end_src
*** num_o::eq
#+begin_src cpp
bool
num_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_num (obj);
return (this->num == that->num);
}
#+end_src
*** num_p
#+begin_src cpp
bool
num_p (shared_ptr <obj_t> a)
{
return a->tag == num_tag;
}
#+end_src
* str
*** str_o
#+begin_src cpp
struct str_o: obj_t
{
string str;
str_o (string str);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
void print (env_t &env);
};
#+end_src
*** str_o::str_o
#+begin_src cpp
str_o::str_o (string str)
{
this->tag = str_tag;
this->str = str;
}
#+end_src
*** make_str
#+begin_src cpp
shared_ptr <str_o>
make_str (string str)
{
return make_shared <str_o> (str);
}
#+end_src
*** str_o::repr
#+begin_src cpp
string
str_o::repr (env_t &env)
{
return "\"" + this->str + "\"";
}
#+end_src
*** str_o::print
#+begin_src cpp
void
str_o::print (env_t &env)
{
cout << this->str;
}
#+end_src
*** as_str
#+begin_src cpp
shared_ptr <str_o>
as_str (shared_ptr <obj_t> obj)
{
assert (obj->tag == str_tag);
return static_pointer_cast <str_o> (obj);
}
#+end_src
*** str_o::eq
#+begin_src cpp
bool
str_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_str (obj);
return (this->str == that->str);
}
#+end_src
*** str_p
#+begin_src cpp
bool
str_p (shared_ptr <obj_t> a)
{
return a->tag == str_tag;
}
#+end_src
*** str_length
#+begin_src cpp
shared_ptr <num_o>
str_length (shared_ptr <str_o> str)
{
auto size = str->str.size ();
return make_num (static_cast <num_t> (size));
}
#+end_src
*** str_append
#+begin_src cpp
shared_ptr <str_o>
str_append (
shared_ptr <str_o> ante,
shared_ptr <str_o> succ)
{
return make_str (ante->str + succ->str);
}
#+end_src
*** str_slice
#+begin_src cpp
shared_ptr <str_o>
str_slice (
shared_ptr <str_o> str,
shared_ptr <num_o> begin,
shared_ptr <num_o> end)
{
auto size = str->str.size ();
assert (begin->num >= 0);
assert (end->num < size);
auto length = end->num - begin->num;
return make_str (str->str.substr (begin->num, length));
}
#+end_src
*** str_ref
#+begin_src cpp
shared_ptr <str_o>
str_ref (
shared_ptr <str_o> str,
shared_ptr <num_o> index)
{
auto size = str->str.size ();
assert (index->num >= 0);
assert (index->num < size);
auto c = str->str [index->num];
auto s = string ();
s += c;
return make_str (s);
}
#+end_src
*** str_head
#+begin_src cpp
shared_ptr <str_o>
str_head (shared_ptr <str_o> str)
{
auto size = str->str.size ();
assert (size >= 1);
auto c = str->str [0];
auto s = string ();
s += c;
return make_str (s);
}
#+end_src
*** str_rest
#+begin_src cpp
shared_ptr <str_o>
str_rest (shared_ptr <str_o> str)
{
auto size = str->str.size ();
return make_str (str->str.substr (1, size -1));
}
#+end_src
* sym
*** sym_o
#+begin_src cpp
struct sym_o: obj_t
{
symbol sym;
sym_o (symbol sym);
bool eq (shared_ptr <obj_t> obj);
symbol repr (env_t &env);
void print (env_t &env);
};
#+end_src
*** sym_o::sym_o
#+begin_src cpp
sym_o::sym_o (symbol sym)
{
this->tag = sym_tag;
this->sym = sym;
}
#+end_src
*** make_sym
#+begin_src cpp
shared_ptr <sym_o>
make_sym (symbol sym)
{
return make_shared <sym_o> (sym);
}
#+end_src
*** sym_o::repr
#+begin_src cpp
symbol
sym_o::repr (env_t &env)
{
return "'" + this->sym;
}
#+end_src
*** sym_o::print
#+begin_src cpp
void
sym_o::print (env_t &env)
{
cout << this->sym;
}
#+end_src
*** as_sym
#+begin_src cpp
shared_ptr <sym_o>
as_sym (shared_ptr <obj_t> obj)
{
assert (obj->tag == sym_tag);
return static_pointer_cast <sym_o> (obj);
}
#+end_src
*** sym_o::eq
#+begin_src cpp
bool
sym_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_sym (obj);
return (this->sym == that->sym);
}
#+end_src
*** sym_p
#+begin_src cpp
bool
sym_p (shared_ptr <obj_t> a)
{
return a->tag == sym_tag;
}
#+end_src
*** sym_length
#+begin_src cpp
shared_ptr <num_o>
sym_length (
shared_ptr <sym_o> sym)
{
auto size = sym->sym.size ();
return make_num (static_cast <num_t> (size));
}
#+end_src
*** sym_append
#+begin_src cpp
shared_ptr <sym_o>
sym_append (
shared_ptr <sym_o> ante,
shared_ptr <sym_o> succ)
{
return make_sym (ante->sym + succ->sym);
}
#+end_src
*** sym_slice
#+begin_src cpp
shared_ptr <sym_o>
sym_slice (
shared_ptr <sym_o> sym,
shared_ptr <num_o> begin,
shared_ptr <num_o> end)
{
auto size = sym->sym.size ();
assert (begin->num >= 0);
assert (end->num < size);
auto length = end->num - begin->num;
return make_sym (sym->sym.substr (begin->num, length));
}
#+end_src
*** sym_ref
#+begin_src cpp
shared_ptr <sym_o>
sym_ref (
shared_ptr <sym_o> sym,
shared_ptr <num_o> index)
{
auto size = sym->sym.size ();
assert (index->num >= 0);
assert (index->num < size);
auto c = sym->sym [index->num];
auto s = symbol ();
s += c;
return make_sym (s);
}
#+end_src
*** sym_head
#+begin_src cpp
shared_ptr <sym_o>
sym_head (shared_ptr <sym_o> sym)
{
auto size = sym->sym.size ();
assert (size >= 1);
auto c = sym->sym [0];
auto s = symbol ();
s += c;
return make_sym (s);
}
#+end_src
*** sym_rest
#+begin_src cpp
shared_ptr <sym_o>
sym_rest (shared_ptr <sym_o> sym)
{
auto size = sym->sym.size ();
return make_sym (sym->sym.substr (1, size -1));
}
#+end_src
* list
*** null_c
#+begin_src cpp
shared_ptr <data_o>
null_c ()
{
return make_data (
null_tag,
name_vector_t (),
obj_map_t ());
}
#+end_src
*** null_p
#+begin_src cpp
bool
null_p (shared_ptr <obj_t> a)
{
return a->tag == null_tag;
}
#+end_src
*** cons_c
#+begin_src cpp
shared_ptr <data_o>
cons_c (
shared_ptr <obj_t> car,
shared_ptr <obj_t> cdr)
{
auto obj_map = obj_map_t ();
obj_map ["car"] = car;
obj_map ["cdr"] = cdr;
return make_data (
cons_tag,
name_vector_t (),
obj_map);
}
#+end_src
*** cons_p
#+begin_src cpp
bool
cons_p (shared_ptr <obj_t> a)
{
return a->tag == cons_tag;
}
#+end_src
*** car
#+begin_src cpp
shared_ptr <obj_t>
car (shared_ptr <obj_t> cons)
{
assert (cons_p (cons));
return cons->obj_map ["car"];
}
#+end_src
*** cdr
#+begin_src cpp
shared_ptr <obj_t>
cdr (shared_ptr <obj_t> cons)
{
assert (cons_p (cons));
return cons->obj_map ["cdr"];
}
#+end_src
*** list_p
#+begin_src cpp
bool
list_p (shared_ptr <obj_t> a)
{
return null_p (a)
or cons_p (a);
}
#+end_src
*** list_size
#+begin_src cpp
size_t
list_size (shared_ptr <obj_t> l)
{
assert (list_p (l));
auto size = 0;
while (! null_p (l)) {
size++;
l = cdr (l);
}
return size;
}
#+end_src
*** list_length
#+begin_src cpp
shared_ptr <num_o>
list_length (shared_ptr <obj_t> l)
{
auto size = list_size (l);
auto length = static_cast <num_t> (size);
return make_num (length);
}
#+end_src
*** list_reverse
#+begin_src cpp
shared_ptr <obj_t>
list_reverse (shared_ptr <obj_t> l)
{
assert (list_p (l));
auto result = null_c ();
while (! null_p (l)) {
auto obj = car (l);
result = cons_c (obj, result);
l = cdr (l);
}
return result;
}
#+end_src
*** list_append
#+begin_src cpp
shared_ptr <obj_t>
list_append (
shared_ptr <obj_t> ante,
shared_ptr <obj_t> succ)
{
auto l = list_reverse (ante);
auto result = succ;
while (! null_p (l)) {
auto obj = car (l);
result = cons_c (obj, result);
l = cdr (l);
}
return result;
}
#+end_src
*** unit_list
#+begin_src cpp
shared_ptr <obj_t>
unit_list (shared_ptr <obj_t> obj)
{
return cons_c (obj, null_c ());
}
#+end_src
* vect
*** vect_o
#+begin_src cpp
struct vect_o: obj_t
{
obj_vector_t obj_vector;
vect_o (obj_vector_t obj_vector);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** vect_o::vect_o
#+begin_src cpp
vect_o::vect_o (obj_vector_t obj_vector)
{
this->tag = vect_tag;
this->obj_vector = obj_vector;
}
#+end_src
*** make_vect
#+begin_src cpp
shared_ptr <vect_o>
make_vect (obj_vector_t obj_vector)
{
return make_shared <vect_o> (obj_vector);
}
#+end_src
*** as_vect
#+begin_src cpp
shared_ptr <vect_o>
as_vect (shared_ptr <obj_t> obj)
{
assert (obj->tag == vect_tag);
return static_pointer_cast <vect_o> (obj);
}
#+end_src
*** vect_eq
#+begin_src cpp
bool
vect_eq (
obj_vector_t &lhs,
obj_vector_t &rhs)
{
if (lhs.size () != rhs.size ()) return false;
auto size = lhs.size ();
size_t index = 0;
while (index < size) {
if (! obj_eq (lhs [index], rhs [index]))
return false;
index++;
}
return true;
}
#+end_src
*** vect_o::eq
#+begin_src cpp
bool
vect_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_vect (obj);
return vect_eq (this->obj_vector, that->obj_vector);
}
#+end_src
*** vect_o::repr
#+begin_src cpp
string
vect_o::repr (env_t &env)
{
string repr = "[";
for (auto &obj: this->obj_vector) {
repr += obj->repr (env);
repr += " ";
}
if (! repr.empty ()) repr.pop_back ();
repr += "]";
return repr;
}
#+end_src
*** vect_p
#+begin_src cpp
bool
vect_p (shared_ptr <obj_t> a)
{
return a->tag == vect_tag;
}
#+end_src
*** list_to_vect
#+begin_src cpp
shared_ptr <vect_o>
list_to_vect (shared_ptr <obj_t> l)
{
auto obj_vector = obj_vector_t ();
while (cons_p (l)) {
obj_vector.push_back (car (l));
l = cdr (l);
}
return make_vect (obj_vector);
}
#+end_src
*** vect_to_list
#+begin_src cpp
shared_ptr <obj_t>
vect_to_list (shared_ptr <vect_o> vect)
{
auto obj_vector = vect->obj_vector;
auto result = null_c ();
auto begin = obj_vector.rbegin ();
auto end = obj_vector.rend ();
for (auto it = begin; it != end; it++)
result = cons_c (*it, result);
return result;
}
#+end_src
*** vect_length
#+begin_src cpp
shared_ptr <num_o>
vect_length (shared_ptr <vect_o> vect)
{
return make_num (vect->obj_vector.size ());
}
#+end_src
*** vect_append
#+begin_src cpp
shared_ptr <vect_o>
vect_append (
shared_ptr <vect_o> ante,
shared_ptr <vect_o> succ)
{
auto obj_vector = obj_vector_t ();
for (auto obj: ante->obj_vector)
obj_vector.push_back (obj);
for (auto obj: succ->obj_vector)
obj_vector.push_back (obj);
return make_vect (obj_vector);
}
#+end_src
*** vect_slice
#+begin_src cpp
shared_ptr <vect_o>
vect_slice (
shared_ptr <vect_o> vect,
shared_ptr <num_o> begin,
shared_ptr <num_o> end)
{
auto size = vect->obj_vector.size ();
assert (begin->num >= 0);
assert (end->num < size);
auto obj_vector = obj_vector_t ();
for (auto it = vect->obj_vector.begin () + begin->num;
it != vect->obj_vector.begin () + end->num;
it++) {
auto obj = *it;
obj_vector.push_back (obj);
}
return make_vect (obj_vector);
}
#+end_src
*** vect_ref
#+begin_src cpp
shared_ptr <obj_t>
vect_ref (
shared_ptr <vect_o> vect,
shared_ptr <num_o> index)
{
auto size = vect->obj_vector.size ();
assert (index->num >= 0);
assert (index->num < size);
return vect->obj_vector [index->num];
}
#+end_src
*** vect_head
#+begin_src cpp
shared_ptr <obj_t>
vect_head (shared_ptr <vect_o> vect)
{
auto size = vect->obj_vector.size ();
assert (size >= 1);
return vect->obj_vector [0];
}
#+end_src
*** vect_rest
#+begin_src cpp
shared_ptr <vect_o>
vect_rest (shared_ptr <vect_o> vect)
{
auto size = vect->obj_vector.size ();
assert (size >= 1);
auto obj_vector = obj_vector_t ();
for (auto it = vect->obj_vector.begin () + 1;
it != vect->obj_vector.end ();
it++) {
auto obj = *it;
obj_vector.push_back (obj);
}
return make_vect (obj_vector);
}
#+end_src
*** vect_reverse
#+begin_src cpp
shared_ptr <vect_o>
vect_reverse (shared_ptr <vect_o> vect)
{
auto obj_vector = vect->obj_vector;
reverse (obj_vector.begin (),
obj_vector.end ());
return make_vect (obj_vector);
}
#+end_src
*** unit_vect
#+begin_src cpp
shared_ptr <vect_o>
unit_vect (shared_ptr <obj_t> obj)
{
auto obj_vector = obj_vector_t ();
obj_vector.push_back (obj);
return make_vect (obj_vector);
}
#+end_src
* maybe
*** nothing_c
#+begin_src cpp
shared_ptr <data_o>
nothing_c ()
{
return make_data (
nothing_tag,
name_vector_t (),
obj_map_t ());
}
#+end_src
*** nothing_p
#+begin_src cpp
bool
nothing_p (shared_ptr <obj_t> a)
{
return a->tag == nothing_tag;
}
#+end_src
*** just_c
#+begin_src cpp
shared_ptr <data_o>
just_c (shared_ptr <obj_t> value)
{
auto obj_map = obj_map_t ();
obj_map ["value"] = value;
return make_data (
just_tag,
name_vector_t (),
obj_map);
}
#+end_src
*** just_p
#+begin_src cpp
bool
just_p (shared_ptr <obj_t> a)
{
return a->tag == just_tag;
}
#+end_src
*** value_of_just
#+begin_src cpp
shared_ptr <obj_t>
value_of_just (shared_ptr <obj_t> just)
{
assert (just_p (just));
return just->obj_map ["value"];
}
#+end_src
*** maybe_p
#+begin_src cpp
bool
maybe_p (shared_ptr <obj_t> a)
{
return nothing_p (a)
or just_p (a);
}
#+end_src
* dict
*** dict_o
#+begin_src cpp
struct dict_o: obj_t
{
dict_o (obj_map_t obj_map);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** dict_o::dict_o
#+begin_src cpp
dict_o::dict_o (obj_map_t obj_map)
{
this->tag = dict_tag;
this->obj_map = obj_map;
}
#+end_src
*** make_dict
#+begin_src cpp
shared_ptr <dict_o>
make_dict (obj_map_t obj_map)
{
return make_shared <dict_o> (obj_map);
}
#+end_src
*** as_dict
#+begin_src cpp
shared_ptr <dict_o>
as_dict (shared_ptr <obj_t> obj)
{
assert (obj->tag == dict_tag);
return static_pointer_cast <dict_o> (obj);
}
#+end_src
*** dict_o::eq
#+begin_src cpp
bool
dict_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_dict (obj);
return obj_map_eq (this->obj_map, that->obj_map);
}
#+end_src
*** dict_o::repr
#+begin_src cpp
string
dict_o::repr (env_t &env)
{
string repr = "{";
repr += obj_map_repr (env, this->obj_map);
repr += "}";
return repr;
}
#+end_src
*** dict_p
#+begin_src cpp
bool
dict_p (shared_ptr <obj_t> a)
{
return a->tag == dict_tag;
}
#+end_src
*** list_to_dict
#+begin_src cpp
shared_ptr <dict_o>
list_to_dict (shared_ptr <obj_t> l)
{
auto obj_map = obj_map_t ();
while (! null_p (l)) {
auto pair = car (l);
auto sym = as_sym (car (pair));
auto obj = car (cdr (pair));
obj_map [sym->sym] = obj;
l = cdr (l);
}
return make_dict (obj_map);
}
#+end_src
*** dict_to_list
#+begin_src cpp
shared_ptr <obj_t>
dict_to_list (shared_ptr <dict_o> dict)
{
auto result = null_c ();
for (auto &kv: dict->obj_map) {
auto sym = make_sym (kv.first);
auto obj = kv.second;
auto pair = cons_c (sym, unit_list (obj));
result = cons_c (pair, result);
}
return result;
}
#+end_src
*** dict_to_flat_reversed_list
#+begin_src cpp
shared_ptr <obj_t>
dict_to_flat_reversed_list (shared_ptr <dict_o> dict)
{
auto result = null_c ();
for (auto &kv: dict->obj_map) {
auto sym = make_sym (kv.first);
auto key = cons_c (
make_sym ("quote"),
unit_list (sym));
auto obj = kv.second;
result = cons_c (obj, result);
result = cons_c (key, result);
}
return result;
}
#+end_src
*** dict_length
#+begin_src cpp
shared_ptr <num_o>
dict_length (shared_ptr <dict_o> dict)
{
return make_num (dict->obj_map.size ());
}
#+end_src
*** dict_key_list
#+begin_src cpp
shared_ptr <obj_t>
dict_key_list (shared_ptr <dict_o> dict)
{
auto result = null_c ();
for (auto &kv: dict->obj_map) {
auto sym = make_sym (kv.first);
result = cons_c (sym, result);
}
return result;
}
#+end_src
*** dict_value_list
#+begin_src cpp
shared_ptr <obj_t>
dict_value_list (shared_ptr <dict_o> dict)
{
auto result = null_c ();
for (auto &kv: dict->obj_map) {
auto obj = kv.second;
result = cons_c (obj, result);
}
return result;
}
#+end_src
*** dict_insert
#+begin_src cpp
shared_ptr <dict_o>
dict_insert (
shared_ptr <dict_o> dict,
shared_ptr <sym_o> sym,
shared_ptr <obj_t> value)
{
auto obj_map = dict->obj_map;
auto key = sym->sym;
obj_map [key] = value;
return make_dict (obj_map);
}
#+end_src
*** dict_merge
#+begin_src cpp
shared_ptr <dict_o>
dict_merge (
shared_ptr <dict_o> ante,
shared_ptr <dict_o> succ)
{
auto obj_map = ante->obj_map;
for (auto &kv: succ->obj_map) {
auto key = kv.first;
auto value = kv.second;
obj_map [key] = value;
}
return make_dict (obj_map);
}
#+end_src
*** dict_find
#+begin_src cpp
shared_ptr <obj_t>
dict_find (
shared_ptr <dict_o> dict,
shared_ptr <sym_o> sym)
{
auto obj_map = dict->obj_map;
auto key = sym->sym;
auto it = obj_map.find (key);
if (it != obj_map.end ()) {
auto value = it->second;
return just_c (value);
} else {
return nothing_c ();
}
}
#+end_src
* scan
*** space_char_p
#+begin_src cpp
bool
space_char_p (char c)
{
return c == ' '
or c == '\n'
or c == '\t';
}
#+end_src
*** delimiter_char_p
#+begin_src cpp
bool
delimiter_char_p (char c)
{
return c == '('
or c == ')'
or c == '['
or c == ']'
or c == '{'
or c == '}'
or c == ','
or c == '`'
or c == '\'';
}
#+end_src
*** semicolon_char_p
#+begin_src cpp
bool
semicolon_char_p (char c)
{
return (c == ';');
}
#+end_src
*** newline_char_p
#+begin_src cpp
bool
newline_char_p (char c)
{
return (c == '\n');
}
#+end_src
*** string_from_char
#+begin_src cpp
string
string_from_char (char c)
{
string str = "";
str.push_back (c);
return str;
}
#+end_src
*** doublequote_char_p
#+begin_src cpp
bool
doublequote_char_p (char c)
{
return c == '"';
}
#+end_src
*** find_word_length
#+begin_src cpp
size_t
find_word_length (string code, size_t begin)
{
size_t length = code.length ();
size_t index = begin;
while (true) {
if (index == length)
return index - begin;
char c = code [index];
if (space_char_p (c) or
doublequote_char_p (c) or
semicolon_char_p (c) or
delimiter_char_p (c))
return index - begin;
index++;
}
}
#+end_src
*** find_string_length
#+begin_src cpp
size_t
find_string_length (string code, size_t begin)
{
size_t length = code.length ();
size_t index = begin + 1;
while (true) {
if (index == length) {
cout << "- fatal error : find_string_length" << "\n";
cout << " doublequote mismatch" << "\n";
exit (1);
}
char c = code [index];
if (doublequote_char_p (c))
return index - begin + 1;
index++;
}
}
#+end_src
*** find_comment_length
#+begin_src cpp
size_t
find_comment_length (string code, size_t begin)
{
size_t length = code.length ();
size_t index = begin;
while (true) {
if (index == length) {
cout << "- fatal error : find_string_length" << "\n";
cout << " end-of-line mismatch" << "\n";
exit (1);
}
char c = code [index];
if (newline_char_p (c))
return index - begin + 1;
index++;
}
}
#+end_src
*** scan_word_vector
#+begin_src cpp
string_vector_t
scan_word_vector (string code)
{
auto string_vector = string_vector_t ();
size_t i = 0;
while (i < code.length ()) {
char c = code [i];
if (space_char_p (c)) {
i++;
} else if (delimiter_char_p (c)) {
string_vector.push_back (string_from_char (c));
i++;
} else if (semicolon_char_p (c)) {
auto length = find_comment_length (code, i);
i += length;
} else if (doublequote_char_p (c)) {
auto length = find_string_length (code, i);
string str = code.substr (i, length);
string_vector.push_back (str);
i += length;
} else {
auto length = find_word_length (code, i);
string word = code.substr (i, length);
string_vector.push_back (word);
i += length;
}
}
return string_vector;
}
#+end_src
*** test_scan
#+begin_src cpp
void
test_scan ()
{
auto code = "(cons-c <car> <cdr>)";
auto string_vector = scan_word_vector (code);
assert (string_vector.size () == 5);
assert (string_vector [0] == "(");
assert (string_vector [1] == "cons-c");
assert (string_vector [2] == "<car>");
assert (string_vector [3] == "<cdr>");
assert (string_vector [4] == ")");
{
auto code = "\"123\"";
auto string_vector = scan_word_vector (code);
assert (string_vector.size () == 1);
assert (string_vector [0] == "\"123\"");
}
}
#+end_src
* sexp
*** scan_word_list -- drop `,`
#+begin_src cpp
shared_ptr <obj_t>
scan_word_list (shared_ptr <str_o> code)
{
auto word_vector = scan_word_vector (code->str);
auto begin = word_vector.rbegin ();
auto end = word_vector.rend ();
auto collect = null_c ();
for (auto it = begin; it != end; it++) {
auto word = *it;
if (word != ",") {
auto obj = make_str (word);
collect = cons_c (obj, collect);
}
}
return collect;
}
#+end_src
*** bar_word_p
#+begin_src cpp
bool
bar_word_p (string word)
{
return word == "("
or word == "["
or word == "{";
}
#+end_src
*** ket_word_p
#+begin_src cpp
bool
ket_word_p (string word)
{
return word == ")"
or word == "]"
or word == "}";
}
#+end_src
*** quote_word_p
#+begin_src cpp
bool
quote_word_p (string word)
{
return word == "'"
or word == "`";
}
#+end_src
*** unquote_word_p
#+begin_src cpp
bool
unquote_word_p (string word)
{
return word == "~"
or word == "~@";
}
#+end_src
*** bar_word_to_ket_word
#+begin_src cpp
string
bar_word_to_ket_word (string bar)
{
assert (bar_word_p (bar));
if (bar == "(") return ")";
if (bar == "[") return "]";
if (bar == "{") return "}";
cout << "bar_word_to_ket_word fail\n";
exit (1);
}
#+end_src
*** word_list_head_with_bar_ket_counter
#+begin_src cpp
shared_ptr <obj_t>
word_list_head_with_bar_ket_counter (
shared_ptr <obj_t> word_list,
string bar,
string ket,
size_t counter)
{
if (counter == 0) {
return null_c ();
}
auto head = as_str (car (word_list));
auto word = head->str;
if (word == bar) {
return cons_c (
head, word_list_head_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter + 1));
} else if (word == ket) {
return cons_c (
head, word_list_head_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter - 1));
} else {
return cons_c (
head, word_list_head_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter));
}
}
#+end_src
*** word_list_head
#+begin_src cpp
shared_ptr <obj_t>
word_list_head (shared_ptr <obj_t> word_list)
{
assert (cons_p (word_list));
auto head = as_str (car (word_list));
auto word = head->str;
if (bar_word_p (word)) {
auto bar = word;
auto ket = bar_word_to_ket_word (word);
return cons_c (
head, word_list_head_with_bar_ket_counter (
cdr (word_list),
bar, ket, 1));
} else if (quote_word_p (word)) {
return cons_c (
head, word_list_head (cdr (word_list)));
} else if (unquote_word_p (word)) {
return cons_c (
head, word_list_head (cdr (word_list)));
} else {
return unit_list (head);
}
}
#+end_src
*** word_list_rest_with_bar_ket_counter
#+begin_src cpp
shared_ptr <obj_t>
word_list_rest_with_bar_ket_counter (
shared_ptr <obj_t> word_list,
string bar,
string ket,
size_t counter)
{
if (counter == 0)
return word_list;
auto head = as_str (car (word_list));
auto word = head->str;
if (word == bar)
return word_list_rest_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter + 1);
if (word == ket)
return word_list_rest_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter - 1);
else
return word_list_rest_with_bar_ket_counter (
cdr (word_list),
bar, ket, counter);
}
#+end_src
*** word_list_rest
#+begin_src cpp
shared_ptr <obj_t>
word_list_rest (shared_ptr <obj_t> word_list)
{
assert (cons_p (word_list));
auto head = as_str (car (word_list));
auto word = head->str;
if (bar_word_p (word)) {
auto bar = word;
auto ket = bar_word_to_ket_word (word);
return word_list_rest_with_bar_ket_counter (
cdr (word_list),
bar, ket, 1);
}
else if (quote_word_p (word))
return word_list_rest (cdr (word_list));
else if (unquote_word_p (word))
return word_list_rest (cdr (word_list));
else
return cdr (word_list);
}
#+end_src
*** word_list_drop_ket
#+begin_src cpp
shared_ptr <obj_t>
word_list_drop_ket (
shared_ptr <obj_t> word_list,
string ket)
{
auto head = car (word_list);
auto rest = cdr (word_list);
if (null_p (rest))
return null_c ();
auto cdr_rest = cdr (rest);
auto car_rest = as_str (car (rest));
auto word = car_rest->str;
if (null_p (cdr_rest)) {
assert (word == ket);
return unit_list (head);
} else {
return cons_c (
head,
word_list_drop_ket (rest, ket));
}
}
#+end_src
*** str_word_p
#+begin_src cpp
bool
str_word_p (string str)
{
auto size = str.size ();
if (size < 2) return false;
if (str [0] != '"') return false;
if (str [size-1] != '"') return false;
return true;
}
#+end_src
*** string_string_to_string
#+begin_src cpp
string
string_string_to_string (string str)
{
auto size = str.size () - 2;
return str.substr (1, size);
}
#+end_src
*** num_word_p
#+begin_src cpp
bool
num_word_p (string str)
{
auto size = str.size ();
if (size < 1) return false;
if (str [0] == '-')
return num_word_p (str.substr (1, size - 1));
auto string_vector = string_split (str, '.');
if (string_vector.size () == 0) return false;
if (string_vector.size () >= 3) return false;
auto pos = str.find_first_not_of ("0123456789.");
if (pos != string::npos) {
return false;
} else {
return true;
}
}
#+end_src
*** sexp_list_to_vect
#+begin_src cpp
shared_ptr <vect_o>
sexp_list_to_vect (shared_ptr <obj_t> sexp_list)
{
return list_to_vect (sexp_list);
}
#+end_src
*** sexp_list_prefix_assign_with_last_sexp
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_prefix_assign (shared_ptr <obj_t> sexp_list);
shared_ptr <obj_t>
sexp_list_prefix_assign_with_last_sexp (
shared_ptr <obj_t> sexp_list,
shared_ptr <obj_t> last_sexp)
{
if (null_p (sexp_list)) {
return unit_list (last_sexp);
} else {
auto head = car (sexp_list);
if (sym_p (head) and as_sym (head) ->sym == "=") {
auto next = car (cdr (sexp_list));
auto rest = cdr (cdr (sexp_list));
auto new_last_sexp = cons_c (
head, cons_c (
last_sexp,
unit_list (next)));
return cons_c (
new_last_sexp,
sexp_list_prefix_assign (rest));
} else {
auto rest = cdr (sexp_list);
return cons_c (
last_sexp,
sexp_list_prefix_assign_with_last_sexp (rest, head));
}
}
}
#+end_src
*** sexp_list_prefix_assign
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_prefix_assign (shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list))
return sexp_list;
else {
return sexp_list_prefix_assign_with_last_sexp (
cdr (sexp_list),
car (sexp_list));
}
}
#+end_src
*** sexp_list_assign_to_pair
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_assign_to_pair (shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list))
return sexp_list;
else
return cons_c (
cdr (car (sexp_list)),
sexp_list_assign_to_pair (cdr (sexp_list)));
}
#+end_src
*** sexp_list_to_dict
#+begin_src cpp
shared_ptr <dict_o>
sexp_list_to_dict (shared_ptr <obj_t> sexp_list)
{
return list_to_dict (
sexp_list_assign_to_pair (
sexp_list_prefix_assign (sexp_list)));
}
#+end_src
*** [note] about sexp
- sexp-t := str-t | sym-t | num-t |
(list-t sexp-t) | (vect-t sexp-t) | (dict-t sym-t sexp-t)
- literal in quote
( ) -- list-t
[ ] -- vect-t
{ } -- dict-t
*** parse_sexp
#+begin_src cpp
shared_ptr <obj_t>
parse_sexp_list (shared_ptr <obj_t> word_list);
shared_ptr <obj_t>
parse_sexp (shared_ptr <obj_t> word_list)
{
auto head = as_str (car (word_list));
auto word = head->str;
auto rest = cdr (word_list);
if (word == "(")
return parse_sexp_list (
word_list_drop_ket (rest, ")"));
else if (word == "[")
return sexp_list_to_vect (
parse_sexp_list (
word_list_drop_ket (rest, "]")));
else if (word == "{")
return sexp_list_to_dict (
parse_sexp_list (
word_list_drop_ket (rest, "}")));
else if (word == "'")
return cons_c (make_sym ("quote"),
unit_list (parse_sexp (rest)));
else if (word == "`")
return cons_c (make_sym ("quasiquote"),
unit_list (parse_sexp (rest)));
else if (word == "~")
return cons_c (make_sym ("unquote"),
unit_list (parse_sexp (rest)));
else if (word == "~@")
return cons_c (make_sym ("unquote-splicing"),
unit_list (parse_sexp (rest)));
else if (num_word_p (word))
return make_num (s2n (word));
else if (str_word_p (word))
return make_str (string_string_to_string (word));
else
return make_sym (word);
}
#+end_src
*** parse_sexp_list
#+begin_src cpp
shared_ptr <obj_t>
parse_sexp_list (shared_ptr <obj_t> word_list)
{
if (null_p (word_list))
return word_list;
else
return cons_c (
parse_sexp (word_list_head (word_list)),
parse_sexp_list (word_list_rest (word_list)));
}
#+end_src
*** sexp_repr
#+begin_src cpp
string
sexp_list_repr (env_t &env, shared_ptr <obj_t> sexp_list);
string
sexp_repr (env_t &env, shared_ptr <obj_t> sexp)
{
if (null_p (sexp)) {
return "()";
} else if (cons_p (sexp)) {
return "(" + sexp_list_repr (env, sexp) + ")";
} else if (vect_p (sexp)) {
auto v = as_vect (sexp);
auto l = vect_to_list (v);
return "[" + sexp_list_repr (env, l) + "]";
} else if (dict_p (sexp)) {
auto d = as_dict (sexp);
auto l = dict_to_list (d);
return "{" + sexp_list_repr (env, l) + "}";
} else if (str_p (sexp)) {
auto str = as_str (sexp);
return '"' + str->str + '"';
} else if (sym_p (sexp)) {
auto sym = as_sym (sexp);
return sym->sym;
} else {
return sexp->repr (env);
}
}
#+end_src
*** sexp_list_repr
#+begin_src cpp
string
sexp_list_repr (env_t &env, shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list))
return "";
else if (null_p (cdr (sexp_list)))
return sexp_repr (env, car (sexp_list));
else if (! cons_p (cdr (sexp_list)))
return
sexp_repr (env, car (sexp_list)) + " . " +
sexp_repr (env, cdr (sexp_list));
else {
return
sexp_repr (env, car (sexp_list)) + " " +
sexp_list_repr (env, cdr (sexp_list));
}
}
#+end_src
* system
*** system_env_find
#+begin_src cpp
string
system_env_find (string name)
{
auto env_var = name.c_str ();
const char* env_p = getenv (env_var);
if (env_p) {
return string (env_p);
} else {
return string ();
}
}
#+end_src
*** dollar_string_p
#+begin_src cpp
bool
dollar_string_p (string s)
{
auto size = s.size ();
if (size < 2) return false;
return s [0] == '$';
}
#+end_src
*** dollar_string_to_name
#+begin_src cpp
name_t
dollar_string_to_name (string dollar_string)
{
assert (dollar_string_p (dollar_string));
auto size = dollar_string.size ();
return dollar_string.substr (1, size -1);
}
#+end_src
*** expend_path
#+begin_src cpp
path_t
expend_path (path_t p)
{
auto string_vector = string_split (p.string (), '/');
auto result_vector = string_vector_t ();
for (auto str: string_vector) {
if (dollar_string_p (str)) {
auto name = dollar_string_to_name (str);
auto result = system_env_find (name);
if (result == "") {
cout << "- fatal error : expend_path" << "\n";
cout << " a var is unbound" << "\n";
cout << " var : " << str << "\n";
exit (1);
}
auto pos = result.find (":");
if (pos != string::npos) {
cout << "- fatal error : expend_path" << "\n";
cout << " a var must be bound to one string" << "\n";
cout << " var : " << str << "\n";
cout << " string list : " << result << "\n";
exit (1);
}
result_vector.push_back (result);
} else {
result_vector.push_back (str);
}
}
return path_t (string_vector_join (result_vector, '/'));
}
#+end_src
* module
*** module_o
#+begin_src cpp
struct module_o: obj_t
{
env_t module_env;
module_o (env_t module_env);
bool eq (shared_ptr <obj_t> obj);
string repr (env_t &env);
};
#+end_src
*** module_o::module_o
#+begin_src cpp
module_o::module_o (env_t module_env)
{
this->tag = module_tag;
this->module_env = module_env;
for (auto &kv: module_env.box_map) {
auto name = kv.first;
auto box = kv.second;
if (! box->empty_p) {
this->obj_map [name] = box->obj;
}
}
}
#+end_src
*** [todo] eq_env_p
#+begin_src cpp
bool
eq_env_p (env_t &lhs, env_t &rhs)
{
return false;
}
#+end_src
*** module_o::eq
#+begin_src cpp
bool
module_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = static_pointer_cast <module_o> (obj);
return eq_env_p (this->module_env, that->module_env);
}
#+end_src
*** module_o::repr
#+begin_src cpp
string
module_o::repr (env_t &env)
{
return "(module)";
}
#+end_src
* compile
*** forward declaration
#+begin_src cpp
shared_ptr <jojo_t>
sym_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <sym_o> sym);
shared_ptr <jojo_t>
sexp_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp);
shared_ptr <jojo_t>
sexp_list_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp_list);
#+end_src
*** lit_compile
***** lit_jo
******* lit_jo_t
#+begin_src cpp
struct lit_jo_t: jo_t
{
shared_ptr <obj_t> obj;
lit_jo_t (shared_ptr <obj_t> obj);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* lit_jo_t::lit_jo_t
#+begin_src cpp
lit_jo_t::
lit_jo_t (shared_ptr <obj_t> obj)
{
this->obj = obj;
}
#+end_src
******* lit_jo_t::copy
#+begin_src cpp
jo_t *
lit_jo_t::copy ()
{
return new lit_jo_t (this->obj);
}
#+end_src
******* lit_jo_t::exe
#+begin_src cpp
void
lit_jo_t::exe (env_t &env, scope_t &scope)
{
env.obj_stack.push (this->obj);
}
#+end_src
******* lit_jo_t::repr
#+begin_src cpp
string
lit_jo_t::repr (env_t &env)
{
return this->obj->repr (env);
}
#+end_src
***** lit_compile
#+begin_src cpp
shared_ptr <jojo_t>
lit_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
auto jo_vector = jo_vector_t ();
jo_vector.push_back (new lit_jo_t (sexp));;
auto jojo = make_shared <jojo_t> (jo_vector);
return jojo;
}
#+end_src
*** dot_in_word_compile
***** dot_jo
******* dot_jo_t
#+begin_src cpp
struct dot_jo_t: jo_t
{
name_t name;
jo_t * copy ();
dot_jo_t (name_t name);
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* dot_jo_t::dot_jo_t
#+begin_src cpp
dot_jo_t::dot_jo_t (name_t name)
{
this->name = name;
}
#+end_src
******* dot_jo_t::copy
#+begin_src cpp
jo_t *
dot_jo_t::copy ()
{
return new dot_jo_t (this->name);
}
#+end_src
******* dot_jo_t::exe
#+begin_src cpp
void
dot_jo_t::exe (env_t &env, scope_t &scope)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto it = obj->obj_map.find (this->name);
if (it != obj->obj_map.end ()) {
env.obj_stack.push (it->second);
} else {
auto type = type_of (env, obj);
auto it = type->obj_map.find (this->name);
if (it != type->obj_map.end ()) {
if (it->second->tag == closure_tag) {
auto method = static_pointer_cast <closure_o>
(it->second);
assert (method->name_vector.size () == 1);
env.obj_stack.push (obj);
method->apply (env, 1);
} else {
env.obj_stack.push (it->second);
}
} else {
cout << "- fatal error : dot_jo_t::exe" << "\n";
cout << " unknown field : " << this->name << "\n";
cout << " fail to find it in both object and type" << "\n";
exit (1);
}
}
}
#+end_src
******* dot_jo_t::repr
#+begin_src cpp
string
dot_jo_t::repr (env_t &env)
{
return "." + this->name;
}
#+end_src
***** dot_in_word_p
#+begin_src cpp
bool
dot_in_word_p (string str)
{
if (str_word_p (str)) return false;
auto pos = str.find (".");
return (pos != string::npos);
}
#+end_src
***** dot_in_word_compile
#+begin_src cpp
shared_ptr <jojo_t>
dot_in_word_compile (
env_t &env,
static_scope_t &static_scope,
string str)
{
auto string_vector = string_split (str, '.');
auto jojo = make_shared <jojo_t> (jo_vector_t ());
auto name = string_vector [0];
if (name != "") {
auto sym = make_sym (name);
jojo = sym_compile (env, static_scope, sym);
}
auto begin = string_vector.begin () + 1;
auto end = string_vector.end ();
auto jo_vector = jo_vector_t ();
for (auto it = begin; it != end; it++) {
jo_vector.push_back (new dot_jo_t (*it));
}
return jojo_append (jojo, make_shared <jojo_t> (jo_vector));
}
#+end_src
*** dot_word_p
#+begin_src cpp
bool
dot_word_p (string str)
{
auto size = str.size ();
if (size < 1) return false;
return (str [0] == '.');
}
#+end_src
*** ref_compile
***** ref_jo
******* ref_jo_t
#+begin_src cpp
struct ref_jo_t: jo_t
{
box_t *box;
ref_jo_t (box_t *);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* ref_jo_t::ref_jo_t
#+begin_src cpp
ref_jo_t::ref_jo_t (box_t *box)
{
this->box = box;
}
#+end_src
******* ref_jo_t::copy
#+begin_src cpp
jo_t *
ref_jo_t::copy ()
{
return new ref_jo_t (this->box);
}
#+end_src
******* ref_jo_t::exe
#+begin_src cpp
void
ref_jo_t::exe (env_t &env, scope_t &scope)
{
if (this->box->empty_p) {
cout << "- fatal error : ref_jo_t::exe fail" << "\n";
cout << " undefined name : "
<< name_of_box (env, box) << "\n";
exit (1);
} else {
env.obj_stack.push (this->box->obj);
}
}
#+end_src
******* ref_jo_t::repr
#+begin_src cpp
string
ref_jo_t::repr (env_t &env)
{
return name_of_box (env, this->box);
}
#+end_src
***** local_ref_jo
******* local_ref_jo_t
#+begin_src cpp
struct local_ref_jo_t: jo_t
{
size_t level;
size_t index;
local_ref_jo_t (size_t level, size_t index);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* local_ref_jo_t::local_ref_jo_t
#+begin_src cpp
local_ref_jo_t::
local_ref_jo_t (size_t level, size_t index)
{
this->level = level;
this->index = index;
}
#+end_src
******* local_ref_jo_t::copy
#+begin_src cpp
jo_t *
local_ref_jo_t::copy ()
{
return new local_ref_jo_t (this->level, this->index);
}
#+end_src
******* local_ref_jo_t::exe
#+begin_src cpp
void
local_ref_jo_t::exe (env_t &env, scope_t &scope)
{
// this is the only place where
// the scope in the arg of exe is uesd.
auto bind_vector =
scope [scope.size () - this->level - 1];
auto bind =
bind_vector [bind_vector.size () - this->index - 1];
auto obj = bind.second;
env.obj_stack.push (obj);
}
#+end_src
******* local_ref_jo_t::repr
#+begin_src cpp
string
local_ref_jo_t::repr (env_t &env)
{
return "local." +
to_string (this->level) + "." +
to_string (this->index);
}
#+end_src
***** ref_compile
#+begin_src cpp
shared_ptr <jojo_t>
ref_compile (
env_t &env,
static_scope_t &static_scope,
name_t name)
{
auto jo_vector = jo_vector_t ();
auto it = static_scope.find (name);
if (it != static_scope.end ()) {
auto local_ref = it->second;
auto local_ref_jo = new local_ref_jo_t
(local_ref.first,
local_ref.second);
jo_vector.push_back (local_ref_jo);
}
else
jo_vector.push_back (new ref_jo_t (boxing (env, name)));
return make_shared <jojo_t> (jo_vector);
}
#+end_src
*** sym_compile
#+begin_src cpp
shared_ptr <jojo_t>
sym_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <sym_o> sym)
{
auto word = sym->sym;
if (dot_in_word_p (word))
return dot_in_word_compile (env, static_scope, word);
else
return ref_compile (env, static_scope, word);
}
#+end_src
*** vect_compile
***** collect_vect_jo
******* collect_vect_jo_t
#+begin_src cpp
struct collect_vect_jo_t: jo_t
{
size_t counter;
collect_vect_jo_t (size_t counter);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* collect_vect_jo_t::collect_vect_jo_t
#+begin_src cpp
collect_vect_jo_t::
collect_vect_jo_t (size_t counter)
{
this->counter = counter;
}
#+end_src
******* collect_vect_jo_t::copy
#+begin_src cpp
jo_t *
collect_vect_jo_t::copy ()
{
return new collect_vect_jo_t (this->counter);
}
#+end_src
******* collect_vect_jo_t::exe
#+begin_src cpp
void
collect_vect_jo_t::exe (env_t &env, scope_t &scope)
{
size_t index = 0;
auto obj_vector = obj_vector_t ();
while (index < this->counter) {
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
obj_vector.push_back (obj);
index++;
}
reverse (obj_vector.begin (),
obj_vector.end ());
auto vect = make_vect (obj_vector);
env.obj_stack.push (vect);
}
#+end_src
******* collect_vect_jo_t::repr
#+begin_src cpp
string
collect_vect_jo_t::repr (env_t &env)
{
return "(collect-vect " + to_string (this->counter) + ")";
}
#+end_src
***** vect_compile
#+begin_src cpp
shared_ptr <jojo_t>
vect_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <vect_o> vect)
{
auto sexp_list = vect_to_list (vect);
auto jojo = sexp_list_compile
(env, static_scope, sexp_list);
auto counter = list_size (sexp_list);
jo_vector_t jo_vector = {
new collect_vect_jo_t (counter),
};
auto ending_jojo = make_shared <jojo_t> (jo_vector);
return jojo_append (jojo, ending_jojo);
}
#+end_src
*** dict_compile
***** collect_dict_jo
******* collect_dict_jo_t
#+begin_src cpp
struct collect_dict_jo_t: jo_t
{
size_t counter;
collect_dict_jo_t (size_t counter);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* collect_dict_jo_t::collect_dict_jo_t
#+begin_src cpp
collect_dict_jo_t::
collect_dict_jo_t (size_t counter)
{
this->counter = counter;
}
#+end_src
******* collect_dict_jo_t::copy
#+begin_src cpp
jo_t *
collect_dict_jo_t::copy ()
{
return new collect_dict_jo_t (this->counter);
}
#+end_src
******* collect_dict_jo_t::exe
#+begin_src cpp
void
collect_dict_jo_t::exe (
env_t &env,
scope_t &scope)
{
size_t index = 0;
auto obj_map = obj_map_t ();
while (index < this->counter) {
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto str = env.obj_stack.top ();
env.obj_stack.pop ();
auto key = as_sym (str);
obj_map [key->sym] = obj;
index++;
}
auto dict = make_dict (obj_map);
env.obj_stack.push (dict);
}
#+end_src
******* collect_dict_jo_t::repr
#+begin_src cpp
string
collect_dict_jo_t::repr (env_t &env)
{
return "(collect-dict " + to_string (this->counter) + ")";
}
#+end_src
***** dict_compile
#+begin_src cpp
shared_ptr <jojo_t>
dict_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <dict_o> dict)
{
auto sexp_list = dict_to_flat_reversed_list (dict);
auto jojo = sexp_list_compile
(env, static_scope, sexp_list);
auto counter = list_size (sexp_list);
counter = counter / 2;
jo_vector_t jo_vector = {
new collect_dict_jo_t (counter),
};
auto ending_jojo = make_shared <jojo_t> (jo_vector);
return jojo_append (jojo, ending_jojo);
}
#+end_src
*** keyword_compile
***** keyword
******* keyword_fn
#+begin_src cpp
using keyword_fn = function
<shared_ptr <jojo_t> (
env_t &,
static_scope_t &,
shared_ptr <obj_t>)>;
#+end_src
******* keyword_o
#+begin_src cpp
struct keyword_o: obj_t
{
keyword_fn fn;
keyword_o (keyword_fn fn);
bool eq (shared_ptr <obj_t> obj);
};
#+end_src
******* keyword_o::keyword_o
#+begin_src cpp
keyword_o::
keyword_o (keyword_fn fn)
{
this->tag = keyword_tag;
this->fn = fn;
}
#+end_src
******* keyword_o::eq
#+begin_src cpp
bool
keyword_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
return this != obj.get ();
}
#+end_src
******* keyword_p
#+begin_src cpp
bool
keyword_p (shared_ptr <obj_t> a)
{
return a->tag == keyword_tag;
}
#+end_src
******* define_keyword
#+begin_src cpp
void
define_keyword (env_t &env, name_t name, keyword_fn fn)
{
define (env, name, make_shared <keyword_o> (fn));
}
#+end_src
******* keyword_sexp_p
#+begin_src cpp
bool
keyword_sexp_p (env_t &env, shared_ptr <obj_t> sexp)
{
if (! cons_p (sexp)) return false;
if (! sym_p (car (sexp))) return false;
auto head = as_sym (car (sexp));
auto name = head->sym;
auto it = env.box_map.find (name);
if (it != env.box_map.end ()) {
auto box = it->second;
if (box->empty_p) return false;
if (keyword_p (box->obj)) return true;
else return false;
} else {
return false;
}
}
#+end_src
******* keyword_fn_from_name
#+begin_src cpp
keyword_fn
keyword_fn_from_name (env_t &env, name_t name)
{
auto it = env.box_map.find (name);
if (it != env.box_map.end ()) {
auto box = it->second;
if (box->empty_p) {
cout << "- fatal error: keyword_fn_from_name fail\n";
exit (1);
}
if (keyword_p (box->obj)) {
auto keyword = static_pointer_cast <keyword_o>
(box->obj);
return keyword->fn;
} else {
cout << "- fatal error: keyword_fn_from_name fail\n";
exit (1);
};
} else {
cout << "- fatal error: keyword_fn_from_name fail\n";
exit (1);
}
}
#+end_src
***** keyword_compile
#+begin_src cpp
shared_ptr <jojo_t>
keyword_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
auto head = as_sym (car (sexp));
auto body = cdr (sexp);
auto name = head->sym;
auto fn = keyword_fn_from_name (env, name);
return fn (env, static_scope, body);
}
#+end_src
*** macro_compile
***** macro
******* macro_o
#+begin_src cpp
struct macro_o: obj_t
{
shared_ptr <obj_t> obj;
macro_o (shared_ptr <obj_t> obj);
bool eq (shared_ptr <obj_t> obj);
};
#+end_src
******* macro_o::macro_o
#+begin_src cpp
macro_o::
macro_o (shared_ptr <obj_t> obj)
{
this->tag = macro_tag;
this->obj = obj;
}
#+end_src
******* make_macro
#+begin_src cpp
shared_ptr <macro_o>
make_macro (shared_ptr <obj_t> obj)
{
return make_shared <macro_o> (obj);
}
#+end_src
******* macro_p
#+begin_src cpp
bool
macro_p (shared_ptr <obj_t> a)
{
return a->tag == macro_tag;
}
#+end_src
******* as_macro
#+begin_src cpp
shared_ptr <macro_o>
as_macro (shared_ptr <obj_t> obj)
{
assert (obj->tag == macro_tag);
return static_pointer_cast <macro_o> (obj);
}
#+end_src
******* macro_o::eq
#+begin_src cpp
bool
macro_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
auto that = as_macro (obj);
return obj_eq (this->obj, that->obj);
}
#+end_src
******* forward declaration of sexp_eval
#+begin_src cpp
shared_ptr <obj_t>
sexp_eval (env_t &env, shared_ptr <obj_t> sexp);
#+end_src
******* macro_sexp_p
#+begin_src cpp
bool
macro_sexp_p (env_t &env, shared_ptr <obj_t> sexp)
{
if (! cons_p (sexp)) return false;;
auto head = car (sexp);
if (! sym_p (head)) return false;
auto sym = as_sym (head);
auto name = sym->sym;
auto found = find_obj_from_name (env, name);
if (! found) return false;
auto obj = sexp_eval (env, head);
return macro_p (obj);
}
#+end_src
******* macro_eval
#+begin_src cpp
shared_ptr <obj_t>
macro_eval (env_t &env, shared_ptr <obj_t> sexp)
{
assert (cons_p (sexp));
auto head = car (sexp);
auto rest = cdr (sexp);
auto obj = sexp_eval (env, head);
auto macro = as_macro (obj);
env.obj_stack.push (rest);
auto base = env.frame_stack.size ();
macro->obj->apply (env, 1);
env.run_with_base (base);
auto new_sexp = env.obj_stack.top ();
env.obj_stack.pop ();
return new_sexp;
}
#+end_src
******* define_prim_macro
#+begin_src cpp
void
define_prim_macro (env_t &env, name_t name, prim_fn fn)
{
auto name_vector = name_vector_t ();
name_vector.push_back ("body");
auto prim = make_prim (
name_vector, fn, obj_map_t ());
auto macro = make_macro (prim);
define (env, name, macro);
}
#+end_src
***** macro_compile
#+begin_src cpp
shared_ptr <jojo_t>
macro_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
return sexp_compile (
env,
static_scope,
macro_eval (env, sexp));
}
#+end_src
*** call_compile
***** apply_jo
******* apply_jo_t
#+begin_src cpp
struct apply_jo_t: jo_t
{
size_t arity;
apply_jo_t (size_t arity);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* apply_jo_t::apply_jo_t
#+begin_src cpp
apply_jo_t::
apply_jo_t (size_t arity)
{
this->arity = arity;
}
#+end_src
******* apply_jo_t::copy
#+begin_src cpp
jo_t *
apply_jo_t::copy ()
{
return new apply_jo_t (this->arity);
}
#+end_src
******* apply_jo_t::exe
#+begin_src cpp
void
apply_jo_t::exe (env_t &env, scope_t &scope)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
obj->apply (env, this->arity);
}
#+end_src
******* apply_jo_t::repr
#+begin_src cpp
string
apply_jo_t::repr (env_t &env)
{
return "(apply " +
to_string (this->arity) + ")";
}
#+end_src
***** arity_of_body
#+begin_src cpp
size_t
arity_of_body (env_t &env, shared_ptr <obj_t> body)
{
assert (list_p (body));
auto arity = 0;
while (! null_p (body)) {
auto head = car (body);
if (! sym_p (head)) {
arity++;
} else {
auto sym = as_sym (head) ->sym;
if (dot_word_p (sym)) {
// arity = arity;
} else if (sym == "drop") {
arity--;
} else if (sym == "dup") {
arity++;
} else if (sym == "over") {
arity++;
} else if (sym == "tuck") {
arity++;
} else if (sym == "swap") {
// arity = arity;
} else {
arity++;
}
}
body = cdr (body);
}
return arity;
}
#+end_src
***** call_compile
- the head still must be one word.
#+begin_src cpp
shared_ptr <jojo_t>
call_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
auto head = car (sexp);
auto body = cdr (sexp);
auto jo_vector = jo_vector_t ();
auto arity = arity_of_body (env, body);
jo_vector.push_back (new apply_jo_t (arity));
auto jojo = make_shared <jojo_t> (jo_vector);
auto head_jojo = sexp_compile (env, static_scope, head);
auto body_jojo = sexp_list_compile (env, static_scope, body);
jojo = jojo_append (head_jojo, jojo);
jojo = jojo_append (body_jojo, jojo);
return jojo;
}
#+end_src
*** call_with_arg_dict_compile
***** apply_to_arg_dict_jo
******* apply_to_arg_dict_jo_t
#+begin_src cpp
struct apply_to_arg_dict_jo_t: jo_t
{
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* apply_to_arg_dict_jo_t::copy
#+begin_src cpp
jo_t *
apply_to_arg_dict_jo_t::copy ()
{
return new apply_to_arg_dict_jo_t ();
}
#+end_src
******* apply_to_arg_dict_jo_t::exe
#+begin_src cpp
void
apply_to_arg_dict_jo_t::exe (
env_t &env,
scope_t &scope)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
obj->apply_to_arg_dict (env);
}
#+end_src
******* apply_to_arg_dict_jo_t::repr
#+begin_src cpp
string
apply_to_arg_dict_jo_t::repr (env_t &env)
{
return "(apply-to-arg-dict)";
}
#+end_src
***** apply_to_arg_dict
******* closure_o::apply_to_arg_dict
#+begin_src cpp
void
closure_o::apply_to_arg_dict (env_t &env)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto arg_dict = as_dict (obj);
auto bind_vector = bind_vector_merge_obj_map (
env, this->bind_vector, arg_dict->obj_map);
auto size = this->name_vector.size ();
auto have = number_of_obj_in_bind_vector (bind_vector);
if (size == have) {
auto scope = scope_extend (
this->scope, bind_vector);
auto frame = make_shared <frame_t> (
this->jojo, scope);
env.frame_stack.push (frame);
} else {
auto closure = make_closure (
this->name_vector,
this->jojo,
bind_vector,
this->scope);
env.obj_stack.push (closure);
}
}
#+end_src
******* prim_o::apply_to_arg_dict
#+begin_src cpp
void
prim_o::apply_to_arg_dict (env_t &env)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto arg_dict = as_dict (obj);
auto obj_map = obj_map_merge (
env, this->obj_map, arg_dict->obj_map);
auto size = this->name_vector.size ();
auto have = obj_map.size ();
if (size == have) {
this->fn (env, obj_map);
} else {
auto prim = make_prim (
this->name_vector,
this->fn,
obj_map);
env.obj_stack.push (prim);
}
}
#+end_src
******* data_o::apply_to_arg_dict
#+begin_src cpp
void
data_o::apply_to_arg_dict (env_t &env)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto arg_dict = as_dict (obj);
auto obj_map = obj_map_merge (
env, this->obj_map, arg_dict->obj_map);
// auto size = this->name_vector.size ();
// auto have = obj_map.size ();
auto data = make_data (
this->tag,
this->name_vector,
obj_map);
env.obj_stack.push (data);
}
#+end_src
***** call_with_arg_dict_sexp_p
#+begin_src cpp
bool
call_with_arg_dict_sexp_p (
env_t &env,
shared_ptr <obj_t> sexp)
{
if (! cons_p (sexp)) return false;
auto l = cdr (sexp);
while (! null_p (l)) {
auto head = car (l);
if (sym_p (head) and as_sym (head) ->sym == "=") {
return true;
}
if (cons_p (head)) {
auto head_head = car (head);
if (sym_p (head_head) and
as_sym (head_head) ->sym == "=")
{
return true;
}
}
l = cdr (l);
}
return false;
}
#+end_src
***** call_with_arg_dict_compile
#+begin_src cpp
shared_ptr <jojo_t>
call_with_arg_dict_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
auto head = car (sexp);
auto body = cdr (sexp);
auto jo_vector = jo_vector_t ();
jo_vector.push_back (new apply_to_arg_dict_jo_t ());
auto jojo = make_shared <jojo_t> (jo_vector);
auto head_jojo = sexp_compile (env, static_scope, head);
auto dict = sexp_list_to_dict (body);
auto body_jojo = dict_compile (env, static_scope, dict);
jojo = jojo_append (head_jojo, jojo);
jojo = jojo_append (body_jojo, jojo);
return jojo;
}
#+end_src
*** sexp_compile
#+begin_src cpp
shared_ptr <jojo_t>
sexp_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp)
{
if (str_p (sexp) or num_p (sexp)) {
return lit_compile (env, static_scope, sexp);
} else if (sym_p (sexp)) {
auto sym = as_sym (sexp);
return sym_compile (env, static_scope, sym);
} else if (vect_p (sexp)) {
return vect_compile (env, static_scope, as_vect (sexp));
} else if (dict_p (sexp)) {
return dict_compile (env, static_scope, as_dict (sexp));
} else if (keyword_sexp_p (env, sexp)) {
return keyword_compile (env, static_scope, sexp);
} else if (macro_sexp_p (env, sexp)) {
return macro_compile (env, static_scope, sexp);
} else if (call_with_arg_dict_sexp_p (env, sexp)) {
return call_with_arg_dict_compile (env, static_scope, sexp);
} else {
assert (cons_p (sexp));
return call_compile (env, static_scope, sexp);
}
}
#+end_src
*** sexp_list_compile
#+begin_src cpp
shared_ptr <jojo_t>
sexp_list_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> sexp_list)
{
auto jojo = make_shared <jojo_t> (jo_vector_t ());
if (null_p (sexp_list))
return jojo;
else {
assert (cons_p (sexp_list));
auto head_jojo = sexp_compile (
env, static_scope, car (sexp_list));
auto body_jojo = sexp_list_compile (
env, static_scope, cdr (sexp_list));
return jojo_append (head_jojo, body_jojo);
}
}
#+end_src
* run
*** top_keyword
***** top_keyword_fn
#+begin_src cpp
using top_keyword_fn = function
<void (env_t &, shared_ptr <obj_t>)>;
#+end_src
***** top_keyword_o
#+begin_src cpp
struct top_keyword_o: obj_t
{
top_keyword_fn fn;
top_keyword_o (top_keyword_fn fn);
bool eq (shared_ptr <obj_t> obj);
};
#+end_src
***** top_keyword_o::top_keyword_o
#+begin_src cpp
top_keyword_o::
top_keyword_o (top_keyword_fn fn)
{
this->tag = top_keyword_tag;
this->fn = fn;
}
#+end_src
***** top_keyword_o::eq
#+begin_src cpp
bool
top_keyword_o::eq (shared_ptr <obj_t> obj)
{
if (this->tag != obj->tag) return false;
return this != obj.get ();
}
#+end_src
***** top_keyword_p
#+begin_src cpp
bool
top_keyword_p (shared_ptr <obj_t> a)
{
return a->tag == top_keyword_tag;
}
#+end_src
***** define_top_keyword
#+begin_src cpp
void
define_top_keyword (env_t &env, name_t name, top_keyword_fn fn)
{
define (env, name, make_shared <top_keyword_o> (fn));
}
#+end_src
***** top_keyword_sexp_p
#+begin_src cpp
bool
top_keyword_sexp_p (env_t &env, shared_ptr <obj_t> sexp)
{
if (! cons_p (sexp)) return false;
if (! sym_p ((car (sexp)))) return false;
auto head = as_sym (car (sexp));
auto name = head->sym;
auto it = env.box_map.find (name);
if (it != env.box_map.end ()) {
auto box = it->second;
if (box->empty_p) return false;
if (top_keyword_p (box->obj)) return true;
else return false;
} else {
return false;
}
}
#+end_src
***** top_keyword_fn_from_name
#+begin_src cpp
top_keyword_fn
top_keyword_fn_from_name (env_t &env, name_t name)
{
auto it = env.box_map.find (name);
if (it != env.box_map.end ()) {
auto box = it->second;
if (box->empty_p) {
cout << "- fatal error: top_keyword_fn_from_name fail\n";
exit (1);
}
if (top_keyword_p (box->obj)) {
auto top_keyword = static_pointer_cast <top_keyword_o>
(box->obj);
return top_keyword->fn;
} else {
cout << "- fatal error: top_keyword_fn_from_name fail\n";
exit (1);
};
} else {
cout << "- fatal error: top_keyword_fn_from_name fail\n";
exit (1);
}
}
#+end_src
*** jojo_run
#+begin_src cpp
void
jojo_run (
env_t &env,
scope_t &scope,
shared_ptr <jojo_t> jojo)
{
auto base = env.frame_stack.size ();
env.frame_stack.push (make_shared <frame_t> (jojo, scope));
env.run_with_base (base);
}
#+end_src
*** jojo_eval
#+begin_src cpp
shared_ptr <obj_t>
jojo_eval (
env_t &env,
scope_t &scope,
shared_ptr <jojo_t> jojo)
{
jojo_run (env, scope, jojo);
auto result = env.obj_stack.top ();
env.obj_stack.pop ();
return result;
}
#+end_src
*** jojo_run_in_new_frame
#+begin_src cpp
void
jojo_run_in_new_frame (env_t &env, shared_ptr <jojo_t> jojo)
{
auto base = env.frame_stack.size ();
env.frame_stack.push (new_frame_from_jojo (jojo));
env.run_with_base (base);
}
#+end_src
*** jojo_eval_in_new_frame
#+begin_src cpp
shared_ptr <obj_t>
jojo_eval_in_new_frame (env_t &env, shared_ptr <jojo_t> jojo)
{
jojo_run_in_new_frame (env, jojo);
auto result = env.obj_stack.top ();
env.obj_stack.pop ();
return result;
}
#+end_src
*** sexp_run
#+begin_src cpp
void
sexp_run (env_t &env, shared_ptr <obj_t> sexp)
{
if (top_keyword_sexp_p (env, sexp)) {
cout << "- fatal error : sexp_run" << "\n";
cout << " can not handle top_keyword_sexp" << "\n";
cout << " sexp : " << sexp_repr (env, sexp) << "\n";
exit (1);
} else {
auto static_scope = static_scope_t ();
auto jojo = sexp_compile (env, static_scope, sexp);
jojo_run_in_new_frame (env, jojo);
}
}
#+end_src
*** sexp_list_run
#+begin_src cpp
void
sexp_list_run (env_t &env, shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list))
return;
else {
sexp_run (env, car (sexp_list));
sexp_list_run (env, cdr (sexp_list));
}
}
#+end_src
*** sexp_eval
#+begin_src cpp
shared_ptr <obj_t>
sexp_eval (env_t &env, shared_ptr <obj_t> sexp)
{
auto size_before = env.obj_stack.size ();
sexp_run (env, sexp);
auto size_after = env.obj_stack.size ();
if (size_after - size_before == 1) {
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
return obj;
} else {
cout << "- fatal error : sexp_eval mismatch" << "\n";
cout << " sexp must eval to one value" << "\n";
cout << " sexp : " << sexp_repr (env, sexp) << "\n";
cout << " stack size before : " << size_before << "\n";
cout << " stack size after : " << size_after << "\n";
exit (1);
}
}
#+end_src
*** top_sexp_run
#+begin_src cpp
void
top_sexp_run (env_t &env, shared_ptr <obj_t> sexp)
{
if (top_keyword_sexp_p (env, sexp)) {
auto head = as_sym (car (sexp));
auto body = cdr (sexp);
auto name = head->sym;
auto fn = top_keyword_fn_from_name (env, name);
fn (env, body);
} else {
auto static_scope = static_scope_t ();
auto jojo = sexp_compile (env, static_scope, sexp);
jojo_run_in_new_frame (env, jojo);
if (! env.obj_stack.empty ())
env.obj_stack.pop ();
}
}
#+end_src
*** top_sexp_list_run_without_infix_assign
#+begin_src cpp
void
top_sexp_list_run_without_infix_assign (
env_t &env,
shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list))
return;
else {
top_sexp_run (env, car (sexp_list));
top_sexp_list_run_without_infix_assign (
env,
cdr (sexp_list));
}
}
#+end_src
*** top_sexp_list_run
#+begin_src cpp
void
top_sexp_list_run (env_t &env, shared_ptr <obj_t> sexp_list)
{
top_sexp_list_run_without_infix_assign (
env, sexp_list_prefix_assign (sexp_list));
}
#+end_src
*** code_run
#+begin_src cpp
void
code_run (env_t &env, shared_ptr <str_o> code)
{
auto word_list = scan_word_list (code);
auto sexp_list = parse_sexp_list (word_list);
top_sexp_list_run (env, sexp_list);
}
#+end_src
*** code_from_module_path
#+begin_src cpp
shared_ptr <str_o>
code_from_module_path (env_t &env, path_t module_path)
{
auto input_file = ifstream (module_path);
auto buffer = stringstream ();
buffer << input_file.rdbuf ();
auto code = make_str (buffer.str ());
return code;
}
#+end_src
*** respect_current_dir
#+begin_src cpp
path_t
respect_current_dir (env_t &env, path_t p)
{
p = expend_path (p);
auto normal_path = path_t ();
if (p.is_absolute ()) {
normal_path = p;
} else {
assert (p.is_relative ());
normal_path = env.current_dir / p;
}
// normal_path = fs::canonical (normal_path);
return normal_path;
}
#+end_src
*** respect_module_path
#+begin_src cpp
path_t
respect_module_path (env_t &env, path_t p)
{
p = expend_path (p);
auto normal_path = path_t ();
if (p.is_absolute ()) {
normal_path = p;
} else {
assert (p.is_relative ());
normal_path = env.module_path.parent_path () / p;
}
// normal_path = fs::canonical (normal_path);
return normal_path;
}
#+end_src
*** env_from_module_path
#+begin_src cpp
void
expose_core (env_t &env);
env_t
env_from_module_path (path_t module_path)
{
auto env = env_t ();
module_path = respect_current_dir (env, module_path);
if (! fs::exists (module_path)) {
cout << "- fatal error : env_from_module_path" << "\n";
cout << " file does not exists : " << module_path << "\n";
exit (1);
}
if (! fs::is_regular_file (module_path)) {
cout << "- fatal error : env_from_module_path" << "\n";
cout << " not regular file : " << module_path << "\n";
exit (1);
}
env.module_path = module_path;
expose_core (env);
auto code = code_from_module_path (env, env.module_path);
code_run (env, code);
return env;
}
#+end_src
* assign
*** prefix_of_string
#+begin_src cpp
name_t
prefix_of_string (string str)
{
auto string_vector = string_split (str, '.');
assert (string_vector.size () > 0);
if (string_vector.size () == 1)
return "";
else {
string_vector.pop_back ();
return string_vector_join (string_vector, '.');
}
}
#+end_src
*** name_of_string
#+begin_src cpp
name_t
name_of_string (string str)
{
auto string_vector = string_split (str, '.');
assert (string_vector.size () > 0);
return string_vector [string_vector.size () - 1];
}
#+end_src
*** (= <name> (data ...))
***** assign_data_p
#+begin_src cpp
bool
assign_data_p (env_t &env, shared_ptr <obj_t> body)
{
if (! cons_p (body))
return false;
if (! sym_p (car (body)))
return false;
if (! cons_p (cdr (body)))
return false;
if (! cons_p (car (cdr (body))))
return false;
if (! sym_p (car (car (cdr (body)))))
return false;
auto sym = as_sym (car (car (cdr (body))));
if (sym->sym != "data")
return false;
if (null_p (cdr (car (cdr (body)))))
return true;
if (! sym_p (car (cdr (car (cdr (body))))))
return true;
else
return true;
}
#+end_src
***** tk_assign_data
#+begin_src cpp
void
tk_assign_data (env_t &env, shared_ptr <obj_t> body)
{
auto head = as_sym (car (body));
auto prefix = prefix_of_string (head->sym);
auto type_name = name_of_string (head->sym);
auto data_name = name_t2c (type_name);
auto pred_name = name_t2p (type_name);
auto tag_of_type = tagging (env, head->sym);
auto rest = cdr (body);
auto data_body = cdr ((car (rest)));
auto name_vect = list_to_vect (data_body);
auto name_vector = name_vector_t ();
for (auto obj: name_vect->obj_vector) {
auto sym = as_sym (obj);
name_vector.push_back (sym->sym);
}
assign_type
(env, prefix, type_name, tag_of_type, {});
assign_data
(env, prefix, data_name, tag_of_type, name_vector);
}
#+end_src
*** (= (<name> ...) ...)
***** assign_lambda_sugar_p
#+begin_src cpp
bool
assign_lambda_sugar_p (env_t &env, shared_ptr <obj_t> body)
{
if (! cons_p (body))
return false;
if (! cons_p (car (body)))
return false;
return true;
}
#+end_src
***** assign_lambda_desugar
#+begin_src cpp
shared_ptr <obj_t>
assign_lambda_desugar (env_t &env, shared_ptr <obj_t> body)
{
auto head = car (body);
auto name = car (head);
auto lambda_body = cdr (body);
lambda_body = cons_c (
list_to_vect (cdr (head)),
lambda_body);
lambda_body = cons_c (
make_sym ("lambda"),
lambda_body);
lambda_body = unit_list (lambda_body);
return cons_c (name, lambda_body);
}
#+end_src
*** (= <name> ...)
***** sexp_patch_this
#+begin_src cpp
shared_ptr <obj_t>
sexp_patch_this (env_t &env, shared_ptr <obj_t> sexp)
{
auto this_str = make_sym ("this");
obj_vector_t obj_vector = { this_str };
auto vect = make_vect (obj_vector);
auto lambda_body = unit_list (sexp);
lambda_body = cons_c (vect, lambda_body);
lambda_body = cons_c (make_sym ("lambda"), lambda_body);
return lambda_body;
}
#+end_src
***** tk_assign_value
#+begin_src cpp
void
tk_assign_value (env_t &env, shared_ptr <obj_t> body)
{
auto head = as_sym (car (body));
auto rest = cdr (body);
assert (null_p (cdr (rest)));
auto sexp = car (rest);
auto name = name_of_string (head->sym);
auto prefix = prefix_of_string (head->sym);
if (prefix != "")
sexp = sexp_patch_this (env, sexp);
auto obj = sexp_eval (env, sexp);
assign (env, prefix, name, obj);
}
#+end_src
*** tk_assign
#+begin_src cpp
void
tk_assign (env_t &env, shared_ptr <obj_t> body)
{
if (assign_data_p (env, body))
tk_assign_data (env, body);
else if (assign_lambda_sugar_p (env, body))
tk_assign_value (env, assign_lambda_desugar (env, body));
else
tk_assign_value (env, body);
}
#+end_src
* syntax
*** (do)
***** assign_sexp_p
#+begin_src cpp
bool
assign_sexp_p (
env_t &env,
shared_ptr <obj_t> sexp)
{
if (! cons_p (sexp)) return false;
auto head = car (sexp);
if (! sym_p (head)) return false;
auto sym = as_sym (head);
if (sym->sym != "=") return false;
return true;
}
#+end_src
***** assign_sexp_normalize
#+begin_src cpp
shared_ptr <obj_t>
assign_sexp_normalize (
env_t &env,
shared_ptr <obj_t> sexp)
{
auto head = car (sexp);
auto body = cdr (sexp);
if (assign_lambda_sugar_p (env, body))
return cons_c (
head,
assign_lambda_desugar (env, body));
else
return sexp;
}
#+end_src
***** do_body_trans
#+begin_src cpp
shared_ptr <obj_t>
do_body_trans (
env_t &env,
shared_ptr <obj_t> body)
{
if (null_p (body)) return body;
auto sexp = car (body);
auto rest = cdr (body);
if (null_p (rest))
return body;
else if (assign_sexp_p (env, sexp)) {
sexp = assign_sexp_normalize (env, sexp);
auto obj_vector = obj_vector_t ();
obj_vector.push_back (cdr (sexp));
auto let_sexp = cons_c (
make_sym ("let"),
cons_c (
make_vect (obj_vector),
rest));
return unit_list (let_sexp);
} else {
auto drop = unit_list (make_sym ("drop"));
body = do_body_trans (env, rest);
body = cons_c (drop, body);
body = cons_c (sexp, body);
return body;
}
}
#+end_src
***** k_do
#+begin_src cpp
shared_ptr <jojo_t>
k_do (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
body = sexp_list_prefix_assign (body);
body = do_body_trans (env, body);
return sexp_list_compile (env, static_scope, body);
}
#+end_src
*** (lambda)
***** lambda_jo
******* lambda_jo_t
#+begin_src cpp
struct lambda_jo_t: jo_t
{
name_vector_t name_vector;
shared_ptr <jojo_t> jojo;
lambda_jo_t (
name_vector_t name_vector,
shared_ptr <jojo_t> jojo);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* lambda_jo_t::lambda_jo_t
#+begin_src cpp
lambda_jo_t::
lambda_jo_t (
name_vector_t name_vector,
shared_ptr <jojo_t> jojo)
{
this->name_vector = name_vector;
this->jojo = jojo;
}
#+end_src
******* lambda_jo_t::copy
#+begin_src cpp
jo_t *
lambda_jo_t::copy ()
{
return new lambda_jo_t (this->name_vector, this->jojo);
}
#+end_src
******* lambda_jo_t::exe
#+begin_src cpp
void
lambda_jo_t::exe (env_t &env, scope_t &scope)
{
auto closure = make_closure (
this->name_vector,
this->jojo,
bind_vector_from_name_vector (this->name_vector),
scope);
env.obj_stack.push (closure);
}
#+end_src
******* lambda_jo_t::repr
#+begin_src cpp
string
lambda_jo_t::repr (env_t &env)
{
return "(lambda " +
name_vector_repr (this->name_vector) +
" " +
jojo_repr (env, this->jojo) +
")";
}
#+end_src
***** obj_vector_to_name_vector
#+begin_src cpp
name_vector_t
obj_vector_to_name_vector (env_t &env, obj_vector_t &obj_vect)
{
auto name_vector = name_vector_t ();
for (auto &obj: obj_vect) {
auto sym = as_sym (obj);
name_vector.push_back (sym->sym);
}
return name_vector;
}
#+end_src
***** k_lambda
#+begin_src cpp
shared_ptr <jojo_t>
k_lambda (
env_t &env,
static_scope_t &old_static_scope,
shared_ptr <obj_t> body)
{
auto name_vect = as_vect (car (body));
auto rest = cdr (body);
auto name_vector = obj_vector_to_name_vector (
env, name_vect->obj_vector);
auto static_scope = static_scope_extend (
env, old_static_scope, name_vector);
auto rest_jojo = sexp_compile (
env, static_scope,
cons_c (
make_sym ("do"),
rest));
jo_vector_t jo_vector = {
new lambda_jo_t (name_vector, rest_jojo),
};
return make_shared <jojo_t> (jo_vector);
}
#+end_src
*** (let)
***** m_let
#+begin_src cpp
void
m_let (env_t &env, obj_map_t &obj_map)
{
auto body = obj_map ["body"];
auto head = car (body);
auto rest = cdr (body);
auto binding_vect = as_vect (head);
binding_vect = vect_reverse (binding_vect);
rest = cons_c (make_sym ("do"), rest);
for (auto binding: binding_vect->obj_vector) {
auto name = car (binding);
auto obj = car (cdr (binding));
rest = unit_list (rest);
rest = cons_c (unit_vect (name), rest);
rest = cons_c (make_sym ("lambda"), rest);
rest = cons_c (rest, unit_list (obj));
}
env.obj_stack.push (rest);
}
#+end_src
*** (macro)
***** macro_maker_jo
******* macro_maker_jo_t
#+begin_src cpp
struct macro_maker_jo_t: jo_t
{
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* macro_maker_jo_t::copy
#+begin_src cpp
jo_t *
macro_maker_jo_t::copy ()
{
return new macro_maker_jo_t ();
}
#+end_src
******* macro_maker_jo_t::exe
#+begin_src cpp
void
macro_maker_jo_t::exe (env_t &env, scope_t &scope)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
if (closure_p (obj)) {
auto macro = make_macro (obj);
env.obj_stack.push (macro);
} else {
cout << "- fatal error : macro_maker_jo_t::exe" << "\n";
cout << " can only make macro from closure" << "\n";
exit (1);
}
}
#+end_src
******* macro_maker_jo_t::repr
#+begin_src cpp
string
macro_maker_jo_t::repr (env_t &env)
{
return "(macro_maker)";
}
#+end_src
***** k_macro
#+begin_src cpp
shared_ptr <jojo_t>
k_macro (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto jo_vector = jo_vector_t ();
jo_vector.push_back (new macro_maker_jo_t ());
auto lambda_jojo = k_lambda (env, static_scope, body);
auto jojo = make_shared <jojo_t> (jo_vector);
return jojo_append (lambda_jojo, jojo);
}
#+end_src
*** (case)
***** case_jo
******* case_jo_t
#+begin_src cpp
struct case_jo_t: jo_t
{
jojo_map_t jojo_map;
shared_ptr <jojo_t> default_jojo;
case_jo_t (jojo_map_t jojo_map);
case_jo_t (
jojo_map_t jojo_map,
shared_ptr <jojo_t> default_jojo);
bool has_default_jojo_p ();
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* case_jo_t::case_jo_t
#+begin_src cpp
case_jo_t::
case_jo_t (jojo_map_t jojo_map)
{
this->jojo_map = jojo_map;
this->default_jojo = nullptr;
}
case_jo_t::
case_jo_t (jojo_map_t jojo_map,
shared_ptr <jojo_t> default_jojo)
{
this->jojo_map = jojo_map;
this->default_jojo = default_jojo;
}
#+end_src
******* case_jo_t::has_default_jojo_p
#+begin_src cpp
bool
case_jo_t::has_default_jojo_p ()
{
return this->default_jojo != nullptr;
}
#+end_src
******* case_jo_t::copy
#+begin_src cpp
jo_t *
case_jo_t::copy ()
{
return new case_jo_t
(this->jojo_map,
this->default_jojo);
}
#+end_src
******* case_jo_t::exe
#+begin_src cpp
void
case_jo_t::exe (env_t &env, scope_t &scope)
{
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
auto it = this->jojo_map.find (obj->tag);
if (it != this->jojo_map.end ()) {
auto jojo = it->second;
auto frame = make_shared <frame_t> (jojo, scope);
env.frame_stack.push (frame);
} else if (this->has_default_jojo_p ()) {
auto jojo = this->default_jojo;
auto frame = make_shared <frame_t> (jojo, scope);
env.frame_stack.push (frame);
} else {
cout << "- fatal error : case_jo_t::exe mismatch" << "\n";
cout << " tag : " << obj->tag << "\n";
exit (1);
}
}
#+end_src
******* [todo] case_jo_t::repr
#+begin_src cpp
string
case_jo_t::repr (env_t &env)
{
return "(case)";
}
#+end_src
***** case_compile
#+begin_src cpp
shared_ptr <jojo_t>
case_compile (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto jojo_map = jojo_map_t ();
shared_ptr <jojo_t> default_jojo = nullptr;
while (! null_p (body)) {
auto one = car (body);
auto head = as_sym (car (one));
auto rest = cdr (one);
auto name = head->sym;
if (name == "_") {
auto jojo = sexp_list_compile (env, static_scope, rest);
body = cdr (body);
default_jojo = jojo;
} else {
auto tag = tagging (env, name);
auto jojo = sexp_list_compile (env, static_scope, rest);
jojo_map [tag] = jojo;
body = cdr (body);
}
}
jo_vector_t jo_vector = {
new case_jo_t (jojo_map, default_jojo),
};
return make_shared <jojo_t> (jo_vector);
}
#+end_src
***** k_case
#+begin_src cpp
shared_ptr <jojo_t>
k_case (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto head = car (body);
auto rest = cdr (body);
auto head_jojo = sexp_compile (env, static_scope, head);
auto rest_jojo = case_compile (env, static_scope, rest);
return jojo_append (head_jojo, rest_jojo);
}
#+end_src
*** (quote)
***** sexp_qoute_compile
#+begin_src cpp
shared_ptr <jojo_t>
sexp_qoute_compile (
env_t &env,
shared_ptr <obj_t> sexp)
{
jo_vector_t jo_vector = {
new lit_jo_t (sexp),
};
auto jojo = make_shared <jojo_t> (jo_vector);
return jojo;
}
#+end_src
***** k_quote
#+begin_src cpp
shared_ptr <jojo_t>
k_quote (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
assert (cons_p (body));
assert (null_p (cdr (body)));
auto sexp = car (body);
return sexp_qoute_compile (env, sexp);
}
#+end_src
*** (*) -- literal list
***** collect_list_jo
******* collect_list_jo_t
#+begin_src cpp
struct collect_list_jo_t: jo_t
{
size_t counter;
collect_list_jo_t (size_t counter);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* collect_list_jo_t::collect_list_jo_t
#+begin_src cpp
collect_list_jo_t::
collect_list_jo_t (size_t counter)
{
this->counter = counter;
}
#+end_src
******* collect_list_jo_t::copy
#+begin_src cpp
jo_t *
collect_list_jo_t::copy ()
{
return new collect_list_jo_t (this->counter);
}
#+end_src
******* collect_list_jo_t::exe
#+begin_src cpp
void
collect_list_jo_t::exe (env_t &env, scope_t &scope)
{
size_t index = 0;
auto collection = null_c ();
while (index < this->counter) {
auto obj = env.obj_stack.top ();
env.obj_stack.pop ();
collection = cons_c (obj, collection);
index++;
}
env.obj_stack.push (collection);
}
#+end_src
******* collect_list_jo_t::repr
#+begin_src cpp
string
collect_list_jo_t::repr (env_t &env)
{
return "(collect-list " + to_string (this->counter) + ")";
}
#+end_src
***** k_list
#+begin_src cpp
shared_ptr <jojo_t>
k_list (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto sexp_list = body;
auto jojo = sexp_list_compile
(env, static_scope, sexp_list);
auto counter = list_size (sexp_list);
jo_vector_t jo_vector = {
new collect_list_jo_t (counter),
};
auto ending_jojo = make_shared <jojo_t> (jo_vector);
return jojo_append (jojo, ending_jojo);
}
#+end_src
*** (note)
***** k_note
#+begin_src cpp
shared_ptr <jojo_t>
k_note (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
body = cons_c (make_sym ("note"), body);
jo_vector_t jo_vector = {
new lit_jo_t (body),
};
auto jojo = make_shared <jojo_t> (jo_vector);
return jojo;
}
#+end_src
*** (assert)
***** assert_jo
******* assert_jo_t
#+begin_src cpp
struct assert_jo_t: jo_t
{
shared_ptr <obj_t> body;
shared_ptr <jojo_t> jojo;
assert_jo_t (
shared_ptr <obj_t> body,
shared_ptr <jojo_t> jojo);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* assert_jo_t::assert_jo_t
#+begin_src cpp
assert_jo_t::
assert_jo_t (
shared_ptr <obj_t> body,
shared_ptr <jojo_t> jojo)
{
this->body = body;
this->jojo = jojo;
}
#+end_src
******* assert_jo_t::copy
#+begin_src cpp
jo_t *
assert_jo_t::copy ()
{
return new assert_jo_t
(this->body,
this->jojo);
}
#+end_src
******* assert_jo_t::exe
#+begin_src cpp
void
assert_jo_t::exe (env_t &env, scope_t &scope)
{
auto base = env.frame_stack.size ();
env.frame_stack.push (
make_shared <frame_t> (
this->jojo,
scope));
env.run_with_base (base);
auto result = env.obj_stack.top ();
if (true_p (result)) {
return;
} else {
env.frame_stack_report ();
env.obj_stack_report ();
cout << "- assert fail : " << "\n";
cout << " " << sexp_list_repr (env, this->body) << "\n";
exit (1);
}
}
#+end_src
******* assert_jo_t::repr
#+begin_src cpp
string
assert_jo_t::repr (env_t &env)
{
return "(assert)";
}
#+end_src
***** k_assert
#+begin_src cpp
shared_ptr <jojo_t>
k_assert (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto jojo = sexp_list_compile (env, static_scope, body);
jo_vector_t jo_vector = {
new assert_jo_t (body, jojo),
};
return make_shared <jojo_t> (jo_vector);
}
#+end_src
*** (if)
***** if_jo
******* if_jo_t
#+begin_src cpp
struct if_jo_t: jo_t
{
shared_ptr <jojo_t> pred_jojo;
shared_ptr <jojo_t> then_jojo;
shared_ptr <jojo_t> else_jojo;
if_jo_t (
shared_ptr <jojo_t> pred_jojo,
shared_ptr <jojo_t> then_jojo,
shared_ptr <jojo_t> else_jojo);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* if_jo_t::if_jo_t
#+begin_src cpp
if_jo_t::
if_jo_t (
shared_ptr <jojo_t> pred_jojo,
shared_ptr <jojo_t> then_jojo,
shared_ptr <jojo_t> else_jojo)
{
this->pred_jojo = pred_jojo;
this->then_jojo = then_jojo;
this->else_jojo = else_jojo;
}
#+end_src
******* if_jo_t::copy
#+begin_src cpp
jo_t *
if_jo_t::copy ()
{
return new if_jo_t
(this->pred_jojo,
this->then_jojo,
this->else_jojo);
}
#+end_src
******* if_jo_t::exe
#+begin_src cpp
void
if_jo_t::exe (env_t &env, scope_t &scope)
{
auto result = jojo_eval (env, scope, pred_jojo);
if (true_p (result)) {
env.frame_stack.push (
make_shared <frame_t> (
this->then_jojo,
scope));
} else if (false_p (result)) {
env.frame_stack.push (
make_shared <frame_t> (
this->else_jojo,
scope));
} else {
cout << "- fatal error : if_jo_t::exe" << "\n";
cout << " pred_jojo run to non bool value" << "\n";
exit (1);
}
}
#+end_src
******* if_jo_t::repr
#+begin_src cpp
string
if_jo_t::repr (env_t &env)
{
return "(if)";
}
#+end_src
***** k_if
#+begin_src cpp
shared_ptr <jojo_t>
k_if (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto size = list_size (body);
assert (size == 3);
auto pred_sexp = car (body);
auto then_sexp = car (cdr (body));
auto else_sexp = car (cdr (cdr (body)));
auto pred_jojo = sexp_compile (env, static_scope, pred_sexp);
auto then_jojo = sexp_compile (env, static_scope, then_sexp);
auto else_jojo = sexp_compile (env, static_scope, else_sexp);
jo_vector_t jo_vector = {
new if_jo_t (pred_jojo, then_jojo, else_jojo),
};
return make_shared <jojo_t> (jo_vector);
}
#+end_src
*** (when)
***** when_jo
******* when_jo_t
#+begin_src cpp
struct when_jo_t: jo_t
{
shared_ptr <jojo_t> pred_jojo;
shared_ptr <jojo_t> then_jojo;
when_jo_t (
shared_ptr <jojo_t> pred_jojo,
shared_ptr <jojo_t> then_jojo);
jo_t * copy ();
void exe (env_t &env, scope_t &scope);
string repr (env_t &env);
};
#+end_src
******* when_jo_t::when_jo_t
#+begin_src cpp
when_jo_t::
when_jo_t (
shared_ptr <jojo_t> pred_jojo,
shared_ptr <jojo_t> then_jojo)
{
this->pred_jojo = pred_jojo;
this->then_jojo = then_jojo;
}
#+end_src
******* when_jo_t::copy
#+begin_src cpp
jo_t *
when_jo_t::copy ()
{
return new when_jo_t
(this->pred_jojo,
this->then_jojo);
}
#+end_src
******* when_jo_t::exe
#+begin_src cpp
void
when_jo_t::exe (env_t &env, scope_t &scope)
{
auto result = jojo_eval (env, scope, pred_jojo);
if (true_p (result)) {
env.frame_stack.push (
make_shared <frame_t> (
this->then_jojo,
scope));
} else if (false_p (result)) {
env.obj_stack.push (result);
} else {
cout << "- fatal error : when_jo_t::exe" << "\n";
cout << " pred_jojo run to non bool value" << "\n";
exit (1);
}
}
#+end_src
******* when_jo_t::repr
#+begin_src cpp
string
when_jo_t::repr (env_t &env)
{
return "(when)";
}
#+end_src
***** k_when
#+begin_src cpp
shared_ptr <jojo_t>
k_when (
env_t &env,
static_scope_t &static_scope,
shared_ptr <obj_t> body)
{
auto size = list_size (body);
assert (size == 2);
auto pred_sexp = car (body);
auto then_sexp = car (cdr (body));
auto pred_jojo = sexp_compile (env, static_scope, pred_sexp);
auto then_jojo = sexp_compile (env, static_scope, then_sexp);
jo_vector_t jo_vector = {
new when_jo_t (pred_jojo, then_jojo),
};
return make_shared <jojo_t> (jo_vector);
}
#+end_src
*** (quasiquote)
***** sexp_quote_and_unquote
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_quote_and_unquote (
env_t &env,
shared_ptr <obj_t> sexp_list);
shared_ptr <obj_t>
sexp_quote_and_unquote (
env_t &env,
shared_ptr <obj_t> sexp)
{
if (str_p (sexp) or num_p (sexp)) {
return sexp;
} else if (sym_p (sexp)) {
return cons_c (
make_sym ("quote"),
unit_list (sexp));
} else if (null_p (sexp)) {
return cons_c (
make_sym ("quote"),
unit_list (sexp));
} else if (vect_p (sexp)) {
auto l = vect_to_list (as_vect (sexp));
return cons_c (
make_sym ("list-to-vect"),
unit_list (sexp_list_quote_and_unquote (env, l)));
} else if (dict_p (sexp)) {
auto l = dict_to_list (as_dict (sexp));
return cons_c (
make_sym ("list-to-dict"),
unit_list (sexp_list_quote_and_unquote (env, l)));
} else {
assert (cons_p (sexp));
auto head = car (sexp);
if (sym_p (head) and as_sym (head) ->sym == "unquote") {
auto rest = cdr (sexp);
assert (cons_p (rest));
assert (null_p (cdr (rest)));
return car (rest);
} else {
return sexp_list_quote_and_unquote (
env,
sexp);
}
}
}
#+end_src
***** sexp_list_quote_and_unquote
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_quote_and_unquote (
env_t &env,
shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list)) {
return unit_list (make_sym ("*"));
} else {
assert (cons_p (sexp_list));
auto sexp = car (sexp_list);
if (cons_p (sexp) and
sym_p (car (sexp)) and
as_sym (car (sexp)) ->sym == "unquote-splicing")
{
auto rest = cdr (sexp);
assert (cons_p (rest));
assert (null_p (cdr (rest)));
sexp = car (rest);
} else {
sexp = cons_c (
make_sym ("*"),
unit_list (sexp_quote_and_unquote (env, sexp)));
}
auto result = sexp_list_quote_and_unquote (
env, cdr (sexp_list));
result = unit_list (result);
result = cons_c (sexp, result);
result = cons_c (make_sym ("list-append"), result);
return result;
}
}
#+end_src
***** m_quasiquote
#+begin_src cpp
void
m_quasiquote (
env_t &env,
obj_map_t &obj_map)
{
auto body = obj_map ["body"];
assert (cons_p (body));
assert (null_p (cdr (body)));
auto sexp = car (body);
auto new_sexp = sexp_quote_and_unquote (env, sexp);
env.obj_stack.push (new_sexp);
}
#+end_src
*** (and)
***** sexp_list_and
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_and (env_t &env, shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list)) {
return make_sym ("true-c");
} else if (null_p (cdr (sexp_list))) {
return car (sexp_list);
} else {
auto head = car (sexp_list);
auto rest = cdr (sexp_list);
head = cons_c (
make_sym ("not"),
unit_list (head));
auto result = unit_list (sexp_list_and (env, rest));
result = cons_c (
make_sym ("false-c"),
result);
result = cons_c (
head,
result);
result = cons_c (
make_sym ("if"),
result);
return result;
}
}
#+end_src
***** m_and
#+begin_src cpp
void
m_and (env_t &env, obj_map_t &obj_map)
{
auto body = obj_map ["body"];
env.obj_stack.push (sexp_list_and (env, body));
}
#+end_src
*** (or)
***** sexp_list_or
#+begin_src cpp
shared_ptr <obj_t>
sexp_list_or (env_t &env, shared_ptr <obj_t> sexp_list)
{
if (null_p (sexp_list)) {
return make_sym ("false-c");
} else if (null_p (cdr (sexp_list))) {
return car (sexp_list);
} else {
auto head = car (sexp_list);
auto rest = cdr (sexp_list);
auto result = unit_list (sexp_list_or (env, rest));
result = cons_c (
make_sym ("true-c"),
result);
result = cons_c (
head,
result);
result = cons_c (
make_sym ("if"),
result);
return result;
}
}
#+end_src
***** m_or
#+begin_src cpp
void
m_or (env_t &env, obj_map_t &obj_map)
{
auto body = obj_map ["body"];
env.obj_stack.push (sexp_list_or (env, body));
}
#+end_src
*** (cond)
***** vect_list_cond
#+begin_src cpp
shared_ptr <obj_t>
vect_list_cond (env_t &env, shared_ptr <obj_t> vect_list)
{
assert (! null_p (vect_list));
auto head = car (vect_list);
auto rest = cdr (vect_list);
auto l = vect_to_list (as_vect (head));
auto question = car (l);
auto answer = cons_c (
make_sym ("do"),
cdr (l));
if (null_p (rest)) {
if (sym_p (question) and
as_sym (question) ->sym == "else")
{
return answer;
} else {
auto result = null_c ();
result = cons_c (answer, result);
result = cons_c (question, result);
result = cons_c (make_sym ("when"), result);
return result;
}
} else {
auto result = unit_list (vect_list_cond (env, rest));
result = cons_c (answer, result);
result = cons_c (question, result);
result = cons_c (make_sym ("if"), result);
return result;
}
}
#+end_src
***** m_cond
#+begin_src cpp
void
m_cond (env_t &env, obj_map_t &obj_map)
{
auto body = obj_map ["body"];
env.obj_stack.push (vect_list_cond (env, body));
}
#+end_src
* expose
*** expose_type
#+begin_src cpp
void
expose_type (env_t &env)
{
define_prim (
env, { "type-of", "obj" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["obj"];
env.obj_stack.push (type_of (env, obj));
});
}
#+end_src
*** expose_bool
#+begin_src cpp
void
expose_bool (env_t &env)
{
define (env, "true-c", true_c ());
define (env, "true", true_c ());
define (env, "false-c", false_c ());
define (env, "false", false_c ());
define_prim (
env, { "not", "bool" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["bool"];
assert (bool_p (obj));
env.obj_stack.push (make_bool (false_p (obj)));
});
}
#+end_src
*** expose_num
***** expose_num_predicate
#+begin_src cpp
void
expose_num_predicate (env_t &env)
{
define_prim (
env, { "lt", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push (make_bool (x->num < y->num));
});
define_prim (
env, { "gt", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push (make_bool (x->num > y->num));
});
define_prim (
env, { "lteq", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push (make_bool (x->num <= y->num));
});
define_prim (
env, { "gteq", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push (make_bool (x->num >= y->num));
});
define_prim (
env, { "even-p", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push (make_bool (0 == fmod (x->num, 2)));
});
define_prim (
env, { "odd-p", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push (make_bool (1 == fmod (x->num, 2)));
});
}
#+end_src
***** expose_num_1
#+begin_src cpp
void
expose_num_1 (env_t &env)
{
define_prim (
env, { "inc", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (x->num + 1));
});
define_prim (
env, { "dec", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (x->num - 1));
});
define_prim (
env, { "add", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (x->num + y->num));
});
define_prim (
env, { "sub", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (x->num - y->num));
});
define_prim (
env, { "max", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (fmax (x->num, y->num)));
});
define_prim (
env, { "min", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (fmin (x->num, y->num)));
});
define_prim (
env, { "neg", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (- x->num));
});
define_prim (
env, { "abs", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (fabs (x->num)));
});
}
#+end_src
***** expose_num_2
#+begin_src cpp
void
expose_num_2 (env_t &env)
{
define_prim (
env, { "mul", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (x->num * y->num));
});
define_prim (
env, { "div", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (x->num / y->num));
});
define_prim (
env, { "mod", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (fmod (x->num, y->num)));
});
define_prim (
env, { "hypot", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (hypot (x->num, y->num)));
});
define_prim (
env, { "sqrt", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (sqrt (x->num)));
});
define_prim (
env, { "cbrt", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (cbrt (x->num)));
});
}
#+end_src
***** expose_num_3
#+begin_src cpp
void
expose_num_3 (env_t &env)
{
define_prim (
env, { "pow", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (pow (x->num, y->num)));
});
define_prim (
env, { "expe", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (exp (x->num)));
});
define_prim (
env, { "exp2", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (exp2 (x->num)));
});
define_prim (
env, { "expm1", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (expm1 (x->num)));
});
define_prim (
env, { "loge", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (log (x->num)));
});
define_prim (
env, { "log10", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (log10 (x->num)));
});
define_prim (
env, { "log2", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (log2 (x->num)));
});
define_prim (
env, { "log1p", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (log1p (x->num)));
});
}
#+end_src
***** expose_num_trigonometry
#+begin_src cpp
void
expose_num_trigonometry (env_t &env)
{
define_prim (
env, { "sin", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (sin (x->num)));
});
define_prim (
env, { "cos", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (cos (x->num)));
});
define_prim (
env, { "tan", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (tan (x->num)));
});
define_prim (
env, { "asin", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (asin (x->num)));
});
define_prim (
env, { "acos", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (acos (x->num)));
});
define_prim (
env, { "atan", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (atan (x->num)));
});
define_prim (
env, { "atan2", "x", "y" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
auto y = as_num (obj_map ["y"]);
env.obj_stack.push
(make_num (atan2 (x->num, y->num)));
});
define_prim (
env, { "sinh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (sinh (x->num)));
});
define_prim (
env, { "cosh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (cosh (x->num)));
});
define_prim (
env, { "tanh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (tanh (x->num)));
});
define_prim (
env, { "asinh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (asinh (x->num)));
});
define_prim (
env, { "acosh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (acosh (x->num)));
});
define_prim (
env, { "atanh", "x" },
[] (env_t &env, obj_map_t &obj_map)
{
auto x = as_num (obj_map ["x"]);
env.obj_stack.push
(make_num (atanh (x->num)));
});
}
#+end_src
***** expose_num
#+begin_src cpp
void
expose_num (env_t &env)
{
expose_num_predicate (env);
expose_num_1 (env);
expose_num_2 (env);
expose_num_3 (env);
expose_num_trigonometry (env);
}
#+end_src
*** expose_str
#+begin_src cpp
void
expose_str (env_t &env)
{
define_prim (
env, { "str-print", "str" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["str"];
auto str = as_str (obj);
cout << str->str;
env.obj_stack.push (str);
});
define_prim (
env, { "str-length", "str" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_length (as_str (obj_map ["str"])));
});
define_prim (
env, { "str-append", "ante", "succ" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_append (
as_str (obj_map ["ante"]),
as_str (obj_map ["succ"])));
});
define_prim (
env, { "str-slice", "str", "begin", "end" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_slice (
as_str (obj_map ["str"]),
as_num (obj_map ["begin"]),
as_num (obj_map ["end"])));
});
define_prim (
env, { "str-ref", "str", "index" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_ref (
as_str (obj_map ["str"]),
as_num (obj_map ["index"])));
});
define_prim (
env, { "str-head", "str" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_head (as_str (obj_map ["str"])));
});
define_prim (
env, { "str-rest", "str" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
str_rest (as_str (obj_map ["str"])));
});
}
#+end_src
*** expose_sym
#+begin_src cpp
void
expose_sym (env_t &env)
{
define_prim (
env, { "sym-print", "sym" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["sym"];
assert (sym_p (obj));
auto sym = as_sym (obj);
cout << sym->sym;
env.obj_stack.push (sym);
});
define_prim (
env, { "sym-length", "sym" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_length (
as_sym (obj_map ["sym"])));
});
define_prim (
env, { "sym-append", "ante", "succ" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_append (
as_sym (obj_map ["ante"]),
as_sym (obj_map ["succ"])));
});
define_prim (
env, { "sym-slice", "sym", "begin", "end" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_slice (
as_sym (obj_map ["sym"]),
as_num (obj_map ["begin"]),
as_num (obj_map ["end"])));
});
define_prim (
env, { "sym-ref", "sym", "index" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_ref (
as_sym (obj_map ["sym"]),
as_num (obj_map ["index"])));
});
define_prim (
env, { "sym-head", "sym" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_head (as_sym (obj_map ["sym"])));
});
define_prim (
env, { "sym-rest", "sym" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
sym_rest (as_sym (obj_map ["sym"])));
});
}
#+end_src
*** expose_list
***** jj_cons_c
#+begin_src cpp
shared_ptr <data_o>
jj_cons_c ()
{
return make_data (
cons_tag,
name_vector_t ({ "car", "cdr" }),
obj_map_t ());
}
#+end_src
***** expose_list
#+begin_src cpp
void
expose_list (env_t &env)
{
define (env, "null-c", null_c ());
define (env, "null", null_c ());
define (env, "cons-c", jj_cons_c ());
define (env, "cons", jj_cons_c ());
define_prim (
env, { "list-length", "list" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
list_length (obj_map ["list"]));
});
define_prim (
env, { "list-reverse", "list" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
list_reverse (obj_map ["list"]));
});
define_prim (
env, { "list-append", "ante", "succ" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
list_append (
obj_map ["ante"],
obj_map ["succ"]));
});
}
#+end_src
*** expose_vect
#+begin_src cpp
void
expose_vect (env_t &env)
{
define_prim (
env, { "list-to-vect", "list" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
list_to_vect (
obj_map ["list"]));
});
define_prim (
env, { "vect-to-list", "vect" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_to_list (as_vect (obj_map ["vect"])));
});
define_prim (
env, { "vect-length", "vect" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_length (as_vect (obj_map ["vect"])));
});
define_prim (
env, { "vect-append", "ante", "succ" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_append (
as_vect (obj_map ["ante"]),
as_vect (obj_map ["succ"])));
});
define_prim (
env, { "vect-slice", "vect", "begin", "end" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_slice (
as_vect (obj_map ["vect"]),
as_num (obj_map ["begin"]),
as_num (obj_map ["end"])));
});
define_prim (
env, { "vect-ref", "vect", "index" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_ref (
as_vect (obj_map ["vect"]),
as_num (obj_map ["index"])));
});
define_prim (
env, { "vect-head", "vect" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_head (as_vect (obj_map ["vect"])));
});
define_prim (
env, { "vect-rest", "vect" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_rest (as_vect (obj_map ["vect"])));
});
define_prim (
env, { "unit-vect", "obj" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
unit_vect (obj_map ["obj"]));
});
define_prim (
env, { "vect-reverse", "vect" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
vect_reverse (as_vect (obj_map ["vect"])));
});
}
#+end_src
*** expose_maybe
***** jj_just_c
#+begin_src cpp
shared_ptr <data_o>
jj_just_c ()
{
return make_data (
just_tag,
name_vector_t ({ "value" }),
obj_map_t ());
}
#+end_src
***** expose_maybe
#+begin_src cpp
void
expose_maybe (env_t &env)
{
define (env, "nothing-c", nothing_c ());
define (env, "nothing", nothing_c ());
define (env, "just-c", jj_just_c ());
define (env, "just", jj_just_c ());
}
#+end_src
*** expose_dict
#+begin_src cpp
void
expose_dict (env_t &env)
{
define_prim (
env, { "list-to-dict", "list" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
list_to_dict (
obj_map ["list"]));
});
define_prim (
env, { "dict-to-list", "dict" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_to_list (as_dict (obj_map ["dict"])));
});
define_prim (
env, { "dict-length", "dict" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_length (as_dict (obj_map ["dict"])));
});
define_prim (
env, { "dict-key-list", "dict" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_key_list (as_dict (obj_map ["dict"])));
});
define_prim (
env, { "dict-value-list", "dict" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_value_list (as_dict (obj_map ["dict"])));
});
define_prim (
env, { "dict-insert", "dict", "key", "value" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_insert (
as_dict (obj_map ["dict"]),
as_sym (obj_map ["key"]),
obj_map ["value"]));
});
define_prim (
env, { "dict-merge", "ante", "succ" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_merge (
as_dict (obj_map ["ante"]),
as_dict (obj_map ["succ"])));
});
define_prim (
env, { "dict-find", "dict", "key" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
dict_find (
as_dict (obj_map ["dict"]),
as_sym (obj_map ["key"])));
});
}
#+end_src
*** expose_sexp
#+begin_src cpp
void
expose_sexp (env_t &env)
{
define_prim (
env, { "scan-word-list", "code" },
[] (env_t &env, obj_map_t &obj_map)
{
// -- str-t -> (list-t str-t)
env.obj_stack.push (
scan_word_list (as_str (obj_map ["code"])));
});
define_prim (
env, { "parse-sexp", "word-list" },
[] (env_t &env, obj_map_t &obj_map)
{
// -- (list-t str-t) -> sexp-t
env.obj_stack.push (parse_sexp (obj_map ["word-list"]));
});
define_prim (
env, { "parse-sexp-list", "word-list" },
[] (env_t &env, obj_map_t &obj_map)
{
// -- (list-t str-t) -> (list-t sexp-t)
env.obj_stack.push (
parse_sexp_list (obj_map ["word-list"]));
});
define_prim (
env, { "sexp-repr", "sexp" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
make_str (sexp_repr (env, obj_map ["sexp"])));
});
define_prim (
env, { "sexp-list-repr", "sexp-list" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (
make_str (sexp_list_repr (env, obj_map ["sexp-list"])));
});
}
#+end_src
*** expose_top_keyword
#+begin_src cpp
void
expose_top_keyword (env_t &env)
{
}
#+end_src
*** expose_keyword
#+begin_src cpp
void
expose_keyword (env_t &env)
{
}
#+end_src
*** expose_system
#+begin_src cpp
void
expose_system (env_t &env)
{
define_prim (
env, { "system-env-find", "name" },
[] (env_t &env, obj_map_t &obj_map)
{
// -- str-t -> str-t
auto str = as_str (obj_map ["name"]);
auto name = str->str;
env.obj_stack.push (make_str (system_env_find (name)));
});
}
#+end_src
*** expose_module
***** jj_import
#+begin_src cpp
sig_t jj_import_sig = { "import", "module-path" };
// -- str-t -> module-t
void jj_import (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["module-path"];
auto str = as_str (obj);
auto module_path = path_t (str->str);
module_path = respect_module_path
(env, module_path);
auto module_env = env_from_module_path (module_path);
auto mod = make_shared <module_o> (module_env);
env.obj_stack.push (mod);
}
#+end_src
***** expose_module
#+begin_src cpp
void
expose_module (env_t &env)
{
define_prim (env,
jj_import_sig,
jj_import);
}
#+end_src
*** expose_stack
#+begin_src cpp
void
expose_stack (env_t &env)
{
define_prim (
env, { "drop" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.pop ();
});
define_prim (
env, { "dup" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = env.obj_stack.top ();
env.obj_stack.push (obj);
});
define_prim (
env, { "over" },
[] (env_t &env, obj_map_t &obj_map)
{
auto b = env.obj_stack.top ();
env.obj_stack.pop ();
auto a = env.obj_stack.top ();
env.obj_stack.pop ();
env.obj_stack.push (a);
env.obj_stack.push (b);
env.obj_stack.push (a);
});
define_prim (
env, { "tuck" },
[] (env_t &env, obj_map_t &obj_map)
{
auto b = env.obj_stack.top ();
env.obj_stack.pop ();
auto a = env.obj_stack.top ();
env.obj_stack.pop ();
env.obj_stack.push (b);
env.obj_stack.push (a);
env.obj_stack.push (b);
});
define_prim (
env, { "swap" },
[] (env_t &env, obj_map_t &obj_map)
{
auto b = env.obj_stack.top ();
env.obj_stack.pop ();
auto a = env.obj_stack.top ();
env.obj_stack.pop ();
env.obj_stack.push (b);
env.obj_stack.push (a);
});
}
#+end_src
*** expose_syntax
#+begin_src cpp
void
expose_syntax (env_t &env)
{
define_top_keyword (env, "=", tk_assign);
define_keyword (env, "lambda", k_lambda);
define_keyword (env, "macro", k_macro);
define_keyword (env, "case", k_case);
define_keyword (env, "quote", k_quote);
define_keyword (env, "*", k_list);
define_keyword (env, "note", k_note);
define_keyword (env, "assert", k_assert);
define_keyword (env, "if", k_if);
define_keyword (env, "when", k_when);
define_keyword (env, "do", k_do);
define_prim_macro (env, "let", m_let);
define_prim_macro (env, "quasiquote", m_quasiquote);
define_prim_macro (env, "and", m_and);
define_prim_macro (env, "or", m_or);
define_prim_macro (env, "cond", m_cond);
}
#+end_src
*** expose_misc
#+begin_src cpp
void
expose_misc (env_t &env)
{
define_prim (
env, { "repr", "obj" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["obj"];
env.obj_stack.push (
make_str (obj->repr (env)));
});
define_prim (
env, { "print", "obj" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["obj"];
obj->print (env);
env.obj_stack.push (obj);
});
define_prim (
env, { "println", "obj" },
[] (env_t &env, obj_map_t &obj_map)
{
auto obj = obj_map ["obj"];
obj->print (env);
cout << "\n" << flush;
env.obj_stack.push (obj);
});
define_prim (
env, { "nl" },
[] (env_t &env, obj_map_t &obj_map)
{
cout << "\n" << flush;
auto nl = make_str ("\n");
env.obj_stack.push (nl);
});
define_prim (
env, { "eq", "lhs", "rhs" },
[] (env_t &env, obj_map_t &obj_map)
{
auto lhs = obj_map ["lhs"];
auto rhs = obj_map ["rhs"];
env.obj_stack.push (
make_bool (
obj_eq (lhs, rhs)));
});
define_prim (
env, { "env-report" },
[] (env_t &env, obj_map_t &obj_map)
{
env.report ();
env.obj_stack.push (true_c ());
});
define_prim (
env, { "env-stack-report" },
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack_report ();
env.obj_stack.push (true_c ());
});
define_prim (
env, { "env-frame-report" },
[] (env_t &env, obj_map_t &obj_map)
{
env.frame_stack_report ();
env.obj_stack.push (true_c ());
});
}
#+end_src
*** expose_core
#+begin_src cpp
void
expose_core (env_t &env)
{
expose_bool (env);
expose_num (env);
expose_str (env);
expose_sym (env);
expose_list (env);
expose_vect (env);
expose_maybe (env);
expose_dict (env);
expose_sexp (env);
expose_top_keyword (env);
expose_keyword (env);
expose_system (env);
expose_module (env);
expose_syntax (env);
expose_type (env);
expose_stack (env);
expose_misc (env);
}
#+end_src
* epilog
*** test
***** test_step
#+begin_src cpp
void
test_step ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
{
env.run ();
assert_stack_size (env, 2);
assert_pop_eq (env, make_str ("world"));
assert_pop_eq (env, make_str ("bye"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_data
#+begin_src cpp
void
test_data ()
{
auto env = env_t ();
obj_map_t obj_map = {
{"car", make_str ("bye")},
{"cdr", make_str ("world")},
};
define (env, "last-cry",
make_data (
cons_tag,
name_vector_t ({ "car", "cdr" }),
obj_map));
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "last-cry")),
new dot_jo_t ("car"),
new ref_jo_t (boxing (env, "last-cry")),
new dot_jo_t ("cdr"),
new ref_jo_t (boxing (env, "last-cry")),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
{
env.run ();
assert_stack_size (env, 3);
assert_pop_eq (
env, make_data (
cons_tag,
name_vector_t ({ "car", "cdr" }),
obj_map));
assert_pop_eq (env, make_str ("world"));
assert_pop_eq (env, make_str ("bye"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_apply
#+begin_src cpp
void
test_apply ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
jo_vector_t body = {
new local_ref_jo_t (0, 0),
new local_ref_jo_t (0, 1),
};
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new lambda_jo_t ({ "x", "y" },
make_shared <jojo_t> (body)),
new apply_jo_t (2),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
// env.double_report ();
{
env.run ();
assert_stack_size (env, 2);
assert_pop_eq (env, make_str ("world"));
assert_pop_eq (env, make_str ("bye"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_lambda_curry
#+begin_src cpp
void
test_lambda_curry ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
jo_vector_t body = {
new local_ref_jo_t (0, 0),
new local_ref_jo_t (0, 1),
};
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new lambda_jo_t ({ "x", "y" },
make_shared <jojo_t> (body)),
new apply_jo_t (1),
new apply_jo_t (1),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
// {
// env.report ();
// env.step_and_report ();
// env.step_and_report ();
// env.step_and_report ();
// env.step_and_report ();
// env.step_and_report ();
// env.step_and_report ();
// env.step_and_report ();
// }
{
env.run ();
assert_stack_size (env, 2);
assert_pop_eq (env, make_str ("bye"));
assert_pop_eq (env, make_str ("world"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_data_cons
#+begin_src cpp
void
test_data_cons ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
define (env, "cons-c",
make_data (
cons_tag,
name_vector_t ({ "car", "cdr" }),
obj_map_t ()));
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new ref_jo_t (boxing (env, "cons-c")),
new apply_jo_t (2),
new dot_jo_t ("cdr"),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
// env.double_report ();
{
env.run ();
assert_stack_size (env, 1);
assert_pop_eq (env, make_str ("world"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_data_cons_curry
#+begin_src cpp
void
test_data_cons_curry ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
define (env, "cons-c",
make_data (
cons_tag,
name_vector_t ({ "car", "cdr" }),
obj_map_t ()));
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new ref_jo_t (boxing (env, "cons-c")),
new apply_jo_t (1),
new apply_jo_t (1),
new dot_jo_t ("car"),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
// env.double_report ();
{
env.run ();
assert_stack_size (env, 1);
assert_pop_eq (env, make_str ("world"));
assert_stack_size (env, 0);
}
}
#+end_src
***** test_prim
#+begin_src cpp
void
test_prim ()
{
auto env = env_t ();
define (env, "s1", make_str ("bye"));
define (env, "s2", make_str ("world"));
auto swap =
[] (env_t &env, obj_map_t &obj_map)
{
env.obj_stack.push (obj_map ["y"]);
env.obj_stack.push (obj_map ["x"]);
};
define (env, "swap",
make_prim (
name_vector_t { "x", "y" },
swap,
obj_map_t ()));
jo_vector_t jo_vector = {
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new ref_jo_t (boxing (env, "swap")),
new apply_jo_t (2),
new ref_jo_t (boxing (env, "s1")),
new ref_jo_t (boxing (env, "s2")),
new ref_jo_t (boxing (env, "swap")),
new apply_jo_t (1),
new apply_jo_t (1),
};
env.frame_stack.push (new_frame_from_jo_vector (jo_vector));
// env.double_report ();
{
env.run ();
assert_stack_size (env, 4);
assert_pop_eq (env, make_str ("world"));
assert_pop_eq (env, make_str ("bye"));
assert_pop_eq (env, make_str ("bye"));
assert_pop_eq (env, make_str ("world"));
assert_stack_size (env, 0);
}
}
#+end_src
*** test_all
#+begin_src cpp
void
test_all ()
{
test_step ();
test_data ();
test_apply ();
test_lambda_curry ();
test_data_cons ();
test_data_cons_curry ();
test_prim ();
test_scan ();
}
#+end_src
*** the_story_begins
#+begin_src cpp
void
the_story_begins (string_vector_t arg_vector)
{
for (auto module_path_string: arg_vector) {
auto module_path = path_t (module_path_string);
env_from_module_path (module_path);
}
}
#+end_src
*** main
#+begin_src cpp
int
main (int argc, char **argv)
{
test_all ();
auto arg_vector = string_vector_t ();
for (auto i = 1; i < argc; i++) {
arg_vector.push_back (string (argv[i]));
}
the_story_begins (arg_vector);
return 0;
}
#+end_src