trac_lang 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/examples/golf.trl ADDED
@@ -0,0 +1,113 @@
1
+
2
+ Code Golf
3
+
4
+ #(PS,Loading examples/golf.trl...)'
5
+
6
+ TRAC is never going to win a Code Golf competition. It's lack of primitives
7
+ makes it difficult to do anything under a hundred characters. However, trying
8
+ to figure out how to write certain things in TRAC does help you learn the ins
9
+ and outs of the language. Below are a few of my attempts at some of the Code
10
+ Golf challenges.
11
+
12
+ -------------------------------------------------------------------------------
13
+ The Curious Case of Steve Ballmer - 158 characters
14
+
15
+ #(DS,x,Steve Ballmer still does not know;what he did;wrong;with mobile)#(SS,x,;)#(DS,,(#(PS,(a.
16
+ ))#(EQ,b,.,,(#(,a b,#(CS,x,.))))))#(SS,,a,b)#(,#(CS,x),#(CS,x))'
17
+
18
+ Ungolfed Version:
19
+
20
+ (
21
+ #(DS,sentence,Steve Ballmer still does not know;what he did;wrong;with mobile)
22
+ #(SS,sentence,;)
23
+ #(DS,print-phrase,
24
+ (#(PS,(<phrase>.
25
+ ))#(EQ,<next-phrase>,*END*,,(
26
+ #(print-phrase,<phrase> <next-phrase>,#(CS,sentence,*END*)))
27
+ )))
28
+ #(SS,print-phrase,<phrase>,<next-phrase>)
29
+ #(print-phrase,#(CS,sentence),#(CS,sentence))
30
+ )
31
+
32
+ -------------------------------------------------------------------------------
33
+ Am I A Secondary Taxi? - 219 characters
34
+
35
+ #(DS,3,(#(ML,n,#(ML,n,n))))#(SS,3,n)#(DS,,(#(EQ,#(AD,#(3,i),#(3,j)),n,(#(DS,+,#(AD,1,#(+)))))))#(SS,,n,i,j)#(DS,x,(#(,n,i,j)#(EQ,j,n,(#(GR,#(+),1,T,F)),(#(EQ,i,n,(#(,n,1,#(AD,1,j))),(#(,n,#(AD,1,i),j)))))))#(SS,x,n,i,j)'
36
+
37
+ Ungolfed version:
38
+
39
+ (
40
+ #(DS,cube,
41
+ (#(ML,<n>,#(ML,<n>,<n>))))
42
+ #(SS,cube,<n>)
43
+
44
+ #(DS,test,
45
+ (#(EQ,<n>,#(AD,#(cube,<i>),#(cube,<j>)),
46
+ (#(DS,total,#(AD,1,#(total)))))))
47
+ #(SS,test,n,i,j)
48
+
49
+ #(DS,taxi,
50
+ (#(test,<n>,<i>,<j>)
51
+ #(EQ,<j>,<n>,
52
+ (#(GR,#(total),1,T,F)),
53
+ (#(EQ,<i>,<n>,
54
+ (#(test,<n>,1,#(AD,1,<j>))),
55
+ (#(test,<n>,#(AD,1,<i>),<j>)))))))
56
+ #(SS,taxi,<n>,<i>,<j>)
57
+ )
58
+
59
+ -------------------------------------------------------------------------------
60
+ Unique Is Cheap - 99 characters
61
+
62
+ Assume string to test is contained in form s:
63
+
64
+ #(DS,$,(#(EQ,c,**,+,(#(DS,c,#(AD,1,#(c)))#($,#(CC,s,**),#(AD,+,#(c)))))))#(SS,$,c,+)#($,#(CC,s,**))'
65
+
66
+ Ungolfed version:
67
+
68
+ Assume string to test is contained in form "string":
69
+
70
+ (
71
+ #(DS,cost,
72
+ (#(EQ,<c>,**,<total>,
73
+ (#(DS,<c>,#(AD,1,#(<c>)))
74
+ #(cost,#(CC,string,**),#(AD,<total>,#(<c>)))
75
+ )
76
+ )))
77
+ #(SS,cost,<c>,<total>)
78
+ #(cost,#(CC,string,**))
79
+ )
80
+
81
+ -------------------------------------------------------------------------------
82
+ Fewest (distinct) characters for Turing Completeness - 6 characters
83
+
84
+ hash, open-paren, close-paren, comma, D and S
85
+
86
+ With these six characters, you have the commands DS, SS, and DD.
87
+
88
+ How do you define branching? We can use the fact that when you define a form
89
+ with the same name as an existing form, the existing form is replaced. This
90
+ technique comes from page 19 of Chapter 9 of the Beginner's Manual for TRAC
91
+ Language:
92
+
93
+ https://web.archive.org/web/20050214150205/http://tracfoundation.org:80/trac64/T64manual.htm
94
+ (
95
+ #(DS,DDD,(#(DS,(DDS),(SDD))#(DS,(DSD),(DSS))#((DDS))))
96
+ #(SS,DDD,DDS,DSD,DSS,SDD)
97
+ )
98
+ Ungolfed version:
99
+ (
100
+ #(DS,"eq",
101
+ (#(DS,(a),(F))
102
+ #(DS,(b),(T))
103
+ #((a))
104
+ ))
105
+ #(SS,"eq",a,b,T,F)
106
+ )
107
+
108
+ If a equals b, then the definition of b will overwrite the definition of a, and
109
+ T will be returned. Otherwise, F will be returned.
110
+
111
+
112
+ #(PS,(success!
113
+ ))'
data/examples/list.trl ADDED
@@ -0,0 +1,125 @@
1
+
2
+ List Processing
3
+
4
+ #(PS,Loading examples/list.trl...)'
5
+
6
+ Basics
7
+ ------
8
+
9
+ We need another anonymous form class for creating the links that make up lists.
10
+
11
+ #(anonymous,link)'
12
+
13
+ We define nil as an empty list, containing nothing.
14
+
15
+ #(DS,nil)'
16
+
17
+ Now we can define the list primitives. These are basically the same as used in
18
+ Lisp. Notice that I use the dot special character for delimiting, so that
19
+ lists can contain any data.
20
+
21
+ The cons form has some error checking because it's very easy to forget to put
22
+ in the final nil when you're constructing a list.
23
+
24
+ #(DS,cons,(
25
+ #(EQ,(list),,(
26
+ #(link,#(.),(value)#(.)nil)
27
+ ),(
28
+ #(link,#(.),(value)#(.)(list))
29
+ ))
30
+ ))
31
+ #(sss,cons,(value,list))'
32
+ #(DS,car,(#(CS,list)#(CR,list)))
33
+ #(SS,car,list)'
34
+ #(DS,cdr,(#(CS,list,,#(CS,list))#(CR,list)))
35
+ #(SS,cdr,list)'
36
+
37
+ #(DS,null?,(#(EQ,list,nil,(T),(F))))
38
+ #(SS,null?,list,T,F)'
39
+
40
+ Pair? is just a synonym for link?, the test that checks if the given value is a
41
+ defined link. Atom? is an antonym for link?.
42
+
43
+ #(DS,pair?,(#(link?,item,(T),(F))))
44
+ #(SS,pair?,item,T,F)'
45
+
46
+ #(DS,atom?,(#(link?,item,(F),(T))))
47
+ #(SS,atom?,item,T,F)'
48
+
49
+ List is our synatic sugar for repeated cons'ing.
50
+
51
+ #(DS,list,(
52
+ #(DS,args,(objs))
53
+ #(SS,args,(,))
54
+ #(DS,[list],(
55
+ #(EQ,(value),#(.),nil,(
56
+ #(cons,(value),#([list],##(CS,args,#(.))))
57
+ ))
58
+ ))
59
+ #(SS,[list],value)
60
+ #([list],#(CS,args,#(.)))#(DD,args,[list])
61
+ ))
62
+ #(sss,list,objs)'
63
+
64
+ You use it like this:
65
+ (
66
+ #(list,(1/2,1/3,1/4))
67
+ )
68
+ And it would be nice to be able to display the contents of our lists:
69
+
70
+ #(DS,print-list,(
71
+ #(null?,<list>,nil,(
72
+ #(car,<list>)(,)#(print-list,#(cdr,<list>))
73
+ ))
74
+ ))
75
+ #(sss,print-list,<list>)'
76
+
77
+
78
+ List Functions
79
+ --------------
80
+
81
+ Now with the basics of list handling defined, we can define some functions on
82
+ lists. These definitions are practically the same that you would see in any
83
+ version of Lisp. I got these definitions from section 2.2 of Structure and
84
+ Interpretation of Programs.
85
+
86
+ #(DS,length,(#(null?,list,count,(#(length,#(cdr,list),#(AD,1,count))))))
87
+ #(SS,length,list,count)'
88
+
89
+ #(DS,append,(
90
+ #(null?,list1,list2,(
91
+ #(cons,#(car,list1),#(append,#(cdr,list1),list2))
92
+ ))
93
+ ))
94
+ #(sss,append,(list1,list2))'
95
+
96
+ #(DS,map,(
97
+ #(null?,items,nil,(
98
+ #(cons,#(proc,#(car,items)),#(map,proc,#(cdr,items)))
99
+ ))
100
+ ))
101
+ #(sss,map,(proc,items))'
102
+
103
+ #(DS,accumulate,(
104
+ #(null?,seq,init,(
105
+ #(op,#(car,seq),#(accumulate,op,init,#(cdr,seq)))
106
+ ))
107
+ ))
108
+ #(sss,accumulate,(op,init,seq))'
109
+
110
+ #(DS,interval,(
111
+ #(GR,low,high,nil,(
112
+ #(cons,low,#(interval,#(AD,1,low),high))
113
+ ))
114
+ ))
115
+ #(sss,interval,(low,high))'
116
+
117
+ Here's an example use. Give the decimal expansion of the sum of the first five
118
+ terms of the harmonic series: 1/1, 1/2, 1/3, etc.
119
+ (
120
+ #(DVD,#(argr,#(accumulate,addr,0,#(map,rcpr,#(interval,1,5))))) => 2.283333333
121
+ )
122
+
123
+
124
+ #(PS,(success!
125
+ ))'
data/examples/math.trl ADDED
@@ -0,0 +1,351 @@
1
+
2
+ Mathematics
3
+
4
+ #(PS,Loading examples/math.trl...)'
5
+
6
+
7
+ One of the things you have to be careful with TRAC numbers is the fact that any
8
+ string is a number. If the string doesn't have any numeric characters at the
9
+ end of it, it's considered zero. That means that abc, --0 and the empty string
10
+ are all equal to zero. Because of this property, you can't normally use EQ to
11
+ test numbers.
12
+
13
+
14
+ Negate
15
+ ------
16
+
17
+ Notice I negate a negative number by multiplying by negative one. The order in
18
+ the #(ML) command is important to preserve any prefix the number might have.
19
+
20
+ #(DS,-,(#(ML,n,-1)))
21
+ #(SS,-,n)'
22
+
23
+
24
+ Absolute Value
25
+ --------------
26
+
27
+ Negate if you're less than zero.
28
+
29
+ #(DS,abs,(#(GR,0,n,#(-,n),n)))
30
+ #(SS,abs,n)'
31
+
32
+
33
+ Sign
34
+ ----
35
+
36
+ Determine the sign of the given number. Returns one, zero or negative one
37
+ depending. Because these numbers don't have text prefixes, they can be
38
+ compared with EQ.
39
+
40
+ #(DS,sgn,(
41
+ #(GR,0,n,-1,(
42
+ #(GR,n,0,1,0)
43
+ ))
44
+ ))
45
+ #(sss,sgn,n)'
46
+
47
+
48
+ Sign Case
49
+ ---------
50
+
51
+ This creates a control statement which executes different code depending on
52
+ what sign the given number is. This simplifies some of our later code.
53
+
54
+ #(DS,sgn?,(
55
+ #(GR,<a>,0,(P),(
56
+ #(GR,0,<a>,(N),(Z))
57
+ ))
58
+ ))
59
+ #(sss,sgn?,(<a>,P,Z,N))
60
+
61
+ We use this as follows:
62
+ (
63
+ #(sgn?,#(a),positive!,zero.,negative)
64
+ )
65
+
66
+
67
+ Numeric Equal
68
+ -------------
69
+
70
+ The EQ command in TRAC compares strings, not numbers. To compare numbers you
71
+ need to use the GR command. If neither of two numbers is greater then they
72
+ must be equal. It looks really weird to test if a > b and b > a, but because
73
+ of the short-circuit propery of and, it works.
74
+
75
+ #(DS,eqn,(
76
+ #(and,(GR,a,b),(GR,b,a),(F),(T))
77
+ ))
78
+ #(sss,eqn,(a,b,T,F))'
79
+
80
+
81
+ Modulo
82
+ ------
83
+
84
+ Division in TRAC is floored division, so the modulo always has the same sign
85
+ as the divisor. The "mod+" script calculates the modulo for positive numbers,
86
+ while the "mod" script calculates it for all numbers. If there was a way to
87
+ change the sign of TRAC numbers without using multiplication, then all
88
+ multiplication could be eliminated here.
89
+
90
+ The "Z" parameter is returned when "b" is zero. The "mod+" script does not
91
+ check for a "b" of zero, so will go into an infinite loop if you give it such
92
+ a "b".
93
+
94
+ #(DS,mod+,(
95
+ #(GR,<a>,<b>,(
96
+ #(mod+,#(SU,<a>,<b>),<b>)
97
+ ),(
98
+ #(GR,<b>,<a>,<a>,0)
99
+ ))
100
+ ))
101
+ #(sss,mod+,(<a>,<b>))
102
+
103
+ Check all the combinations of sign "a" and "b" can have, including an "a" or
104
+ "b" of zero. If "a" is zero, just return "a", since anything modulo zero is
105
+ zero. This is consistent with DV so that:
106
+ (
107
+ #(AD,#(ML,b,#(DV,a,b)),#(mod,a,b)) == a
108
+ )
109
+
110
+ #(DS,mod,(
111
+ #(sgn?,<a>,(
112
+ #(sgn?,<b>,(
113
+ #(mod+,<a>,<b>)
114
+ ),(
115
+ Z
116
+ ),(
117
+ #(AD,<b>,#(mod+,<a>,#(abs,<b>)))
118
+ ))
119
+ ),(
120
+ <a>
121
+ ),(
122
+ #(sgn?,<b>,(
123
+ #(SU,<b>,#(mod+,#(abs,<a>),<b>))
124
+ ),(
125
+ Z
126
+ ),(
127
+ #(-,#(mod+,#(abs,<a>),#(abs,<b>),(Z)))
128
+ ))
129
+ ))
130
+ ))
131
+ #(sss,mod,(<a>,<b>,Z))'
132
+
133
+
134
+ Divides
135
+ -------
136
+
137
+ Test if one number divides another. The "Z" parameter is returned if "a" is
138
+ zero.
139
+
140
+ #(DS,div?,(
141
+ #(eqn,0,<a>,(Z),(
142
+ #(eqn,0,(#(mod,<b>,<a>)),(T),(F))
143
+ ))
144
+ ))
145
+ #(sss,div?,(<a>,<b>,T,F,Z))'
146
+
147
+
148
+ Greatest Common Divisor
149
+ -----------------------
150
+
151
+ Standard definition of greatest common divisor. The [gcd] form tests positive
152
+ integers, while the gcd form works for all integers.
153
+
154
+ #(DS,[gcd],(
155
+ #(eqn,<b>,0,<a>,(
156
+ #(gcd,<b>,#(mod,<a>,<b>))
157
+ ))
158
+ ))
159
+ #(sss,[gcd],(<a>,<b>))'
160
+
161
+ #(DS,gcd,(
162
+ #(sgn?,#(SU,<a>,<b>),(
163
+ #([gcd],<a>,<b>)
164
+ ),(
165
+ <a>
166
+ ),(
167
+ #([gcd],<b>,<a>)
168
+ ))
169
+ ))
170
+ #(sss,gcd,(<a>,<b>))'
171
+
172
+
173
+ Ceiling
174
+ -------
175
+
176
+ TRAC division takes the floor of the division. But sometimes you need the
177
+ ceiling. The "Z" parameter is returned if "b" is zero.
178
+
179
+ #(DS,ceil,(
180
+ #(div?,<b>,<a>,(
181
+ #(DV,<a>,<b>)
182
+ ),(
183
+ #(AD,1,#(DV,<a>,<b>))
184
+ ),(
185
+ Z
186
+ ))
187
+ ))
188
+ #(sss,ceil,(<a>,<b>,Z))'
189
+
190
+
191
+ Euclidean Division
192
+ ------------------
193
+
194
+ This division will truncate toward zero, instead of truncating down like normal
195
+ TRAC division does. The Z parameter is returned if b is zero.
196
+
197
+ #(DS,DV0,(
198
+ #(sgn?,<b>,(
199
+ #(sgn?,<a>,(
200
+ #(DV,<a>,<b>)
201
+ ),(
202
+ <a>
203
+ ),(
204
+ #(-,#(DV,#(-,<a>),<b>))
205
+ ))
206
+ ),(
207
+ Z
208
+ ),(
209
+ #(sgn?,<a>,(
210
+ #(-,#(DV,<a>,#(-,<b>)))
211
+ ),(
212
+ <a>
213
+ ),(
214
+ #(DV,#(-,<a>),#(-,<b>))
215
+ ))
216
+ ))
217
+ ))
218
+ #(sss,DV0,(<a>,<b>,Z))'
219
+
220
+
221
+ Euclidean Modulo
222
+ ----------------
223
+
224
+ Here's a modulo compatible with Euclidean division. The Z parameter is
225
+ returned if b is zero.
226
+
227
+ #(DS,mod0,(
228
+ #(SU,<a>,#(ML,<b>,#(DV0,<a>,<b>,(Z))))
229
+ ))
230
+ #(sss,mod0,(<a>,<b>,Z))'
231
+
232
+
233
+ Decimal to Octal
234
+ ----------------
235
+ Recursively convert a decimal number to octal. This will go into an infinite
236
+ loop if you try in on negative numbers. That's because TRAC doesn't have a
237
+ specific word size, so a negative octal number has an infinite number of 7's
238
+ in front of it.
239
+
240
+ #(DS,to_oct,(#(eqn,<dec>,0,,(#(to_oct,#(DV,<dec>,8))#(mod,<dec>,8)))))
241
+ #(SS,to_oct,<dec>)'
242
+
243
+
244
+ Octal to Decimal
245
+ ----------------
246
+ This one is more string-based. Since I can't do numeric calculations with
247
+ octals, I have to read the octal number as a string, character by character,
248
+ and then interpret each character as a number.
249
+
250
+ #(DS,to_dec,(
251
+ #(DS,[octal],<octal>)
252
+ #(DS,[to_dec],(
253
+ #(EQ,<digit>,--,
254
+ (#(DD,[octal],[to_dec])<result>),
255
+ (#([to_dec],##(CC,[octal],--),#(AD,<digit>,#(ML,8,<result>))))
256
+ )
257
+ ))
258
+ #(SS,[to_dec],<digit>,<result>)
259
+ #([to_dec],##(CC,[octal],--))
260
+ ))
261
+ #(sss,to_dec,<octal>)'
262
+
263
+
264
+ Random
265
+ ------
266
+
267
+ Now we can define a random number generator. This is a linear congruential
268
+ generator from Wikipedia, using the Borland C/C++ multiplier.
269
+
270
+ https://en.wikipedia.org/wiki/Linear_congruential_generator
271
+
272
+ Remember to define the seed value to an octal number before you call random the
273
+ first time.
274
+
275
+ #(DS,random,(
276
+ #(DS,seed,
277
+ #(BS,#(to_oct,
278
+ #(AD,1,#(ML,22695477,#(to_dec,#(seed))))
279
+ ),-16)
280
+ )
281
+ #(DS,seed,#(BI,#(seed),177777))
282
+ #(seed)
283
+ ))
284
+ #(scrub,random)'
285
+
286
+ One interesting thing to notice in this definition. The "seed" is a number,
287
+ not a script. So I don't use protecting parentheses around its definition
288
+ because I want the definition calculated immediately. This is different from
289
+ almost every other definition I've written in these files, which is why I
290
+ mention it.
291
+
292
+
293
+ Power
294
+ -----
295
+
296
+ Recursive definition of raising a number to a given power. Negative powers
297
+ will return zero.
298
+
299
+ #(DS,power,(
300
+ #(GR,0,<n>,0,(
301
+ #(GR,<n>,0,(
302
+ #(ML,<base>,#(power,<base>,#(SU,<n>,1)))
303
+ ),1)
304
+ ))
305
+ ))
306
+ #(scrub,power)
307
+ #(SS,power,<base>,<n>)'
308
+
309
+
310
+ Power of Two
311
+ ------------
312
+
313
+ This should be much faster than calling the usual power script.
314
+
315
+ #(DS,power2,(#(to_dec,1#(times,n,0))))
316
+ #(SS,power2,n)'
317
+
318
+
319
+ Power of Ten
320
+ ------------
321
+
322
+ A power of ten is just a one with a bunch of zeros after it.
323
+
324
+ #(DS,power10,(1#(times,n,0)))
325
+ #(SS,power10,n)'
326
+
327
+
328
+ Divide Into Decimal
329
+ -------------------
330
+
331
+ This gives you a decimal expansion of a division. By using the Euclidean
332
+ division defined above, it works with both negative and positive numbers.
333
+
334
+ #(DS,decimal-places,10)'
335
+
336
+ #(DS,[DVD],(
337
+ #(GR,<p>,#(decimal-places),,(
338
+ #(DV,<a>,<b>)
339
+ #([DVD],#(ML,10,#(mod,<a>,<b>)),<b>,#(AD,<p>,1))
340
+ ))
341
+ ))
342
+ #(sss,[DVD],(<a>,<b>,<p>))'
343
+
344
+ #(DS,DVD,(
345
+ #(DV0,<a>,<b>,Z).#([DVD],#(ML,10,#(mod,#(abs,<a>),#(abs,<b>))),#(abs,<b>))
346
+ ))
347
+ #(sss,DVD,(<a>,<b>,Z))'
348
+
349
+
350
+ #(PS,(success!
351
+ ))'