• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisionbd1c5672f1056ee58cfe3398d115efaaa21311de (tree)
Time2020-02-11 23:34:25
Authordhrname <dhrname@user...>
Commiterdhrname

Log Message

Modulize orderedpair

Change Summary

Incremental Difference

--- a/source_code/Makefile
+++ b/source_code/Makefile
@@ -2,8 +2,8 @@ CC = gcc
22 DEBUGMODE = -Wall -std=c11 -O0 -g -pg
33 NODEBUGMODE = -Wall -std=c11 -O2
44 SHELL = /bin/sh
5-HEADERS = shadowstar.h star.h orderedpair/pair.h orderedpair/list/item.h orderedpair/list/tree/btree.h orderedpair/list/tree/nodelist/ntree.h orderedpair/list/tree/nodelist/class/class.h
6-OBJECT = shadowstar.o exception.o
5+HEADERS = shadowstar.h star.h orderedpair/list/tree/nodelist/class/class.h
6+OBJECT = shadowstar.o exception.o pair.o item.o ntree.o
77
88 all : startest star
99 .PHONY : all
@@ -13,6 +13,12 @@ all : startest star
1313
1414 exception.o: orderedpair/exception.h
1515
16+pair.o: orderedpair/pair.h
17+
18+item.o: orderedpair/list/item.h
19+
20+ntree.o: orderedpair/list/tree/nodelist/ntree.h
21+
1622 star.o: $(HEADERS)
1723
1824 shadowstar.o: $(HEADERS)
@@ -24,4 +30,4 @@ startest: startest.o $(OBJECT)
2430 $(CC) $(NODEBUGMODE) -o ../$@ startest.o $(OBJECT)
2531
2632 clean:
27- rm -f shadowstar.o startest.o star.o exception.o
33+ rm -f startest.o star.o $(OBJECT)
--- /dev/null
+++ b/source_code/item.c
@@ -0,0 +1,30 @@
1+/*
2+ * item.c
3+ *
4+ * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp>
5+ *
6+ *
7+ */
8+#include "shadowstar.h"
9+
10+/*item.cでは、リストの項目を取得するための関数を実装する*/
11+
12+/*ST_setChurchNumber 関数
13+ * C言語でラムダ計算のchurch数を部分的に再現するための関数*/
14+ST_Ordered_Pair *ST_setChurchNumber (uint_fast32_t length, Ord2ST_Ordered_Pair f, ST_Ordered_Pair *list)
15+{
16+ int32_t i;
17+ for (i = 0; i < length; i++)
18+ {
19+ /*lengthが4の場合、list = f(f(f(f(list))));*/
20+ list = (*f)(list);
21+ }
22+ return list;
23+}
24+
25+/*ST_getItem 関数
26+ * 入力されたリストの最後からnum番目にある項目の最初の値を取り出す(num >= 0)*/
27+ST_First_Type ST_getItem (ST_Ordered_Pair *list, uint_fast32_t num)
28+{
29+ return ST_first( ST_setChurchNumber(num, ST_second, list) );
30+}
Binary files /dev/null and b/source_code/item.o differ
--- /dev/null
+++ b/source_code/ntree.c
@@ -0,0 +1,395 @@
1+/*
2+ * ntree.c
3+ *
4+ * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp>
5+ *
6+ *
7+ */
8+#include "shadowstar.h"
9+
10+/*N木(N tree)構造*/
11+
12+/*以下では、複数の枝分かれができるN木構造を実装する*/
13+
14+/*ST_getBoundVariable 関数
15+ * 二分木リストとして表現された関数抽象abstractionの束縛変数(Bound Variable)を数値化したものを取得する
16+ * ここでいう束縛変数とは、λx.Mのときの、変数xを指す*/
17+ST_First_Type ST_getBoundVariable (ST_Ordered_Pair *abstraction)
18+{
19+ return ST_first(abstraction);
20+}
21+
22+
23+/*空ノードを表現するポインタ*/
24+ST_Node_Tree __ST_EMPTY_NODE = {
25+ NULL,
26+ ST_UNKNOWN_NODE,
27+ NULL,
28+ NULL,
29+ NULL,
30+ NULL,
31+ NULL
32+};
33+ST_Node ST_EMPTY_NODE = &__ST_EMPTY_NODE;
34+
35+/*ST_isEmptyNode 関数
36+ * 引数の値がST_EMPTY_NODEであるかどうかを判別する関数*/
37+bool ST_isEmptyNode (ST_Node node)
38+{
39+ if (node == ST_EMPTY_NODE)
40+ {
41+ return true;
42+ }
43+ else if (NULL == node)
44+ {
45+ errno = EINVAL;
46+ eprint_log("NULL argument error on the function ST_isEmptyNode:");
47+ return false;
48+ }
49+ else
50+ {
51+ return false;
52+ }
53+}
54+
55+/*check_null インライン関数
56+ * ノードでNULLチェックを行う*/
57+static inline bool check_null (ST_Node node)
58+{
59+ if (NULL == node)
60+ {
61+ errno = EINVAL;
62+ eprint_log("NULL argument error:");
63+ return true;
64+ }
65+ else
66+ {
67+ return false;
68+ }
69+}
70+
71+/*ST_createNode 関数
72+ * 引数はフリーリスト用のノード(子ノードは後述するST_freenode 関数でルートノードとして扱われる)
73+ * 返り値が新たに作られるノード*/
74+ST_Node ST_createNode(ST_Free_Node freelist)
75+{
76+ errno_before_eprint = CREATE_NODE_ERROR;
77+
78+ if (check_null(freelist))
79+ {
80+ return ST_EMPTY_NODE;
81+ }
82+
83+ ST_Node s;
84+
85+ s = (ST_Node) ST_emalloc(sizeof(ST_Node_Tree));
86+ s->nodeValue = ST_EMPTY;
87+ s->lastChild = ST_EMPTY_NODE;
88+ s->previousSibling = ST_EMPTY_NODE;
89+ s->nextSibling = ST_EMPTY_NODE;
90+ s->parentNode = ST_EMPTY_NODE;
91+ s->nodeType = ST_UNKNOWN_NODE;
92+
93+ if (!ST_isEmptyNode(freelist))
94+ {
95+ /*freelistに、メモリ解放用ルートノードとして追加挿入*/
96+ ST_Node lastChild = ST_getLastChild(freelist);
97+ s->previousSibling = lastChild;
98+ lastChild->nextSibling = s;
99+ freelist->lastChild = s;
100+ s->parentNode = freelist;
101+ }
102+
103+ errno_before_eprint = Init_errno_before_eprint;
104+
105+ return s;
106+}
107+
108+/*ST_setNodeValue 関数
109+ * 引数にノードの値をセットする*/
110+void ST_setNodeValue(ST_Node node, ST_Ordered_Pair *nodeValue)
111+{
112+ if (NULL == nodeValue)
113+ {
114+ errno = EINVAL;
115+ eprint_log("argument error on the function ST_setNodeValue:");
116+ return;
117+ }
118+ node->nodeValue = nodeValue;
119+}
120+
121+/*ST_removeChild 関数
122+ * 一番目の引数を親ノードparentとして、二番目の引数である子ノードchildをparentから引き離す
123+ * 返り値はchild、ただし、エラーの時はST_EMPTY_NODE*/
124+ST_Node ST_removeChild(ST_Node parent, ST_Node child)
125+{
126+ errno_before_eprint = REMOVE_CHILD_ERROR;
127+
128+ /*エラーのパターンとしては、
129+ * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/
130+
131+ if ( (NULL == parent) || ST_isEmptyNode(parent))
132+ {
133+ errno = EINVAL;
134+ eprint_log("ST_EMPTY_NODE parent argument error on the function ST_removeChild:");
135+ return ST_EMPTY_NODE;
136+ }
137+
138+ if ( (NULL == child) || ST_isEmptyNode(child))
139+ {
140+ errno = EINVAL;
141+ eprint_log("ST_EMPTY_NODE argument error on the function ST_removeChild:");
142+ return ST_EMPTY_NODE;
143+ }
144+
145+ child->parentNode = ST_EMPTY_NODE;
146+
147+ /*nodeが抜けた後、隣接ノードに関するメンバは書き換えておく*/
148+ if (!ST_isEmptyNode(child->previousSibling))
149+ {
150+ child->previousSibling->nextSibling = child->nextSibling;
151+ }
152+ if (!ST_isEmptyNode(child->nextSibling))
153+ {
154+ child->nextSibling->previousSibling = child->previousSibling;
155+ }
156+
157+ if (ST_getLastChild(parent) == child)
158+ {
159+ /*末尾ノードがnodeである場合はparentノードのメンバを書きかえておく*/
160+ parent->lastChild = ST_getPreviousNode(child);
161+ }
162+
163+ child->nextSibling = ST_EMPTY_NODE;
164+ child->previousSibling = ST_EMPTY_NODE;
165+
166+ errno_before_eprint = Init_errno_before_eprint;
167+
168+ return child;
169+}
170+
171+/*ST_insertBefore 関数
172+ * 副作用がある関数なので、扱いには注意を要する
173+ * 一番目の引数parentが親ノード。三番目の引数ノードprevの前隣りに、二番目の引数ノードnodeを挿入
174+ * 三番目の引数が空ノードであれば、親ノードに末子ノードとして登録される
175+ * 返り値は、挿入に成功したとき引数node、失敗したときは空ノードを返す*/
176+ST_Node ST_insertBefore(ST_Node parent, ST_Node node, ST_Node prev)
177+{
178+ errno_before_eprint = INSERT_BEFORE_ERROR;
179+
180+ /*挿入に失敗するパターンとしては、
181+ * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/
182+ if ( (NULL == parent) || ST_isEmptyNode(parent))
183+ {
184+ errno = EINVAL;
185+ eprint_log("ST_EMPTY_NODE parent argument error on the function ST_insertBefore:");
186+ return ST_EMPTY_NODE;
187+ }
188+
189+ if ( (NULL == node) || ST_isEmptyNode(node))
190+ {
191+ errno = EINVAL;
192+ eprint_log("ST_EMPTY_NODE argument error on the function ST_insertBefore:");
193+ return ST_EMPTY_NODE;
194+ }
195+
196+ /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー
197+ * というのは、循環参照を引き起こすため*/
198+ ST_Node p = parent;
199+
200+ while (!ST_isEmptyNode(p))
201+ {
202+ if (p == node)
203+ {
204+ eprint_log("Reference error on the function ST_insertBefore:");
205+ return ST_EMPTY_NODE;
206+ }
207+
208+ p = ST_getParentNode(p);
209+ }
210+
211+ ST_Node pnode = ST_getParentNode(node);
212+
213+ if (!ST_isEmptyNode(pnode))
214+ {
215+ /*nodeがすでに、他の枝に挿入されていた場合*/
216+ ST_removeChild(pnode, node);
217+ }
218+
219+ node->parentNode = parent;
220+
221+ if (ST_isEmptyNode(prev))
222+ {
223+ /*末尾ノードが存在するときは、そのノードのメンバも書きかえておく*/
224+ ST_Node lastChild = ST_getLastChild(parent);
225+ if (!ST_isEmptyNode(lastChild))
226+ {
227+ lastChild->nextSibling = node;
228+ node->previousSibling = lastChild;
229+ }
230+ /*末尾ノードとして挿入*/
231+ parent->lastChild = node;
232+ }
233+ else if (NULL != prev)
234+ {
235+ ST_Node prevOfPrev = prev->previousSibling;
236+ if (!ST_isEmptyNode(prevOfPrev))
237+ {
238+ /*prevの隣接ノードのnextSiblingメンバを書きかえておく*/
239+ prevOfPrev->nextSibling = node;
240+ }
241+ node->previousSibling = prevOfPrev;
242+ prev->previousSibling = node;
243+ node->nextSibling = prev;
244+ }
245+
246+ errno_before_eprint = Init_errno_before_eprint;
247+
248+ return node;
249+}
250+
251+/*ST_getNodeValue 関数
252+ * 引数で指定されたノードの値を取得*/
253+ST_Ordered_Pair *ST_getNodeValue(ST_Node node)
254+{
255+ errno_before_eprint = GET_NODE_VALUE_ERROR;
256+
257+ if (check_null(node))
258+ {
259+ return ST_EMPTY;
260+ }
261+
262+ if (ST_isEmptyNode(node) || (NULL == node->nodeValue))
263+ {
264+ return ST_EMPTY;
265+ }
266+
267+ errno_before_eprint = Init_errno_before_eprint;
268+
269+ return node->nodeValue;
270+}
271+
272+/*ST_getLastChild 関数
273+ * 引数で指定されたノードの子リストの最後尾を取得*/
274+ST_Node ST_getLastChild(ST_Node node)
275+{
276+ errno_before_eprint = GET_LAST_CHILD_ERROR;
277+
278+ if (check_null(node))
279+ {
280+ return ST_EMPTY_NODE;
281+ }
282+
283+ if (ST_isEmptyNode(node) || (NULL == node->lastChild))
284+ {
285+ return node;
286+ }
287+
288+ errno_before_eprint = Init_errno_before_eprint;
289+
290+ return node->lastChild;
291+}
292+
293+/*ST_getPreviousNode 関数
294+ * 引数で指定されたノードにとって、前隣りのノードを取得*/
295+ST_Node ST_getPreviousNode(ST_Node node)
296+{
297+ errno_before_eprint = GET_PREVIOUS_NODE_ERROR;
298+
299+ if (check_null(node))
300+ {
301+ return ST_EMPTY_NODE;
302+ }
303+
304+ if (ST_isEmptyNode(node) || (NULL == node->previousSibling))
305+ {
306+ return node;
307+ }
308+
309+ errno_before_eprint = Init_errno_before_eprint;
310+
311+ return node->previousSibling;
312+}
313+
314+/*ST_getParentNode 関数
315+ * 引数の親ノードを取得*/
316+ST_Node ST_getParentNode(ST_Node node)
317+{
318+ errno_before_eprint = GET_PARENT_NODE_ERROR;
319+
320+ if (check_null(node))
321+ {
322+ errno_before_eprint = Init_errno_before_eprint;
323+ return ST_EMPTY_NODE;
324+ }
325+
326+ if (ST_isEmptyNode(node) || (NULL == node->parentNode))
327+ {
328+ errno_before_eprint = Init_errno_before_eprint;
329+ return ST_EMPTY_NODE;
330+ }
331+
332+ errno_before_eprint = Init_errno_before_eprint;
333+
334+ return node->parentNode;
335+}
336+
337+/*ST_copyNode 関数
338+ * 二番目の引数で指定されたノードのコピーを作成して、返す
339+ * 子ノードも含めて深くコピーするが、隣接ノードはコピーしない
340+ * 一番目の引数はST_freenodeで使うためのフリーリスト*/
341+ST_Node ST_copyNode(ST_Free_Node freelist, ST_Node node)
342+{
343+ errno_before_eprint = COPY_NODE_ERROR;
344+
345+ if ((NULL == node) || ST_isEmptyNode(node))
346+ {
347+ /*nodeが無効値、NULLである場合はエラー
348+ *ST_EMPTY_NODEを返す*/
349+ errno = EINVAL;
350+ eprint_log("Argument error on the function ST_copyNode:");
351+ return ST_EMPTY_NODE;
352+ }
353+
354+ ST_Node copy = ST_createNode(freelist);
355+ ST_setNodeValue(copy, ST_getNodeValue(node));
356+ copy->nodeType = node->nodeType;
357+
358+ /*コピーしたい子ノードにおける現在のノード*/
359+ ST_Node current = ST_EMPTY_NODE;
360+ /*コピーしたい子ノード*/
361+ ST_Node child = ST_getLastChild(node);
362+ /*nodeの子ノードを次々とコピーしていく*/
363+ while (!ST_isEmptyNode(child))
364+ {
365+ /*currentにはST_copyNode(child)の値が代入される*/
366+ current = ST_insertBefore(copy, ST_copyNode(ST_EMPTY_NODE, child), current);
367+ child = ST_getPreviousNode(child);
368+ }
369+
370+ errno_before_eprint = Init_errno_before_eprint;
371+
372+ return copy;
373+}
374+
375+/*ST_freenode 関数
376+ * 引数freelistに登録されたノードを、子ノードも含めて、全て深く解放していく
377+ * その際、ノード値そのものも解放する*/
378+void ST_freenode (ST_Free_Node freelist)
379+{
380+ if ( (NULL == freelist) || ST_isEmptyNode(freelist))
381+ {
382+ return;
383+ }
384+
385+ ST_Node prev = ST_getLastChild(freelist);
386+
387+ while (!ST_isEmptyNode(prev))
388+ {
389+ ST_Node node = prev;
390+ prev = ST_getPreviousNode(node);
391+ ST_freenode(node);
392+ }
393+ free(freelist);
394+ freelist = NULL;
395+}
Binary files /dev/null and b/source_code/ntree.o differ
--- /dev/null
+++ b/source_code/pair.c
@@ -0,0 +1,156 @@
1+/*
2+ * exception.c
3+ *
4+ * Copyright (C) 2017 dhrname <dhrnamesie@joestar.sakura.ne.jp>
5+ *
6+ *
7+ */
8+#include "shadowstar.h"
9+
10+/*以下の連結リスト構造については数学の集合とラムダ計算と操作的意味論を参照のこと
11+ * 集合モデル (
12+ * ここでは、:=を定義とする(任意の対象a, b, cに対して常に成立する)
13+ * 空集合 := {}
14+ * 対、あるいはNo Ordered Pair := {a, b}
15+ * 集合の性質として{a, b} = {b, a}
16+ * 順序対 あるいは、Ordered Pair := (a, b)とおいて、
17+ * (a, b) := {a, {a, b}}
18+ * 順序対の定義より、
19+ * (a, b) ≠ (b, a)
20+ * n項組 あるいは、n組、n-tupples := [a, b, c, ... ]とすると、
21+ * [a, b, c] := (a, ( b, (c, {}) ) )で表せる
22+ *
23+ * isEmpty(a) 引数aが空集合であれば、true、そうでなければ、false
24+ * pair(a, b) 順序対(a, b)を作成
25+ * first(c) cが順序対(a, b)ならば、そのうち、aを返す
26+ * second(c) cが順序対(a, b)ならば、そのうち、bを返す
27+ * pair(a, pair(b, pair(c, 空集合)は連結リストとなる*/
28+
29+/*ST_EMPTY
30+ * 空リストを表現する構造体のconstポインタ
31+ * クロージャのある他の言語では、関数で実装する*/
32+
33+/*構造体__ST_EMPTYを作っておく*/
34+ST_Ordered_Pair __STEMPTY = {
35+ 0.0,
36+ NULL,
37+ 0
38+};
39+
40+/*ST_EMPTY
41+ * 空リストを表現する構造体のポインタ
42+ * クロージャのある他の言語では、関数で実装する*/
43+ST_Ordered_Pair *ST_EMPTY = &__STEMPTY;
44+
45+/*ST_isEmpty 関数
46+ * 引数のlistがST_EMPTYかどうかをチェックするときに使う。ST_EMPTYならばtrue( = 1)
47+ * NULLは不具合が起きるので、入力すればエラーを報告してtrueを返す*/
48+bool ST_isEmpty (ST_Ordered_Pair *list)
49+{
50+ if (NULL == list)
51+ {
52+ errno = EINVAL;
53+ eprint_log("NULL argument error on the function ST_isEmpty:");
54+ return true;
55+ }
56+ else if (list == ST_EMPTY)
57+ {
58+ return true;
59+ }
60+ else
61+ {
62+ return false;
63+ }
64+}
65+
66+/*ST_first 関数
67+ * 順序対の一番目を返す
68+ * ST_pair関数で指定された第一引数(例えば、ST_pair(a,b)ならばa)を返す)*/
69+ST_First_Type ST_first (ST_Ordered_Pair *list)
70+{
71+ if (ST_isEmpty(list))
72+ {
73+ return 0.0;
74+ } else
75+ {
76+ return list->first;
77+ }
78+}
79+
80+/*ST_second 関数
81+ * 順序対の二番目を返す
82+ * ST_pair関数で指定された第二引数(例えば、ST_pair(a,b)ならばb)を返す)*/
83+ST_Ordered_Pair *ST_second (ST_Ordered_Pair *list)
84+{
85+ if ( ST_isEmpty(list) || (list->second == NULL) )
86+ {
87+ /*ペアの二番目を取得できない場合は、自分自身を返す*/
88+ return ST_EMPTY;
89+ }
90+ else
91+ {
92+ return list->second;
93+ }
94+}
95+
96+/*メモリ割り当てを呼び出す関数
97+ * 引数nはメモリのサイズ*/
98+void *ST_emalloc(size_t n)
99+{
100+ void *p;
101+ p = calloc(1, n);
102+ if (p == NULL)
103+ {
104+ errno = ENOBUFS;
105+ eprintf("%u bytes failed on the function ST_emalloc:", n);
106+ }
107+ return p;
108+}
109+
110+/*ST_freelist関数
111+ * 引数のlistを解放させる
112+ * 他から参照されていない限り、ST_EMPTY以外のリストすべてが対象*/
113+void ST_freelist (ST_Ordered_Pair *list)
114+{
115+ if (ST_isEmpty(list))
116+ {
117+ return;
118+ }
119+
120+ ST_Ordered_Pair *next;
121+
122+ for (;!ST_isEmpty(list) || (list->lifepoint >= 1);list = next)
123+ {
124+ next = ST_second(list);
125+ if (ST_isEmpty(next))
126+ {
127+ break;
128+ }
129+ else
130+ {
131+ free(list);
132+ /*参照カウンタを減らしておく*/
133+ next->lifepoint--;
134+ list = NULL;
135+ }
136+ }
137+}
138+
139+/*ST_pair関数
140+ * 第一引数と第二引数とで順序対を作る*/
141+ST_Ordered_Pair *ST_pair (ST_First_Type n, ST_Ordered_Pair *p)
142+{
143+ ST_Ordered_Pair *s;
144+
145+ s = (ST_Ordered_Pair *) ST_emalloc(sizeof(ST_Ordered_Pair));
146+ s->first = n;
147+ s->second = p;
148+ s->lifepoint = 0;
149+
150+ if (!ST_isEmpty(p))
151+ {
152+ p->lifepoint++;
153+ }
154+ return s;
155+}
156+
Binary files /dev/null and b/source_code/pair.o differ
--- a/source_code/shadowstar.c
+++ b/source_code/shadowstar.c
@@ -671,556 +671,10 @@ ST_Node ST_eval(ST_Ordered_Pair *list, ST_Node blist)
671671 return ST_copyNode(ST_EMPTY_NODE, blist);
672672 }
673673
674-/*以下の連結リスト構造については数学の集合とラムダ計算と操作的意味論を参照のこと
675- * 集合モデル (
676- * ここでは、:=を定義とする(任意の対象a, b, cに対して常に成立する)
677- * 空集合 := {}
678- * 対、あるいはNo Ordered Pair := {a, b}
679- * 集合の性質として{a, b} = {b, a}
680- * 順序対 あるいは、Ordered Pair := (a, b)とおいて、
681- * (a, b) := {a, {a, b}}
682- * 順序対の定義より、
683- * (a, b) ≠ (b, a)
684- * n項組 あるいは、n組、n-tupples := [a, b, c, ... ]とすると、
685- * [a, b, c] := (a, ( b, (c, {}) ) )で表せる
686- *
687- * isEmpty(a) 引数aが空集合であれば、true、そうでなければ、false
688- * pair(a, b) 順序対(a, b)を作成
689- * first(c) cが順序対(a, b)ならば、そのうち、aを返す
690- * second(c) cが順序対(a, b)ならば、そのうち、bを返す
691- * pair(a, pair(b, pair(c, 空集合)は連結リストとなる*/
692674
693-/*ST_EMPTY
694- * 空リストを表現する構造体のconstポインタ
695- * クロージャのある他の言語では、関数で実装する*/
696675
697-/*構造体__ST_EMPTYを作っておく*/
698-ST_Ordered_Pair __STEMPTY = {
699- 0.0,
700- NULL,
701- 0
702-};
703-
704-/*ST_EMPTY
705- * 空リストを表現する構造体のポインタ
706- * クロージャのある他の言語では、関数で実装する*/
707-ST_Ordered_Pair *ST_EMPTY = &__STEMPTY;
708-
709-/*ST_isEmpty 関数
710- * 引数のlistがST_EMPTYかどうかをチェックするときに使う。ST_EMPTYならばtrue( = 1)
711- * NULLは不具合が起きるので、入力すればエラーを報告してtrueを返す*/
712-bool ST_isEmpty (ST_Ordered_Pair *list)
713-{
714- if (NULL == list)
715- {
716- errno = EINVAL;
717- eprint_log("NULL argument error on the function ST_isEmpty:");
718- return true;
719- }
720- else if (list == ST_EMPTY)
721- {
722- return true;
723- }
724- else
725- {
726- return false;
727- }
728-}
729-
730-/*ST_first 関数
731- * 順序対の一番目を返す
732- * ST_pair関数で指定された第一引数(例えば、ST_pair(a,b)ならばa)を返す)*/
733-ST_First_Type ST_first (ST_Ordered_Pair *list)
734-{
735- if (ST_isEmpty(list))
736- {
737- return 0.0;
738- } else
739- {
740- return list->first;
741- }
742-}
743-
744-/*ST_second 関数
745- * 順序対の二番目を返す
746- * ST_pair関数で指定された第二引数(例えば、ST_pair(a,b)ならばb)を返す)*/
747-ST_Ordered_Pair *ST_second (ST_Ordered_Pair *list)
748-{
749- if ( ST_isEmpty(list) || (list->second == NULL) )
750- {
751- /*ペアの二番目を取得できない場合は、自分自身を返す*/
752- return ST_EMPTY;
753- }
754- else
755- {
756- return list->second;
757- }
758-}
759-
760-/*メモリ割り当てを呼び出す関数
761- * 引数nはメモリのサイズ*/
762-void *ST_emalloc(size_t n)
763-{
764- void *p;
765- p = calloc(1, n);
766- if (p == NULL)
767- {
768- errno = ENOBUFS;
769- eprintf("%u bytes failed on the function ST_emalloc:", n);
770- }
771- return p;
772-}
773-
774-/*ST_freelist関数
775- * 引数のlistを解放させる
776- * 他から参照されていない限り、ST_EMPTY以外のリストすべてが対象*/
777-void ST_freelist (ST_Ordered_Pair *list)
778-{
779- if (ST_isEmpty(list))
780- {
781- return;
782- }
783-
784- ST_Ordered_Pair *next;
785-
786- for (;!ST_isEmpty(list) || (list->lifepoint >= 1);list = next)
787- {
788- next = ST_second(list);
789- if (ST_isEmpty(next))
790- {
791- break;
792- }
793- else
794- {
795- free(list);
796- /*参照カウンタを減らしておく*/
797- next->lifepoint--;
798- list = NULL;
799- }
800- }
801-}
802-
803-/*ST_pair関数
804- * 第一引数と第二引数とで順序対を作る*/
805-ST_Ordered_Pair *ST_pair (ST_First_Type n, ST_Ordered_Pair *p)
806-{
807- ST_Ordered_Pair *s;
808-
809- s = (ST_Ordered_Pair *) ST_emalloc(sizeof(ST_Ordered_Pair));
810- s->first = n;
811- s->second = p;
812- s->lifepoint = 0;
813-
814- if (!ST_isEmpty(p))
815- {
816- p->lifepoint++;
817- }
818- return s;
819-}
820-
821-/*ST_setChurchNumber 関数
822- * C言語でラムダ計算のchurch数を部分的に再現するための関数*/
823-ST_Ordered_Pair *ST_setChurchNumber (uint_fast32_t length, Ord2ST_Ordered_Pair f, ST_Ordered_Pair *list)
824-{
825- int32_t i;
826- for (i = 0; i < length; i++)
827- {
828- /*lengthが4の場合、list = f(f(f(f(list))));*/
829- list = (*f)(list);
830- }
831- return list;
832-}
833-
834-/*ST_getItem 関数
835- * 入力されたリストの最後からnum番目にある項目の最初の値を取り出す(num >= 0)*/
836-ST_First_Type ST_getItem (ST_Ordered_Pair *list, uint_fast32_t num)
837-{
838- return ST_first( ST_setChurchNumber(num, ST_second, list) );
839-}
840-
841-
842-/*ST_getBoundVariable 関数
843- * 二分木リストとして表現された関数抽象abstractionの束縛変数(Bound Variable)を数値化したものを取得する
844- * ここでいう束縛変数とは、λx.Mのときの、変数xを指す*/
845-ST_First_Type ST_getBoundVariable (ST_Ordered_Pair *abstraction)
846-{
847- return ST_first(abstraction);
848-}
849-
850-
851-/*空ノードを表現するポインタ*/
852-ST_Node_Tree __ST_EMPTY_NODE = {
853- NULL,
854- ST_UNKNOWN_NODE,
855- NULL,
856- NULL,
857- NULL,
858- NULL,
859- NULL
860-};
861-ST_Node ST_EMPTY_NODE = &__ST_EMPTY_NODE;
862-
863-/*ST_isEmptyNode 関数
864- * 引数の値がST_EMPTY_NODEであるかどうかを判別する関数*/
865-bool ST_isEmptyNode (ST_Node node)
866-{
867- if (node == ST_EMPTY_NODE)
868- {
869- return true;
870- }
871- else if (NULL == node)
872- {
873- errno = EINVAL;
874- eprint_log("NULL argument error on the function ST_isEmptyNode:");
875- return false;
876- }
877- else
878- {
879- return false;
880- }
881-}
882-
883-/*check_null インライン関数
884- * ノードでNULLチェックを行う*/
885-static inline bool check_null (ST_Node node)
886-{
887- if (NULL == node)
888- {
889- errno = EINVAL;
890- eprint_log("NULL argument error:");
891- return true;
892- }
893- else
894- {
895- return false;
896- }
897-}
898-
899-/*ST_createNode 関数
900- * 引数はフリーリスト用のノード(子ノードは後述するST_freenode 関数でルートノードとして扱われる)
901- * 返り値が新たに作られるノード*/
902-ST_Node ST_createNode(ST_Free_Node freelist)
903-{
904- errno_before_eprint = CREATE_NODE_ERROR;
905-
906- if (check_null(freelist))
907- {
908- return ST_EMPTY_NODE;
909- }
910-
911- ST_Node s;
912-
913- s = (ST_Node) ST_emalloc(sizeof(ST_Node_Tree));
914- s->nodeValue = ST_EMPTY;
915- s->lastChild = ST_EMPTY_NODE;
916- s->previousSibling = ST_EMPTY_NODE;
917- s->nextSibling = ST_EMPTY_NODE;
918- s->parentNode = ST_EMPTY_NODE;
919- s->nodeType = ST_UNKNOWN_NODE;
920-
921- if (!ST_isEmptyNode(freelist))
922- {
923- /*freelistに、メモリ解放用ルートノードとして追加挿入*/
924- ST_Node lastChild = ST_getLastChild(freelist);
925- s->previousSibling = lastChild;
926- lastChild->nextSibling = s;
927- freelist->lastChild = s;
928- s->parentNode = freelist;
929- }
930-
931- errno_before_eprint = Init_errno_before_eprint;
932-
933- return s;
934-}
935-
936-/*ST_setNodeValue 関数
937- * 引数にノードの値をセットする*/
938-void ST_setNodeValue(ST_Node node, ST_Ordered_Pair *nodeValue)
939-{
940- if (NULL == nodeValue)
941- {
942- errno = EINVAL;
943- eprint_log("argument error on the function ST_setNodeValue:");
944- return;
945- }
946- node->nodeValue = nodeValue;
947-}
948-
949-/*ST_removeChild 関数
950- * 一番目の引数を親ノードparentとして、二番目の引数である子ノードchildをparentから引き離す
951- * 返り値はchild、ただし、エラーの時はST_EMPTY_NODE*/
952-ST_Node ST_removeChild(ST_Node parent, ST_Node child)
953-{
954- errno_before_eprint = REMOVE_CHILD_ERROR;
955-
956- /*エラーのパターンとしては、
957- * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/
958-
959- if ( (NULL == parent) || ST_isEmptyNode(parent))
960- {
961- errno = EINVAL;
962- eprint_log("ST_EMPTY_NODE parent argument error on the function ST_removeChild:");
963- return ST_EMPTY_NODE;
964- }
965-
966- if ( (NULL == child) || ST_isEmptyNode(child))
967- {
968- errno = EINVAL;
969- eprint_log("ST_EMPTY_NODE argument error on the function ST_removeChild:");
970- return ST_EMPTY_NODE;
971- }
972-
973- child->parentNode = ST_EMPTY_NODE;
974-
975- /*nodeが抜けた後、隣接ノードに関するメンバは書き換えておく*/
976- if (!ST_isEmptyNode(child->previousSibling))
977- {
978- child->previousSibling->nextSibling = child->nextSibling;
979- }
980- if (!ST_isEmptyNode(child->nextSibling))
981- {
982- child->nextSibling->previousSibling = child->previousSibling;
983- }
984-
985- if (ST_getLastChild(parent) == child)
986- {
987- /*末尾ノードがnodeである場合はparentノードのメンバを書きかえておく*/
988- parent->lastChild = ST_getPreviousNode(child);
989- }
990-
991- child->nextSibling = ST_EMPTY_NODE;
992- child->previousSibling = ST_EMPTY_NODE;
993-
994- errno_before_eprint = Init_errno_before_eprint;
995-
996- return child;
997-}
998-
999-/*ST_insertBefore 関数
1000- * 副作用がある関数なので、扱いには注意を要する
1001- * 一番目の引数parentが親ノード。三番目の引数ノードprevの前隣りに、二番目の引数ノードnodeを挿入
1002- * 三番目の引数が空ノードであれば、親ノードに末子ノードとして登録される
1003- * 返り値は、挿入に成功したとき引数node、失敗したときは空ノードを返す*/
1004-ST_Node ST_insertBefore(ST_Node parent, ST_Node node, ST_Node prev)
1005-{
1006- errno_before_eprint = INSERT_BEFORE_ERROR;
1007-
1008- /*挿入に失敗するパターンとしては、
1009- * parentか、nodeの値がNULL、あるいはST_EMPTY_NODEのとき*/
1010- if ( (NULL == parent) || ST_isEmptyNode(parent))
1011- {
1012- errno = EINVAL;
1013- eprint_log("ST_EMPTY_NODE parent argument error on the function ST_insertBefore:");
1014- return ST_EMPTY_NODE;
1015- }
1016-
1017- if ( (NULL == node) || ST_isEmptyNode(node))
1018- {
1019- errno = EINVAL;
1020- eprint_log("ST_EMPTY_NODE argument error on the function ST_insertBefore:");
1021- return ST_EMPTY_NODE;
1022- }
1023-
1024- /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー
1025- * というのは、循環参照を引き起こすため*/
1026- ST_Node p = parent;
1027676
1028- while (!ST_isEmptyNode(p))
1029- {
1030- if (p == node)
1031- {
1032- eprint_log("Reference error on the function ST_insertBefore:");
1033- return ST_EMPTY_NODE;
1034- }
1035-
1036- p = ST_getParentNode(p);
1037- }
1038-
1039- ST_Node pnode = ST_getParentNode(node);
1040-
1041- if (!ST_isEmptyNode(pnode))
1042- {
1043- /*nodeがすでに、他の枝に挿入されていた場合*/
1044- ST_removeChild(pnode, node);
1045- }
1046-
1047- node->parentNode = parent;
1048-
1049- if (ST_isEmptyNode(prev))
1050- {
1051- /*末尾ノードが存在するときは、そのノードのメンバも書きかえておく*/
1052- ST_Node lastChild = ST_getLastChild(parent);
1053- if (!ST_isEmptyNode(lastChild))
1054- {
1055- lastChild->nextSibling = node;
1056- node->previousSibling = lastChild;
1057- }
1058- /*末尾ノードとして挿入*/
1059- parent->lastChild = node;
1060- }
1061- else if (NULL != prev)
1062- {
1063- ST_Node prevOfPrev = prev->previousSibling;
1064- if (!ST_isEmptyNode(prevOfPrev))
1065- {
1066- /*prevの隣接ノードのnextSiblingメンバを書きかえておく*/
1067- prevOfPrev->nextSibling = node;
1068- }
1069- node->previousSibling = prevOfPrev;
1070- prev->previousSibling = node;
1071- node->nextSibling = prev;
1072- }
1073-
1074- errno_before_eprint = Init_errno_before_eprint;
1075-
1076- return node;
1077-}
1078677
1079-/*ST_getNodeValue 関数
1080- * 引数で指定されたノードの値を取得*/
1081-ST_Ordered_Pair *ST_getNodeValue(ST_Node node)
1082-{
1083- errno_before_eprint = GET_NODE_VALUE_ERROR;
1084-
1085- if (check_null(node))
1086- {
1087- return ST_EMPTY;
1088- }
1089-
1090- if (ST_isEmptyNode(node) || (NULL == node->nodeValue))
1091- {
1092- return ST_EMPTY;
1093- }
1094-
1095- errno_before_eprint = Init_errno_before_eprint;
1096-
1097- return node->nodeValue;
1098-}
1099-
1100-/*ST_getLastChild 関数
1101- * 引数で指定されたノードの子リストの最後尾を取得*/
1102-ST_Node ST_getLastChild(ST_Node node)
1103-{
1104- errno_before_eprint = GET_LAST_CHILD_ERROR;
1105-
1106- if (check_null(node))
1107- {
1108- return ST_EMPTY_NODE;
1109- }
1110-
1111- if (ST_isEmptyNode(node) || (NULL == node->lastChild))
1112- {
1113- return node;
1114- }
1115-
1116- errno_before_eprint = Init_errno_before_eprint;
1117-
1118- return node->lastChild;
1119-}
1120-
1121-/*ST_getPreviousNode 関数
1122- * 引数で指定されたノードにとって、前隣りのノードを取得*/
1123-ST_Node ST_getPreviousNode(ST_Node node)
1124-{
1125- errno_before_eprint = GET_PREVIOUS_NODE_ERROR;
1126-
1127- if (check_null(node))
1128- {
1129- return ST_EMPTY_NODE;
1130- }
1131-
1132- if (ST_isEmptyNode(node) || (NULL == node->previousSibling))
1133- {
1134- return node;
1135- }
1136-
1137- errno_before_eprint = Init_errno_before_eprint;
1138-
1139- return node->previousSibling;
1140-}
1141-
1142-/*ST_getParentNode 関数
1143- * 引数の親ノードを取得*/
1144-ST_Node ST_getParentNode(ST_Node node)
1145-{
1146- errno_before_eprint = GET_PARENT_NODE_ERROR;
1147-
1148- if (check_null(node))
1149- {
1150- errno_before_eprint = Init_errno_before_eprint;
1151- return ST_EMPTY_NODE;
1152- }
1153-
1154- if (ST_isEmptyNode(node) || (NULL == node->parentNode))
1155- {
1156- errno_before_eprint = Init_errno_before_eprint;
1157- return ST_EMPTY_NODE;
1158- }
1159-
1160- errno_before_eprint = Init_errno_before_eprint;
1161-
1162- return node->parentNode;
1163-}
1164-
1165-/*ST_copyNode 関数
1166- * 二番目の引数で指定されたノードのコピーを作成して、返す
1167- * 子ノードも含めて深くコピーするが、隣接ノードはコピーしない
1168- * 一番目の引数はST_freenodeで使うためのフリーリスト*/
1169-ST_Node ST_copyNode(ST_Free_Node freelist, ST_Node node)
1170-{
1171- errno_before_eprint = COPY_NODE_ERROR;
1172-
1173- if ((NULL == node) || ST_isEmptyNode(node))
1174- {
1175- /*nodeが無効値、NULLである場合はエラー
1176- *ST_EMPTY_NODEを返す*/
1177- errno = EINVAL;
1178- eprint_log("Argument error on the function ST_copyNode:");
1179- return ST_EMPTY_NODE;
1180- }
1181-
1182- ST_Node copy = ST_createNode(freelist);
1183- ST_setNodeValue(copy, ST_getNodeValue(node));
1184- copy->nodeType = node->nodeType;
1185-
1186- /*コピーしたい子ノードにおける現在のノード*/
1187- ST_Node current = ST_EMPTY_NODE;
1188- /*コピーしたい子ノード*/
1189- ST_Node child = ST_getLastChild(node);
1190- /*nodeの子ノードを次々とコピーしていく*/
1191- while (!ST_isEmptyNode(child))
1192- {
1193- /*currentにはST_copyNode(child)の値が代入される*/
1194- current = ST_insertBefore(copy, ST_copyNode(ST_EMPTY_NODE, child), current);
1195- child = ST_getPreviousNode(child);
1196- }
1197-
1198- errno_before_eprint = Init_errno_before_eprint;
1199-
1200- return copy;
1201-}
1202-
1203-/*ST_freenode 関数
1204- * 引数freelistに登録されたノードを、子ノードも含めて、全て深く解放していく
1205- * その際、ノード値そのものも解放する*/
1206-void ST_freenode (ST_Free_Node freelist)
1207-{
1208- if ( (NULL == freelist) || ST_isEmptyNode(freelist))
1209- {
1210- return;
1211- }
1212-
1213- ST_Node prev = ST_getLastChild(freelist);
1214-
1215- while (!ST_isEmptyNode(prev))
1216- {
1217- ST_Node node = prev;
1218- prev = ST_getPreviousNode(node);
1219- ST_freenode(node);
1220- }
1221- free(freelist);
1222- freelist = NULL;
1223-}
1224678
1225679
1226680 /*ST_readFile 関数
Binary files a/source_code/shadowstar.o and b/source_code/shadowstar.o differ