OSDN Git Service

9c46edf7cfb16fbc3721e6492a3458714dac91b4
[simplecms/utakata.git] / src / primitive_util.cpp
1 #include <assert.h>
2
3 #include "object.h"
4 #include "primitive.h"
5 #include "primitive_util.h"
6 #include "primitive_class.h"
7 #include "type.h"
8 #include "data_castor.h"
9
10 using namespace utakata;
11 using namespace utakata::interpreter;
12
13 IObject* interpreter::util::makeCons(const data::Object& car,
14                                      const data::Object& cdr)
15 {
16     return new interpreter::primitive::Cons(car, cdr);
17 }
18
19 IObject* interpreter::util::makeNil()
20 {
21     return new interpreter::primitive::Nil();
22 }
23
24 IObject* interpreter::util::makeString(const smart_ptr<unicode::UniString>& data)
25 {
26     return new interpreter::primitive::String();
27 }
28
29 IObject* interpreter::util::makeCharactor(const smart_ptr<unicode::UniChar>& data)
30 {
31     return new interpreter::primitive::Charactor();
32 }
33
34 IObject* interpreter::util::makeNumber(const smart_ptr<unicode::UniString>& real,
35                                        const smart_ptr<unicode::UniString>& imagin,
36                                        bool exact, int radix)
37 {
38     return new interpreter::primitive::Number(real, imagin, exact, radix);
39 }
40
41 IObject* interpreter::util::makeBoolean(bool b)
42 {
43     return new interpreter::primitive::Boolean(b);
44 }
45
46 IObject* interpreter::util::makeSymbol(const smart_ptr<unicode::UniString>& data)
47 {
48     return new interpreter::primitive::Symbol(data);
49 }
50
51 IObject* interpreter::util::makeByteVector(const std::vector<data::Object>& vec)
52 {
53     return new interpreter::primitive::ByteVector(vec);
54 }
55
56 IObject* interpreter::util::makeVector(const std::vector<data::Object>& vec)
57 {
58     return new interpreter::primitive::Vector(vec);
59 }
60
61 void interpreter::util::concat(data::Object& c, const data::Object& dat)
62 {
63     // Consオブジェクトであるcの末尾に、datを追加する。
64     // datはconsである必要は無い。
65     // cがconsでは無い場合、これは成功しない。
66     assert(data::instanceof(c, type::Type(primitive::PrimitiveClass<primitive::Cons>().class_name())) &&
67            "not cons");
68
69     primitive::Cons* m = data::DataCastor<primitive::Cons>()(c);
70     if (m->cdr().getSpace().isNull())
71     {
72         // 最初期でこうなっていたら、これにはそのまま突っ込むことができる。
73         m->setCdr(dat);
74     }
75     else
76     {
77         // Consか、NullObjectに当たるまでループで回す。
78         while (!m->cdr().getSpace().isNull())
79         {
80             if (data::instanceof(
81                     m->cdr(),
82                     type::Type(primitive::PrimitiveClass<primitive::Cons>().class_name())))
83             {
84                 // consで、かつcdrが空かどうかを調べる。
85                 m = data::DataCastor<primitive::Cons>()(m->cdr());
86                 continue;
87             }
88             else
89             {
90                 // Cons以外のオブジェクトがcdrに入っていた場合、これはリストでは
91                 // 無いため、何も行われない。
92                 return;
93             }
94         }
95
96         // 抜けた時点で末尾であるので、cdrを設定する。
97         m->setCdr(dat);
98     }
99 }
100
101 data::Object& interpreter::util::getLastCons(data::Object& c)
102 {
103     // 渡されたオブジェクトがconsの場合、末尾のConsを返す。
104     // 末尾と判断するポイントは、cdrがnilであるか、cdrがcons以外の場合。
105     // cdrがnilの時点で、リストは終了しているとみなされるため。
106
107     assert(data::instanceof(c, type::Type(primitive::PrimitiveClass<primitive::Cons>().class_name())) &&
108            "not cons");
109
110     primitive::Cons* cons = data::DataCastor<primitive::Cons>()(c);
111     smart_ptr<interpreter::IClass> cclass = cons->getClass();
112
113     while (data::instanceof(cons->cdr(), type::Type(cclass->class_name())))
114     {
115         // consである間、後ろに移動しつづけてみる。
116         cons = data::DataCastor<primitive::Cons>()(cons->cdr());
117     }
118
119     return cons->cdr();
120 }