Mowkow 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mowkow-0.1.0/Mowkow.egg-info/PKG-INFO +117 -0
- mowkow-0.1.0/Mowkow.egg-info/SOURCES.txt +14 -0
- mowkow-0.1.0/Mowkow.egg-info/dependency_links.txt +1 -0
- mowkow-0.1.0/Mowkow.egg-info/entry_points.txt +2 -0
- mowkow-0.1.0/Mowkow.egg-info/top_level.txt +1 -0
- mowkow-0.1.0/PKG-INFO +117 -0
- mowkow-0.1.0/README.md +108 -0
- mowkow-0.1.0/mowkow/__init__.py +0 -0
- mowkow-0.1.0/mowkow/_data.py +248 -0
- mowkow-0.1.0/mowkow/_error.py +40 -0
- mowkow-0.1.0/mowkow/_eval.py +541 -0
- mowkow-0.1.0/mowkow/_parse.py +269 -0
- mowkow-0.1.0/mowkow/library_kor.scm +252 -0
- mowkow-0.1.0/mowkow/main.py +360 -0
- mowkow-0.1.0/pyproject.toml +23 -0
- mowkow-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: Mowkow
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Mowkow: A Korean LISP Interpreter
|
|
5
|
+
Author-email: Gyun Woo <woogyun@pnu.edu>
|
|
6
|
+
Keywords: Korean,LISP,coding,programming,interpreter
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# mowkow
|
|
11
|
+
머꼬: 한글 LISP
|
|
12
|
+
|
|
13
|
+
## 실행 방법
|
|
14
|
+
Python 3.10 이상을 설치한 후 다음 명령을 수행합니다.
|
|
15
|
+
```
|
|
16
|
+
python main.py
|
|
17
|
+
```
|
|
18
|
+
Windows 운영체제에서는 dist의 mk.exe를 다운로드하셔서 명령 프롬프트에서 다음과 같이 수행합니다.
|
|
19
|
+
```
|
|
20
|
+
mk.exe
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
종료하려면 그냥 엔터를 입력하면 됩니다.
|
|
24
|
+
|
|
25
|
+
## 테스트 입력
|
|
26
|
+
|
|
27
|
+
다음 입력을 수행해 보세요.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
> (+ 10 20)
|
|
31
|
+
30
|
|
32
|
+
> (그대로 10)
|
|
33
|
+
10
|
|
34
|
+
> (그대로 (+ 10 20))
|
|
35
|
+
30
|
|
36
|
+
> (그대로 '(+ 10 20))
|
|
37
|
+
(+ 10 20)
|
|
38
|
+
> (절댓값 (- 20))
|
|
39
|
+
오류: <내장함수 '-'>: 인수 개수 오류입니다.
|
|
40
|
+
> (절댓값 (- 0 20))
|
|
41
|
+
20
|
|
42
|
+
> (머 '(1 2 3))
|
|
43
|
+
1
|
|
44
|
+
> (꼬 '(1 2 3))
|
|
45
|
+
(2 3)
|
|
46
|
+
> (잠시 ((이 2) (삼 3)) (+ 이 삼))
|
|
47
|
+
5
|
|
48
|
+
> (정의 (합 수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1)))))
|
|
49
|
+
> (합 4)
|
|
50
|
+
10
|
|
51
|
+
> (정의 합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))
|
|
52
|
+
> (합 5)
|
|
53
|
+
15
|
|
54
|
+
> (잠시 ((인수 5) (합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))) (합 인수))
|
|
55
|
+
15
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 테스트 프로그램
|
|
59
|
+
두 양수를 입력받아 최대공약수와 최소공배수를 구하는 프로그램(`gcd_lcm.mk`)의 예를 보면 다음과 같습니다.
|
|
60
|
+
```
|
|
61
|
+
(정의 (나머지 가 나)
|
|
62
|
+
(- 가 (* (/ 가 나) 나)))
|
|
63
|
+
|
|
64
|
+
(정의 (최대공약수 가 나)
|
|
65
|
+
(만약 (= 나 0)
|
|
66
|
+
가
|
|
67
|
+
(최대공약수 나 (나머지 가 나))))
|
|
68
|
+
|
|
69
|
+
(정의 (최소공배수 가 나)
|
|
70
|
+
(/ (* 가 나) (최대공약수 가 나)))
|
|
71
|
+
|
|
72
|
+
(정의 가 (읽기))
|
|
73
|
+
(정의 나 (읽기))
|
|
74
|
+
(쓰기 (최대공약수 가 나))
|
|
75
|
+
(쓰기 (최소공배수 가 나))
|
|
76
|
+
```
|
|
77
|
+
위 프로그램은 다음과 같이 수행할 수 있습니다.
|
|
78
|
+
```
|
|
79
|
+
> python main.py gcd_lcm.mk
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## 테스트 코드
|
|
84
|
+
|
|
85
|
+
테스트 코드 폴더의 테스트 파일 source.mk를 수행하려면 다음과 같이 수행하시면 됩니다.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
python main.py test_code/source.mk
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
윈도우 실행 파일 mk.exe로 수행하시려면 다음과 같이 수행하시면 됩니다.
|
|
92
|
+
```
|
|
93
|
+
mk.exe test_code/source.mk
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Windows용 배치 파일
|
|
97
|
+
|
|
98
|
+
머꼬 프로그램 파일은 UTF-8 인코딩으로 작성해야 합니다.
|
|
99
|
+
`test_code`의 예제 프로그램도 그렇게 작성된 것입니다.
|
|
100
|
+
이를 Windows의 명령 프롬프트(`cmd`) 창에서 보려면 문자 인코딩을 UTF-8 인코딩으로 바꾸어야 합니다.
|
|
101
|
+
이때 다음 명령어를 사용하실 수 있습니다.
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
gomk
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
다시 원래 인코딩(code page 949, EUC-KR 호환)으로 명령 프롬프트를 회복하시려면 다음 명령어를 사용하시기 바랍니다.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
kmog
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Authors
|
|
114
|
+
|
|
115
|
+
* **우균(Gyun Woo)** - *최초 작업* - [Gyun Woo](https://github.com/woogyun)
|
|
116
|
+
|
|
117
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
Mowkow.egg-info/PKG-INFO
|
|
4
|
+
Mowkow.egg-info/SOURCES.txt
|
|
5
|
+
Mowkow.egg-info/dependency_links.txt
|
|
6
|
+
Mowkow.egg-info/entry_points.txt
|
|
7
|
+
Mowkow.egg-info/top_level.txt
|
|
8
|
+
mowkow/__init__.py
|
|
9
|
+
mowkow/_data.py
|
|
10
|
+
mowkow/_error.py
|
|
11
|
+
mowkow/_eval.py
|
|
12
|
+
mowkow/_parse.py
|
|
13
|
+
mowkow/library_kor.scm
|
|
14
|
+
mowkow/main.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mowkow
|
mowkow-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: Mowkow
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Mowkow: A Korean LISP Interpreter
|
|
5
|
+
Author-email: Gyun Woo <woogyun@pnu.edu>
|
|
6
|
+
Keywords: Korean,LISP,coding,programming,interpreter
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# mowkow
|
|
11
|
+
머꼬: 한글 LISP
|
|
12
|
+
|
|
13
|
+
## 실행 방법
|
|
14
|
+
Python 3.10 이상을 설치한 후 다음 명령을 수행합니다.
|
|
15
|
+
```
|
|
16
|
+
python main.py
|
|
17
|
+
```
|
|
18
|
+
Windows 운영체제에서는 dist의 mk.exe를 다운로드하셔서 명령 프롬프트에서 다음과 같이 수행합니다.
|
|
19
|
+
```
|
|
20
|
+
mk.exe
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
종료하려면 그냥 엔터를 입력하면 됩니다.
|
|
24
|
+
|
|
25
|
+
## 테스트 입력
|
|
26
|
+
|
|
27
|
+
다음 입력을 수행해 보세요.
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
> (+ 10 20)
|
|
31
|
+
30
|
|
32
|
+
> (그대로 10)
|
|
33
|
+
10
|
|
34
|
+
> (그대로 (+ 10 20))
|
|
35
|
+
30
|
|
36
|
+
> (그대로 '(+ 10 20))
|
|
37
|
+
(+ 10 20)
|
|
38
|
+
> (절댓값 (- 20))
|
|
39
|
+
오류: <내장함수 '-'>: 인수 개수 오류입니다.
|
|
40
|
+
> (절댓값 (- 0 20))
|
|
41
|
+
20
|
|
42
|
+
> (머 '(1 2 3))
|
|
43
|
+
1
|
|
44
|
+
> (꼬 '(1 2 3))
|
|
45
|
+
(2 3)
|
|
46
|
+
> (잠시 ((이 2) (삼 3)) (+ 이 삼))
|
|
47
|
+
5
|
|
48
|
+
> (정의 (합 수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1)))))
|
|
49
|
+
> (합 4)
|
|
50
|
+
10
|
|
51
|
+
> (정의 합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))
|
|
52
|
+
> (합 5)
|
|
53
|
+
15
|
|
54
|
+
> (잠시 ((인수 5) (합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))) (합 인수))
|
|
55
|
+
15
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 테스트 프로그램
|
|
59
|
+
두 양수를 입력받아 최대공약수와 최소공배수를 구하는 프로그램(`gcd_lcm.mk`)의 예를 보면 다음과 같습니다.
|
|
60
|
+
```
|
|
61
|
+
(정의 (나머지 가 나)
|
|
62
|
+
(- 가 (* (/ 가 나) 나)))
|
|
63
|
+
|
|
64
|
+
(정의 (최대공약수 가 나)
|
|
65
|
+
(만약 (= 나 0)
|
|
66
|
+
가
|
|
67
|
+
(최대공약수 나 (나머지 가 나))))
|
|
68
|
+
|
|
69
|
+
(정의 (최소공배수 가 나)
|
|
70
|
+
(/ (* 가 나) (최대공약수 가 나)))
|
|
71
|
+
|
|
72
|
+
(정의 가 (읽기))
|
|
73
|
+
(정의 나 (읽기))
|
|
74
|
+
(쓰기 (최대공약수 가 나))
|
|
75
|
+
(쓰기 (최소공배수 가 나))
|
|
76
|
+
```
|
|
77
|
+
위 프로그램은 다음과 같이 수행할 수 있습니다.
|
|
78
|
+
```
|
|
79
|
+
> python main.py gcd_lcm.mk
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## 테스트 코드
|
|
84
|
+
|
|
85
|
+
테스트 코드 폴더의 테스트 파일 source.mk를 수행하려면 다음과 같이 수행하시면 됩니다.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
python main.py test_code/source.mk
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
윈도우 실행 파일 mk.exe로 수행하시려면 다음과 같이 수행하시면 됩니다.
|
|
92
|
+
```
|
|
93
|
+
mk.exe test_code/source.mk
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Windows용 배치 파일
|
|
97
|
+
|
|
98
|
+
머꼬 프로그램 파일은 UTF-8 인코딩으로 작성해야 합니다.
|
|
99
|
+
`test_code`의 예제 프로그램도 그렇게 작성된 것입니다.
|
|
100
|
+
이를 Windows의 명령 프롬프트(`cmd`) 창에서 보려면 문자 인코딩을 UTF-8 인코딩으로 바꾸어야 합니다.
|
|
101
|
+
이때 다음 명령어를 사용하실 수 있습니다.
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
gomk
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
다시 원래 인코딩(code page 949, EUC-KR 호환)으로 명령 프롬프트를 회복하시려면 다음 명령어를 사용하시기 바랍니다.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
kmog
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Authors
|
|
114
|
+
|
|
115
|
+
* **우균(Gyun Woo)** - *최초 작업* - [Gyun Woo](https://github.com/woogyun)
|
|
116
|
+
|
|
117
|
+
|
mowkow-0.1.0/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# mowkow
|
|
2
|
+
머꼬: 한글 LISP
|
|
3
|
+
|
|
4
|
+
## 실행 방법
|
|
5
|
+
Python 3.10 이상을 설치한 후 다음 명령을 수행합니다.
|
|
6
|
+
```
|
|
7
|
+
python main.py
|
|
8
|
+
```
|
|
9
|
+
Windows 운영체제에서는 dist의 mk.exe를 다운로드하셔서 명령 프롬프트에서 다음과 같이 수행합니다.
|
|
10
|
+
```
|
|
11
|
+
mk.exe
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
종료하려면 그냥 엔터를 입력하면 됩니다.
|
|
15
|
+
|
|
16
|
+
## 테스트 입력
|
|
17
|
+
|
|
18
|
+
다음 입력을 수행해 보세요.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
> (+ 10 20)
|
|
22
|
+
30
|
|
23
|
+
> (그대로 10)
|
|
24
|
+
10
|
|
25
|
+
> (그대로 (+ 10 20))
|
|
26
|
+
30
|
|
27
|
+
> (그대로 '(+ 10 20))
|
|
28
|
+
(+ 10 20)
|
|
29
|
+
> (절댓값 (- 20))
|
|
30
|
+
오류: <내장함수 '-'>: 인수 개수 오류입니다.
|
|
31
|
+
> (절댓값 (- 0 20))
|
|
32
|
+
20
|
|
33
|
+
> (머 '(1 2 3))
|
|
34
|
+
1
|
|
35
|
+
> (꼬 '(1 2 3))
|
|
36
|
+
(2 3)
|
|
37
|
+
> (잠시 ((이 2) (삼 3)) (+ 이 삼))
|
|
38
|
+
5
|
|
39
|
+
> (정의 (합 수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1)))))
|
|
40
|
+
> (합 4)
|
|
41
|
+
10
|
|
42
|
+
> (정의 합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))
|
|
43
|
+
> (합 5)
|
|
44
|
+
15
|
|
45
|
+
> (잠시 ((인수 5) (합 (람다 (수) (만약 (= 수 0) 0 (+ 수 (합 (- 수 1))))))) (합 인수))
|
|
46
|
+
15
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 테스트 프로그램
|
|
50
|
+
두 양수를 입력받아 최대공약수와 최소공배수를 구하는 프로그램(`gcd_lcm.mk`)의 예를 보면 다음과 같습니다.
|
|
51
|
+
```
|
|
52
|
+
(정의 (나머지 가 나)
|
|
53
|
+
(- 가 (* (/ 가 나) 나)))
|
|
54
|
+
|
|
55
|
+
(정의 (최대공약수 가 나)
|
|
56
|
+
(만약 (= 나 0)
|
|
57
|
+
가
|
|
58
|
+
(최대공약수 나 (나머지 가 나))))
|
|
59
|
+
|
|
60
|
+
(정의 (최소공배수 가 나)
|
|
61
|
+
(/ (* 가 나) (최대공약수 가 나)))
|
|
62
|
+
|
|
63
|
+
(정의 가 (읽기))
|
|
64
|
+
(정의 나 (읽기))
|
|
65
|
+
(쓰기 (최대공약수 가 나))
|
|
66
|
+
(쓰기 (최소공배수 가 나))
|
|
67
|
+
```
|
|
68
|
+
위 프로그램은 다음과 같이 수행할 수 있습니다.
|
|
69
|
+
```
|
|
70
|
+
> python main.py gcd_lcm.mk
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## 테스트 코드
|
|
75
|
+
|
|
76
|
+
테스트 코드 폴더의 테스트 파일 source.mk를 수행하려면 다음과 같이 수행하시면 됩니다.
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
python main.py test_code/source.mk
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
윈도우 실행 파일 mk.exe로 수행하시려면 다음과 같이 수행하시면 됩니다.
|
|
83
|
+
```
|
|
84
|
+
mk.exe test_code/source.mk
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Windows용 배치 파일
|
|
88
|
+
|
|
89
|
+
머꼬 프로그램 파일은 UTF-8 인코딩으로 작성해야 합니다.
|
|
90
|
+
`test_code`의 예제 프로그램도 그렇게 작성된 것입니다.
|
|
91
|
+
이를 Windows의 명령 프롬프트(`cmd`) 창에서 보려면 문자 인코딩을 UTF-8 인코딩으로 바꾸어야 합니다.
|
|
92
|
+
이때 다음 명령어를 사용하실 수 있습니다.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
gomk
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
다시 원래 인코딩(code page 949, EUC-KR 호환)으로 명령 프롬프트를 회복하시려면 다음 명령어를 사용하시기 바랍니다.
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
kmog
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Authors
|
|
105
|
+
|
|
106
|
+
* **우균(Gyun Woo)** - *최초 작업* - [Gyun Woo](https://github.com/woogyun)
|
|
107
|
+
|
|
108
|
+
|
|
File without changes
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#coding: utf-8
|
|
2
|
+
|
|
3
|
+
# Ph 4(eval): Pair.car() and Pair.cdr()
|
|
4
|
+
# global car(Data) and cdr(Data)
|
|
5
|
+
# Symbol.value(self)
|
|
6
|
+
# global islist(Data): recursive
|
|
7
|
+
# Data.issymbol(), Data.isint(), Symbol.issymbol(), Int.isint()
|
|
8
|
+
# islist(Data)
|
|
9
|
+
# bug: Pair의 함수 이름과 필드 이름을 똑같이 car, cdr로 설정했었음.
|
|
10
|
+
# -> 필드를 _car, _cdr로 바꿈
|
|
11
|
+
|
|
12
|
+
# Ph 5(car): class Builtin
|
|
13
|
+
# global mkbuiltin, cplist
|
|
14
|
+
# Pair.setcar(Data)
|
|
15
|
+
# Integer.value()
|
|
16
|
+
|
|
17
|
+
# Ph 7(clo): class Closure
|
|
18
|
+
# Data.isclosure()
|
|
19
|
+
# global allsymbols(Data)
|
|
20
|
+
# from _error import *
|
|
21
|
+
|
|
22
|
+
# Ph 10(var): Closure.__init__ does not use allsymbols
|
|
23
|
+
# but checks the parameter types manually
|
|
24
|
+
|
|
25
|
+
# Ph 11(macro): Macro(Data) class is a copycat of Closure(Data)
|
|
26
|
+
# Macro.isclosure()를 Macro.ismacro()로 대체
|
|
27
|
+
# Data.ismacro() 추가
|
|
28
|
+
# Macro 생성자를 호출하는 전역 함수 mkmacro 추가
|
|
29
|
+
|
|
30
|
+
from ._error import ErrType, ErrSyntax
|
|
31
|
+
|
|
32
|
+
class Data:
|
|
33
|
+
"""클래스 Data는 머꼬의 모든 데이터 클래스의 부모 클래스입니다."""
|
|
34
|
+
def __init__(self):
|
|
35
|
+
"""Data 클래스는 추상 클래스이므로 비워 두었습니다."""
|
|
36
|
+
def ispair(self) -> bool:
|
|
37
|
+
"""짝(pair)인지 점검하는 함수. 짝이면 참"""
|
|
38
|
+
return False
|
|
39
|
+
def isnil(self) -> bool:
|
|
40
|
+
"""공(nil)인지 점검하는 함수. 공이면 참"""
|
|
41
|
+
return False
|
|
42
|
+
def issymbol(self) -> bool:
|
|
43
|
+
return False
|
|
44
|
+
def isint(self) -> bool:
|
|
45
|
+
return False
|
|
46
|
+
def isstr(self) -> bool:
|
|
47
|
+
return False
|
|
48
|
+
def isbuiltin(self) -> bool:
|
|
49
|
+
return False
|
|
50
|
+
def isclosure(self) -> bool:
|
|
51
|
+
return False
|
|
52
|
+
def ismacro(self) -> bool:
|
|
53
|
+
return False
|
|
54
|
+
def value(self) -> None:
|
|
55
|
+
""" place holder for value """
|
|
56
|
+
return None
|
|
57
|
+
def car(self) -> None:
|
|
58
|
+
"""place holder for car"""
|
|
59
|
+
return None
|
|
60
|
+
def cdr(self) -> None:
|
|
61
|
+
"""place holder for cdr"""
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
class Nil(Data):
|
|
65
|
+
def __init__(self):
|
|
66
|
+
pass
|
|
67
|
+
def __str__(self):
|
|
68
|
+
return "공"
|
|
69
|
+
def isnil(self) -> bool:
|
|
70
|
+
return True
|
|
71
|
+
|
|
72
|
+
class Pair(Data):
|
|
73
|
+
def __init__(self, car_val: Data, cdr_val: Data):
|
|
74
|
+
self._car, self._cdr = car_val, cdr_val
|
|
75
|
+
def ispair(self) -> bool:
|
|
76
|
+
return True
|
|
77
|
+
def __str__(self) -> str:
|
|
78
|
+
rval = f"({self._car}"
|
|
79
|
+
tail = self._cdr
|
|
80
|
+
while not tail.isnil():
|
|
81
|
+
if tail.ispair(): # Bug230111: self.cdr.ispair() -> tail.ispair()
|
|
82
|
+
rval += f" {tail._car}" # type: ignore
|
|
83
|
+
tail = tail._cdr # type: ignore
|
|
84
|
+
else:
|
|
85
|
+
rval += f" . {tail}"
|
|
86
|
+
break # break가 꼭 필요함
|
|
87
|
+
rval += ")"
|
|
88
|
+
return rval
|
|
89
|
+
def setcar(self, car_val: Data) -> None:
|
|
90
|
+
self._car = car_val
|
|
91
|
+
def setcdr(self, cdr_val: Data) -> None:
|
|
92
|
+
self._cdr = cdr_val
|
|
93
|
+
def car(self) -> Data:
|
|
94
|
+
return self._car
|
|
95
|
+
def cdr(self) -> Data:
|
|
96
|
+
return self._cdr
|
|
97
|
+
|
|
98
|
+
class Symbol(Data):
|
|
99
|
+
def __init__(self, s: str):
|
|
100
|
+
self._val = s
|
|
101
|
+
def issymbol(self) -> bool:
|
|
102
|
+
return True
|
|
103
|
+
def __str__(self) -> str:
|
|
104
|
+
return self._val
|
|
105
|
+
def value(self) -> str:
|
|
106
|
+
return self._val
|
|
107
|
+
|
|
108
|
+
class Integer(Data):
|
|
109
|
+
def __init__(self, i: int):
|
|
110
|
+
self._val = i
|
|
111
|
+
def isint(self) -> bool:
|
|
112
|
+
return True
|
|
113
|
+
def __str__(self) -> str:
|
|
114
|
+
return str(self._val)
|
|
115
|
+
def value(self) -> int:
|
|
116
|
+
return self._val
|
|
117
|
+
|
|
118
|
+
class String(Data):
|
|
119
|
+
def __init__(self, s: str):
|
|
120
|
+
self._val = s
|
|
121
|
+
def isstr(self) -> bool:
|
|
122
|
+
return True
|
|
123
|
+
def __str__(self) -> str:
|
|
124
|
+
return self._val # Des250429: f'"{self._val}"'로 했다가 바꾸었음
|
|
125
|
+
def value(self) -> str:
|
|
126
|
+
return self._val
|
|
127
|
+
|
|
128
|
+
class Builtin(Data):
|
|
129
|
+
def __init__(self, fn):
|
|
130
|
+
self._fun = fn
|
|
131
|
+
def isbuiltin(self) -> bool:
|
|
132
|
+
return not super().isbuiltin()
|
|
133
|
+
def __str__(self) -> str:
|
|
134
|
+
fname = f"{self._fun}".split()[2]
|
|
135
|
+
return f"#<내장 함수: {fname}>"
|
|
136
|
+
def fun(self):
|
|
137
|
+
return self._fun
|
|
138
|
+
|
|
139
|
+
class Closure(Data):
|
|
140
|
+
def __init__(self, env: Data, params: Data, body: Data):
|
|
141
|
+
## commented out for ch 10 (variadic)
|
|
142
|
+
# if not islist(params) or not islist(body):
|
|
143
|
+
# raise ErrSyntax() ####
|
|
144
|
+
# allsymbols(params)
|
|
145
|
+
if not islist(body):
|
|
146
|
+
raise ErrSyntax()
|
|
147
|
+
p = params
|
|
148
|
+
while not p.isnil():
|
|
149
|
+
if p.issymbol(): # the last symbol such as c in (f a b . c)
|
|
150
|
+
break
|
|
151
|
+
elif not p.ispair() or not car(p).issymbol():
|
|
152
|
+
raise ErrType("<#클로저>")
|
|
153
|
+
p = cdr(p) # pyright: ignore[reportArgumentType]
|
|
154
|
+
self._val = cons(env, cons(params, body))
|
|
155
|
+
def isclosure(self) -> bool:
|
|
156
|
+
return not super().isclosure()
|
|
157
|
+
def __str__(self) -> str:
|
|
158
|
+
return f"#<클로저>"
|
|
159
|
+
def val(self) -> Data: # returns the closure value (lambda)
|
|
160
|
+
return self._val
|
|
161
|
+
def env(self) -> Data:
|
|
162
|
+
return car(self._val) # pyright: ignore[reportArgumentType]
|
|
163
|
+
def params(self) -> Data:
|
|
164
|
+
return car(cdr(self._val)) # pyright: ignore[reportArgumentType]
|
|
165
|
+
def body(self) -> Data:
|
|
166
|
+
return cdr(cdr(self._val)) # pyright: ignore[reportArgumentType]
|
|
167
|
+
|
|
168
|
+
class Macro(Data):
|
|
169
|
+
def __init__(self, env: Data, params: Data, body: Data):
|
|
170
|
+
if not islist(body):
|
|
171
|
+
raise ErrSyntax()
|
|
172
|
+
p = params
|
|
173
|
+
while not p.isnil():
|
|
174
|
+
if p.issymbol(): # the last symbol such as c in (f a b . c)
|
|
175
|
+
break
|
|
176
|
+
elif not p.ispair() or not car(p).issymbol():
|
|
177
|
+
raise ErrType("<#매크로>")
|
|
178
|
+
p = cdr(p) # pyright: ignore[reportArgumentType]
|
|
179
|
+
self._val = cons(env, cons(params, body))
|
|
180
|
+
def ismacro(self) -> bool:
|
|
181
|
+
return True
|
|
182
|
+
def __str__(self) -> str:
|
|
183
|
+
return f"#<매크로>"
|
|
184
|
+
def val(self) -> Data: # returns the closure value (lambda)
|
|
185
|
+
return self._val
|
|
186
|
+
|
|
187
|
+
def cons(car_val: Data, cdr_val: Data) -> Data:
|
|
188
|
+
return Pair(car_val, cdr_val)
|
|
189
|
+
|
|
190
|
+
def car(p: Data) -> Data:
|
|
191
|
+
return p.car()
|
|
192
|
+
|
|
193
|
+
def cdr(p: Data) -> Data:
|
|
194
|
+
return p.cdr()
|
|
195
|
+
|
|
196
|
+
def mkint(ival: int) -> Data:
|
|
197
|
+
return Integer(ival)
|
|
198
|
+
|
|
199
|
+
def mksym(sval: str) -> Data:
|
|
200
|
+
return Symbol(sval)
|
|
201
|
+
|
|
202
|
+
def mkstr(sval: str) -> Data:
|
|
203
|
+
return String(sval)
|
|
204
|
+
|
|
205
|
+
def mkbuiltin(fn) -> Data:
|
|
206
|
+
return Builtin(fn)
|
|
207
|
+
|
|
208
|
+
def mkclosure(env: Data, params: Data, body: Data) -> Data:
|
|
209
|
+
return Closure(env, params, body)
|
|
210
|
+
|
|
211
|
+
def mkmacro(env: Data, params: Data, body: Data) -> Data:
|
|
212
|
+
return Macro(env, params, body)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
nil = Nil()
|
|
216
|
+
|
|
217
|
+
def islist(d: Data) -> bool:
|
|
218
|
+
if d.isnil():
|
|
219
|
+
return True
|
|
220
|
+
else:
|
|
221
|
+
return d.ispair() and islist(cdr(d)) # pyright: ignore[reportArgumentType]
|
|
222
|
+
# Bug_20230104_a: cdr(d).ispair() -> islist(cdr(d))
|
|
223
|
+
|
|
224
|
+
def cplist(ls: Data) -> Data:
|
|
225
|
+
if ls.isnil():
|
|
226
|
+
return nil
|
|
227
|
+
head = cons(car(ls), nil) # pyright: ignore[reportArgumentType]
|
|
228
|
+
prev = head
|
|
229
|
+
ls = cdr(ls) # pyright: ignore[reportArgumentType]
|
|
230
|
+
while not ls.isnil():
|
|
231
|
+
prev.setcdr(cons(car(ls), nil)) # pyright: ignore[reportAttributeAccessIssue, reportArgumentType]
|
|
232
|
+
prev = cdr(prev) # pyright: ignore[reportArgumentType]
|
|
233
|
+
ls = cdr(ls) # pyright: ignore[reportArgumentType]
|
|
234
|
+
return head
|
|
235
|
+
|
|
236
|
+
def allsymbols(params: Data) -> None:
|
|
237
|
+
p = params
|
|
238
|
+
while not p.isnil():
|
|
239
|
+
if not car(p).issymbol(): # pyright: ignore[reportArgumentType]
|
|
240
|
+
raise ErrType("<#클로저>")
|
|
241
|
+
p = cdr(p) # pyright: ignore[reportArgumentType]
|
|
242
|
+
|
|
243
|
+
if __name__ == '__main__':
|
|
244
|
+
print(mkint(1910))
|
|
245
|
+
print(mksym("안녕"))
|
|
246
|
+
print(mkstr("안녕, 문자열?"))
|
|
247
|
+
print(cons(mkint(8), cons(mkint(2), cons(mkint(9), nil))))
|
|
248
|
+
print(cons(mkint(3), mkint(4)))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#coding: utf-8
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
IsVerbose = False
|
|
6
|
+
|
|
7
|
+
def eprint(*args, **kwargs) -> None:
|
|
8
|
+
'''stderr에 출력하는 함수'''
|
|
9
|
+
print(*args, file=sys.stderr, **kwargs)
|
|
10
|
+
|
|
11
|
+
# making the hierarchy of Errors
|
|
12
|
+
# To do: enriching the arguments of errors
|
|
13
|
+
# translate into Korean
|
|
14
|
+
|
|
15
|
+
class ErrLisp(Exception):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
class ErrSyntax(ErrLisp):
|
|
19
|
+
def __init__(self:ErrLisp):
|
|
20
|
+
pass
|
|
21
|
+
def __str__(self:ErrLisp) -> str:
|
|
22
|
+
return "구문 오류"
|
|
23
|
+
|
|
24
|
+
class ErrUnbound(ErrLisp):
|
|
25
|
+
def __init__(self, sym: str):
|
|
26
|
+
self.symname = sym
|
|
27
|
+
def __str__(self:ErrLisp) -> str:
|
|
28
|
+
return f"이름 '{self.symname}'을(를) 찾을 수 없습니다." # pyright: ignore[reportAttributeAccessIssue]
|
|
29
|
+
|
|
30
|
+
class ErrArgs(ErrLisp):
|
|
31
|
+
def __init__(self, fun: str):
|
|
32
|
+
self.funname = fun
|
|
33
|
+
def __str__(self:ErrLisp) -> str:
|
|
34
|
+
return f"함수 {self.funname}: 인수 개수 오류입니다." # pyright: ignore[reportAttributeAccessIssue]
|
|
35
|
+
|
|
36
|
+
class ErrType(ErrLisp):
|
|
37
|
+
def __init__(self, fun: str):
|
|
38
|
+
self.funname = fun
|
|
39
|
+
def __str__(self:ErrLisp) -> str:
|
|
40
|
+
return f"함수 {self.funname}: 타입 오류입니다." # pyright: ignore[reportAttributeAccessIssue]
|