@fraczak/k 6.0.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/DOCS/book.html ADDED
@@ -0,0 +1,65 @@
1
+ <div data-align="center">
2
+ <pre><code> { } { }
3
+ / \ {.lang name} |
4
+ lang by --&gt; name
5
+ | | |
6
+ &#39;k&#39; &#39;wojtek&#39; &#39;k&#39;</code></pre>
7
+ </div>
8
+ <h1 id="the-k-language-book">The k-language Book</h1>
9
+ <p>This book describes the k programming language - a minimal functional
10
+ language for transforming tree-structured data using partial functions
11
+ and algebraic data types.</p>
12
+ <h2 id="table-of-contents">Table of Contents</h2>
13
+ <ol type="1">
14
+ <li><a href="book/01-introduction.md">Introduction</a></li>
15
+ <li><a href="book/02-syntax-and-values.md">Syntax and Values</a><br />
16
+ </li>
17
+ <li><a href="book/03-types-as-finite-automata.md">Types as Finite
18
+ Automata</a></li>
19
+ <li><a href="book/04-partial-functions-and-composition.md">Partial
20
+ Functions and Composition</a></li>
21
+ <li><a href="book/05-typing-filters-and-normalization.md">Typing,
22
+ Filters, and Normalization</a></li>
23
+ <li><a href="book/06-values-in-memory.md">Values in Memory</a></li>
24
+ <li><a href="book/07-the-partial-function-abi.md">The Partial Function
25
+ ABI</a></li>
26
+ <li><a href="book/08-operational-semantics-and-execution.md">Operational
27
+ Semantics and Execution</a></li>
28
+ <li><a href="book/09-compiler-architecture.md">Compiler
29
+ Architecture</a></li>
30
+ <li><a href="book/10-from-ast-to-intermediate-representation.md">From
31
+ AST to Intermediate Representation</a></li>
32
+ <li><a href="book/11-llvm-basics.md">LLVM Basics</a></li>
33
+ <li><a href="book/12-code-generation.md">Code Generation</a></li>
34
+ <li><a href="book/13-linking-and-execution.md">Linking and
35
+ Execution</a></li>
36
+ <li><a href="book/14-canonical-serialization.md">Canonical
37
+ Serialization</a></li>
38
+ <li><a href="book/15-optimization-and-folding.md">Optimization and
39
+ Folding</a></li>
40
+ <li><a href="book/16-toward-a-universal-schema-registry.md">Toward a
41
+ Universal Schema Registry</a></li>
42
+ </ol>
43
+ <h2 id="appendices">Appendices</h2>
44
+ <ul>
45
+ <li><a
46
+ href="book/appendix-a-implementing-a-prototype-compiler-in-python.md">Appendix
47
+ A: Implementing a Prototype Compiler in Python</a></li>
48
+ <li><a
49
+ href="book/appendix-b-incorporating-external-predefined-types-and-functions.md">Appendix
50
+ B: Incorporating External Predefined Types and Functions</a></li>
51
+ </ul>
52
+ <hr />
53
+ <p><em>Note: This is the master file. Individual chapters are stored in
54
+ the <code>book/</code> directory for easier editing and maintenance.
55
+ Each chapter can be edited independently and the changes will be
56
+ reflected when the individual files are viewed.</em></p>
57
+ <h2 id="usage">Usage</h2>
58
+ <ul>
59
+ <li><strong>For reading</strong>: Click on any chapter link above to
60
+ read individual chapters</li>
61
+ <li><strong>For editing</strong>: Edit the individual chapter files in
62
+ the <code>book/</code> directory</li>
63
+ <li><strong>For publishing</strong>: Combine chapters as needed for
64
+ different output formats</li>
65
+ </ul>
package/DOCS/book.pdf ADDED
Binary file
package/DOCS/book.tex ADDED
@@ -0,0 +1,150 @@
1
+ % Options for packages loaded elsewhere
2
+ \PassOptionsToPackage{unicode}{hyperref}
3
+ \PassOptionsToPackage{hyphens}{url}
4
+ \documentclass[
5
+ ]{article}
6
+ \usepackage{xcolor}
7
+ \usepackage{amsmath,amssymb}
8
+ \setcounter{secnumdepth}{-\maxdimen} % remove section numbering
9
+ \usepackage{iftex}
10
+ \ifPDFTeX
11
+ \usepackage[T1]{fontenc}
12
+ \usepackage[utf8]{inputenc}
13
+ \usepackage{textcomp} % provide euro and other symbols
14
+ \else % if luatex or xetex
15
+ \usepackage{unicode-math} % this also loads fontspec
16
+ \defaultfontfeatures{Scale=MatchLowercase}
17
+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
18
+ \fi
19
+ \usepackage{lmodern}
20
+ \ifPDFTeX\else
21
+ % xetex/luatex font selection
22
+ \fi
23
+ % Use upquote if available, for straight quotes in verbatim environments
24
+ \IfFileExists{upquote.sty}{\usepackage{upquote}}{}
25
+ \IfFileExists{microtype.sty}{% use microtype if available
26
+ \usepackage[]{microtype}
27
+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
28
+ }{}
29
+ \makeatletter
30
+ \@ifundefined{KOMAClassName}{% if non-KOMA class
31
+ \IfFileExists{parskip.sty}{%
32
+ \usepackage{parskip}
33
+ }{% else
34
+ \setlength{\parindent}{0pt}
35
+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}
36
+ }{% if KOMA class
37
+ \KOMAoptions{parskip=half}}
38
+ \makeatother
39
+ \setlength{\emergencystretch}{3em} % prevent overfull lines
40
+ \providecommand{\tightlist}{%
41
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
42
+ \usepackage{bookmark}
43
+ \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
44
+ \urlstyle{same}
45
+ \hypersetup{
46
+ pdftitle={k-language},
47
+ pdfauthor={W. Fraczak},
48
+ hidelinks,
49
+ pdfcreator={LaTeX via pandoc}}
50
+
51
+ \title{k-language}
52
+ \author{W. Fraczak}
53
+ \date{}
54
+
55
+ \begin{document}
56
+ \maketitle
57
+
58
+ \begin{verbatim}
59
+ { } { }
60
+ / \ {.lang name} |
61
+ lang by --> name
62
+ | | |
63
+ 'k' 'wojtek' 'k'
64
+ \end{verbatim}
65
+
66
+ \section{The k-language Book}\label{the-k-language-book}
67
+
68
+ This book describes the k programming language - a minimal functional
69
+ language for transforming tree-structured data using partial functions
70
+ and algebraic data types.
71
+
72
+ \subsection{Table of Contents}\label{table-of-contents}
73
+
74
+ \begin{enumerate}
75
+ \def\labelenumi{\arabic{enumi}.}
76
+ \tightlist
77
+ \item
78
+ \href{book/01-introduction.md}{Introduction}
79
+ \item
80
+ \href{book/02-syntax-and-values.md}{Syntax and Values}\\
81
+ \item
82
+ \href{book/03-types-as-finite-automata.md}{Types as Finite Automata}
83
+ \item
84
+ \href{book/04-partial-functions-and-composition.md}{Partial Functions
85
+ and Composition}
86
+ \item
87
+ \href{book/05-typing-filters-and-normalization.md}{Typing, Filters,
88
+ and Normalization}
89
+ \item
90
+ \href{book/06-values-in-memory.md}{Values in Memory}
91
+ \item
92
+ \href{book/07-the-partial-function-abi.md}{The Partial Function ABI}
93
+ \item
94
+ \href{book/08-operational-semantics-and-execution.md}{Operational
95
+ Semantics and Execution}
96
+ \item
97
+ \href{book/09-compiler-architecture.md}{Compiler Architecture}
98
+ \item
99
+ \href{book/10-from-ast-to-intermediate-representation.md}{From AST to
100
+ Intermediate Representation}
101
+ \item
102
+ \href{book/11-llvm-basics.md}{LLVM Basics}
103
+ \item
104
+ \href{book/12-code-generation.md}{Code Generation}
105
+ \item
106
+ \href{book/13-linking-and-execution.md}{Linking and Execution}
107
+ \item
108
+ \href{book/14-canonical-serialization.md}{Canonical Serialization}
109
+ \item
110
+ \href{book/15-optimization-and-folding.md}{Optimization and Folding}
111
+ \item
112
+ \href{book/16-toward-a-universal-schema-registry.md}{Toward a
113
+ Universal Schema Registry}
114
+ \end{enumerate}
115
+
116
+ \subsection{Appendices}\label{appendices}
117
+
118
+ \begin{itemize}
119
+ \tightlist
120
+ \item
121
+ \href{book/appendix-a-implementing-a-prototype-compiler-in-python.md}{Appendix
122
+ A: Implementing a Prototype Compiler in Python}
123
+ \item
124
+ \href{book/appendix-b-incorporating-external-predefined-types-and-functions.md}{Appendix
125
+ B: Incorporating External Predefined Types and Functions}
126
+ \end{itemize}
127
+
128
+ \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center}
129
+
130
+ \emph{Note: This is the master file. Individual chapters are stored in
131
+ the \texttt{book/} directory for easier editing and maintenance. Each
132
+ chapter can be edited independently and the changes will be reflected
133
+ when the individual files are viewed.}
134
+
135
+ \subsection{Usage}\label{usage}
136
+
137
+ \begin{itemize}
138
+ \tightlist
139
+ \item
140
+ \textbf{For reading}: Click on any chapter link above to read
141
+ individual chapters
142
+ \item
143
+ \textbf{For editing}: Edit the individual chapter files in the
144
+ \texttt{book/} directory
145
+ \item
146
+ \textbf{For publishing}: Combine chapters as needed for different
147
+ output formats
148
+ \end{itemize}
149
+
150
+ \end{document}
package/NAT.k~ ADDED
@@ -0,0 +1,452 @@
1
+ -- Examples for defining arithmetic functions natively
2
+ $ yes_no = < {} yes, {} no >;
3
+ swap_yes_no = < /yes |no, /no |yes > $yes_no;
4
+ yes = {}|yes $yes_no;
5
+ no = yes swap_yes_no;
6
+
7
+ list? = ?< {} nil, {X car, Y cdr} cons > = Y;
8
+ nil = {}|nil list?;
9
+ singleton = {() car, nil cdr} |cons list?;
10
+ cons = {.car car, .cdr cdr} |cons list?;
11
+ nil? = list? / nil nil;
12
+ car = list? /cons .car;
13
+ cdr = list? /cons .cdr;
14
+
15
+ $ bits = < {} _, bits 0, bits 1 >;
16
+
17
+ 0b = {} | _;
18
+ 1_ = | 1;
19
+ 0_ = | 0;
20
+
21
+ 0 = 0b 0_;
22
+ succ = {inv x, 0b y} _inc;
23
+ 1 = 0 succ;
24
+ 2 = 1 succ;
25
+ 3 = 2 succ;
26
+ 4 = 3 succ;
27
+ 5 = 4 succ;
28
+ 6 = 5 succ;
29
+ 7 = 6 succ;
30
+ 8 = 7 succ;
31
+ 9 = 8 succ;
32
+ 10 = 9 succ;
33
+ 11 = 10 succ;
34
+ 12 = 11 succ;
35
+
36
+ empty = $bits < /_ yes, no >;
37
+ empty? = {empty /yes if, () then} .then;
38
+
39
+ concat = ${bits x, bits y} {.x inv x, .y y} concat_;
40
+ concat_ = ${bits x, bits y}
41
+ <
42
+ {.x /0 x, .y 0_ y} concat_,
43
+ {.x /1 x, .y 1_ y} concat_,
44
+ .y
45
+ >;
46
+ inv = {()x, 0b r} _inv;
47
+ _inv = ${bits x, bits r} < {.x /0 x, .r 0_ r} _inv, {.x /1 x, .r 1_ r} _inv, .r >;
48
+
49
+ inOrder = ${bits x, bits y} {.x inv x, .y inv y, yes inOrder} inOrder_;
50
+ inOrder_ = ${bits x, bits y, yes_no inOrder}
51
+ <
52
+ {.x /0 x, .y /0 y, .inOrder inOrder} inOrder_,
53
+ {.x /1 x, .y /1 y, .inOrder inOrder} inOrder_,
54
+ {.x /0 x, .y /1 y, .inOrder inOrder} inOrder_,
55
+ {.x /1 y, .y /0 x, .inOrder swap_yes_no inOrder} inOrder_,
56
+ {.x </0,/1> if, .inOrder swap_yes_no then} .then,
57
+ .inOrder
58
+ >;
59
+
60
+ GT = {inOrder /no if, () then} . then;
61
+
62
+ EQ = GT {.x y, .y x} GT;
63
+
64
+ toBitList = {inv x, nil r} _toBitList;
65
+ _toBitList = <
66
+ {.x empty? if, .r then }.then,
67
+ {.x /0 x, {0 car, .r cdr} cons r} _toBitList,
68
+ {.x /1 x, {1 car, .r cdr} cons r} _toBitList
69
+ >;
70
+ fromBitList =
71
+ <
72
+ cdr <
73
+ {car /0 if, cdr fromBitList 0_ then} .then,
74
+ {car /1 if, cdr fromBitList 1_ then} .then
75
+ >,
76
+ 0b
77
+ > $bits;
78
+
79
+ --------------------------------------
80
+ $ int = < bits '+', bits '-' >;
81
+
82
+ remove_leading_zeros = <
83
+ /0 remove_leading_zeros,
84
+ ()
85
+ >;
86
+ nat = remove_leading_zeros <empty? 0, ()>;
87
+ int = nat | '+' $int;
88
+ abs = $int </'+',/'-'>;
89
+
90
+ pos? = $int {dec /'+' if, () then} .then;
91
+ neg? = $int {/'-' if, () then} .then;
92
+ zero_int? = $int {/'+' /0 empty? if, () then} .then;
93
+ minus_one? = $int {/'-' /1 empty? if, () then} .then;
94
+
95
+ inc = $int <
96
+ /'+' {inv x, 0b y} _inc |'+',
97
+ minus_one? 0 int,
98
+ /'-' {inv x, 0b y} _dec |'-'
99
+ >;
100
+
101
+ _inc = ${bits x, bits y} <
102
+ {.x /0 x, .y 1_ y} concat_,
103
+ {.x /1 x, .y 0_ y} _inc,
104
+ .y 1_
105
+ >;
106
+
107
+ dec = $int <
108
+ zero_int? 1 |'-',
109
+ /'+' {inv x, 0b y} _dec |'+',
110
+ /'-' {inv x, 0b y} _inc |'-'
111
+ > $int;
112
+
113
+ _dec = ?{X x, X y, ...} <
114
+ {.x /1 x, .y 0_ y} concat_,
115
+ {.x /0 x, .y 1_ y} _dec
116
+ > ?X;
117
+
118
+ $carry = <{} 0, {} 1>;
119
+ c0 = {}|0 $carry;
120
+ c1 = {}|1 $carry;
121
+
122
+ plus = ${int x, int y}
123
+ <
124
+ {.x/'+' inv x, .y/'+' inv y, c0 c } _plus inv nat | '+',
125
+ {.x/'-' inv x, .y/'-' inv y, c0 c } _plus inv nat | '-',
126
+ {.y/'-' x, .x/'+' y} GT {.x inv x, .y inv y, c0 c} _minus inv nat | '-',
127
+ {.x/'+' inv x, .y/'-' inv y, c0 c} _minus inv nat |'+',
128
+ {.x/'-' x, .y/'+' y} GT {.x inv x, .y inv y, c0 c} _minus inv nat | '-',
129
+ {.y/'+' inv x, .x/'-' inv y, c0 c} _minus inv nat | '+'
130
+ >
131
+ $int;
132
+
133
+ swap_sign = <
134
+ zero_int?,
135
+ /'+' | '-',
136
+ /'-' | '+'
137
+ >;
138
+
139
+ minus = ${int x, int y}
140
+ {.x x, .y swap_sign y} plus;
141
+
142
+ _plus =
143
+ -- least significant bit first addition with carry
144
+ ${bits x, bits y, carry c}
145
+ <
146
+ {.x empty? if, .y empty? and, <.c/0 0, 1> then} .then,
147
+ {.x empty? if, .c/0 and, .y then} .then,
148
+
149
+ {.x y, .y empty? x, .c c} _plus,
150
+ {<.c/0 0, 1> x,
151
+ .y y, .x empty? c0 c} _plus,
152
+
153
+ {.x /0 x, .y /0 y, .c/0 c0 c} _plus 0_,
154
+ {.x /0 x, .y /0 y, .c/1 c0 c} _plus 1_,
155
+
156
+ {.x /0 x, .y /1 y, .c/0 c0 c} _plus 1_,
157
+ {.x /0 x, .y /1 y, .c/1 c1 c} _plus 0_,
158
+ {.x /1 x, .y /0 y, .c/0 c0 c} _plus 1_,
159
+ {.x /1 x, .y /0 y, .c/1 c1 c} _plus 0_,
160
+
161
+ {.x /1 x, .y /1 y, .c/0 c1 c} _plus 0_,
162
+ {.x /1 x, .y /1 y, .c/1 c1 c} _plus 1_
163
+ >
164
+ ;
165
+
166
+ _minus =
167
+ -- least significat bit first substraction with carry
168
+ ${bits x, bits y, carry c}
169
+ <
170
+ {.x then, .y empty? if, .c/0 and} .then,
171
+ {.x/1 then, .y empty? if, .c/1 and} .then 0_,
172
+ {.x/0 x, .y empty? y, .c/1 c1 c} _minus 1_,
173
+ {.x/0 x, .y/0 y, .c/0 c0 c} _minus 0_,
174
+ {.x/0 x, .y/0 y, .c/1 c1 c} _minus 1_,
175
+ {.x/0 x, .y/1 y, .c/0 c1 c} _minus 1_,
176
+ {.x/0 x, .y/1 y, .c/1 c1 c} _minus 0_,
177
+ {.x/1 x, .y/0 y, .c/0 c0 c} _minus 1_,
178
+ {.x/1 x, .y/0 y, .c/1 c0 c} _minus 0_,
179
+ {.x/1 x, .y/1 y, .c/0 c0 c} _minus 0_,
180
+ {.x/1 x, .y/1 y, .c/1 c1 c} _minus 1_
181
+ >
182
+ ;
183
+
184
+ $ sign = < {} '+' , {} '-' >;
185
+ sign_plus = {}|'+' $sign;
186
+ sign_minus = {}|'-' $sign;
187
+ get_sign = $int </'+' sign_plus, /'-' sign_minus>;
188
+
189
+ times = ${int x, int y}
190
+ {
191
+ <
192
+ {.x/'+' if, .y /'+' and} sign_plus,
193
+ {.x/'-' if, .y /'-' and} sign_plus,
194
+ sign_minus
195
+ > sign,
196
+ {
197
+ 0 result,
198
+ .x abs inv _x,
199
+ .y abs y
200
+ } _times result
201
+ }
202
+ <
203
+ {.sign/'+' if, .result inv int then} .then,
204
+ {.sign/'-' if, .result inv int swap_sign then} .then
205
+ >
206
+ ;
207
+
208
+ _times =
209
+ ${bits result, bits _x, bits y}
210
+ <
211
+ { .y empty? if, .result then } .then,
212
+ {
213
+ .result 0_ result,
214
+ ._x _x,
215
+ .y /0 y
216
+ } _times,
217
+ {
218
+ {._x x, .result 0_ y, c0 c } _plus result,
219
+ ._x _x,
220
+ .y /1 y
221
+ } _times
222
+ >
223
+ ;
224
+
225
+
226
+ mod =
227
+ ${bits x, bits y}
228
+ _log!
229
+ <
230
+ -- if y > x then (x mod y) = x
231
+ {.y x, .x y} GT .y,
232
+ -- else, i.e.
233
+ -- if x >= y then (x mod y) = ((x-y mod 2y) mod y)
234
+ {
235
+ {
236
+ {.x int x, .y int y} minus /"+" x,
237
+ .y inv 0_ inv y
238
+ } mod x,
239
+ .y y
240
+ } mod
241
+ >
242
+ ;
243
+
244
+
245
+ // gratest common divisor
246
+ gcd = ${bits x, bits y}
247
+ <
248
+ {.y x, .x y} GT,
249
+ ()
250
+ > _gcd
251
+ ;
252
+
253
+ _gcd = <
254
+ { .y /0 if, .x then } .then,
255
+ { .y x, mod y } _gcd
256
+ >;
257
+
258
+
259
+
260
+ // div
261
+
262
+ log2_floor =
263
+ ${bits x, bits step}
264
+ -- finds the largest k, such that 'step * 2^k <= x',
265
+ -- returns k1_, i.e., 0 if x < step, and k1_ otherwise.
266
+ {.x x, .step step, 0 log} log2_floor_;
267
+
268
+ log2_floor_ = <
269
+ {{.step x,.x y} GT if, .log then} .then,
270
+ {.x x, {.step x,0 y} GT {.x x,2 y} {.x int x, .y int y} times abs step, .log int inc abs log} log2_floor_
271
+ >;
272
+
273
+
274
+ x_times_2_to_k =
275
+ ${bits x, bits k}
276
+ {.x inv _x, .k int k} _x_times_2_to_the_power_of_k inv
277
+ ;
278
+
279
+ _x_times_2_to_the_power_of_k = <
280
+ {.k zero_int? if, ._x then} .then,
281
+ {._x 0_ _x, .k dec k} _x_times_2_to_the_power_of_k
282
+ >
283
+ ;
284
+
285
+ div =
286
+ ${int x, int y}
287
+ // remember sign
288
+ {
289
+ <
290
+ { .x/'+' if, .y get_sign then } .then,
291
+ { .x/'-' if, .y swap_sign get_sign then } .then
292
+ > sign,
293
+ {.x abs x, .y abs step, 0 int res} _div res_wo_sign
294
+ }
295
+ <
296
+ {.sign/'+' if, {.res_wo_sign.div div, .res_wo_sign.rem rem} then} .then,
297
+ { .res_wo_sign.div swap_sign div, .res_wo_sign.rem rem }
298
+ >
299
+ ;
300
+
301
+ _div =
302
+ {
303
+ .x x,
304
+ .step step,
305
+ .res res,
306
+ {.x x, .step step} log2_floor log
307
+ }
308
+ <
309
+ { .log int zero_int? if, {.res div, .x rem} then } .then,
310
+ {
311
+ {1 x, .log int dec abs k} x_times_2_to_k factor,
312
+ () i
313
+ }
314
+ {
315
+ {.i.x int x, {.i.step int x, .factor int y} times y} minus abs x,
316
+ .i.step step,
317
+ {.i.res x, .factor int y} plus res
318
+ } _div
319
+ >;
320
+
321
+
322
+ lcm =
323
+ ${bits x, bits y}
324
+ {{.x int x, .y int y} times x, gcd int y} div .div abs
325
+ ;
326
+
327
+ factorial = <
328
+ zero_int? 1 int,
329
+ /"+" int {dec factorial x, () y} times
330
+ >;
331
+
332
+ fib_ =
333
+ <
334
+ { .n int dec /"+" n,
335
+ ."fib(n),fib(n.1)" {plus x, .x y} "fib(n),fib(n.1)"
336
+ } fib_,
337
+ ."fib(n),fib(n.1)"
338
+ >
339
+ ;
340
+
341
+ fib = {$bits n, {1 int x, 0 int y} "fib(n),fib(n.1)"} fib_ .x;
342
+
343
+
344
+ --------------------
345
+ $ rat = { int n, int d };
346
+
347
+ rat = ${bits n, bits d} {.n int n, .d int d } normalize_rat;
348
+
349
+ normalize_rat =
350
+ $rat
351
+ <
352
+ { .d/"-" if,
353
+ {
354
+ .n swap_sign n,
355
+ .d swap_sign d
356
+ } then
357
+ } .then,
358
+ ()
359
+ >
360
+ {() x, {.n abs x,.d abs y} gcd int y}
361
+ {
362
+ {.x.n x,.y y} div .div n,
363
+ {.x.d x,.y y} div .div d
364
+ }
365
+ $rat
366
+ ;
367
+
368
+
369
+ plus_rat =
370
+ ${rat x, rat y}
371
+ {
372
+ .x x,
373
+ .y y,
374
+ {.x.d abs x,.y.d abs y} lcm int lcm
375
+ }
376
+ {
377
+ {
378
+ {.x.n x, {.lcm x, .x.d y} div .div y} times x,
379
+ {.y.n x, {.lcm x, .y.d y} div .div y} times y
380
+ } plus n,
381
+ .lcm d
382
+ }
383
+ normalize_rat
384
+ ;
385
+
386
+
387
+ times_rat =
388
+ ${rat x, rat y}
389
+ {
390
+ {.x.n x,.y.n y} times n,
391
+ {.x.d x,.y.d y} times d
392
+ }
393
+ normalize_rat;
394
+
395
+
396
+ minus_rat =
397
+ ${rat x, rat y}
398
+ {
399
+ .x x,
400
+ .y {.n swap_sign n, .d d} y
401
+ }
402
+ plus_rat;
403
+
404
+ inverse_rat =
405
+ $rat
406
+ { .d n, .n d }
407
+ normalize_rat
408
+ ;
409
+
410
+ div_rat =
411
+ ${rat x, rat y}
412
+ { .x x, .y inverse_rat y} times_rat
413
+ ;
414
+
415
+
416
+ --------------------
417
+
418
+ int_rat =
419
+ $rat
420
+ { .n n, .d d, {.n x,.d y} div div }
421
+ { .div.div int, {.div.rem int n, .d d} rat}
422
+ ${int int, rat rat}
423
+ ;
424
+
425
+ /*
426
+ ratToString =
427
+ -- $rat
428
+ [
429
+ .n toJSON,
430
+ "/",
431
+ .d toJSON,
432
+ " = ",
433
+ normalize_rat
434
+ <
435
+ [.d,.n] GT [.1 toJSON ,"/", .0 toJSON] CONCAT,
436
+ {.n 0,[.d,1] EQ 1} [.0 toJSON] CONCAT,
437
+ int_rat [.int toJSON,"+",.rat.n toJSON,"/",.rat.d toJSON] CONCAT
438
+ >
439
+ ] CONCAT
440
+ -- $@string
441
+ ;
442
+
443
+ _rat! = $rat {
444
+ () carryOn,
445
+ ratToString _log! drop
446
+ } .carryOn;
447
+
448
+
449
+
450
+ */
451
+
452
+ times