trac_lang 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1d150f5cbc3fc4e763b191e4e0fa57c08e3fd318
4
+ data.tar.gz: f655796f68d27b84f26a4e1071255f1a17da15d1
5
+ SHA512:
6
+ metadata.gz: 2384ee6d4f74559e7632b0a3fce3baa89edbb7a1607adb742514596652c52db7563f500a845f9c90899d25c2e7e23c42d327bef23a8507e7b543a2a12f1194e8
7
+ data.tar.gz: 7b77743318ed2925a9bbb1254d9ee2faa02211c81a9ca584ad6c121a4bfc00828dd212be028e88e461cd3706b3858d5cbc296180d817a5b76b0a2cb315dfc0bf
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.14.6
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at TODO: Write your email address. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in trac_lang.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # TracLang
2
+
3
+ An implementation of TRAC Language, written in Ruby.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'trac_lang'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install trac_lang
20
+
21
+ ## Usage
22
+
23
+ Once it's installed, you can run:
24
+
25
+ $ trac_lang
26
+
27
+ from the command line to start the TRAC interpreter. You can also give it a file name of a file with TRAC commands in it to load those commands before you start the interpreter. Try the examples/util.trl file to get a number of useful utilities loaded.
28
+
29
+ TRAC is a macro language, meaning it consists solely of replacing strings of text with other strings. In spite of this simplicity, it is surprisingly powerful, to the point where you can create a version of the Y combinator, as follows:
30
+
31
+ #(DS,Y,(
32
+ #(#(lambda,x,(
33
+ #(f,(#(x,x)))
34
+ )),#(lambda,x,(
35
+ #(f,(#(x,x)))
36
+ )))
37
+ ))
38
+ #(SS,Y,f)
39
+
40
+ You can read about the different TRAC commands available in the examples/README.trl file, or read the original manual by the creator of TRAC, Calvin Mooers:
41
+
42
+ https://web.archive.org/web/20050205173449/http://tracfoundation.org:80/t64tech.htm
43
+
44
+ ## Development
45
+
46
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
47
+
48
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
49
+
50
+ ## Contributing
51
+
52
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/trac_lang. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
53
+
54
+
55
+ ## License
56
+
57
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
58
+
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "rdoc/task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ RDoc::Task.new do |rdoc|
10
+ rdoc.rdoc_files.include('lib/**/*.rb')
11
+ rdoc.rdoc_dir = 'doc'
12
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "trac_lang"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,633 @@
1
+
2
+ TRAC Example Code README
3
+
4
+ #(PS,Loading examples/README.trl...)'
5
+
6
+
7
+ Introduction
8
+ -------------------------------------------------------------------------------
9
+
10
+ TRAC is a macro language, meaning it consists solely of replacing strings of
11
+ text with other strings of text. Despite this seeming simplicity, it's
12
+ capable of very sophisticated programming constructs. TRAC was originally
13
+ created in the sixties by Calvin Mooers and implemented by Peter Deutsch.
14
+ The best introduction to TRAC is to read Mooers original user manual, which
15
+ you can find online on the following page:
16
+
17
+ TRAC T64 Version
18
+ https://web.archive.org/web/20050205173449/http://tracfoundation.org:80/t64tech.htm
19
+
20
+ TRAC was featured in Computer Lib/Dream Machines by Ted Nelson.
21
+
22
+ There's a version of TRAC called MINT which was used to write a version of
23
+ EMACS called FreeMACS. You can find a version of it here:
24
+
25
+ C++ Windows/Linux/MacOS X port of Russell Nelson's FreeMACS:
26
+ https://github.com/msandiford/Freemacs
27
+
28
+ Another macro language that's similar to TRAC is TTM. In the following PDF
29
+ file, a number of applications for a macro language are demonstrated,
30
+ including expression parsing. It's a great introduction to what TRAC can do.
31
+
32
+ TTM: An Experimental Interpretive Language
33
+ https://github.com/Unidata/ttm/raw/master/ttm_interpretive_language_pr_07.pdf
34
+
35
+ There are some other implementations of TRAC.
36
+
37
+ In Python:
38
+
39
+ http://code.activestate.com/recipes/577366-trac-interpreter-sixties-programming-language/
40
+
41
+ https://github.com/natkuhn/Trac-in-Python
42
+
43
+ In Perl:
44
+
45
+ At the RetroComputing Museum, search for "TRAC" on the page:
46
+ http://www.catb.org/retro/
47
+
48
+ In Tcl/Tk:
49
+
50
+ Here someone creates a TRAC-like interpreter in Tcl/Tk:
51
+ http://wiki.tcl.tk/11314
52
+
53
+
54
+
55
+ Using TRAC
56
+ -------------------------------------------------------------------------------
57
+
58
+ Each TRAC command starts with one or two hash characters, and are surrounded
59
+ by parentheses, like so:
60
+
61
+ (
62
+ #(PS,Hello World!)
63
+ #(DS,test,##(RS))
64
+ )
65
+
66
+ The first word after the open parenthesis is the command, while the other
67
+ words after are the arguments. The commands above will print "Hello World!"
68
+ and then set the variable "test" to whatever you type in. A complete list of
69
+ TRAC commands appears later in this file.
70
+
71
+ You can either enter TRAC commands in a file and have the file executed, or
72
+ type them in at the command prompt while in the TRAC interpreter. Either
73
+ way, to let the parser know that you're ready for it to execute the command,
74
+ you must end the command with a single quote, known as the meta character.
75
+ You can see an example of this at the beginning of this file and at the end.
76
+ The meta character should not appear within comments such as this, nor within
77
+ protecting parentheses.
78
+
79
+ TRAC was originally written for a teletype - a computer attached to a
80
+ typewriter. Whatever you typed would be printed on a piece of paper, not a
81
+ screen, so there was no such thing as backspacing over your mistakes. So
82
+ working at the prompt is going to be different from what you're used to. The
83
+ "\" character will tell TRAC to ignore the last character you typed and the
84
+ "@" character will tell TRAC to ignore everything you've typed. So if you
85
+ type the following:
86
+ (
87
+ #,\(,@#(O\Ps\S,Hello)
88
+ )
89
+ the TRAC interpreter will see this:
90
+ (
91
+ #(PS,Hello)
92
+ )
93
+ Also, the enter key will not make a command be executed. Instead the meta
94
+ character will, as explained above. So the following is valid TRAC, and
95
+ will print two new lines:
96
+ (
97
+ #(PS,(
98
+
99
+ ))
100
+ )
101
+
102
+ As you can see from this file, text can be mixed freely in TRAC code files,
103
+ and will be ignored. If you want some code to be ignored, just protect it
104
+ with parentheses, like so:
105
+ (
106
+ #(PS,This will not be printed)
107
+ )
108
+
109
+ TRAC does not do a lot of error checking. If you give it a command it
110
+ doesn't recognize, it will ignore it. You can take advantage of this by
111
+ using the empty command to create comments in scripts:
112
+
113
+ #(, This will also not be executed)'
114
+
115
+ Although the command above is executed, since it doesn't exist as a valid
116
+ command it will be replaced by the empty string when it's processed.
117
+
118
+ There are three syntactic groupings in TRAC:
119
+
120
+ * Active Command
121
+ . Starts with single hash character, delimited by matching parentheses
122
+ . Result is result of TRAC or user defined command
123
+ . Result is rescanned for more commands
124
+ * Neutral Command
125
+ . Starts with two hash characters, delimited by matching parentheses
126
+ . Result is result of TRAC command
127
+ . Result is not scanned again
128
+ * Protected Parentheses
129
+ . Delimited by matching parentheses
130
+ . Result is text between parentheses
131
+ . Result is not scanned again
132
+
133
+ There's one last concept about TRAC that needs to be reviewed. When the TRAC
134
+ command DS gives a name to a string, that defined string is called a form.
135
+ Each form has a form pointer, that points to a character in the string.
136
+ Different commands will return what the form pointer is pointing to and then
137
+ increment the form pointer. What is returned and how the form pointer is
138
+ incremented depends on which command is called.
139
+
140
+ Coding Conventions
141
+ -------------------------------------------------------------------------------
142
+
143
+ Carriage returns and line feeds are ignored in TRAC commands unless they're
144
+ protected by parentheses, so commands can have any number of newlines to make
145
+ them more readable. However, spaces and tabs are not ignored, and commands
146
+ are harder to understand if there's no indentation. So, I've written a
147
+ "scrub" script that removes spaces and tabs from forms as well, in the
148
+ examples/util.trl file.
149
+
150
+ In the example code, I've used two spaces for indentation, and started a new
151
+ line for the following:
152
+
153
+ * definitions
154
+ * sequential commands
155
+ * results of tests
156
+
157
+ You can see all of this in the following defintions, which create a script to
158
+ reverse a string.
159
+
160
+ (
161
+
162
+ #(DS,[reverse],( #(, <== define helper script )
163
+ #(EQ,##(CC,<a>,--),--,( #(, <== at end of string? )
164
+ ##(CL,str) #(, <== if so, return answer )
165
+ ),( #(, <== otherwise )
166
+ #(,##(CN,<a>,-1)) #(, <== read prev char, discard )
167
+ #(DS,str,##(CC,<a>)##(CL,str)) #(, <== add last char read )
168
+ #([reverse],<a>) #(, <== call recursively )
169
+ ))
170
+ ))
171
+ #(sss,[reverse],<a>)
172
+
173
+ #(DS,reverse,(#(DS,str,)#([reverse],<a>)))
174
+ #(SS,reverse,<a>)'
175
+
176
+ )
177
+
178
+ In most of my definitions, I've delimited arguments to forms with angle
179
+ brackets. This is not a requirement - TRAC allows you to enter any string
180
+ whatsoever. I used the angle brackets because they stand out and they also
181
+ make the parameter names unique. Look at the following example.
182
+
183
+ (
184
+ #(DS,diff,(#(abs,#(SU,a,b))))
185
+ #(SS,diff,a,b)
186
+ )
187
+
188
+ Because there aren't angle brackets around a and b, the a and b of abs have
189
+ also been made into segment gaps, and we have:
190
+
191
+ (
192
+ #(diff,2,3) => #(23s,#(SU,2,3))
193
+ )
194
+
195
+ TRAC, being error averse, simply returns the empty string from the
196
+ non-existent form 23s.
197
+
198
+ Although TRAC allows you to use any character for anything, I've avoided
199
+ using symbols for operations I've defined. Letters are much easier to type
200
+ than symbols, so for instance, I have:
201
+
202
+ mod for modulo instead of %
203
+ abs for absolute value instead of |.|
204
+ times for repeated action instead of *
205
+
206
+ However, if you prefer symbols instead of names, it would be easy enough for
207
+ you to make a file of synonyms for operations if you want.
208
+
209
+
210
+ TRAC Commands
211
+ -------------------------------------------------------------------------------
212
+
213
+ Each command takes some action and then returns a string as a result.
214
+
215
+ Basic Commands
216
+ --------------
217
+
218
+ DS Define String ( #(DS,name,value) )
219
+ Result: Empty string
220
+
221
+ Defines a string, giving it a name and storing it in form storage.
222
+ Strings that have been given names are called "forms". Strings that have
223
+ TRAC commands in them are called "scripts".
224
+
225
+ When you define a script, remember to protect its definition with
226
+ parentheses or you will end up running the script before it's named.
227
+ (
228
+ #(DS,value,#(AD,a,5))
229
+ #(DS,value2,(#(AD,a,5)))
230
+ )
231
+ Above "value" has been set to 5, since strings without numeric characters
232
+ in them are considered equal to zero. The "value2" on the other hand, has
233
+ been set to( #(AD,a,5) )so later, if we put in a value for "a", it will be
234
+ able to calculate something.
235
+
236
+ SS Segment String ( #(SS,name,arg1,arg2,...) ) Result: empty string
237
+ Result: Empty string
238
+
239
+ Break a defined string into segments, using the given arguments. Each
240
+ argument is searched for in turn, and if found in the named string, a
241
+ numbered hole is punched in the string where the argument was found. The
242
+ parts of the string between the holes are called segments, and the holes
243
+ themselves are called segment gaps. Using the defintions from above:
244
+ (
245
+ #(DS,value2,(#(AD,a,5)))
246
+ #(SS,value2,a)
247
+ )
248
+ Now the form value2 has a hole where the "a" was, which can be filled with
249
+ whatever we want when we call it using the next command.
250
+
251
+ CL Call ( #(CL,name,arg1,arg2,...) )
252
+ Result: Value of form with gaps replaced by given arguments
253
+
254
+ Retrieve a form, replacing any segments gaps in it with the arguments
255
+ provided. Taking the commands from above as before:
256
+ (
257
+ #(DS,value2,(#(AD,a,5)))
258
+ #(SS,value2,a)
259
+ #(CL,value2,5) ==> result 10
260
+ #(CL,value2,121) ==> result 126
261
+ #(CL,value2,#(ML,2,7)) ==> result 70
262
+ #(CL,value2) ==> result 5 (gap replaced by empty string
263
+ which has a value of zero)
264
+ )
265
+ Also, we can call this command neutrally to see what the value of a form
266
+ is.
267
+ (
268
+ ##(CL,value2,--arg1--) ==> result( #(AD,--arg1--,5) )
269
+ )
270
+
271
+ HL Halt ( #(HL) )
272
+ Result: Empty string
273
+
274
+ Stop the TRAC processor.
275
+
276
+
277
+ Console I/O
278
+ -----------
279
+
280
+ PS Print String ( #(PS,value) )
281
+ Result: Empty string
282
+
283
+ Prints the given value to the console. Unless the value is protected by
284
+ parentheses, any carriage return or linefeed character in it will be
285
+ stripped. All other control characters can appear in the value however,
286
+ including ANSI escape codes for controlling the terminal.
287
+
288
+ RC Read Character ( #(RC) )
289
+ Result: Character read
290
+
291
+ Read a single character from the keyboard. Any character can be entered
292
+ this way, include parentheses, the meta character and the two editing
293
+ characters.
294
+
295
+ RS Read String ( #(RS) )
296
+ Result: Value read
297
+
298
+ Read a string from the keyboard, up until the meta character is pressed.
299
+ The string may have any character you can type at the keyboard, with the
300
+ following exceptions:
301
+
302
+ Edit character \ erases previous character from string
303
+ Edit character @ erases entire entered string
304
+ Meta character ends input
305
+
306
+ The meta character is normally set to single quote but you can change it
307
+ to another character using the following command.
308
+
309
+ CM Change Meta ( #(CM) )
310
+ Result: Empty string
311
+
312
+ Change the meta character to a different character. Once it's changed all
313
+ input will use the new meta character until you call this command with a
314
+ different value. You can even change the meta character to the enter key
315
+ if you wish.
316
+
317
+ Form Reading
318
+ ------------
319
+
320
+ CC Call Character ( #(CC,name,eos) )
321
+ Result: Next character of form or eos value if at end of string
322
+
323
+ Returns the next character of the form and increments the form pointer by
324
+ one. If the form pointer is at the end of the string, the eos value is
325
+ returned. This is used to read a form character by character.
326
+
327
+ CN Call N Characters ( #(CN,name,n,eos) )
328
+ Result: Next n characters of form or eos value if at end of string
329
+
330
+ Returns "n" characters from the string and increments the form pointer by
331
+ the same amount. The "n" can be positive or negative. When "n" is
332
+ negative the characters read are still returned in the orginal order they
333
+ are in the string. If "n" is positive and the form pointer is at the end
334
+ of the string, or "n" is negative and the form pointer is at the beginning
335
+ of the string, the eos parameter is returned.
336
+
337
+ This can be called to check if the form pointer is at the beginning or end
338
+ of the string without moving the pointer by using -0 or 0 as the number of
339
+ characters respectively. For example:
340
+ (
341
+ #(CN,string,-0,begin) <= returns "begin" if you're at the beginning of
342
+ the form, and an empty string otherwise
343
+ #(CN,string,0,end) <= returns "end" if you're at the end of the form
344
+ and an empty string otherwise
345
+ )
346
+
347
+ CS Call Segment ( #(CS,name,eos) )
348
+ Result: Next segment of form or eos value if at end of string
349
+
350
+ When you punch holes in a form with the SS command, text between the holes
351
+ is called a segment. This command calls up each segment in turn, and then
352
+ returns the eos argument when the form pointer is at the end of the form.
353
+ For example:
354
+ (
355
+ #(DS,list,2;5;13;7;12)
356
+ #(SS,list,;) <= each number is now in an individual segment
357
+ #(CS,list) <= "2"
358
+ #(CS,list) <= "5"
359
+ #(CL,list,/) <= "13/7/12"
360
+ )
361
+ A gotcha to watch out for - if a segment gap starts the form, an empty
362
+ string will be returned for the first call. For example:
363
+ (
364
+ #(DS,name,<first> <middle-init>. <last>)
365
+ #(SS,name,<first>,<middle-init>,<last>)
366
+ #(CS,name) <= empty string
367
+ #(CS,name) <= single space
368
+ #(CS,name) <= ". "
369
+ #(CL,name,Smith) <= last segment gap is numbered three and
370
+ no third argument was given, so empty
371
+ string is returned
372
+ )
373
+
374
+ IN In String ( #(IN,name,value,eos) )
375
+ Result: String preceeding found value or eos value if at end of string
376
+
377
+ The IN command searches for a string in the given form starting at the
378
+ form pointer. If the value is found, this command returns everything
379
+ between the form pointer and the found string, and then the form pointer
380
+ is moved beyond the found string. If the value is not found, the eos
381
+ value is returned and the form pointer is unchanged.
382
+
383
+ This command can also be used to test if a form with a given name exists.
384
+ Let value be the empty string, something that will never be found in an
385
+ existing form.
386
+ (
387
+ #(IN,x123,,exists)
388
+ If a form with the name x123 exists, "exists" will be returned.
389
+ Otherwise the empty string will be returned since the form doesn't
390
+ exist.
391
+ )
392
+
393
+ CR Call Return ( #(CR,name) )
394
+ Result: Empty string
395
+
396
+ This command moves the form pointer back to the start of the form. There
397
+ is no corresponding command that moves the pointer to the end of the form.
398
+
399
+
400
+ Form Storage
401
+ ------------
402
+
403
+ LN List Names ( #(LN,delimiter) )
404
+ Result: List of form names delimited by given delimiter
405
+
406
+ This command lists the names of all defined forms using the given
407
+ delimiter. Two examples, using space and newline as delimiters:
408
+ (
409
+ #(LN, )scrub count times backslash space return tab escape ...
410
+ #(LN,(
411
+ ))
412
+ scrub
413
+ count
414
+ times
415
+ ...
416
+ )
417
+
418
+ DD Delete Definition ( #(DD,name1,name2,...) )
419
+ Result: Empty string
420
+
421
+ Deletes the named definitions. If one of the names doesn't correspond to
422
+ an existing definition, it's ignored.
423
+
424
+ DA Delete All ( #(DA) )
425
+ Result: Empty string
426
+
427
+ Delete all defined forms.
428
+
429
+ SB Store Block ( #(SB,block-name,form-name1,form-name2,...) )
430
+ Result: Empty string
431
+
432
+ Saves the given forms in a file with the given name and an extension of
433
+ .trl in the default save directory. The file format will be a text file
434
+ with TRAC commands in it for defining, segmenting and possibly moving the
435
+ form pointer of the given forms. The listed forms will be removed from
436
+ the list of definitions, and a new form will be created, with the same
437
+ name as the block name. This form will be used in the following command.
438
+
439
+ FB Fetch Block ( #(FB,block-name) )
440
+ Result: Empty string
441
+
442
+ Reads the file defined by the given form and loads all TRAC commands in
443
+ that file. The file can either have been created by the SB command above
444
+ or created by hand using an editor.
445
+
446
+
447
+ Integer Mathematics
448
+ -------------------
449
+
450
+ Numbers in TRAC are just strings; they are just read in a special way. Any
451
+ leading non-numeric characters are ignored, so numbers can have descriptive
452
+ prefixes, like "apples5" or "salary-john:150000". Numbers have an optional
453
+ sign, and then a string of digits. A string without any digits in it is
454
+ intepreted as a zero.
455
+
456
+ AD Add ( #(AD,n1,n2) )
457
+ Result: Sum of n1 and n2
458
+
459
+ Add two numbers. The prefix for n1 will be copied to the result.
460
+
461
+ SU Subtract ( #(SU,n1,n2) )
462
+ Result: Difference of n1 and n2
463
+
464
+ Subtract two numbers. The prefix for n1 will be copied to the result.
465
+
466
+ ML Multiply ( #(ML,n1,n2) )
467
+ Result: Product of n1 and n2
468
+
469
+ Multiply two numbers. The prefix for n1 will be copied to the result.
470
+
471
+ DV Divide ( #(DV,n1,n2,z) )
472
+ Result: Quotient of n1 and n2, or z if n2 is zero
473
+
474
+ Divide n2 into n1. TRAC truncates down, so for instance, -7 / 3 is -3.
475
+ If n2 is zero, the z parameter is returned.
476
+
477
+
478
+ Octal Mathematics
479
+ -----------------
480
+
481
+ Bit operations are done on octal numbers in TRAC. Unlike integers, octal
482
+ numbers do not carry a non-numeric prefix. TRAC also does not have a word
483
+ size defined, so octal numbers can be of arbitrary length. This means the
484
+ shift and rotate commands will work with the bits you have given them,
485
+ instead of working within a fixed word size.
486
+
487
+ BU Bit Union ( #(BU,o1,o2) )
488
+ Result: Bitwise OR of two octal numbers.
489
+
490
+ BI Bit Intersection ( #(BI,o1,o2) )
491
+ Result: Bitwise AND of two octal numbers.
492
+
493
+ BC Bit Complement ( #(BC,o1) )
494
+ Result: Bitwise complement of octal number.
495
+
496
+ BS Bit Shift ( #(BS,o1,n1) )
497
+ Result: Bit shift of octal number by the decimal number given.
498
+
499
+ BR Bit Rotate ( #(BR,o1,n1) )
500
+ Result: Bit rotation of octal number by the decimal number given.
501
+
502
+
503
+ Debugging
504
+ ---------
505
+
506
+ PF Print Form ( #(PF,name) )
507
+ Result: Empty string
508
+
509
+ Print the value of a form, with indicators to show where the form pointer
510
+ is and where the segment gaps are. For example:
511
+ (
512
+ #(DS,form,abcdefghijklmnop)
513
+ #(SS,form,c,f,j)
514
+ #(CS,form) ==> ab
515
+ #(CS,form) ==> de
516
+ #(CC,form) ==> g
517
+ #(PF,form) ==> ab<1>de<2>g<^>hi<3>klmnop
518
+ )
519
+
520
+ TN Trace On ( #(TN) )
521
+ Result: Empty string
522
+
523
+ Turns trace on. When trace is on, every time TRAC is ready to execute a
524
+ string, it will display it first, and wait for your response. The string
525
+ will be displayed in a special form, delimited by slashes instead of
526
+ parentheses and with asterisks separating arguments instead of commas. If
527
+ you want to execute the command, press enter, and the next command will be
528
+ displayed to you. If you want to quit, press any other key and the TRAC
529
+ processor will be cleared and the idle string will be reloaded. The idle
530
+ string is the following TRAC command:
531
+ (
532
+ #(PS,#(RS))
533
+ )
534
+ This reads a string, executes it, and prints the result. This is loaded
535
+ on startup, whenever a serious error occurs, and when you exit from trace.
536
+
537
+ TF Trace Off ( #(TF) )
538
+ Result: Empty string
539
+
540
+ Turn tracing off. You can debug certain sections of code by surrounding
541
+ it with a trace on and trace off command.
542
+
543
+
544
+ Example Files
545
+ -------------------------------------------------------------------------------
546
+
547
+ README.trl This file
548
+ util.trl Basic utilities for TRAC, including scrub which is needed for
549
+ the rest of the files
550
+ term.trl Terminal control with ANSI escape codes
551
+ math.trl Definition of some basic mathematical functions
552
+ ratio.trl Rational numbers defined in TRAC
553
+ meta.trl Meta-programming including combinators
554
+ list.trl List commands written in TRAC
555
+ golf.trl A few code golf attempts
556
+
557
+
558
+ Things To Watch Out For
559
+ -------------------------------------------------------------------------------
560
+
561
+ Active Call .vs. Neutral Call
562
+
563
+ The result of an active call is rescanned for TRAC commands while the result
564
+ of a neutral call is not. But you need to remember, you can only call a TRAC
565
+ mnemonic command neutrally. User defined commands are always active. So in
566
+ the following:
567
+
568
+ (
569
+ ##(mycmd,1,2,3)
570
+ ##(CL,mycmd,1,2,3)
571
+ )
572
+
573
+ only the second call is a neutral call. The result of the first one is
574
+ rescanned, despite the double hash marks in front of it.
575
+
576
+
577
+ Unprotected Whitespace
578
+
579
+ Newlines and linefeeds are ignored if they are unprotected. This is great
580
+ for the average script, but when you're trying to create a form with newlines
581
+ in it, it can be frustrating. Just remember to protect any newlines you want
582
+ to keep with parentheses. Also, if you use any of my scrub scripts defined
583
+ in examples/util.trl, remember to use (##(CL,space)) instead of a literal
584
+ space when you actually want to use a space character.
585
+
586
+
587
+ CL And The Form Pointer
588
+
589
+ The CL command only returns the part of the form that is past the form
590
+ pointer. So if you ever use one of the form call commands (CC,CN,CS,IN) on a
591
+ script, CL is not going to return what you expect.
592
+ (
593
+ #(DS,diff,(#(GR,a,b,(#(SU,a,b)),(#(SU,b,a)))))
594
+ #(SS,diff,a,b)
595
+
596
+ Find out if script uses "GR"
597
+
598
+ #(EQ,#(IN,diff,GR,-END-),-END-,not-used,used)
599
+
600
+ If we call it now, we get:
601
+
602
+ #(diff,5,2) ==> ,5,2,(#(SU,5,2)),(#(SU,2,5)) (plus another paren)
603
+
604
+ which is more than likely going to cause an error.
605
+ )
606
+
607
+ EQ .vs. GR
608
+
609
+ EQ is for comparing strings, while GR is for comparing numbers. This can
610
+ lead to some confusing results:
611
+
612
+ (
613
+ #(EQ,0,,true,false) => false
614
+
615
+ Even though the empty string is zero numerically, here it's being
616
+ compared as a string, and so it not equal to 0. To find if two numbers
617
+ are equal, you must verify that neither is greater than the other. In
618
+ the examples/math.trl file I define a script called eqn which tests
619
+ numeric equality this way. This will usually not cause problems if you
620
+ don't use prefixes on numbers, but the above can catch you if you're not
621
+ careful.
622
+
623
+ #(GR,b,a,true,false) => false
624
+
625
+ Both "a" and "b" are considered zero numerically, so neither is greater
626
+ than the other, so this will return false no matter which character is
627
+ first. TRAC actually doesn't have any provision for comparing strings
628
+ lexically.
629
+ )
630
+
631
+
632
+ #(PS,(success!
633
+ ))'