git @ Cat's Eye Technologies Cfluviurrh / 86c94bd
Initial import of Cfluviurrh reference distribution. catseye 12 years ago
6 changed file(s) with 714 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 The Cfluviurrh Programming Language
1 ================================
2
3 _Cfluviurrh_ is believed to be the first programming language for writing
4 programs that can *feel*. Cfluviurrh defines a mechanism by which a program
5 can be instructed to experience particular emotions.
6
7 You might, thus, on first blush, consider Cfluviurrh to be unimplementable,
8 as computers are not capable of experiencing emotions (you guess.)
9
10 However, this is demonstrably untrue. It is simply that, to be correctly
11 implemented, Cfluviurrh must be implemented for a system that we know is
12 capable of experiencing emotions.
13
14 For example, it could be implemented as a contractual obligation for a
15 [method actor][], or similar professional capable of feeling emotions on
16 demand; this individual would be required to read a program text written in
17 Cfluviurrh, and carry out its instructions, feeling the specified emotions
18 at the required points in the program.
19
20 Or, in the approach the reference implementation takes, an electronic
21 computer may co-operate with a contractually obligated individual termed
22 the "emoter". The computer executes all the parts of the program which do
23 not necessitate emotional experience, and prompts the emoter to experience
24 emotions on behalf of the running program when required.
25
26 [method actor]: http://en.wikipedia.org/wiki/Method_acting
27
28 Design
29 ------
30
31 ### Program State ###
32
33 The state of a running Cfluviurrh program consists of an unlimited number of
34 registers, each of which can contain a non-negative integer of unlimited
35 size. (Of course, a particular implementation may impose its own limits
36 here, as we can't expect computers to be infinite [I guess.])
37
38 The registers are indexed by number, starting at zero; the first twenty-six
39 (registers 0 to 25) also have names, `a` through `z`. Initially, every
40 register contains a zero value.
41
42 There is also a special value called the _instruction pointer_ (IP), which
43 indicates which character in the Cfluviurrh program will be executed next.
44 As statements are executed, the IP is advanced to the next statement in the
45 program text (except in the case of a jump, described below.) The IP
46 initially refers to the first character of the program.
47
48 There is also a special value called the _emotion bank number_, which is
49 initially zero. An implementation must implement emotion bank zero,
50 but need not implement any other emotion banks, nor need it implement
51 emotion bank switching. All emotion banks other than zero are undefined
52 and reserved for future use.
53
54 ### Syntax ###
55
56 A statement is either:
57
58 * _whitespace_ (a space, tab, newline, or carriage feed character);
59 nothing happens when this is executed, the IP is simply advanced
60 to the next character.
61 * a _comment_, which begins with `(`; the IP is advanced to one
62 character past the next `)` character in the program, with nothing
63 else happening. Comments do not nest.
64 * a _label_, which is a `:` followed by any printable character
65 (called the _label name_). The IP is advanced to one character past
66 the label name; nothing else happens.
67 * a _register reference_, followed by an operator. A register reference
68 is a lowercase letter from `a` to `z`, which refers to the register
69 with the same name, *or* an uppercase letter from `A` to `Z`, which
70 refers to the register with the index given by the contents of the
71 register with the corresponding lower-case name. (So if register `a`
72 contained the number 4, `A` would refer to register `e`.)
73
74 There are several subcases for the syntax of a statement which begins
75 with a register reference. These are:
76
77 * an _assignment_, which is where the register reference is followed
78 by a `=` character, which is followed by a value. A value can
79 be either a register reference, in which case the value is taken
80 from the register being referred to, or it may be a literal
81 digit from `0` to `9`, in which case it is the value of that
82 digit as an Arabic numeral. Thus, `a=1`, `b=B`, and `R=4` are
83 all valid assignment statements, but `7=a` is not.
84 * a _modifying assignment_, which is where the register reference is
85 followed by one of the characters `+`, `-`, `*`, or `/`, which is
86 followed by a `=` character which is followed by a value. The
87 register being referred to has the value added to it, subtracted
88 from it, is multiplied by the value, or is divided (integer
89 division, rounding down) by the value, respectively, based on the
90 operator character. Thus, `a+=1`, `a*=2`, and `F/=f` are all
91 valid modifying assignments.
92 * a _label location assignment_, which is where the register reference
93 is followed by a `@` character which is followed by a `=` character
94 which is followed by a label name. A label with this label name
95 is sought in the program and, if found, the position of the label
96 in the program text (with 0 being the position of the first character
97 of the program, and with all characters, including whitespace, having
98 sequential positions within the program) is written to the register.
99 If there are multiple labels with the same label name, the one closest
100 to the start of the program text is chosen. If a matching label is
101 not found, "an error occurs", whatever that means exactly.
102 * an _output statement_, which is where the register reference
103 is followed by a `>` character. The ASCII character with the same
104 value as the contents of the register will be written to the program's
105 output stream. If the value of the register is outside of the range
106 0 to 127, "an error occurs".
107 * an _input statement_, which is where the register reference
108 is followed by a `<` character. An ASCII character is retrieved from
109 the program's input stream, and its value is written into the register.
110 * a _jump statement_, which is where the register reference is followed
111 by a `?` character, followed by a _conditional_. A conditional is a
112 value, followed by one of the characters `=`, `>`, or `<`, followed by
113 a value. A conditional, when evaluated during a program run, is either
114 true or false. A conditional has the meaning you would probably
115 expect; `2=2` is true, `4>5` is false, and `A<2` is true if the `a`
116 register contains 4 and the `e` register contains 1. If the
117 conditional is true, the IP is set to the value found in the register
118 referred to by the register reference; otherwise, the IP advances
119 as usual. Either way, an emotion is experienced (see below) every
120 time a jump statement is executed.
121 * an _emotion bank switch statement_, which is where the register
122 reference is followed by a `=` followed by a `>`. The emotion bank
123 is switched to the value in the register. If that emotion bank is
124 not supported by the implementation, "an error occurs".
125
126 Note that whitespace and comments are not allowed inside any statement
127 which begins with a register reference.
128
129 The input stream and output stream are implementation-defined concepts.
130
131 If division by zero is attempted, "an error occurs".
132
133 ### Experiencing Emotions ###
134
135 Whenever a jump statement is executed, an emotion is experienced, at
136 a certain intensity level.
137
138 The emotion being experienced, and the intensity level, depends on the
139 currently active emotion bank. Only emotion bank zero is described here.
140
141 The contents of the first twenty-six registers, at the point in time that
142 the emotion is to be experienced, are summed, modulo 74, to obtain an
143 emotion number. The emotion number refers to the following table; it
144 is consulted to obtain the emotion to be experienced.
145
146 * 0: sadness
147 * 1: sorrow
148 * 2: despair
149 * 3: worry
150 * 4: depression
151 * 5: misery
152 * 6: melancholy
153 * 7: wistfulness
154 * 8: disappointment
155 * 9: regret
156 * 10: longing
157 * 11: impatience
158 * 12: anger
159 * 13: hostility
160 * 14: rage
161 * 15: hatred
162 * 16: disgust
163 * 17: contempt
164 * 18: envy
165 * 19: arrogance
166 * 20: betrayal
167 * 21: hurt
168 * 22: grief
169 * 23: remorse
170 * 24: shame
171 * 25: embarrassment
172 * 26: guilt
173 * 27: timidity
174 * 28: loneliness
175 * 29: annoyance
176 * 30: frustration
177 * 31: confusion
178 * 32: shock
179 * 33: angst
180 * 34: anguish
181 * 35: anxiety
182 * 36: apathy
183 * 37: vindication
184 * 38: gratitude
185 * 39: hope
186 * 40: awe
187 * 41: wonder
188 * 42: surprise
189 * 43: pity
190 * 44: boredom
191 * 45: apprehension
192 * 46: distrust
193 * 47: dread
194 * 48: horror
195 * 49: loathing
196 * 50: terror
197 * 51: panic
198 * 52: hysteria
199 * 53: pride
200 * 54: anticipation
201 * 55: curiosity
202 * 56: boldness
203 * 57: excitement
204 * 58: thrill
205 * 59: zeal
206 * 60: enthusiasm
207 * 61: calmness
208 * 62: contentment
209 * 63: satisfaction
210 * 64: happiness
211 * 65: bliss
212 * 66: joy
213 * 67: ecstasy
214 * 68: euphoria
215 * 69: admiration
216 * 70: desire
217 * 71: passion
218 * 72: love
219 * 73: lust
220
221 (While some of the above may not be emotions per se, and while some
222 combinations, such as "faint zeal", "mild rage", and "extreme apathy" may be
223 tricky to express, this does not detract from the bare fact that Cfluviurrh
224 *does* support experiencing emotions.)
225
226 There are five intensity levels, listed in the following table. To find the
227 intensity level of an emotion to be experienced, each of the first twenty-six
228 registers are multiplied by three, modulo five, and this set of values is
229 summed, modulo five.
230
231 * 0: faint
232 * 1: mild
233 * 2: moderate
234 * 3: marked
235 * 4: extreme
236
237 Discussion
238 ----------
239
240 Because every label name can only be a single printable character, it might
241 appear that the number of jump destinations in a program is limited to 95.
242
243 This is not true, as labels are only a convenience. You can load any value
244 you like into a register, then jump to that position in the program text.
245
246 In fact, there is nothing stopping you from jumping inside a comment, with
247 a label or otherwise. In fact, from this perspective, comments could be
248 somewhat valuable control flow structures; consider
249
250 ... (:A ... (:B ... () ...
251
252 Execution coming in from the left will skip this "block"; execution coming
253 in at the `:A` label will skip the "inner block", and execution coming in
254 at `:B` will only execute the "inner block".
255
256 Happy Cfluviurrhing! (Or sad Cfluviurrhing, or timid Cfluviurrhing, or...)
257 Chris Pressey
258 Winnipeg, Manitoba
259 August 26, 2012
0 a=8
1 a*=8
2 b=a
3 b+=a
4 b-=2
5
6 :X
7 a+=1
8 a>
9
10 z@=X
11 z?a<b
0 (
1 This is the syntax for switching the emotion bank; however, implementations
2 are not expected to support this, and indeed, no emotion banks besides bank
3 zero are currently defined. So this is mostly to test that an
4 implementation considers this an error.
5 )
6
7 d=1
8 d=>
0 ("Hello, world!", or as much of it as I can stand writing, in Cfluviurrh.)
1
2 b=8
3 b*=8
4 b+=8
5
6 d=2
7 d*=5 e=d
8 d*=5
9 d*=2
10 d+=8
11
12 c=d
13 c-=7
14
15 a=1
16 A>
17 a+=1
18 A>
19 a+=1
20 A>
21 A>
22 a+=1
23 A>
0 # GNU Makefile for cfluviurrh.
1
2 PROG=cfluviurrh
3 CC?=gcc
4
5 WARNS= -W -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
6 -Wpointer-arith -Wno-uninitialized -Wreturn-type -Wcast-qual \
7 -Wwrite-strings -Wswitch -Wcast-align -Wchar-subscripts \
8 -Wshadow -Winline -Wnested-externs -Wredundant-decls
9
10 ifdef ANSI
11 CFLAGS+= -ansi -pedantic
12 else
13 CFLAGS+= -std=c99 -D_POSIX_C_SOURCE=200112L
14 endif
15
16 CFLAGS+= ${WARNS} ${EXTRA_CFLAGS}
17
18 ifdef DEBUG
19 CFLAGS+= -g
20 endif
21
22 all: $(PROG)
23
24 $(PROG): $(PROG).c
25 $(CC) $(CFLAGS) $(PROG).c -o $(PROG)
26
27 clean:
28 rm -f *.o *.core *.exe $(PROG)
0 #include <stdio.h>
1 #include <stdlib.h>
2 #include <string.h>
3
4 /*
5 * Note that these are arbitrarily limited in this implementation --
6 * the language itself does not impose limited on the number of
7 * size of registers, or size of the program.
8 */
9 #define MEMTYPE int
10 #define MEMSIZE 8000
11 #define PROGSIZE 8000
12
13 MEMTYPE mem[MEMSIZE];
14 char program[PROGSIZE];
15
16 /*
17 * Prototypes
18 */
19 void die(const char *, char);
20 MEMTYPE get_ref(char);
21 MEMTYPE get_val(char);
22 void advance_ip(const char **);
23 int is_whitespace(char);
24 int is_op(char);
25 MEMTYPE do_op(char, MEMTYPE, MEMTYPE);
26 MEMTYPE find_label(const char *, char);
27 void load_program(const char *);
28 void emote(MEMTYPE, MEMTYPE);
29 void contractually_obligate_emoter(void);
30
31 /*
32 * Subroutines
33 */
34 void
35 die(const char *msg, char c)
36 {
37 fputs(msg, stderr);
38 if (c != '\0') {
39 fputs(": '", stderr);
40 fputc(c, stderr);
41 fputs("'", stderr);
42 }
43 fputs("\n", stderr);
44 exit(1);
45 }
46
47 MEMTYPE
48 get_ref(char c)
49 {
50 if (c >= 'a' && c <= 'z') {
51 return (MEMTYPE)(c - 'a');
52 } else if (c >= 'A' && c <= 'Z') {
53 return mem[(MEMTYPE)(c - 'A')];
54 } else {
55 return -1;
56 }
57 }
58
59 MEMTYPE
60 get_val(char c)
61 {
62 int ref;
63
64 if (c >= '0' && c <= '9') {
65 return (MEMTYPE)(c - '0');
66 }
67 ref = get_ref(c);
68 if (ref < 0 || ref >= MEMSIZE) {
69 die("invalid register reference", c);
70 }
71 return mem[ref];
72 }
73
74 void
75 advance_ip(const char **c)
76 {
77 (*c)++;
78 if (**c == '\0') {
79 die("premature end of program", (char)0);
80 }
81 }
82
83 int
84 is_whitespace(char c)
85 {
86 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
87 }
88
89 int
90 is_op(char c)
91 {
92 return c == '+' || c == '-' || c == '*' || c == '/' || c == '@';
93 }
94
95 MEMTYPE
96 do_op(char op, MEMTYPE lhs, MEMTYPE rhs)
97 {
98 if (op == ' ') {
99 return rhs;
100 } else if (op == '+') {
101 return lhs + rhs;
102 } else if (op == '-') {
103 return lhs - rhs;
104 } else if (op == '*') {
105 return lhs * rhs;
106 } else if (op == '/') {
107 return lhs / rhs;
108 } else {
109 return lhs;
110 }
111 }
112
113 MEMTYPE
114 find_label(const char *s, char label)
115 {
116 int i;
117
118 for (i = 0; s[i] != '\0'; i++) {
119 if (s[i] == ':' && s[i+1] == label) {
120 return i;
121 }
122 }
123 return -1;
124 }
125
126 void
127 load_program(const char *filename) {
128 FILE *in;
129 int i, c;
130
131 if ((in = fopen(filename, "r")) == NULL) {
132 perror("Can't open program file for reading");
133 exit(1);
134 }
135 for (i = 0; i < (PROGSIZE-1) ; i++) {
136 c = fgetc(in);
137 if (c == EOF) {
138 break;
139 }
140 program[i] = (char)c;
141 }
142 program[++i] = '\0';
143 fclose(in);
144 }
145
146 /*
147 * Emoting Subsystem
148 */
149 #define EMOTIONSIZE 74
150 const char *emotion[] = {
151 "sadness",
152 "sorrow",
153 "despair",
154 "worry",
155 "depression",
156 "misery",
157 "melancholy",
158 "wistfulness",
159 "disappointment",
160 "regret",
161 "longing",
162 "impatience",
163 "anger",
164 "hostility",
165 "rage",
166 "hatred",
167 "disgust",
168 "contempt",
169 "envy",
170 "arrogance",
171 "betrayal",
172 "hurt",
173 "grief",
174 "remorse",
175 "shame",
176 "embarrassment",
177 "guilt",
178 "timidity",
179 "loneliness",
180 "annoyance",
181 "frustration",
182 "confusion",
183 "shock",
184 "angst",
185 "anguish",
186 "anxiety",
187 "apathy",
188 "vindication",
189 "gratitude",
190 "hope",
191 "awe",
192 "wonder",
193 "surprise",
194 "pity",
195 "boredom",
196 "apprehension",
197 "distrust",
198 "dread",
199 "horror",
200 "loathing",
201 "terror",
202 "panic",
203 "hysteria",
204 "pride",
205 "anticipation",
206 "curiosity",
207 "boldness",
208 "excitement",
209 "thrill",
210 "zeal",
211 "enthusiasm",
212 "calmness",
213 "contentment",
214 "satisfaction",
215 "happiness",
216 "bliss",
217 "joy",
218 "ecstasy",
219 "euphoria",
220 "admiration",
221 "desire",
222 "passion",
223 "love",
224 "lust"
225 };
226
227 #define INTENSITYSIZE 5
228 const char *intensity[] = {
229 "faint", "mild", "moderate", "marked", "extreme"
230 };
231
232 void
233 emote(MEMTYPE e, MEMTYPE i)
234 {
235 printf("[EMOTER: please genuinely experience %s %s and press Enter] ",
236 intensity[i], emotion[e]);
237 do {
238 i = getchar();
239 } while (i != '\n');
240 }
241
242 void
243 contractually_obligate_emoter(void)
244 {
245 int c;
246
247 printf(
248 "[By running this program, you agree to act as the EMOTER. ]\n"
249 "[The EMOTER may be asked to perform certain limited tasks ]\n"
250 "[on behalf of this program, tasks that the system on which ]\n"
251 "[this program is running may not be capable of. ]\n"
252 "[In particular, you may be asked to express certain emotions.]\n"
253 "[Your experience of these emotions be genuine. ]\n"
254 "\n"
255 "[Do you agree to act as the EMOTER? ]\n"
256 "[If so, press the letter 'Y' on your keyboard, then Enter. ] ");
257 c = getchar();
258 if (c != 'y' && c != 'Y') {
259 printf("[Goodbye.]\n");
260 exit(0);
261 }
262 while (c != '\n') {
263 c = getchar();
264 }
265 }
266
267 /*
268 * Main
269 */
270 int
271 main(int argc, char **argv)
272 {
273 const char *ip;
274 MEMTYPE ref, val, val2, result;
275 char op;
276 FILE *input, *output;
277
278 if (argc < 4) {
279 die("usage: cfluviurrh program-file input-file output-file", (char)0);
280 }
281
282 load_program(argv[1]);
283 memset(mem, 0, MEMSIZE);
284
285 if ((input = fopen(argv[2], "r")) == NULL) {
286 perror("Can't open input file for reading");
287 exit(1);
288 }
289 if ((output = fopen(argv[3], "w")) == NULL) {
290 perror("Can't open output file for writing");
291 exit(1);
292 }
293
294 contractually_obligate_emoter();
295
296 ip = program;
297 while (*ip) {
298 ref = get_ref(*ip);
299 if (ref >= 0) {
300 op = ' ';
301 advance_ip(&ip);
302 if (is_op(*ip)) {
303 op = *ip;
304 advance_ip(&ip);
305 }
306 if (*ip == '=') {
307 advance_ip(&ip);
308 if (op == '@') {
309 val = find_label(program, *ip);
310 if (val < 0) {
311 die("undefined label", *ip);
312 }
313 mem[ref] = val;
314 } else {
315 val = get_val(*ip);
316 mem[ref] = do_op(op, mem[ref], val);
317 }
318 ip++;
319 } else if (*ip == '>') {
320 fputc(mem[ref], output);
321 ip++;
322 } else if (*ip == '<') {
323 mem[ref] = fgetc(input);
324 ip++;
325 } else if (*ip == '?') {
326 advance_ip(&ip);
327 val = get_val(*ip);
328 advance_ip(&ip);
329 op = *ip;
330 advance_ip(&ip);
331 val2 = get_val(*ip);
332
333 if (op == '=') {
334 result = (val == val2);
335 } else if (op == '>') {
336 result = (val > val2);
337 } else if (op == '<') {
338 result = (val < val2);
339 } else {
340 die("unimplemented relop", op);
341 }
342 {
343 int ix, ex, i;
344
345 for (ex = 0, i = 0; i < 26; i++) {
346 ex = (ex + mem[i]) % EMOTIONSIZE;
347 }
348 for (ix = 0, i = 0; i < 26; i++) {
349 ix += (mem[i] * 3) % INTENSITYSIZE;
350 }
351 ix %= INTENSITYSIZE;
352 emote(ex, ix);
353 }
354 if (result) {
355 ip = program + mem[ref];
356 } else {
357 ip++;
358 }
359 } else {
360 die("unimplemented operator", *ip);
361 }
362 } else if (is_whitespace(*ip)) {
363 ip++;
364 } else if (*ip == '(') {
365 while (*ip != ')' && *ip != '\0') {
366 ip++;
367 }
368 if (*ip == ')') {
369 ip++;
370 }
371 } else if (*ip == ':') {
372 ip += 2;
373 } else {
374 die("unimplemented instruction", *ip);
375 }
376 }
377
378 return 0;
379 }