##// END OF EJS Templates
MENU
naryl -
r30:3c634d0a default
parent child Browse files
Show More
@@ -1,13 +1,22 b''
1
2 # start
3 act 'ΠŸΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ мСню':
4 gs 'menu'
5 end
6 -
1
7
2 # menu
8 # menu
9 killvar 'usr_menu'
3 ! Π½Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ
10 ! Π½Π΅Ρ‚ ΠΈΠΊΠΎΠ½ΠΊΠΈ
4 $usr_menu[0] = 'Π’Π·ΡΡ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:take_item'
11 $usr_menu[] = 'Π’Π·ΡΡ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:take_item'
5 ! ΠΈΠΊΠΎΠ½ΠΊΠ° Π·Π°Π΄Π°Π½Π° gif-Ρ„Π°ΠΉΠ»ΠΎΠΌ
12 ! ΠΈΠΊΠΎΠ½ΠΊΠ° Π·Π°Π΄Π°Π½Π° gif-Ρ„Π°ΠΉΠ»ΠΎΠΌ
6 $usr_menu[1] = 'ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:put_item:images/put_item.gif'
13 $usr_menu[] = 'ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:put_item:images/put_item.gif'
7 ! ΠΈΠΊΠΎΠ½ΠΊΠ° Π·Π°Π΄Π°Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ $icon_file
14 ! ΠΈΠΊΠΎΠ½ΠΊΠ° Π·Π°Π΄Π°Π½Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ $icon_file
8 $usr_menu[2] = 'ΠžΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:look_item:<<$icon_file>>'
15 $usr_menu[] = 'ΠžΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚:look_item:<<$icon_file>>'
16 ! Π Π°Π·Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ
17 $usr_menu[] = '-:-'
9 ! ΠΏΡƒΠ½ΠΊΡ‚ мСню Π·Π°Π΄Π°Π½ 3-мя ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ
18 ! ΠΏΡƒΠ½ΠΊΡ‚ мСню Π·Π°Π΄Π°Π½ 3-мя ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ
10 $usr_menu[3] = '<<$name>>:<<$loc>>:<<$file>>'
19 $usr_menu[] = '<<$name>>:<<$locname>>:<<$file>>'
11
20
12 menu 'usr_menu' &! ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ мСню ΠΈΠ· 4-Ρ… ΠΏΡƒΠ½ΠΊΡ‚ΠΎΠ²
21 menu 'usr_menu' &! ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ мСню ΠΈΠ· 4-Ρ… ΠΏΡƒΠ½ΠΊΡ‚ΠΎΠ²
13 -
22 -
@@ -1,23 +1,23 b''
1
1
2 <div id="qsp">
2 <div id="qsp">
3 <div class="qsp-col qsp-col1">
3 <div class="qsp-col qsp-col1">
4 <div id="qsp-main" class="qsp-frame">&nbsp;</div>
4 <div id="qsp-main" class="qsp-frame">&nbsp;</div>
5 <div id="qsp-acts" class="qsp-frame">&nbsp;</div>
5 <div id="qsp-acts" class="qsp-frame">&nbsp;</div>
6 <input id="qsp-input" class="qsp-frame">
6 <input id="qsp-input" class="qsp-frame">
7 </div>
7 </div>
8 <div class="qsp-col qsp-col2">
8 <div class="qsp-col qsp-col2">
9 <div id="qsp-stat" class="qsp-frame">&nbsp;</div>
9 <div id="qsp-stat" class="qsp-frame">&nbsp;</div>
10 <div id="qsp-objs" class="qsp-frame">&nbsp;</div>
10 <div id="qsp-objs" class="qsp-frame">&nbsp;</div>
11 </div>
11 </div>
12 <div class="qsp-col qsp-col3">
12 <div class="qsp-col qsp-col3">
13 <a id="qsp-btn-save"><img></a>
13 <a id="qsp-btn-save"><img></a>
14 <a id="qsp-btn-open"><img></a>
14 <a id="qsp-btn-open"><img></a>
15 </div>
15 </div>
16 </div>
16 </div>
17
17
18 <div id="qsp-dropdown">
18 <div id="qsp-dropdown">
19 </div>
19 </div>
20
20
21 <div id="qsp-image-container">
21 <div id="qsp-image-container" class="center-on-screen">
22 <img id="qsp-image">
22 <img id="qsp-image">
23 </div>
23 </div>
@@ -1,121 +1,129 b''
1
1
2 .qsp-frame {
2 .qsp-frame {
3 border: 1px solid black;
3 border: 1px solid black;
4 overflow: auto;
4 overflow: auto;
5 padding: 5px;
5 padding: 5px;
6 box-sizing: border-box;
6 box-sizing: border-box;
7 }
7 }
8
8
9 #qsp {
9 #qsp {
10 position: absolute;
10 position: absolute;
11 display: flex;
11 display: flex;
12 flex-flow: row;
12 flex-flow: row;
13 top: 0;
13 top: 0;
14 left: 0;
14 left: 0;
15 width: 100%;
15 width: 100%;
16 height: 100%;
16 height: 100%;
17 }
17 }
18
18
19 .qsp-col {
19 .qsp-col {
20 display: flex;
20 display: flex;
21 flex-flow: column;
21 flex-flow: column;
22 }
22 }
23
23
24 .qsp-col1 {
24 .qsp-col1 {
25 flex: 7 7 70px;
25 flex: 7 7 70px;
26 }
26 }
27
27
28 .qsp-col2 {
28 .qsp-col2 {
29 flex: 3 3 30px;
29 flex: 3 3 30px;
30 }
30 }
31
31
32 .qsp-col3 {
32 .qsp-col3 {
33 flex: 0 0 40px;
33 flex: 0 0 40px;
34 }
34 }
35
35
36 #qsp-main {
36 #qsp-main {
37 flex: 6 6 60px;
37 flex: 6 6 60px;
38 }
38 }
39
39
40 #qsp-acts {
40 #qsp-acts {
41 flex: 4 4 40px;
41 flex: 4 4 40px;
42 }
42 }
43
43
44 #qsp-input {
44 #qsp-input {
45 }
45 }
46
46
47 #qsp-stat {
47 #qsp-stat {
48 flex: 5 5 50px;
48 flex: 5 5 50px;
49 }
49 }
50
50
51 #qsp-objs {
51 #qsp-objs {
52 flex: 5 5 50px;
52 flex: 5 5 50px;
53 }
53 }
54
54
55 .qsp-act {
55 .qsp-act {
56 display: block;
56 display: block;
57 padding: 2px;
57 padding: 2px;
58 font-size: large;
58 font-size: large;
59 }
59 }
60
60
61 .qsp-act:hover {
61 .qsp-act:hover {
62 outline: #9E9E9E outset 3px
62 outline: #9E9E9E outset 3px
63 }
63 }
64
64
65 /* Dropdown */
65 /* Dropdown */
66
66
67 #qsp-dropdown {
67 #qsp-dropdown {
68 display: none;
68 display: none;
69 position: absolute;
69 position: absolute;
70 background-color: #f1f1f1;
70 background-color: #f1f1f1;
71 min-width: 160px;
71 min-width: 160px;
72 overflow: auto;
72 overflow: auto;
73 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
73 box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
74 z-index: 1;
74 z-index: 1;
75 margin: auto;
75 margin: auto;
76 top: 200;
77 }
76 }
78
77
79 #qsp-dropdown a {
78 #qsp-dropdown a {
80 color: black;
79 color: black;
81 padding: 12px 16px;
80 padding: 12px 16px;
82 text-decoration: none;
81 text-decoration: none;
83 display: block;
82 display: block;
84 }
83 }
85
84
86 #qsp-dropdown a:hover {
85 #qsp-dropdown a:hover {
87 background-color: #ddd;
86 background-color: #ddd;
88 }
87 }
89
88
90 /* Buttons */
89 /* Buttons */
91
90
92 .qsp-col3 a, .qsp-col3 img {
91 .qsp-col3 a, .qsp-col3 img {
93 width: 50px;
92 width: 50px;
94 height: 50px;
93 height: 50px;
95 }
94 }
96
95
97 #qsp-btn-save img {
96 #qsp-btn-save img {
98 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACSklEQVRoge3ZPWgUQRjG8V/iRRFU/GoEQdSohSgWWqQSooVgK9iJFiKCnYV2BkFQsBRBQQwWVsHKIoWxEOzEwmhhogbRMhhFicTvYm+JCUlmZzabRLN/OPaWeZ+ZeW7feXf2lpqampqamnRaImKP4hA2VjCP27hbpoNGwbib2IPreB+IPYY7M7SvxWYM4QNO4QqWyQxVRgdeYnnB+K5A+wUcbB7z+O14hxPx08toLRDTgfv4mjrIJFrwwMS0HsABXMTxlE6LpNYqfE7pPJIBdOKhLM1uxIiLrpG5YtC4GSLMVGGkLdD+GpfxAuvxaVL7oCzN+jCG7iKDVmHkKS5hSSBuJ3bg6hRt+Zrpa553z8bEuoQrUVXk1exwKLBI1ZpPBnAL+0KBqanVim1Ykaifji+yNfIrVphipB1n8BgjCfqZ2IrTuIZXMcIUIydxFj8TtEW4JysW52JEKWtkVHUm4EdzjChSrkgLlmJXghb6m8ep9MN4K25XjvTF3sCaElrT6McS+0w2Mirb+JWhrH4CC/0+UpjUK7Ia5/86f4IeHMHeEvPJ+4km1chHE43k9KROpCyLPrViym8/vjW/b5Jt3acjL7/RzEX5bRg3sjKg+2fK7/PmZ9aZzdTqxwYzp06IBZFaDeHUCbFgUquy1Anx35TfRWXkd+WzCBOcQxEjQ7JH0PmiHW9CQUWM9Mr+Y+osO6ME8nF7Q4FFn8T2y14VDMt2vsFfqCRbZBvTdbLXFI9CgphHyjbsVu4+EcMInuH7HI1XU1NTU7OI+QMFe2N82rtssgAAAABJRU5ErkJggg==');
97 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACSklEQVRoge3ZPWgUQRjG8V/iRRFU/GoEQdSohSgWWqQSooVgK9iJFiKCnYV2BkFQsBRBQQwWVsHKIoWxEOzEwmhhogbRMhhFicTvYm+JCUlmZzabRLN/OPaWeZ+ZeW7feXf2lpqampqamnRaImKP4hA2VjCP27hbpoNGwbib2IPreB+IPYY7M7SvxWYM4QNO4QqWyQxVRgdeYnnB+K5A+wUcbB7z+O14hxPx08toLRDTgfv4mjrIJFrwwMS0HsABXMTxlE6LpNYqfE7pPJIBdOKhLM1uxIiLrpG5YtC4GSLMVGGkLdD+GpfxAuvxaVL7oCzN+jCG7iKDVmHkKS5hSSBuJ3bg6hRt+Zrpa553z8bEuoQrUVXk1exwKLBI1ZpPBnAL+0KBqanVim1Ykaifji+yNfIrVphipB1n8BgjCfqZ2IrTuIZXMcIUIydxFj8TtEW4JysW52JEKWtkVHUm4EdzjChSrkgLlmJXghb6m8ep9MN4K25XjvTF3sCaElrT6McS+0w2Mirb+JWhrH4CC/0+UpjUK7Ia5/86f4IeHMHeEvPJ+4km1chHE43k9KROpCyLPrViym8/vjW/b5Jt3acjL7/RzEX5bRg3sjKg+2fK7/PmZ9aZzdTqxwYzp06IBZFaDeHUCbFgUquy1Anx35TfRWXkd+WzCBOcQxEjQ7JH0PmiHW9CQUWM9Mr+Y+osO6ME8nF7Q4FFn8T2y14VDMt2vsFfqCRbZBvTdbLXFI9CgphHyjbsVu4+EcMInuH7HI1XU1NTU7OI+QMFe2N82rtssgAAAABJRU5ErkJggg==');
99 }
98 }
100
99
101 #qsp-btn-open img {
100 #qsp-btn-open img {
102 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACCklEQVRoge3Yz6sNYRzH8deVexNxSaEoroWFUuomOceSPVnIwsbSxs6Psrgphf9AsrZR7kJWsroUlrZKKZRSl4USGouZk9Npzp1n5pm5x4/nXdNzpvP9Pp/v95nv82OGRCKRSCQS/w8zuIn3yGpe37CEQ6sedQk38BA7G/jO4BQ+YEebQZUxVfH/OxzGVSxX2D4o2mO4jmt4jpNFe6d5mPFkRbvQ0H9h6OqUtR33/xXr0celGn4/sYjXoQ5dJ3ILB7AOW2r4bcIj7GsrkEFpXWyrwwbaf15nXWqv6SqK1abuHDmPjV0EMobhBWIZt8cZVu0j2ZDNHF7gblRozdiO49g1zqDOEzmKJ7gcGVQTzmLDSgZ1Eunh2dD9aewpsXtctH3cwzn5ALysoVWlXZvhleMV5ovfU8J363mciAliRLsRg0Q244vfT3A/zgT2cQHbImIY1S4ldPk9Ii+NH8V9H08DfbfiY6BtiHYpoYmMBr4bbwN9YzfVoEELnew9+blpwBv5u0oI9wPtQrUbkWFaXqOzsZ01IFg7pLQOyp/A58igmhCsHZJInYndNsHa/0wiVWTy9/a5NjprQGvag0Qmwd462iGltdQ8lihqlVVIIn/9/CAvrajDWgTRB8VhMt1/aSljVr4RToc6hJTWioe1jujJD4rfQx2qRvuTyX1JuTIh3UQikUgkEhPnF+1xZ9hHnLjAAAAAAElFTkSuQmCC');
101 background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAACCklEQVRoge3Yz6sNYRzH8deVexNxSaEoroWFUuomOceSPVnIwsbSxs6Psrgphf9AsrZR7kJWsroUlrZKKZRSl4USGouZk9Npzp1n5pm5x4/nXdNzpvP9Pp/v95nv82OGRCKRSCQS/w8zuIn3yGpe37CEQ6sedQk38BA7G/jO4BQ+YEebQZUxVfH/OxzGVSxX2D4o2mO4jmt4jpNFe6d5mPFkRbvQ0H9h6OqUtR33/xXr0celGn4/sYjXoQ5dJ3ILB7AOW2r4bcIj7GsrkEFpXWyrwwbaf15nXWqv6SqK1abuHDmPjV0EMobhBWIZt8cZVu0j2ZDNHF7gblRozdiO49g1zqDOEzmKJ7gcGVQTzmLDSgZ1Eunh2dD9aewpsXtctH3cwzn5ALysoVWlXZvhleMV5ovfU8J363mciAliRLsRg0Q244vfT3A/zgT2cQHbImIY1S4ldPk9Ii+NH8V9H08DfbfiY6BtiHYpoYmMBr4bbwN9YzfVoEELnew9+blpwBv5u0oI9wPtQrUbkWFaXqOzsZ01IFg7pLQOyp/A58igmhCsHZJInYndNsHa/0wiVWTy9/a5NjprQGvag0Qmwd462iGltdQ8lihqlVVIIn/9/CAvrajDWgTRB8VhMt1/aSljVr4RToc6hJTWioe1jujJD4rfQx2qRvuTyX1JuTIh3UQikUgkEhPnF+1xZ9hHnLjAAAAAAElFTkSuQmCC');
103 }
102 }
104
103
105 #qsp-image-container {
104 .center-on-screen {
106 position: absolute;
105 position: absolute;
107 top: 0;
106 top: 0;
108 left: 0;
107 left: 0;
109 height: 100%;
108 height: 100%;
110 width: 100%;
109 width: 100%;
111 display: none;
110 pointer-events: none;
111 display: flex;
112 justify-content: center;
112 justify-content: center;
113 align-items: center;
113 align-items: center;
114 }
114 }
115
115
116 .center-on-screen > * {
117 pointer-events: auto;
118 }
119
120 #qsp-image-container {
121 display: none;
122 }
123
116 /* misc */
124 /* misc */
117
125
118 .disable a {
126 .disable a {
119 pointer-events: none;
127 pointer-events: none;
120 cursor: default;
128 cursor: default;
121 }
129 }
@@ -1,15 +1,34 b''
1
1
2 (in-package sugar-qsp.api)
2 (in-package sugar-qsp.api)
3
3
4 (defpsmacro with-call-args (args &body body)
4 (defpsmacro with-call-args (args &body body)
5 `(progn
5 `(progn
6 (init-args ,args)
6 (init-args ,args)
7 ,@body
7 ,@body
8 (get-result)))
8 (get-result)))
9
9
10 (defpsmacro with-frame (&body body)
10 (defpsmacro with-frame (&body body)
11 `(progn
11 `(progn
12 (push-local-frame)
12 (push-local-frame)
13 (unwind-protect
13 (unwind-protect
14 ,@body
14 ,@body
15 (pop-local-frame))))
15 (pop-local-frame))))
16
17 (defpsmacro inline-call (func &rest args)
18 `(+ (ps-inline ,func)
19 "(\""
20 ,(first args)
21 ,@(loop :for arg :in (cdr args)
22 :collect "\", \""
23 :collect arg)
24 "\");"))
25
26 (defpsmacro with-sleep ((resume-func) &body body)
27 `(new (*promise
28 (lambda (resolve)
29 (start-sleeping)
30 (let ((,resume-func (lambda ()
31 (finish-sleeping)
32 (resolve)))))
33 ,@body))))
34
@@ -1,423 +1,456 b''
1
1
2 (in-package sugar-qsp.api)
2 (in-package sugar-qsp.api)
3
3
4 ;;; API deals with DOM manipulation and some bookkeeping for the
4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 ;;; intrinsics, namely variables
5 ;;; intrinsics, namely variables
6 ;;; API is an implementation detail and has no QSP documentation. It
6 ;;; API is an implementation detail and has no QSP documentation. It
7 ;;; doesn't call intrinsics
7 ;;; doesn't call intrinsics
8
8
9 ;;; Utils
9 ;;; Utils
10
10
11 (defun make-act-html (title img)
11 (defun make-act-html (title img)
12 (+ "<a class='qsp-act' href='" (ps-inline call-act) "(\"" title "\");'>"
12 (+ "<a class='qsp-act' href='" (inline-call call-act title) "'>"
13 (if img (+ "<img src='" img "'>") "")
13 title
14 title
14 "</a>"))
15 "</a>"))
15
16
16 (defun make-menu-item-html (num title img loc)
17 (defun make-menu-item-html (num title img loc)
17 (+ "<a href='" (ps-inline run-menu) "(" num ", \"" loc "\")();'>"
18 (+ "<a href='" (inline-call finish-menu loc) "'>"
18 "<img src='" img "'>"
19 (if img (+ "<img src='" img "'>") "")
19 title
20 title
20 "</a>"))
21 "</a>"))
21
22
23 (defun make-menu-delimiter ()
24 "<hr>")
25
22 (defun report-error (text)
26 (defun report-error (text)
23 (alert text))
27 (alert text))
24
28
25 (defun start-sleeping ()
29 (defun start-sleeping ()
26 (chain (by-id "qsp") class-list (add "disable"))
30 (chain (by-id "qsp") class-list (add "disable")))
27 (setf (root sleeping) t))
28
31
29 (defun finish-sleeping ()
32 (defun finish-sleeping ()
30 (chain (by-id "qsp") class-list (remove "disable"))
33 (chain (by-id "qsp") class-list (remove "disable")))
31 (setf (root sleeping) nil))
32
34
33 (defun sleep (msec)
35 (defun sleep (msec)
34 (start-sleeping)
36 (with-sleep (resume)
35 (new (*promise
37 (set-timeout resume msec)))
36 (lambda (resolve)
37 (set-timeout
38 (lambda ()
39 (finish-sleeping)
40 (resolve))
41 msec)))))
42
38
43 (defun init-dom ()
39 (defun init-dom ()
44 ;; Save/load buttons
40 ;; Save/load buttons
45 (let ((btn (by-id "qsp-btn-save")))
41 (let ((btn (by-id "qsp-btn-save")))
46 (setf (@ btn onclick) savegame)
42 (setf (@ btn onclick) savegame)
47 (setf (@ btn href) "#"))
43 (setf (@ btn href) "#"))
48 (let ((btn (by-id "qsp-btn-open")))
44 (let ((btn (by-id "qsp-btn-open")))
49 (setf (@ btn onclick) opengame)
45 (setf (@ btn onclick) opengame)
50 (setf (@ btn href) "#"))
46 (setf (@ btn href) "#"))
51 ;; Close image on click
47 ;; Close image on click
52 (setf (@ (by-id "qsp-image-container") onclick)
48 (setf (@ (by-id "qsp-image-container") onclick)
53 (show-image nil))
49 (show-image nil))
54 ;; Close the dropdown on any click
50 ;; Close the dropdown on any click
55 (setf (@ window onclick)
51 (setf (@ window onclick)
56 (lambda (event)
52 (lambda (event)
57 (setf (@ (get-frame :dropdown) style display) "none"))))
53 (setf (@ window mouse)
54 (list (@ event page-x)
55 (@ event page-y)))
56 (finish-menu nil))))
58
57
59 (defun call-serv-loc (var-name &rest args)
58 (defun call-serv-loc (var-name &rest args)
60 (let ((loc-name (get-var var-name 0 :str)))
59 (let ((loc-name (get-var var-name 0 :str)))
61 (when loc-name
60 (when loc-name
62 (let ((loc (getprop (root locs) loc-name)))
61 (let ((loc (getprop (root locs) loc-name)))
63 (when loc
62 (when loc
64 (funcall loc args))))))
63 (funcall loc args))))))
65
64
66 ;;; Misc
65 ;;; Misc
67
66
68 (defun newline (key)
67 (defun newline (key)
69 (append-id (key-to-id key) "<br>" t))
68 (append-id (key-to-id key) "<br>" t))
70
69
71 (defun clear-id (id)
70 (defun clear-id (id)
72 (setf (inner-html (by-id id)) ""))
71 (setf (inner-html (by-id id)) ""))
73
72
74 (defvar text-escaper (chain document (create-element :textarea)))
73 (defvar text-escaper (chain document (create-element :textarea)))
75
74
76 (defun prepare-contents (s &optional force-html)
75 (defun prepare-contents (s &optional force-html)
77 (if (or force-html (get-var "USEHTML" 0 :num))
76 (if (or force-html (get-var "USEHTML" 0 :num))
78 s
77 s
79 (progn
78 (progn
80 (setf (@ text-escaper text-content) s)
79 (setf (@ text-escaper text-content) s)
81 (inner-html text-escaper))))
80 (inner-html text-escaper))))
82
81
83 (defun get-id (id &optional force-html)
82 (defun get-id (id &optional force-html)
84 (inner-html (by-id id)))
83 (inner-html (by-id id)))
85
84
86 (defun set-id (id contents &optional force-html)
85 (defun set-id (id contents &optional force-html)
87 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
86 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
88
87
89 (defun append-id (id contents &optional force-html)
88 (defun append-id (id contents &optional force-html)
90 (when contents
89 (when contents
91 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
90 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
92
91
93 ;;; Function calls
92 ;;; Function calls
94
93
95 (defun init-args (args)
94 (defun init-args (args)
96 (dotimes (i (length args))
95 (dotimes (i (length args))
97 (let ((arg (elt args i)))
96 (let ((arg (elt args i)))
98 (if (numberp arg)
97 (if (numberp arg)
99 (set-var args i :num arg)
98 (set-var args i :num arg)
100 (set-var args i :str arg)))))
99 (set-var args i :str arg)))))
101
100
102 (defun get-result ()
101 (defun get-result ()
103 (if (not (equal "" (get-var "RESULT" 0 :str)))
102 (if (not (equal "" (get-var "RESULT" 0 :str)))
104 (get-var "RESULT" 0 :str)
103 (get-var "RESULT" 0 :str)
105 (get-var "RESULT" 0 :num)))
104 (get-var "RESULT" 0 :num)))
106
105
107 (defun call-loc (name args)
106 (defun call-loc (name args)
107 (setf name (chain name (to-upper-case)))
108 (with-frame
108 (with-frame
109 (with-call-args args
109 (with-call-args args
110 (funcall (getprop (root locs) name) args))))
110 (funcall (getprop (root locs) name) args))))
111
111
112 (defun call-act (title)
112 (defun call-act (title)
113 (unless (root sleeping)
114 (with-frame
113 (with-frame
115 (funcall (getprop (root acts) title 'act)))))
114 (funcall (getprop (root acts) title 'act))))
116
115
117 ;;; Text windows
116 ;;; Text windows
118
117
119 (defun key-to-id (key)
118 (defun key-to-id (key)
120 (case key
119 (case key
121 (:main "qsp-main")
120 (:main "qsp-main")
122 (:stat "qsp-stat")
121 (:stat "qsp-stat")
123 (:objs "qsp-objs")
122 (:objs "qsp-objs")
124 (:acts "qsp-acts")
123 (:acts "qsp-acts")
125 (:input "qsp-input")
124 (:input "qsp-input")
125 (:image "qsp-image")
126 (:dropdown "qsp-dropdown")
126 (:dropdown "qsp-dropdown")
127 (t (report-error "Internal error!"))))
127 (t (report-error "Internal error!"))))
128
128
129 (defun get-frame (key)
129 (defun get-frame (key)
130 (by-id (key-to-id key)))
130 (by-id (key-to-id key)))
131
131
132 (defun add-text (key text)
132 (defun add-text (key text)
133 (append-id (key-to-id key) text))
133 (append-id (key-to-id key) text))
134
134
135 (defun get-text (key)
135 (defun get-text (key)
136 (get-id (key-to-id key)))
136 (get-id (key-to-id key)))
137
137
138 (defun clear-text (key)
138 (defun clear-text (key)
139 (clear-id (key-to-id key)))
139 (clear-id (key-to-id key)))
140
140
141 (defun enable-frame (key enable)
141 (defun enable-frame (key enable)
142 (let ((obj (get-frame key)))
142 (let ((obj (get-frame key)))
143 (setf (@ obj style display) (if enable "block" "none"))
143 (setf (@ obj style display) (if enable "block" "none"))
144 (void)))
144 (void)))
145
145
146 ;;; Actions
146 ;;; Actions
147
147
148 (defun add-act (title img act)
148 (defun add-act (title img act)
149 (setf (getprop (root acts) title)
149 (setf (getprop (root acts) title)
150 (create img img act act))
150 (create img img act act))
151 (update-acts))
151 (update-acts))
152
152
153 (defun del-act (title)
153 (defun del-act (title)
154 (delete (getprop (root acts) title))
154 (delete (getprop (root acts) title))
155 (update-acts))
155 (update-acts))
156
156
157 (defun clear-act ()
157 (defun clear-act ()
158 (setf (root acts) (create))
158 (setf (root acts) (create))
159 (clear-id "qsp-acts"))
159 (clear-id "qsp-acts"))
160
160
161 (defun update-acts ()
161 (defun update-acts ()
162 (clear-id "qsp-acts")
162 (clear-id "qsp-acts")
163 (let ((elt (by-id "qsp-acts")))
163 (let ((elt (by-id "qsp-acts")))
164 (for-in (title (root acts))
164 (for-in (title (root acts))
165 (let ((obj (getprop (root acts) title)))
165 (let ((obj (getprop (root acts) title)))
166 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
166 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
167
167
168
168
169 ;;; "Syntax"
169 ;;; "Syntax"
170
170
171 (defun qspfor (name index from to step body)
171 (defun qspfor (name index from to step body)
172 (for ((i from))
172 (for ((i from))
173 ((< i to))
173 ((< i to))
174 ((incf i step))
174 ((incf i step))
175 (set-var name index :num i)
175 (set-var name index :num i)
176 (unless (funcall body)
176 (unless (funcall body)
177 (return-from qspfor))))
177 (return-from qspfor))))
178
178
179 ;;; Variable class
179 ;;; Variable class
180
180
181 (defun *var (name)
181 (defun *var (name)
182 ;; From strings to numbers
182 ;; From strings to numbers
183 (setf (@ this indexes) (create))
183 (setf (@ this indexes) (create))
184 ;; From numbers to {num: 0, str: ""} objects
184 ;; From numbers to {num: 0, str: ""} objects
185 (setf (@ this values) (list))
185 (setf (@ this values) (list))
186 (void))
186 (void))
187
187
188 (defun new-value ()
188 (defun new-value ()
189 (create :num 0 :str ""))
189 (create :num 0 :str ""))
190
190
191 (setf (@ *var prototype index-num)
191 (setf (@ *var prototype index-num)
192 (lambda (index)
192 (lambda (index)
193 (let ((num-index
193 (let ((num-index
194 (if (stringp index)
194 (if (stringp index)
195 (if (in index (@ this indexes))
195 (if (in index (@ this indexes))
196 (getprop (@ this indexes) index)
196 (getprop (@ this indexes) index)
197 (let ((n (length (@ this values))))
197 (let ((n (length (@ this values))))
198 (setf (getprop (@ this indexes) index) n)
198 (setf (getprop (@ this indexes) index) n)
199 n))
199 n))
200 index)))
200 index)))
201 (unless (in num-index (@ this values))
201 (unless (in num-index (@ this values))
202 (setf (elt (@ this values) num-index) (new-value)))
202 (setf (elt (@ this values) num-index) (new-value)))
203 num-index)))
203 num-index)))
204
204
205 (setf (@ *var prototype get)
205 (setf (@ *var prototype get)
206 (lambda (index slot)
206 (lambda (index slot)
207 (unless (or index (= 0 index))
207 (unless (or index (= 0 index))
208 (setf index (1- (length (@ this values)))))
208 (setf index (1- (length (@ this values)))))
209 (getprop (@ this values) (chain this (index-num index)) slot)))
209 (getprop (@ this values) (chain this (index-num index)) slot)))
210
210
211 (setf (@ *var prototype set)
211 (setf (@ *var prototype set)
212 (lambda (index slot value)
212 (lambda (index slot value)
213 (unless (or index (= 0 index))
213 (unless (or index (= 0 index))
214 (setf index (length (@ this values))))
214 (setf index (length (@ this values))))
215 (case slot
215 (case slot
216 (:num (setf value (chain *number (parse-int value))))
216 (:num (setf value (chain *number (parse-int value))))
217 (:str (setf value (chain value (to-string)))))
217 (:str (setf value (chain value (to-string)))))
218 (setf (getprop (@ this values)
218 (setf (getprop (@ this values)
219 (chain this (index-num index))
219 (chain this (index-num index))
220 slot) value)
220 slot) value)
221 (void)))
221 (void)))
222
222
223 (setf (@ *var prototype kill)
223 (setf (@ *var prototype kill)
224 (lambda (index)
224 (lambda (index)
225 (setf (elt (@ this values) (chain this (index-num index)))
225 (setf (elt (@ this values) (chain this (index-num index)))
226 (new-value))
226 (new-value))
227 (delete (getprop 'this 'indexes index))))
227 (delete (getprop 'this 'indexes index))))
228
228
229 ;;; Variables
229 ;;; Variables
230
230
231 (defun var-real-name (name)
231 (defun var-real-name (name)
232 (if (= (@ name 0) #\$)
232 (if (= (@ name 0) #\$)
233 (values (chain name (substr 1)) :str)
233 (values (chain name (substr 1)) :str)
234 (values name :num)))
234 (values name :num)))
235
235
236 (defun ensure-var (name)
236 (defun ensure-var (name)
237 (setf name (chain name (to-upper-case)))
237 (let ((store (var-ref name)))
238 (let ((store (var-ref name)))
238 (unless store
239 (unless store
239 (setf store (new (*var name)))
240 (setf store (new (*var name)))
240 (setf (getprop (root vars) name) store))
241 (setf (getprop (root vars) name) store))
241 store))
242 store))
242
243
243 (defun var-ref (name)
244 (defun var-ref (name)
244 (let ((local-store (current-local-frame)))
245 (let ((local-store (current-local-frame)))
245 (cond ((and local-store (in name local-store))
246 (cond ((and local-store (in name local-store))
246 (getprop local-store name))
247 (getprop local-store name))
247 ((in name (root vars))
248 ((in name (root vars))
248 (getprop (root vars) name))
249 (getprop (root vars) name))
249 (t nil))))
250 (t nil))))
250
251
251 (defun get-var (name index slot)
252 (defun get-var (name index slot)
252 (chain (ensure-var name) (get index slot)))
253 (chain (ensure-var name) (get index slot)))
253
254
254 (defun set-var (name index slot value)
255 (defun set-var (name index slot value)
255 (chain (ensure-var name) (set index slot value))
256 (chain (ensure-var name) (set index slot value))
256 (void))
257 (void))
257
258
258 (defun get-array (name)
259 (defun get-array (name)
260 (setf name (chain name (to-upper-case)))
259 (var-ref name))
261 (var-ref name))
260
262
261 (defun set-array (name value)
263 (defun set-array (name value)
264 (setf name (chain name (to-upper-case)))
262 (let ((store (var-ref name)))
265 (let ((store (var-ref name)))
263 (setf (@ store values) (@ value values))
266 (setf (@ store values) (@ value values))
264 (setf (@ store indexes) (@ value indexes)))
267 (setf (@ store indexes) (@ value indexes)))
265 (void))
268 (void))
266
269
267 (defun kill-var (name &optional index)
270 (defun kill-var (name &optional index)
271 (setf name (chain name (to-upper-case)))
268 (if (and index (not (= 0 index)))
272 (if (and index (not (= 0 index)))
269 (chain (getprop (root vars) name) (kill index))
273 (chain (getprop (root vars) name) (kill index))
270 (delete (getprop (root vars) name)))
274 (delete (getprop (root vars) name)))
271 (void))
275 (void))
272
276
273 (defun array-size (name)
277 (defun array-size (name)
274 (getprop (var-ref name) 'length))
278 (@ (var-ref name) values length))
275
279
276 ;;; Locals
280 ;;; Locals
277
281
278 (defun push-local-frame ()
282 (defun push-local-frame ()
279 (chain (root locals) (push (create)))
283 (chain (root locals) (push (create)))
280 (void))
284 (void))
281
285
282 (defun pop-local-frame ()
286 (defun pop-local-frame ()
283 (chain (root locals) (pop))
287 (chain (root locals) (pop))
284 (void))
288 (void))
285
289
286 (defun current-local-frame ()
290 (defun current-local-frame ()
287 (elt (root locals) (1- (length (root locals)))))
291 (elt (root locals) (1- (length (root locals)))))
288
292
289 (defun new-local (name)
293 (defun new-local (name)
290 (let ((frame (current-local-frame)))
294 (let ((frame (current-local-frame)))
291 (unless (in name frame)
295 (unless (in name frame)
292 (setf (getprop frame name) (create)))
296 (setf (getprop frame name) (create)))
293 (void)))
297 (void)))
294
298
295 ;;; Objects
299 ;;; Objects
296
300
297 (defun update-objs ()
301 (defun update-objs ()
298 (let ((elt (by-id "qsp-objs")))
302 (let ((elt (by-id "qsp-objs")))
299 (setf (inner-html elt) "<ul>")
303 (setf (inner-html elt) "<ul>")
300 (loop :for obj :in (root objs)
304 (loop :for obj :in (root objs)
301 :do (incf (inner-html elt) (+ "<li>" obj)))
305 :do (incf (inner-html elt) (+ "<li>" obj)))
302 (incf (inner-html elt) "</ul>")))
306 (incf (inner-html elt) "</ul>")))
303
307
304 ;;; Menu
308 ;;; Menu
305
309
306 (defun menu (menu-data)
310 (defun open-menu (menu-data)
307 (let ((elt (by-id "qsp-dropdown"))
311 (let ((elt (get-frame :dropdown))
308 (i 0))
312 (i 0))
309 (setf (inner-html elt) "")
310 (loop :for item :in menu-data
313 (loop :for item :in menu-data
311 :do (incf i)
314 :do (incf i)
312 :do (incf (inner-html elt) (make-menu-item-html i
315 :do (incf (inner-html elt)
313 (@ item text)
316 (if (eq item :delimiter)
314 (@ item icon)
317 (make-menu-delimiter i)
315 (@ item loc))))
318 (make-menu-item-html i
319 (@ item :text)
320 (@ item :icon)
321 (@ item :loc)))))
322 (let ((mouse (@ window mouse)))
323 (setf (@ elt style left) (+ (elt mouse 0) "px"))
324 (setf (@ elt style top) (+ (elt mouse 1) "px"))
325 ;; Make sure it's inside the viewport
326 (when (> (@ document body inner-width)
327 (+ (elt mouse 0) (@ elt inner-width)))
328 (incf (@ elt style left) (@ elt inner-width)))
329 (when (> (@ document body inner-height)
330 (+ (elt mouse 0) (@ elt inner-height)))
331 (incf (@ elt style top) (@ elt inner-height))))
316 (setf (@ elt style display) "block")))
332 (setf (@ elt style display) "block")))
317
333
334 (defun finish-menu (loc)
335 (when (root menu-resume)
336 (let ((elt (get-frame :dropdown)))
337 (setf (inner-html elt) "")
338 (setf (@ elt style display) "none")
339 (funcall (root menu-resume))
340 (setf (root menu-resume) nil))
341 (when loc
342 (call-loc loc)))
343 (void))
344
345 (defun menu (menu-data)
346 (with-sleep (resume)
347 (open-menu menu-data)
348 (setf (root menu-resume) resume))
349 (void))
350
318 ;;; Content
351 ;;; Content
319
352
320 (defun clean-audio ()
353 (defun clean-audio ()
321 (loop :for k :in (chain *object (keys (root playing)))
354 (loop :for k :in (chain *object (keys (root playing)))
322 :for v := (getprop (root playing) k)
355 :for v := (getprop (root playing) k)
323 :do (when (@ v ended)
356 :do (when (@ v ended)
324 (delete (@ (root playing) k)))))
357 (delete (@ (root playing) k)))))
325
358
326 (defun show-image (path)
359 (defun show-image (path)
327 (let ((img (by-id "qsp-image")))
360 (let ((img (get-frame :image)))
328 (cond (path
361 (cond (path
329 (setf (@ img src) path)
362 (setf (@ img src) path)
330 (setf (@ img style display) "flex"))
363 (setf (@ img style display) "flex"))
331 (t
364 (t
332 (setf (@ img src) "")
365 (setf (@ img src) "")
333 (setf (@ img style display) "hidden")))))
366 (setf (@ img style display) "hidden")))))
334
367
335 ;;; Saves
368 ;;; Saves
336
369
337 (defun opengame ()
370 (defun opengame ()
338 (let ((element (chain document (create-element :input))))
371 (let ((element (chain document (create-element :input))))
339 (chain element (set-attribute :type :file))
372 (chain element (set-attribute :type :file))
340 (chain element (set-attribute :id :qsp-opengame))
373 (chain element (set-attribute :id :qsp-opengame))
341 (chain element (set-attribute :tabindex -1))
374 (chain element (set-attribute :tabindex -1))
342 (chain element (set-attribute "aria-hidden" t))
375 (chain element (set-attribute "aria-hidden" t))
343 (setf (@ element style display) :block)
376 (setf (@ element style display) :block)
344 (setf (@ element style visibility) :hidden)
377 (setf (@ element style visibility) :hidden)
345 (setf (@ element style position) :fixed)
378 (setf (@ element style position) :fixed)
346 (setf (@ element onchange)
379 (setf (@ element onchange)
347 (lambda (event)
380 (lambda (event)
348 (let* ((file (@ event target files 0))
381 (let* ((file (@ event target files 0))
349 (reader (new (*file-reader))))
382 (reader (new (*file-reader))))
350 (setf (@ reader onload)
383 (setf (@ reader onload)
351 (lambda (ev)
384 (lambda (ev)
352 (block nil
385 (block nil
353 (let ((target (@ ev current-target)))
386 (let ((target (@ ev current-target)))
354 (unless (@ target result)
387 (unless (@ target result)
355 (return))
388 (return))
356 (base64-to-state (@ target result))
389 (base64-to-state (@ target result))
357 (unstash-state)))))
390 (unstash-state)))))
358 (chain reader (read-as-text file)))))
391 (chain reader (read-as-text file)))))
359 (chain document body (append-child element))
392 (chain document body (append-child element))
360 (chain element (click))
393 (chain element (click))
361 (chain document body (remove-child element))))
394 (chain document body (remove-child element))))
362
395
363 (defun savegame ()
396 (defun savegame ()
364 (let ((element (chain document (create-element :a))))
397 (let ((element (chain document (create-element :a))))
365 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
398 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
366 (chain element (set-attribute :download "savegame.sav"))
399 (chain element (set-attribute :download "savegame.sav"))
367 (setf (@ element style display) :none)
400 (setf (@ element style display) :none)
368 (chain document body (append-child element))
401 (chain document body (append-child element))
369 (chain element (click))
402 (chain element (click))
370 (chain document body (remove-child element))))
403 (chain document body (remove-child element))))
371
404
372 (defun stash-state (args)
405 (defun stash-state (args)
373 (call-serv-loc "ONGSAVE")
406 (call-serv-loc "ONGSAVE")
374 (setf (root state-stash)
407 (setf (root state-stash)
375 (chain *j-s-o-n (stringify
408 (chain *j-s-o-n (stringify
376 (create :vars (root vars)
409 (create :vars (root vars)
377 :objs (root objs)
410 :objs (root objs)
378 :loc-args args
411 :loc-args args
379 :msecs (- (chain *date (now)) (root started-at))
412 :msecs (- (chain *date (now)) (root started-at))
380 :timer-interval (root timer-interval)
413 :timer-interval (root timer-interval)
381 :main-html (inner-html
414 :main-html (inner-html
382 (by-id :qsp-main))
415 (get-frame :main))
383 :stat-html (inner-html
416 :stat-html (inner-html
384 (by-id :qsp-stat))
417 (get-frame :stat))
385 :next-location (root current-location)))))
418 :next-location (root current-location)))))
386 (void))
419 (void))
387
420
388 (defun unstash-state ()
421 (defun unstash-state ()
389 (let ((data (chain *j-s-o-n (parse (root state-stash)))))
422 (let ((data (chain *j-s-o-n (parse (root state-stash)))))
390 (clear-act)
423 (clear-act)
391 (setf (root vars) (@ data :vars))
424 (setf (root vars) (@ data :vars))
392 (loop :for k :in (chain *object (keys (root vars)))
425 (loop :for k :in (chain *object (keys (root vars)))
393 :do (chain *object (set-prototype-of (getprop (root vars) k)
426 :do (chain *object (set-prototype-of (getprop (root vars) k)
394 (@ *var prototype))))
427 (@ *var prototype))))
395 (setf (root started-at) (- (chain *date (now)) (@ data :msecs)))
428 (setf (root started-at) (- (chain *date (now)) (@ data :msecs)))
396 (setf (root objs) (@ data :objs))
429 (setf (root objs) (@ data :objs))
397 (setf (root current-location) (@ data :next-location))
430 (setf (root current-location) (@ data :next-location))
398 (setf (inner-html (by-id :qsp-main))
431 (setf (inner-html (get-frame :main))
399 (@ data :main-html))
432 (@ data :main-html))
400 (setf (inner-html (by-id :qsp-stat))
433 (setf (inner-html (get-frame :stat))
401 (@ data :stat-html))
434 (@ data :stat-html))
402 (update-objs)
435 (update-objs)
403 (set-timer (@ data :timer-interval))
436 (set-timer (@ data :timer-interval))
404 (call-serv-loc "ONGLOAD")
437 (call-serv-loc "ONGLOAD")
405 (call-loc (root current-location) (@ data :loc-args))
438 (call-loc (root current-location) (@ data :loc-args))
406 (void)))
439 (void)))
407
440
408 (defun state-to-base64 ()
441 (defun state-to-base64 ()
409 (btoa (encode-u-r-i-component (root state-stash))))
442 (btoa (encode-u-r-i-component (root state-stash))))
410
443
411 (defun base64-to-state (data)
444 (defun base64-to-state (data)
412 (setf (root state-stash) (decode-u-r-i-component (atob data))))
445 (setf (root state-stash) (decode-u-r-i-component (atob data))))
413
446
414 ;;; Timers
447 ;;; Timers
415
448
416 (defun set-timer (interval)
449 (defun set-timer (interval)
417 (setf (root timer-interval) interval)
450 (setf (root timer-interval) interval)
418 (clear-interval (root timer-obj))
451 (clear-interval (root timer-obj))
419 (setf (root timer-obj)
452 (setf (root timer-obj)
420 (set-interval
453 (set-interval
421 (lambda ()
454 (lambda ()
422 (call-serv-loc "COUNTER"))
455 (call-serv-loc "COUNTER"))
423 interval)))
456 interval)))
@@ -1,174 +1,174 b''
1
1
2 (in-package sugar-qsp.lib)
2 (in-package sugar-qsp.lib)
3
3
4 ;;;; Macros implementing some intrinsics where it makes sense
4 ;;;; Macros implementing some intrinsics where it makes sense
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6
6
7 ;;; 1loc
7 ;;; 1loc
8
8
9 ;;; 2var
9 ;;; 2var
10
10
11 (defpsmacro killvar (varname &optional index)
11 (defpsmacro killvar (varname &optional index)
12 `(kill-var ,varname ,index))
12 `(api-call kill-var ,varname ,index))
13
13
14 (defpsmacro killall ()
14 (defpsmacro killall ()
15 `(api-call kill-all))
15 `(api-call kill-all))
16
16
17 ;;; 3expr
17 ;;; 3expr
18
18
19 (defpsmacro obj (name)
19 (defpsmacro obj (name)
20 `(funcall (root objs includes) ,name))
20 `(funcall (root objs includes) ,name))
21
21
22 (defpsmacro loc (name)
22 (defpsmacro loc (name)
23 `(funcall (root locs includes) ,name))
23 `(funcall (root locs includes) ,name))
24
24
25 (defpsmacro no (arg)
25 (defpsmacro no (arg)
26 `(- -1 ,arg))
26 `(- -1 ,arg))
27
27
28 ;;; 4code
28 ;;; 4code
29
29
30 (defpsmacro qspver ()
30 (defpsmacro qspver ()
31 "0.0.1")
31 "0.0.1")
32
32
33 (defpsmacro curloc ()
33 (defpsmacro curloc ()
34 `(root current-location))
34 `(root current-location))
35
35
36 (defpsmacro rnd ()
36 (defpsmacro rnd ()
37 `(funcall rand 1 1000))
37 `(funcall rand 1 1000))
38
38
39 (defpsmacro qspmax (&rest args)
39 (defpsmacro qspmax (&rest args)
40 (if (= 1 (length args))
40 (if (= 1 (length args))
41 `(*math.max.apply nil ,@args)
41 `(*math.max.apply nil ,@args)
42 `(*math.max ,@args)))
42 `(*math.max ,@args)))
43
43
44 (defpsmacro qspmin (&rest args)
44 (defpsmacro qspmin (&rest args)
45 (if (= 1 (length args))
45 (if (= 1 (length args))
46 `(*math.min.apply nil ,@args)
46 `(*math.min.apply nil ,@args)
47 `(*math.min ,@args)))
47 `(*math.min ,@args)))
48
48
49 ;;; 5arrays
49 ;;; 5arrays
50
50
51 (defpsmacro arrsize (name)
51 (defpsmacro arrsize (name)
52 `(api-call array-size ,name))
52 `(api-call array-size ,name))
53
53
54 ;;; 6str
54 ;;; 6str
55
55
56 (defpsmacro len (s)
56 (defpsmacro len (s)
57 `(length ,s))
57 `(length ,s))
58
58
59 (defpsmacro mid (s from &optional count)
59 (defpsmacro mid (s from &optional count)
60 `(chain ,s (substring ,from ,count)))
60 `(chain ,s (substring ,from ,count)))
61
61
62 (defpsmacro ucase (s)
62 (defpsmacro ucase (s)
63 `(chain ,s (to-upper-case)))
63 `(chain ,s (to-upper-case)))
64
64
65 (defpsmacro lcase (s)
65 (defpsmacro lcase (s)
66 `(chain ,s (to-lower-case)))
66 `(chain ,s (to-lower-case)))
67
67
68 (defpsmacro trim (s)
68 (defpsmacro trim (s)
69 `(chain ,s (trim)))
69 `(chain ,s (trim)))
70
70
71 (defpsmacro replace (s from to)
71 (defpsmacro replace (s from to)
72 `(chain ,s (replace ,from ,to)))
72 `(chain ,s (replace ,from ,to)))
73
73
74 (defpsmacro val (s)
74 (defpsmacro val (s)
75 `(parse-int ,s 10))
75 `(parse-int ,s 10))
76
76
77 (defpsmacro qspstr (n)
77 (defpsmacro qspstr (n)
78 `(chain ,n (to-string)))
78 `(chain ,n (to-string)))
79
79
80 ;;; 7if
80 ;;; 7if
81
81
82 ;;; 8sub
82 ;;; 8sub
83
83
84 ;;; 9loops
84 ;;; 9loops
85
85
86 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
86 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
87
87
88 (defpsmacro exit ()
88 (defpsmacro exit ()
89 `(return-from nil (values)))
89 `(return-from nil (values)))
90
90
91 ;;; 10dynamic
91 ;;; 10dynamic
92
92
93 ;;; 11main
93 ;;; 11main
94
94
95 (defpsmacro desc (s)
95 (defpsmacro desc (s)
96 (declare (ignore s))
96 (declare (ignore s))
97 "")
97 "")
98
98
99 ;;; 12stat
99 ;;; 12stat
100
100
101 (defpsmacro showstat (enable)
101 (defpsmacro showstat (enable)
102 `(api-call enable-frame :stat ,enable))
102 `(api-call enable-frame :stat ,enable))
103
103
104 ;;; 13diag
104 ;;; 13diag
105
105
106 (defpsmacro msg (text)
106 (defpsmacro msg (text)
107 `(alert ,text))
107 `(alert ,text))
108
108
109 ;;; 14act
109 ;;; 14act
110
110
111 (defpsmacro showacts (enable)
111 (defpsmacro showacts (enable)
112 `(api-call enable-frame :acts ,enable))
112 `(api-call enable-frame :acts ,enable))
113
113
114 (defpsmacro delact (name)
114 (defpsmacro delact (name)
115 `(api-call del-act ,name))
115 `(api-call del-act ,name))
116
116
117 (defpsmacro cla ()
117 (defpsmacro cla ()
118 `(api-call clear-act))
118 `(api-call clear-act))
119
119
120 ;;; 15objs
120 ;;; 15objs
121
121
122 (defpsmacro showobjs (enable)
122 (defpsmacro showobjs (enable)
123 `(api-call enable-frame :objs ,enable))
123 `(api-call enable-frame :objs ,enable))
124
124
125 (defpsmacro countobj ()
125 (defpsmacro countobj ()
126 `(length (root objs)))
126 `(length (root objs)))
127
127
128 (defpsmacro getobj (index)
128 (defpsmacro getobj (index)
129 `(or (elt (root objs) ,index) ""))
129 `(or (elt (root objs) ,index) ""))
130
130
131 ;;; 16menu
131 ;;; 16menu
132
132
133 ;;; 17sound
133 ;;; 17sound
134
134
135 (defpsmacro isplay (filename)
135 (defpsmacro isplay (filename)
136 `(funcall (root playing includes) ,filename))
136 `(funcall (root playing includes) ,filename))
137
137
138 ;;; 18img
138 ;;; 18img
139
139
140 (defpsmacro view (&optional path)
140 (defpsmacro view (&optional path)
141 `(api-call show-image ,path))
141 `(api-call show-image ,path))
142
142
143 ;;; 19input
143 ;;; 19input
144
144
145 (defpsmacro showinput (enable)
145 (defpsmacro showinput (enable)
146 `(api-call enable-frame :input ,enable))
146 `(api-call enable-frame :input ,enable))
147
147
148 ;;; 20time
148 ;;; 20time
149
149
150 (defpsmacro wait (msec)
150 (defpsmacro wait (msec)
151 `(await (api-call sleep ,msec)))
151 `(await (api-call sleep ,msec)))
152
152
153 (defpsmacro settimer (interval)
153 (defpsmacro settimer (interval)
154 `(api-call set-timer ,interval))
154 `(api-call set-timer ,interval))
155
155
156 ;;; 21local
156 ;;; 21local
157
157
158 (defpsmacro local (var &optional expr)
158 (defpsmacro local (var &optional expr)
159 `(progn
159 `(progn
160 (api-call new-local ,(string (second var)))
160 (api-call new-local ,(string (second var)))
161 ,@(when expr
161 ,@(when expr
162 `((set ,var ,expr)))))
162 `((set ,var ,expr)))))
163
163
164 ;;; 22for
164 ;;; 22for
165
165
166 ;;; misc
166 ;;; misc
167
167
168 (defpsmacro opengame (&optional filename)
168 (defpsmacro opengame (&optional filename)
169 (declare (ignore filename))
169 (declare (ignore filename))
170 `(api-call opengame))
170 `(api-call opengame))
171
171
172 (defpsmacro savegame (&optional filename)
172 (defpsmacro savegame (&optional filename)
173 (declare (ignore filename))
173 (declare (ignore filename))
174 `(api-call savegame))
174 `(api-call savegame))
@@ -1,302 +1,302 b''
1
1
2 (in-package sugar-qsp.lib)
2 (in-package sugar-qsp.lib)
3
3
4 ;;;; Functions and procedures defined by the QSP language.
4 ;;;; Functions and procedures defined by the QSP language.
5 ;;;; They can call api and deal with locations and other data directly.
5 ;;;; They can call api and deal with locations and other data directly.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
7
7
8 ;;; 1loc
8 ;;; 1loc
9
9
10 (defun goto (target args)
10 (defun goto (target args)
11 (api:clear-text :main)
11 (api:clear-text :main)
12 (funcall xgoto target (or args (list)))
12 (funcall xgoto target args)
13 (void))
13 (void))
14
14
15 (defun xgoto (target args)
15 (defun xgoto (target args)
16 (api:clear-act)
16 (api:clear-act)
17 (setf (root current-location) (chain target (to-upper-case)))
17 (setf (root current-location) (chain target (to-upper-case)))
18 (api:stash-state args)
18 (api:stash-state args)
19 (funcall (getprop (root locs) (root current-location))
19 (api:call-loc (root current-location) (or args (list)))
20 (or args (list)))
21 (void))
20 (void))
22
21
23 ;;; 2var
22 ;;; 2var
24
23
25 ;;; 3expr
24 ;;; 3expr
26
25
27 ;;; 4code
26 ;;; 4code
28
27
29 (defun rand (a &optional (b 1))
28 (defun rand (a &optional (b 1))
30 (let ((min (min a b))
29 (let ((min (min a b))
31 (max (max a b)))
30 (max (max a b)))
32 (+ min (chain *math (random (- max min))))))
31 (+ min (chain *math (random (- max min))))))
33
32
34 ;;; 5arrays
33 ;;; 5arrays
35
34
36 (defun copyarr (to from start count)
35 (defun copyarr (to from start count)
37 (multiple-value-bind (to-name to-slot)
36 (multiple-value-bind (to-name to-slot)
38 (api:var-real-name to)
37 (api:var-real-name to)
39 (multiple-value-bind (from-name from-slot)
38 (multiple-value-bind (from-name from-slot)
40 (api:var-real-name from)
39 (api:var-real-name from)
41 (for ((i start))
40 (for ((i start))
42 ((< i (min (api:array-size from-name)
41 ((< i (min (api:array-size from-name)
43 (+ start count))))
42 (+ start count))))
44 ((incf i))
43 ((incf i))
45 (api:set-var to-name (+ start i) to-slot
44 (api:set-var to-name (+ start i) to-slot
46 (api:get-var from-name (+ start i) from-slot))))))
45 (api:get-var from-name (+ start i) from-slot))))))
47
46
48 (defun arrpos (name value &optional (start 0))
47 (defun arrpos (name value &optional (start 0))
49 (multiple-value-bind (real-name slot)
48 (multiple-value-bind (real-name slot)
50 (api:var-real-name name)
49 (api:var-real-name name)
51 (for ((i start)) ((< i (api:array-size name))) ((incf i))
50 (for ((i start)) ((< i (api:array-size name))) ((incf i))
52 (when (eq (api:get-var real-name i slot) value)
51 (when (eq (api:get-var real-name i slot) value)
53 (return-from arrpos i))))
52 (return-from arrpos i))))
54 -1)
53 -1)
55
54
56 (defun arrcomp (name pattern &optional (start 0))
55 (defun arrcomp (name pattern &optional (start 0))
57 (multiple-value-bind (real-name slot)
56 (multiple-value-bind (real-name slot)
58 (api:var-real-name name)
57 (api:var-real-name name)
59 (for ((i start)) ((< i (api:array-size name))) ((incf i))
58 (for ((i start)) ((< i (api:array-size name))) ((incf i))
60 (when (funcall (getprop (api:get-var real-name i slot) 'match) pattern)
59 (when (funcall (getprop (api:get-var real-name i slot) 'match) pattern)
61 (return-from arrcomp i))))
60 (return-from arrcomp i))))
62 -1)
61 -1)
63
62
64 ;;; 6str
63 ;;; 6str
65
64
66 (defun instr (s subs &optional (start 1))
65 (defun instr (s subs &optional (start 1))
67 (+ start (chain s (substring (- start 1)) (search subs))))
66 (+ start (chain s (substring (- start 1)) (search subs))))
68
67
69 (defun isnum (s)
68 (defun isnum (s)
70 (if (is-na-n s)
69 (if (is-na-n s)
71 0
70 0
72 -1))
71 -1))
73
72
74 (defun strcomp (s pattern)
73 (defun strcomp (s pattern)
75 (if (chain s (match pattern))
74 (if (chain s (match pattern))
76 -1
75 -1
77 0))
76 0))
78
77
79 (defun strfind (s pattern group)
78 (defun strfind (s pattern group)
80 (let* ((re (new (*reg-exp pattern)))
79 (let* ((re (new (*reg-exp pattern)))
81 (match (chain re (exec s))))
80 (match (chain re (exec s))))
82 (chain match (group group))))
81 (chain match (group group))))
83
82
84 (defun strpos (s pattern &optional (group 0))
83 (defun strpos (s pattern &optional (group 0))
85 (let* ((re (new (*reg-exp pattern)))
84 (let* ((re (new (*reg-exp pattern)))
86 (match (chain re (exec s)))
85 (match (chain re (exec s)))
87 (found (chain match (group group))))
86 (found (chain match (group group))))
88 (if found
87 (if found
89 (chain s (search found))
88 (chain s (search found))
90 0)))
89 0)))
91
90
92 ;;; 7if
91 ;;; 7if
93
92
94 ;; Has to be a function because it always evaluates all three of its
93 ;; Has to be a function because it always evaluates all three of its
95 ;; arguments
94 ;; arguments
96 (defun iif (cond-expr then-expr else-expr)
95 (defun iif (cond-expr then-expr else-expr)
97 (if cond-expr then-expr else-expr))
96 (if cond-expr then-expr else-expr))
98
97
99 ;;; 8sub
98 ;;; 8sub
100
99
101 (defun gosub (target &rest args)
100 (defun gosub (target &rest args)
102 (funcall (getprop (root locs) target) args)
101 (api:call-loc target args)
103 (void))
102 (void))
104
103
105 (defun func (target &rest args)
104 (defun func (target &rest args)
106 (funcall (getprop (root locs) target) args))
105 (api:call-loc target args))
107
106
108 ;;; 9loops
107 ;;; 9loops
109
108
110 ;;; 10dynamic
109 ;;; 10dynamic
111
110
112 (defun dynamic (block &rest args)
111 (defun dynamic (block &rest args)
113 (when (stringp block)
112 (when (stringp block)
114 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
113 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
115 (api:with-call-args args
114 (api:with-call-args args
116 (funcall block args))
115 (funcall block args))
117 (void))
116 (void))
118
117
119 (defun dyneval (block &rest args)
118 (defun dyneval (block &rest args)
120 (when (stringp block)
119 (when (stringp block)
121 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
120 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
122 (api:with-call-args args
121 (api:with-call-args args
123 (funcall block args)))
122 (funcall block args)))
124
123
125 ;;; 11main
124 ;;; 11main
126
125
127 (defun main-p (s)
126 (defun main-p (s)
128 (api:add-text :main s)
127 (api:add-text :main s)
129 (void))
128 (void))
130
129
131 (defun main-pl (s)
130 (defun main-pl (s)
132 (api:add-text :main s)
131 (api:add-text :main s)
133 (api:newline :main)
132 (api:newline :main)
134 (void))
133 (void))
135
134
136 (defun main-nl (s)
135 (defun main-nl (s)
137 (api:newline :main)
136 (api:newline :main)
138 (api:add-text :main s)
137 (api:add-text :main s)
139 (void))
138 (void))
140
139
141 (defun maintxt (s)
140 (defun maintxt (s)
142 (api:get-text :main)
141 (api:get-text :main)
143 (void))
142 (void))
144
143
145 ;; For clarity (it leaves a lib.desc() call in JS)
144 ;; For clarity (it leaves a lib.desc() call in JS)
146 (defun desc (s)
145 (defun desc (s)
147 "")
146 "")
148
147
149 (defun main-clear ()
148 (defun main-clear ()
150 (api:clear-text :main)
149 (api:clear-text :main)
151 (void))
150 (void))
152
151
153 ;;; 12stat
152 ;;; 12stat
154
153
155 (defun stat-p (s)
154 (defun stat-p (s)
156 (api:add-text :stat s)
155 (api:add-text :stat s)
157 (void))
156 (void))
158
157
159 (defun stat-pl (s)
158 (defun stat-pl (s)
160 (api:add-text :stat s)
159 (api:add-text :stat s)
161 (api:newline :stat)
160 (api:newline :stat)
162 (void))
161 (void))
163
162
164 (defun stat-nl (s)
163 (defun stat-nl (s)
165 (api:newline :stat)
164 (api:newline :stat)
166 (api:add-text :stat s)
165 (api:add-text :stat s)
167 (void))
166 (void))
168
167
169 (defun stattxt (s)
168 (defun stattxt (s)
170 (api:get-text :stat)
169 (api:get-text :stat)
171 (void))
170 (void))
172
171
173 (defun stat-clear ()
172 (defun stat-clear ()
174 (api:clear-text :stat)
173 (api:clear-text :stat)
175 (void))
174 (void))
176
175
177 (defun cls ()
176 (defun cls ()
178 (stat-clear)
177 (stat-clear)
179 (main-clear)
178 (main-clear)
180 (cla)
179 (cla)
181 (cmdclear)
180 (cmdclear)
182 (void))
181 (void))
183
182
184 ;;; 13diag
183 ;;; 13diag
185
184
186 ;;; 14act
185 ;;; 14act
187
186
188 (defun curacts ()
187 (defun curacts ()
189 (let ((acts (root acts)))
188 (let ((acts (root acts)))
190 (lambda ()
189 (lambda ()
191 (setf (root acts) acts)
190 (setf (root acts) acts)
192 (void))))
191 (void))))
193
192
194 ;;; 15objs
193 ;;; 15objs
195
194
196 (defun addobj (name)
195 (defun addobj (name)
197 (chain (root objs) (push name))
196 (chain (root objs) (push name))
198 (api:update-objs)
197 (api:update-objs)
199 (void))
198 (void))
200
199
201 (defun delobj (name)
200 (defun delobj (name)
202 (let ((index (chain (root objs) (index-of name))))
201 (let ((index (chain (root objs) (index-of name))))
203 (when (> index -1)
202 (when (> index -1)
204 (killobj (1+ index))))
203 (killobj (1+ index))))
205 (void))
204 (void))
206
205
207 (defun killobj (&optional (num nil))
206 (defun killobj (&optional (num nil))
208 (if (eq nil num)
207 (if (eq nil num)
209 (setf (root objs) (list))
208 (setf (root objs) (list))
210 (chain (root objs) (splice (1- num) 1)))
209 (chain (root objs) (splice (1- num) 1)))
211 (api:update-objs)
210 (api:update-objs)
212 (void))
211 (void))
213
212
214 ;;; 16menu
213 ;;; 16menu
215
214
216 (defun menu (menu-name)
215 (defun menu (menu-name)
217 (let ((menu-data (list)))
216 (let ((menu-data (list)))
218 (loop :for item :in (api:get-array (api:var-real-name menu-name))
217 (loop :for item-obj :in (@ (api:get-array (api:var-real-name menu-name)) values)
218 :for item := (@ item-obj :str)
219 :do (cond ((string= item "")
219 :do (cond ((string= item "")
220 (break))
220 (break))
221 ((string= item "-:-")
221 ((string= item "-:-")
222 (chain menu-data (push :delimiter)))
222 (chain menu-data (push :delimiter)))
223 (t
223 (t
224 (let* ((tokens (chain item (split ":"))))
224 (let* ((tokens (chain item (split ":"))))
225 (when (= (length tokens) 2)
225 (when (= (length tokens) 2)
226 (chain tokens (push "")))
226 (chain tokens (push "")))
227 (let* ((text (chain tokens (splice 0 (- (length tokens) 2)) (join ":")))
227 (let* ((text (chain tokens (splice 0 (- (length tokens) 2)) (join ":")))
228 (loc (getprop tokens (- (length tokens) 2)))
228 (loc (getprop tokens (- (length tokens) 2)))
229 (icon (getprop tokens (- (length tokens) 1))))
229 (icon (getprop tokens (- (length tokens) 1))))
230 (chain menu-data
230 (chain menu-data
231 (push (create text text
231 (push (create :text text
232 loc loc
232 :loc loc
233 icon icon))))))))
233 :icon icon))))))))
234 (api:menu menu-data)
234 (api:menu menu-data)
235 (void)))
235 (void)))
236
236
237 ;;; 17sound
237 ;;; 17sound
238
238
239 (defun play (filename &optional (volume 100))
239 (defun play (filename &optional (volume 100))
240 (let ((audio (new (*audio filename))))
240 (let ((audio (new (*audio filename))))
241 (setf (getprop (root playing) filename) audio)
241 (setf (getprop (root playing) filename) audio)
242 (setf (@ audio volume) (* volume 0.01))
242 (setf (@ audio volume) (* volume 0.01))
243 (chain audio (play))))
243 (chain audio (play))))
244
244
245 (defun close (filename)
245 (defun close (filename)
246 (funcall (root playing filename) stop)
246 (funcall (root playing filename) stop)
247 (delete (root playing filename))
247 (delete (root playing filename))
248 (void))
248 (void))
249
249
250 (defun closeall ()
250 (defun closeall ()
251 (loop :for k :in (chain *object (keys (root playing)))
251 (loop :for k :in (chain *object (keys (root playing)))
252 :for v := (getprop (root playing) k)
252 :for v := (getprop (root playing) k)
253 :do (funcall v stop))
253 :do (funcall v stop))
254 (setf (root playing) (create)))
254 (setf (root playing) (create)))
255
255
256 ;;; 18img
256 ;;; 18img
257
257
258 (defun refint ()
258 (defun refint ()
259 ;; "Force interface update" Uh... what exactly do we do here?
259 ;; "Force interface update" Uh... what exactly do we do here?
260 (api:report-error "REFINT is not supported")
260 (api:report-error "REFINT is not supported")
261 )
261 )
262
262
263 ;;; 19input
263 ;;; 19input
264
264
265 (defun usertxt ()
265 (defun usertxt ()
266 (let ((input (by-id "qsp-input")))
266 (let ((input (by-id "qsp-input")))
267 (@ input value)))
267 (@ input value)))
268
268
269 (defun cmdclear ()
269 (defun cmdclear ()
270 (let ((input (by-id "qsp-input")))
270 (let ((input (by-id "qsp-input")))
271 (setf (@ input value) "")))
271 (setf (@ input value) "")))
272
272
273 (defun input (text)
273 (defun input (text)
274 (chain window (prompt text)))
274 (chain window (prompt text)))
275
275
276 ;;; 20time
276 ;;; 20time
277
277
278 (defun msecscount ()
278 (defun msecscount ()
279 (- (chain *date (now)) (root started-at)))
279 (- (chain *date (now)) (root started-at)))
280
280
281 ;;; 21local
281 ;;; 21local
282
282
283 ;;; 22for
283 ;;; 22for
284
284
285 ;;; misc
285 ;;; misc
286
286
287 (defun rgb (red green blue)
287 (defun rgb (red green blue)
288 (flet ((rgb-to-hex (comp)
288 (flet ((rgb-to-hex (comp)
289 (let ((hex (chain (*number comp) (to-string 16))))
289 (let ((hex (chain (*number comp) (to-string 16))))
290 (if (< (length hex) 2)
290 (if (< (length hex) 2)
291 (+ "0" hex)
291 (+ "0" hex)
292 hex))))
292 hex))))
293 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
293 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
294
294
295 (defun openqst ()
295 (defun openqst ()
296 (api:report-error "OPENQST is not supported."))
296 (api:report-error "OPENQST is not supported."))
297
297
298 (defun addqst ()
298 (defun addqst ()
299 (api:report-error "ADDQST is not supported. Bundle the library with the main game."))
299 (api:report-error "ADDQST is not supported. Bundle the library with the main game."))
300
300
301 (defun killqst ()
301 (defun killqst ()
302 (api:report-error "KILLQST is not supported."))
302 (api:report-error "KILLQST is not supported."))
@@ -1,39 +1,41 b''
1
1
2 (in-package sugar-qsp.js)
2 (in-package sugar-qsp.js)
3
3
4 ;;; Contains symbols from standard JS library to avoid obfuscating
4 ;;; Contains symbols from standard JS library to avoid obfuscating
5 ;;; and/or namespacing them
5 ;;; and/or namespacing them
6
6
7 (cl:defmacro syms (cl:&rest syms)
7 (cl:defmacro syms (cl:&rest syms)
8 `(cl:progn
8 `(cl:progn
9 ,@(cl:loop :for sym :in syms
9 ,@(cl:loop :for sym :in syms
10 :collect `(cl:export ',sym))))
10 :collect `(cl:export ',sym))))
11
11
12 (syms
12 (syms
13 ;; main
13 ;; main
14 window
14 window
15 *object
15 *object
16 now
16 now
17 onload
17 onload
18 keys includes
18 keys includes
19 has-own-property
19 has-own-property
20 ;; api
20 ;; api
21 document get-element-by-id
21 document get-element-by-id
22 onclick onchange
22 onclick onchange
23 atob btoa
23 atob btoa split
24 alert prompt
24 alert prompt
25 set-timeout set-interval clear-interval
25 set-timeout set-interval clear-interval
26 *promise *j-s-o-n
26 *promise *j-s-o-n
27 href parse
27 href parse
28 set-prototype-of
28 set-prototype-of
29 body append-child remove-child
29 body append-child remove-child
30 add ; remove (is already in COMMON-LISP)
30 add ; remove (is already in COMMON-LISP)
31 create-element set-attribute class-list
31 create-element set-attribute class-list
32 *file-reader read-as-text
32 *file-reader read-as-text
33 style display src
33 style display src
34 page-x page-y
35 top left
34 ;; lib
36 ;; lib
35 *number parse-int
37 *number parse-int
36 to-upper-case concat
38 to-string to-upper-case concat
37 click target current-target files index-of result
39 click target current-target files index-of result
38 decode-u-r-i-component splice
40 decode-u-r-i-component splice
39 )
41 )
@@ -1,43 +1,44 b''
1
1
2 (in-package sugar-qsp.main)
2 (in-package sugar-qsp.main)
3
3
4 (setf (root)
4 (setf (root)
5 (create
5 (create
6 ;;; Game session state
6 ;;; Game session state
7 ;; Variables
7 ;; Variables
8 vars (create)
8 vars (create)
9 ;; Inventory (objects)
9 ;; Inventory (objects)
10 objs (list)
10 objs (list)
11 current-location nil
11 current-location nil
12 ;; Game time
12 ;; Game time
13 started-at (chain *date (now))
13 started-at (chain *date (now))
14 ;; Timers
14 ;; Timers
15 timer-interval 500
15 timer-interval 500
16 timer-obj nil
16 timer-obj nil
17 ;;; Transient state
17 ;;; Transient state
18 ;; Savegame data
18 ;; Savegame data
19 state-stash (create)
19 state-stash (create)
20 ;; List of audio files being played
20 ;; List of audio files being played
21 playing (create)
21 playing (create)
22 ;; Local variables stack (starts with an empty frame)
22 ;; Local variables stack (starts with an empty frame)
23 locals (list)
23 locals (list)
24 ;;; Game data
24 ;;; Game data
25 ;; ACTions
25 ;; ACTions
26 acts (create)
26 acts (create)
27 ;; Locations
27 ;; Locations
28 locs (create)))
28 locs (create)))
29
29
30 ;; Launch the game from the first location
30 ;; Launch the game from the first location
31 (setf (@ window onload)
31 (setf (@ window onload)
32 (lambda ()
32 (lambda ()
33 (#.(intern "INIT-DOM" "SUGAR-QSP.API"))
33 (#.(intern "INIT-DOM" "SUGAR-QSP.API"))
34 ;; For MSECCOUNT
34 ;; For MSECCOUNT
35 (setf (root started-at) (chain *date (now)))
35 (setf (root started-at) (chain *date (now)))
36 ;; For $COUNTER and SETTIMER
36 ;; For $COUNTER and SETTIMER
37 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
37 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
38 (root timer-interval))
38 (root timer-interval))
39 ;; Start the first location
39 (funcall (getprop (root locs)
40 (funcall (getprop (root locs)
40 (chain *object (keys (root locs)) 0))
41 (chain *object (keys (root locs)) 0))
41 (list))
42 (list))
42 (values)))
43 (values)))
43
44
@@ -1,614 +1,619 b''
1
1
2 (in-package sugar-qsp)
2 (in-package sugar-qsp)
3
3
4 ;;;; Parses TXT source to an intermediate representation
4 ;;;; Parses TXT source to an intermediate representation
5
5
6 ;;; Utility
6 ;;; Utility
7
7
8 (defun remove-nth (list nth)
8 (defun remove-nth (list nth)
9 (append (subseq list 0 nth)
9 (append (subseq list 0 nth)
10 (subseq list (1+ nth))))
10 (subseq list (1+ nth))))
11
11
12 (defun not-quote (char)
12 (defun not-quote (char)
13 (not (eql #\' char)))
13 (not (eql #\' char)))
14
14
15
15
16 (defun not-doublequote (char)
16 (defun not-doublequote (char)
17 (not (eql #\" char)))
17 (not (eql #\" char)))
18
18
19 (defun not-brace (char)
19 (defun not-brace (char)
20 (not (eql #\} char)))
20 (not (eql #\} char)))
21
21
22 (defun not-integer (string)
22 (defun not-integer (string)
23 (when (find-if-not #'digit-char-p string)
23 (when (find-if-not #'digit-char-p string)
24 t))
24 t))
25
25
26 (defun not-newline (char)
26 (defun not-newline (char)
27 (not (eql #\newline char)))
27 (not (eql #\newline char)))
28
28
29 (defun id-any-char (char)
29 (defun id-any-char (char)
30 (and
30 (and
31 (not (digit-char-p char))
31 (not (digit-char-p char))
32 (not (eql #\newline char))
32 (not (eql #\newline char))
33 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
33 (not (find char " !:&=<>+-*/,'\"()[]{}"))))
34
34
35 (defun intern-first (list)
35 (defun intern-first (list)
36 (list* (intern (string-upcase (first list)) :lib)
36 (list* (intern (string-upcase (first list)) :lib)
37 (rest list)))
37 (rest list)))
38
38
39 (eval-when (:compile-toplevel :load-toplevel :execute)
39 (eval-when (:compile-toplevel :load-toplevel :execute)
40 (defun remove-nil (list)
40 (defun remove-nil (list)
41 (remove nil list)))
41 (remove nil list)))
42
42
43 (defun binop-rest (list)
43 (defun binop-rest (list)
44 (destructuring-bind (ws1 operator ws2 operand2)
44 (destructuring-bind (ws1 operator ws2 operand2)
45 list
45 list
46 (declare (ignore ws1 ws2))
46 (declare (ignore ws1 ws2))
47 (list (intern (string-upcase operator) :lib) operand2)))
47 (list (intern (string-upcase operator) :lib) operand2)))
48
48
49 (defun do-binop% (left-op other-ops)
49 (defun do-binop% (left-op other-ops)
50 (if (null other-ops)
50 (if (null other-ops)
51 left-op
51 left-op
52 (destructuring-bind ((operator right-op) &rest rest-ops)
52 (destructuring-bind ((operator right-op) &rest rest-ops)
53 other-ops
53 other-ops
54 (if (and (listp left-op)
54 (if (and (listp left-op)
55 (eq (first left-op)
55 (eq (first left-op)
56 operator))
56 operator))
57 (do-binop% (append left-op (list right-op)) rest-ops)
57 (do-binop% (append left-op (list right-op)) rest-ops)
58 (do-binop% (list operator left-op right-op) rest-ops)))))
58 (do-binop% (list operator left-op right-op) rest-ops)))))
59
59
60 (defun do-binop (list)
60 (defun do-binop (list)
61 (destructuring-bind (left-op rest-ops)
61 (destructuring-bind (left-op rest-ops)
62 list
62 list
63 (do-binop% left-op
63 (do-binop% left-op
64 (mapcar #'binop-rest rest-ops))))
64 (mapcar #'binop-rest rest-ops))))
65
65
66 (p:defrule line-continuation (and #\_ #\newline)
66 (p:defrule line-continuation (and #\_ #\newline)
67 (:constant nil))
67 (:constant nil))
68
68
69 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
69 (p:defrule text-spaces (+ (or #\space #\tab line-continuation))
70 (:text t))
70 (:text t))
71
71
72 (p:defrule spaces (+ (or #\space #\tab line-continuation))
72 (p:defrule spaces (+ (or #\space #\tab line-continuation))
73 (:constant nil)
73 (:constant nil)
74 (:error-report nil))
74 (:error-report nil))
75
75
76 (p:defrule spaces? (* (or #\space #\tab line-continuation))
76 (p:defrule spaces? (* (or #\space #\tab line-continuation))
77 (:constant nil)
77 (:constant nil)
78 (:error-report nil))
78 (:error-report nil))
79
79
80 (p:defrule colon #\:
80 (p:defrule colon #\:
81 (:constant nil))
81 (:constant nil))
82
82
83 (p:defrule equal #\=
83 (p:defrule equal #\=
84 (:constant nil))
84 (:constant nil))
85
85
86 (p:defrule alphanumeric (alphanumericp character))
86 (p:defrule alphanumeric (alphanumericp character))
87
87
88 (p:defrule not-newline (not-newline character))
88 (p:defrule not-newline (not-newline character))
89
89
90 (p:defrule squote-esc "''"
90 (p:defrule squote-esc "''"
91 (:lambda (list)
91 (:lambda (list)
92 (p:text (elt list 0))))
92 (p:text (elt list 0))))
93
93
94 (p:defrule dquote-esc "\"\""
94 (p:defrule dquote-esc "\"\""
95 (:lambda (list)
95 (:lambda (list)
96 (p:text (elt list 0))))
96 (p:text (elt list 0))))
97
97
98 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
98 (p:defrule sstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "\"exec:")))
99 (or squote-esc (not-quote character))))
99 (or squote-esc (not-quote character))))
100 (:lambda (list)
100 (:lambda (list)
101 (p:text (mapcar #'second list))))
101 (p:text (mapcar #'second list))))
102
102
103 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
103 (p:defrule dstring-chars (+ (and (and (p:! "<<") (p:! (p:~ "'exec:")))
104 (or dquote-esc (not-doublequote character))))
104 (or dquote-esc (not-doublequote character))))
105 (:lambda (list)
105 (:lambda (list)
106 (p:text (mapcar #'second list))))
106 (p:text (mapcar #'second list))))
107
107
108 ;;; Identifiers
108 ;;; Identifiers
109
109
110 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit for freelib func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt step str strcomp strfind strpos to trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
110 (defparameter *keywords* '(act addlib addobj addqst and arrcomp arrpos arrsize cla clear *clear close clr *clr cls cmdclear cmdclr copyarr counter countobj curacts curloc debug delact dellib delobj desc disablescroll disablesubex dynamic dyneval else elseif end exit for freelib func getobj gosub goto gs gt if iif inclib input instr isnum isplay jump killall killobj killqst killvar lcase lcolor len let loc local maintxt max menu mid min mod msecscount msg nl *nl no nosave obj opengame openqst or p *p pl *pl play qspver rand refint replace rgb rnd savegame selact selobj set settimer showacts showinput showobjs showstat stattxt step str strcomp strfind strpos to trim ucase unsel unselect usercom user_text usrtxt val view wait xgoto xgt))
111
111
112 (defun trim-$ (str)
112 (defun trim-$ (str)
113 (if (char= #\$ (elt str 0))
113 (if (char= #\$ (elt str 0))
114 (subseq str 1)
114 (subseq str 1)
115 str))
115 str))
116
116
117 (defun qsp-keyword-p (id)
117 (defun qsp-keyword-p (id)
118 (member (intern (trim-$ (string-upcase id))) *keywords*))
118 (member (intern (trim-$ (string-upcase id))) *keywords*))
119
119
120 (defun not-qsp-keyword-p (id)
120 (defun not-qsp-keyword-p (id)
121 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
121 (not (member (intern (trim-$ (string-upcase id))) *keywords*)))
122
122
123 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
123 (p:defrule qsp-keyword (qsp-keyword-p identifier-raw))
124
124
125 (p:defrule id-first (id-any-char character))
125 (p:defrule id-first (id-any-char character))
126 (p:defrule id-next (or (id-any-char character)
126 (p:defrule id-next (or (id-any-char character)
127 (digit-char-p character)))
127 (digit-char-p character)))
128 (p:defrule identifier-raw (and id-first (* id-next))
128 (p:defrule identifier-raw (and id-first (* id-next))
129 (:lambda (list)
129 (:lambda (list)
130 (intern (string-upcase (p:text list)) :lib)))
130 (intern (string-upcase (p:text list)) :lib)))
131
131
132 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
132 (p:defrule identifier (not-qsp-keyword-p identifier-raw))
133
133
134 ;;; Strings
134 ;;; Strings
135
135
136 (p:defrule qsp-string (or normal-string brace-string))
136 (p:defrule qsp-string (or normal-string brace-string))
137
137
138 (p:defrule normal-string (or sstring dstring)
138 (p:defrule normal-string (or sstring dstring)
139 (:lambda (str)
139 (:lambda (str)
140 (list* 'lib:str (or str (list "")))))
140 (list* 'lib:str (or str (list "")))))
141
141
142 (p:defrule sstring (and #\' (* (or string-interpol
142 (p:defrule sstring (and #\' (* (or string-interpol
143 sstring-exec
143 sstring-exec
144 sstring-chars))
144 sstring-chars))
145 #\')
145 #\')
146 (:function second))
146 (:function second))
147
147
148 (p:defrule dstring (and #\" (* (or string-interpol
148 (p:defrule dstring (and #\" (* (or string-interpol
149 dstring-exec
149 dstring-exec
150 dstring-chars))
150 dstring-chars))
151 #\")
151 #\")
152 (:function second))
152 (:function second))
153
153
154 (p:defrule string-interpol (and "<<" expression ">>")
154 (p:defrule string-interpol (and "<<" expression ">>")
155 (:function second))
155 (:function second))
156
156
157 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
157 (p:defrule sstring-exec-body (+ (or squote-esc (not-doublequote character)))
158 (:text t))
158 (:text t))
159
159
160 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
160 (p:defrule dstring-exec-body (+ (or dquote-esc (not-quote character)))
161 (:text t))
161 (:text t))
162
162
163 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
163 (p:defrule sstring-exec (and (p:~ "\"exec:") sstring-exec-body #\")
164 (:lambda (list)
164 (:lambda (list)
165 (list* 'lib:exec (p:parse 'exec-body (second list)))))
165 (list* 'lib:exec (p:parse 'exec-body (second list)))))
166
166
167 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
167 (p:defrule dstring-exec (and (p:~ "'exec:") dstring-exec-body #\')
168 (:lambda (list)
168 (:lambda (list)
169 (list* 'lib:exec (p:parse 'exec-body (second list)))))
169 (list* 'lib:exec (p:parse 'exec-body (second list)))))
170
170
171 (p:defrule brace-string (and #\{ before-statement block-body #\})
171 (p:defrule brace-string (and #\{ before-statement block-body #\})
172 (:lambda (list)
172 (:lambda (list)
173 (list* 'lib:qspblock (third list))))
173 (list* 'lib:qspblock (third list))))
174
174
175 ;;; Location
175 ;;; Location
176
176
177 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
177 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
178 (* location))
178 (* location))
179 (:function second))
179 (:function second))
180
180
181 (p:defrule location (and location-header block-body location-end)
181 (p:defrule location (and location-header block-body location-end)
182 (:destructure (header body end)
182 (:destructure (header body end)
183 (declare (ignore end))
183 (declare (ignore end))
184 `(lib:location (,header) ,@body)))
184 `(lib:location (,header) ,@body)))
185
185
186 (p:defrule location-header (and #\#
186 (p:defrule location-header (and #\#
187 (+ not-newline)
187 (+ not-newline)
188 (and #\newline spaces? before-statement))
188 (and #\newline spaces? before-statement))
189 (:destructure (spaces1 name spaces2)
189 (:destructure (spaces1 name spaces2)
190 (declare (ignore spaces1 spaces2))
190 (declare (ignore spaces1 spaces2))
191 (string-upcase (string-trim " " (p:text name)))))
191 (string-upcase (string-trim " " (p:text name)))))
192
192
193 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
193 (p:defrule location-end (and #\- (* not-newline) #\newline before-statement)
194 (:constant nil))
194 (:constant nil))
195
195
196 ;;; Block body
196 ;;; Block body
197
197
198 (p:defrule newline-block-body (and #\newline spaces? block-body)
198 (p:defrule newline-block-body (and #\newline spaces? block-body)
199 (:function third))
199 (:function third))
200
200
201 (p:defrule block-body (* statement)
201 (p:defrule block-body (* statement)
202 (:function remove-nil))
202 (:function remove-nil))
203
203
204 ;; Just for <a href="exec:...'>
204 ;; Just for <a href="exec:...'>
205 ;; Explicitly called from that rule's production
205 ;; Explicitly called from that rule's production
206 (p:defrule exec-body (and before-statement line-body)
206 (p:defrule exec-body (and before-statement line-body)
207 (:function second))
207 (:function second))
208
208
209 (p:defrule line-body (and inline-statement (* next-inline-statement))
209 (p:defrule line-body (and inline-statement (* next-inline-statement))
210 (:lambda (list)
210 (:lambda (list)
211 (list* (first list) (second list))))
211 (list* (first list) (second list))))
212
212
213 (p:defrule before-statement (* (or #\newline spaces))
213 (p:defrule before-statement (* (or #\newline spaces))
214 (:constant nil))
214 (:constant nil))
215
215
216 (p:defrule statement-end (or statement-end-real statement-end-block-close))
216 (p:defrule statement-end (or statement-end-real statement-end-block-close))
217
217
218 (p:defrule statement-end-real (and (or #\newline
218 (p:defrule statement-end-real (and (or #\newline
219 (and #\& spaces? (p:& statement%)))
219 (and #\& spaces? (p:& statement%)))
220 before-statement)
220 before-statement)
221 (:constant nil))
221 (:constant nil))
222
222
223 (p:defrule statement-end-block-close (or (p:& #\}))
223 (p:defrule statement-end-block-close (or (p:& #\}))
224 (:constant nil))
224 (:constant nil))
225
225
226 (p:defrule inline-statement (and statement% spaces?)
226 (p:defrule inline-statement (and statement% spaces?)
227 (:function first))
227 (:function first))
228
228
229 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
229 (p:defrule next-inline-statement (and #\& spaces? inline-statement)
230 (:function third))
230 (:function third))
231
231
232 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
232 (p:defrule not-a-non-statement (and (p:! (p:~ "elseif"))
233 (p:! (p:~ "else"))
233 (p:! (p:~ "else"))
234 (p:! (p:~ "end"))))
234 (p:! (p:~ "end"))))
235
235
236 (p:defrule statement (and inline-statement statement-end)
236 (p:defrule statement (and inline-statement statement-end)
237 (:function first))
237 (:function first))
238
238
239 (p:defrule statement% (and not-a-non-statement
239 (p:defrule statement% (and not-a-non-statement
240 (or label comment string-output
240 (or label comment string-output
241 block non-returning-intrinsic local
241 block non-returning-intrinsic local
242 assignment expression-output))
242 assignment expression-output))
243 (:function second))
243 (:function second))
244
244
245 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
245 (p:defrule expr-stopper (or comment block non-returning-intrinsic))
246
246
247 (p:defrule string-output qsp-string
247 (p:defrule string-output qsp-string
248 (:lambda (string)
248 (:lambda (string)
249 (list 'lib:main-pl string)))
249 (list 'lib:main-pl string)))
250
250
251 (p:defrule expression-output expression
251 (p:defrule expression-output expression
252 (:lambda (list)
252 (:lambda (list)
253 (list 'lib:main-pl list)))
253 (list 'lib:main-pl list)))
254
254
255 (p:defrule label (and colon identifier)
255 (p:defrule label (and colon identifier)
256 (:lambda (list)
256 (:lambda (list)
257 (intern (string (second list)) :keyword)))
257 (intern (string (second list)) :keyword)))
258
258
259 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
259 (p:defrule comment (and #\! (* (or qsp-string brace-comment text-spaces not-newline)))
260 (:constant nil))
260 (:constant nil))
261
261
262 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
262 (p:defrule brace-comment (and #\{ (* (not-brace character)) #\})
263 (:constant nil))
263 (:constant nil))
264
264
265 (p:defrule local (and (p:~ "local") spaces variable (p:? (and spaces? #\= spaces? expression)))
265 (p:defrule local (and (p:~ "local") spaces variable (p:? (and spaces? #\= spaces? expression)))
266 (:lambda (list)
266 (:lambda (list)
267 (list* 'lib:local (third list)
267 (list* 'lib:local (third list)
268 (when (fourth list)
268 (when (fourth list)
269 (list (fourth (fourth list)))))))
269 (list (fourth (fourth list)))))))
270
270
271 ;;; Blocks
271 ;;; Blocks
272
272
273 (p:defrule block (or block-act block-if block-for))
273 (p:defrule block (or block-act block-if block-for))
274
274
275 (p:defrule block-if (and block-if-head block-if-body)
275 (p:defrule block-if (and block-if-head block-if-body)
276 (:destructure (head body)
276 (:destructure (head body)
277 `(lib:qspcond (,@head ,@(first body))
277 `(lib:qspcond (,@head ,@(first body))
278 ,@(rest body))))
278 ,@(rest body))))
279
279
280 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
280 (p:defrule block-if-head (and (p:~ "if") spaces expression spaces? colon spaces?)
281 (:function remove-nil)
281 (:function remove-nil)
282 (:function cdr))
282 (:function cdr))
283
283
284 (p:defrule block-if-body (or block-if-ml block-if-sl)
284 (p:defrule block-if-body (or block-if-ml block-if-sl)
285 (:destructure (if-body elseifs else &rest ws)
285 (:destructure (if-body elseifs else &rest ws)
286 (declare (ignore ws))
286 (declare (ignore ws))
287 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
287 `(,(remove-nil if-body) ,@elseifs ,@(when else `((else ,@else))))))
288
288
289 (p:defrule block-if-sl (and line-body
289 (p:defrule block-if-sl (and line-body
290 (p:? block-if-elseif-inline)
290 (p:? block-if-elseif-inline)
291 (p:? block-if-else-inline)
291 (p:? block-if-else-inline)
292 spaces?))
292 spaces?))
293
293
294 (p:defrule block-if-ml (and (and #\newline spaces?)
294 (p:defrule block-if-ml (and (and #\newline spaces?)
295 block-body
295 block-body
296 (p:? block-if-elseif)
296 (p:? block-if-elseif)
297 (p:? block-if-else)
297 (p:? block-if-else)
298 block-if-end)
298 block-if-end)
299 (:lambda (list)
299 (:lambda (list)
300 (cdr list)))
300 (cdr list)))
301
301
302 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
302 (p:defrule block-if-elseif-inline (and block-if-elseif-head line-body (p:? block-if-elseif-inline))
303 (:destructure (head statements elseif)
303 (:destructure (head statements elseif)
304 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
304 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
305
305
306 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
306 (p:defrule block-if-elseif (and block-if-elseif-head statement-end block-body (p:? block-if-elseif))
307 (:destructure (head ws statements elseif)
307 (:destructure (head ws statements elseif)
308 (declare (ignore ws))
308 (declare (ignore ws))
309 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
309 `((,@(rest head) ,@(remove-nil statements)) ,@elseif)))
310
310
311 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
311 (p:defrule block-if-elseif-head (and (p:~ "elseif") spaces expression spaces? colon spaces?)
312 (:function remove-nil)
312 (:function remove-nil)
313 (:function intern-first))
313 (:function intern-first))
314
314
315 (p:defrule block-if-else-inline (and block-if-else-head line-body)
315 (p:defrule block-if-else-inline (and block-if-else-head line-body)
316 (:function second))
316 (:function second))
317
317
318 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
318 (p:defrule block-if-else (and block-if-else-head #\newline spaces? block-body)
319 (:function fourth))
319 (:function fourth))
320
320
321 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
321 (p:defrule block-if-else-head (and (p:~ "else") spaces?)
322 (:constant nil))
322 (:constant nil))
323
323
324 (p:defrule block-if-end (and (p:~ "end")
324 (p:defrule block-if-end (and (p:~ "end")
325 (p:? (and spaces (p:~ "if"))))
325 (p:? (and spaces (p:~ "if"))))
326 (:constant nil))
326 (:constant nil))
327
327
328 (p:defrule block-act (and block-act-head (or block-ml block-sl))
328 (p:defrule block-act (and block-act-head (or block-ml block-sl))
329 (:lambda (list)
329 (:lambda (list)
330 (apply #'append list)))
330 (apply #'append list)))
331
331
332 (p:defrule block-act-head (and (p:~ "act") spaces? qsp-string spaces?
332 (p:defrule block-act-head (and (p:~ "act") spaces? qsp-string spaces?
333 (p:? block-act-head-img)
333 (p:? block-act-head-img)
334 colon spaces?)
334 colon spaces?)
335 (:lambda (list)
335 (:lambda (list)
336 (intern-first (list (first list)
336 (intern-first (list (first list)
337 (third list)
337 (third list)
338 (or (fifth list) '(lib:str ""))))))
338 (or (fifth list) '(lib:str ""))))))
339
339
340 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
340 (p:defrule block-act-head-img (and #\, spaces? qsp-string spaces?)
341 (:lambda (list)
341 (:lambda (list)
342 (or (third list) "")))
342 (or (third list) "")))
343
343
344 (p:defrule block-for (and block-for-head (or block-ml block-sl))
344 (p:defrule block-for (and block-for-head (or block-ml block-sl))
345 (:lambda (list)
345 (:lambda (list)
346 (apply #'append list)))
346 (apply #'append list)))
347
347
348 (p:defrule block-for-head (and (p:~ "for") spaces variable spaces? equal spaces? expression
348 (p:defrule block-for-head (and (p:~ "for") spaces variable spaces? equal spaces? expression
349 (p:~ "to") spaces expression
349 (p:~ "to") spaces expression
350 block-for-head-step
350 block-for-head-step
351 colon spaces?)
351 colon spaces?)
352 (:lambda (list)
352 (:lambda (list)
353 (unless (eq (fourth (third list)) :num)
353 (unless (eq (fourth (third list)) :num)
354 (error "For counter variable must be numeric."))
354 (error "For counter variable must be numeric."))
355 (list 'lib:qspfor
355 (list 'lib:qspfor
356 (elt list 2)
356 (elt list 2)
357 (elt list 6)
357 (elt list 6)
358 (elt list 9)
358 (elt list 9)
359 (elt list 10))))
359 (elt list 10))))
360
360
361 (p:defrule block-for-head-step (p:? (and (p:~ "step") spaces expression spaces?))
361 (p:defrule block-for-head-step (p:? (and (p:~ "step") spaces expression spaces?))
362 (:lambda (list)
362 (:lambda (list)
363 (if list
363 (if list
364 (third list)
364 (third list)
365 1)))
365 1)))
366
366
367 (p:defrule block-sl line-body)
367 (p:defrule block-sl line-body)
368
368
369 (p:defrule block-ml (and newline-block-body block-end)
369 (p:defrule block-ml (and newline-block-body block-end)
370 (:lambda (list)
370 (:lambda (list)
371 (apply #'list* (butlast list))))
371 (apply #'list* (butlast list))))
372
372
373 (p:defrule block-end (and (p:~ "end"))
373 (p:defrule block-end (and (p:~ "end"))
374 (:constant nil))
374 (:constant nil))
375
375
376 ;;; Calls
376 ;;; Calls
377
377
378 (p:defrule first-argument (and expression spaces?)
378 (p:defrule first-argument (and expression spaces?)
379 (:function first))
379 (:function first))
380 (p:defrule next-argument (and "," spaces? expression)
380 (p:defrule next-argument (and "," spaces? expression)
381 (:function third))
381 (:function third))
382 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
382 (p:defrule arguments (or parenthesized-arguments plain-arguments no-arguments))
383 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
383 (p:defrule parenthesized-arguments (and spaces? #\( base-arguments #\))
384 (:function third))
384 (:function third))
385 (p:defrule plain-arguments (and spaces? base-arguments)
385 (p:defrule plain-arguments (and spaces? base-arguments)
386 (:function second))
386 (:function second))
387 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
387 (p:defrule no-arguments (or (and spaces? (p:& #\newline))
388 (and spaces? (p:& #\&))
388 (and spaces? (p:& #\&))
389 spaces?)
389 spaces?)
390 (:constant nil))
390 (:constant nil))
391 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
391 (p:defrule base-arguments (or (and first-argument (* next-argument)) spaces?)
392 (:lambda (list)
392 (:lambda (list)
393 (if (null list)
393 (if (null list)
394 nil
394 nil
395 (list* (first list) (second list)))))
395 (list* (first list) (second list)))))
396
396
397 ;;; Intrinsics
397 ;;; Intrinsics
398
398
399 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
399 (defmacro defintrinsics ((rule-name returning-rule-name non-returning-rule-name) &body clauses)
400 `(progn
400 `(progn
401 ,@(loop :for clause :in clauses
401 ,@(loop :for clause :in clauses
402 :collect `(defintrinsic ,@clause))
402 :collect `(defintrinsic ,@clause))
403 (p:defrule ,returning-rule-name (or ,@(remove-nil
403 (p:defrule ,returning-rule-name (or ,@(remove-nil
404 (mapcar (lambda (clause)
404 (mapcar (lambda (clause)
405 (when (second clause)
405 (when (second clause)
406 (alexandria:symbolicate
406 (alexandria:symbolicate
407 'intrinsic- (first clause))))
407 'intrinsic- (first clause))))
408 clauses))))
408 clauses))))
409 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
409 (p:defrule ,non-returning-rule-name (or ,@(remove-nil
410 (mapcar (lambda (clause)
410 (mapcar (lambda (clause)
411 (unless (second clause)
411 (unless (second clause)
412 (alexandria:symbolicate
412 (alexandria:symbolicate
413 'intrinsic- (first clause))))
413 'intrinsic- (first clause))))
414 clauses))))
414 clauses))))
415 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
415 (p:defrule ,rule-name (or ,returning-rule-name ,non-returning-rule-name))))
416
416
417 (defmacro defintrinsic (sym returning &optional (min-arity 0) (max-arity 10) &rest names)
417 (defmacro defintrinsic (sym returning &optional (min-arity 0) (max-arity 10) &rest names)
418 (declare (ignore returning))
418 (declare (ignore returning))
419 (setf names
419 (setf names
420 (if names
420 (if names
421 (mapcar #'string-upcase names)
421 (mapcar #'string-upcase names)
422 (list (string sym))))
422 (list (string sym))))
423 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
423 `(p:defrule ,(alexandria:symbolicate 'intrinsic- sym)
424 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
424 (and (p:? #\$) (or ,@(loop :for name :in names :collect `(p:~ ,name)))
425 arguments)
425 arguments)
426 (:destructure (dollar name arguments)
426 (:destructure (dollar name arguments)
427 (declare (ignore dollar))
427 (declare (ignore dollar))
428 (unless (<= ,min-arity (length arguments) ,max-arity)
428 (unless (<= ,min-arity (length arguments) ,max-arity)
429 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
429 (error "Intrinsic ~A expects between ~A and ~A arguments but ~A were provided:~%~S"
430 name ,min-arity ,max-arity (length arguments) arguments))
430 name ,min-arity ,max-arity (length arguments) arguments))
431 (list* ',(intern (string sym) :lib) arguments))))
431 (list* ',(intern (string sym) :lib) arguments))))
432
432
433 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
433 (defintrinsics (intrinsic returning-intrinsic non-returning-intrinsic)
434 ;; Transitions
434 ;; Transitions
435 (goto% nil 0 10 "gt" "goto")
435 (goto% nil 0 10 "gt" "goto")
436 (xgoto% nil 0 10 "xgt" "xgoto")
436 (xgoto% nil 0 10 "xgt" "xgoto")
437 ;; Variables
437 ;; Variables
438 (killvar nil 0 2)
438 (killvar nil 0 2)
439 ;; Expressions
439 ;; Expressions
440 (obj t 1 1)
440 (obj t 1 1)
441 (loc t 1 1)
441 (loc t 1 1)
442 (no t 1 1)
442 (no t 1 1)
443 ;; Basic
443 ;; Basic
444 (qspver t 0 0)
444 (qspver t 0 0)
445 (curloc t 0 0)
445 (curloc t 0 0)
446 (rand t 1 2)
446 (rand t 1 2)
447 (rnd t 0 0)
447 (rnd t 0 0)
448 (qspmax t 1 10 "max")
448 (qspmax t 1 10 "max")
449 (qspmin t 1 10 "min")
449 (qspmin t 1 10 "min")
450 ;; Arrays
450 ;; Arrays
451 (killall nil 0 0)
451 (killall nil 0 0)
452 (copyarr nil 2 4)
452 (copyarr nil 2 4)
453 (arrsize t 1 1)
453 (arrsize t 1 1)
454 (arrpos t 2 3)
454 (arrpos t 2 3)
455 (arrcomp t 2 3)
455 (arrcomp t 2 3)
456 ;; Strings
456 ;; Strings
457 (len t 1 1)
457 (len t 1 1)
458 (mid t 2 3)
458 (mid t 2 3)
459 (ucase t 1 1)
459 (ucase t 1 1)
460 (lcase t 1 1)
460 (lcase t 1 1)
461 (trim t 1 1)
461 (trim t 1 1)
462 (replace t 2 3)
462 (replace t 2 3)
463 (instr t 2 3)
463 (instr t 2 3)
464 (isnum t 1 1)
464 (isnum t 1 1)
465 (val t 1 1)
465 (val t 1 1)
466 (qspstr t 1 1 "str")
466 (qspstr t 1 1 "str")
467 (strcomp t 2 2)
467 (strcomp t 2 2)
468 (strfind t 2 3)
468 (strfind t 2 3)
469 (strpos t 2 3)
469 (strpos t 2 3)
470 ;; IF
470 ;; IF
471 (iif t 2 3)
471 (iif t 2 3)
472 ;; Subs
472 ;; Subs
473 (gosub nil 1 10 "gosub" "gs")
473 (gosub nil 1 10 "gosub" "gs")
474 (func t 1 10)
474 (func t 1 10)
475 (exit nil 0 0)
475 (exit nil 0 0)
476 ;; Jump
476 ;; Jump
477 (jump nil 1 1)
477 (jump nil 1 1)
478 ;; Dynamic
478 ;; Dynamic
479 (dynamic nil 1 10)
479 (dynamic nil 1 10)
480 (dyneval t 1 10)
480 (dyneval t 1 10)
481 ;; Sound
481 ;; Sound
482 (play nil 1 2)
482 (play nil 1 2)
483 (isplay t 1 1)
483 (isplay t 1 1)
484 (close nil 1 1)
484 (close nil 1 1)
485 (closeall nil 0 0 "close all")
485 (closeall nil 0 0 "close all")
486 ;; Main window
486 ;; Main window
487 (main-pl nil 1 1 "*pl")
487 (main-pl nil 1 1 "*pl")
488 (main-nl nil 0 1 "*nl")
488 (main-nl nil 0 1 "*nl")
489 (main-p nil 1 1 "*p")
489 (main-p nil 1 1 "*p")
490 (maintxt t 0 0)
490 (maintxt t 0 0)
491 (desc t 1 1)
491 (desc t 1 1)
492 (main-clear nil 0 0 "*clear" "*clr")
492 (main-clear nil 0 0 "*clear" "*clr")
493 ;; Aux window
493 ;; Aux window
494 (showstat nil 1 1)
494 (showstat nil 1 1)
495 (stat-pl nil 1 1 "pl")
495 (stat-pl nil 1 1 "pl")
496 (stat-nl nil 0 1 "nl")
496 (stat-nl nil 0 1 "nl")
497 (stat-p nil 1 1 "p")
497 (stat-p nil 1 1 "p")
498 (stattxt t 0 0)
498 (stattxt t 0 0)
499 (stat-clear nil 0 0 "clear" "clr")
499 (stat-clear nil 0 0 "clear" "clr")
500 (cls nil 0 0)
500 (cls nil 0 0)
501 ;; Dialog
501 ;; Dialog
502 (msg nil 1 1)
502 (msg nil 1 1)
503 ;; Acts
503 ;; Acts
504 (showacts nil 1 1)
504 (showacts nil 1 1)
505 (delact nil 1 1 "delact" "del act")
505 (delact nil 1 1 "delact" "del act")
506 (curacts t 0 0)
506 (curacts t 0 0)
507 (cla nil 0 0)
507 (cla nil 0 0)
508 ;; Objects
508 ;; Objects
509 (showobjs nil 1 1)
509 (showobjs nil 1 1)
510 (addobj nil 1 3 "addobj" "add obj")
510 (addobj nil 1 3 "addobj" "add obj")
511 (delobj nil 1 1 "delobj" "del obj")
511 (delobj nil 1 1 "delobj" "del obj")
512 (killobj nil 0 1)
512 (killobj nil 0 1)
513 (countobj t 0 0)
513 (countobj t 0 0)
514 (getobj t 1 1)
514 (getobj t 1 1)
515 ;; Menu
515 ;; Menu
516 (menu nil 1 1)
516 (menu nil 1 1)
517 ;; Images
517 ;; Images
518 (refint nil 0 0)
518 (refint nil 0 0)
519 (view nil 0 1)
519 (view nil 0 1)
520 ;; Fonts
520 ;; Fonts
521 (rgb t 3 3)
521 (rgb t 3 3)
522 ;; Input
522 ;; Input
523 (showinput nil 1 1)
523 (showinput nil 1 1)
524 (usertxt t 0 0 "user_text" "usrtxt")
524 (usertxt t 0 0 "user_text" "usrtxt")
525 (cmdclear nil 0 0 "cmdclear" "cmdclr")
525 (cmdclear nil 0 0 "cmdclear" "cmdclr")
526 (input t 1 1)
526 (input t 1 1)
527 ;; Files
527 ;; Files
528 (openqst nil 1 1)
528 (openqst nil 1 1)
529 (addqst nil 1 1 "addqst" "addlib" "inclib")
529 (addqst nil 1 1 "addqst" "addlib" "inclib")
530 (killqst nil 1 1 "killqst" "dellib" "freelib")
530 (killqst nil 1 1 "killqst" "dellib" "freelib")
531 (opengame nil 0 0)
531 (opengame nil 0 0)
532 (savegame nil 0 0)
532 (savegame nil 0 0)
533 ;; Real time
533 ;; Real time
534 (wait nil 1 1)
534 (wait nil 1 1)
535 (msecscount t 0 0)
535 (msecscount t 0 0)
536 (settimer nil 1 1))
536 (settimer nil 1 1))
537
537
538 ;;; Expression
538 ;;; Expression
539
539
540 (p:defrule expression or-expr)
540 (p:defrule expression or-expr)
541
541
542 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
542 (p:defrule or-expr (and and-expr (* (and spaces? or-op spaces? and-expr)))
543 (:function do-binop))
543 (:function do-binop))
544
544
545 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
545 (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr)))
546 (:function do-binop))
546 (:function do-binop))
547
547
548 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
548 (p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>"
549 "=" "<" ">" "!")
549 "=" "<" ">" "!")
550 spaces? sum-expr)))
550 spaces? sum-expr)))
551 (:function do-binop))
551 (:function do-binop))
552
552
553 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
553 (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr)))
554 (:function do-binop))
554 (:function do-binop))
555
555
556 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
556 (p:defrule mod-expr (and mul-expr (* (and spaces? (p:~ "mod") spaces? mul-expr)))
557 (:function do-binop))
557 (:function do-binop))
558
558
559 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
559 (p:defrule mul-expr (and unary-expr (* (and spaces? (or #\* #\/) spaces? unary-expr)))
560 (:function do-binop))
560 (:function do-binop))
561
561
562 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
562 (p:defrule unary-expr (and (p:? (or #\+ #\-)) atom-expr)
563 (:lambda (list)
563 (:lambda (list)
564 (let ((expr (remove-nil list)))
564 (let ((expr (remove-nil list)))
565 (if (= 1 (length expr))
565 (if (= 1 (length expr))
566 (first expr)
566 (first expr)
567 (intern-first expr)))))
567 (intern-first expr)))))
568
568
569 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
569 (p:defrule atom-expr (and (or variable literal returning-intrinsic paren-expr) spaces?)
570 (:function first))
570 (:function first))
571
571
572 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
572 (p:defrule paren-expr (and #\( spaces? expression spaces? #\))
573 (:function third))
573 (:function third))
574
574
575 (p:defrule or-op (p:~ "or")
575 (p:defrule or-op (p:~ "or")
576 (:constant "or"))
576 (:constant "or"))
577
577
578 (p:defrule and-op (p:~ "and")
578 (p:defrule and-op (p:~ "and")
579 (:constant "and"))
579 (:constant "and"))
580
580
581 ;;; Variables
581 ;;; Variables
582
582
583 (p:defrule variable (and identifier (p:? array-index))
583 (p:defrule variable (and identifier (p:? array-index))
584 (:destructure (id idx)
584 (:destructure (id idx)
585 (let ((idx (case idx
586 (nil 0)
587 (:last nil)
588 (t idx))))
585 (if (char= #\$ (elt (string id) 0))
589 (if (char= #\$ (elt (string id) 0))
586 (list 'lib:qspvar (intern (subseq (string-upcase id) 1) :lib) (or idx 0) :str)
590 (list 'lib:qspvar (intern (subseq (string-upcase id) 1) :lib) idx :str)
587 (list 'lib:qspvar id (or idx 0) :num))))
591 (list 'lib:qspvar id idx :num)))))
588
592
589 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
593 (p:defrule array-index (and #\[ spaces? (p:? expression) spaces? #\])
590 (:function third))
594 (:lambda (list)
595 (or (third list) :last)))
591
596
592 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
597 (p:defrule assignment (or kw-assignment plain-assignment op-assignment)
593 (:destructure (qspvar eq expr)
598 (:destructure (qspvar eq expr)
594 (declare (ignore eq))
599 (declare (ignore eq))
595 (list 'lib:set qspvar expr)))
600 (list 'lib:set qspvar expr)))
596
601
597 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
602 (p:defrule kw-assignment (and (or (p:~ "let") (p:~ "set")) spaces? (or op-assignment plain-assignment))
598 (:function third))
603 (:function third))
599
604
600 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
605 (p:defrule op-assignment (and variable spaces? (or "+" "-" "*" "/") #\= spaces? expression)
601 (:destructure (qspvar ws1 op eq ws2 expr)
606 (:destructure (qspvar ws1 op eq ws2 expr)
602 (declare (ignore ws1 ws2))
607 (declare (ignore ws1 ws2))
603 (list qspvar eq (intern-first (list op qspvar expr)))))
608 (list qspvar eq (intern-first (list op qspvar expr)))))
604
609
605 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
610 (p:defrule plain-assignment (and variable spaces? #\= spaces? expression)
606 (:function remove-nil))
611 (:function remove-nil))
607
612
608 ;;; Non-string literals
613 ;;; Non-string literals
609
614
610 (p:defrule literal (or qsp-string brace-string number))
615 (p:defrule literal (or qsp-string brace-string number))
611
616
612 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
617 (p:defrule number (+ (or #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
613 (:lambda (list)
618 (:lambda (list)
614 (parse-integer (p:text list))))
619 (parse-integer (p:text list))))
General Comments 0
You need to be logged in to leave comments. Login now