10From [Julien Beasley](https://github.com/zass30/Nock5KCSharp):
13 using System.Collections.Generic;
16 using System.Text.RegularExpressions;
18 namespace NockInterpreter
22 static Dictionary<string, Noun> memocache = new Dictionary<string, Noun>();
24 public static Noun Nock(Noun noun)
28 if (memocache.TryGetValue(noun.ToString(), out cache_noun))
33 if (Atom.IsAtom(noun))
34 throw new Exception("Infinite loop nocking an atom: " + noun.ToString());
37 Noun subject = noun.n1;
38 if (Noun.IsCell(noun.n2))
40 Cell formula = (Cell)noun.n2;
41 if (Noun.IsAtom(formula.n1)) // we have lines 25-37 of spec
43 Atom op = (Atom)formula.n1;
44 Noun operands = formula.n2;
48 case 0: // 25 :: *[a 0 b] /[b a]
49 memocache[noun.ToString()] = fas(operands, subject);
50 return memocache[noun.ToString()];
51 case 1: // 26 :: *[a 1 b] b
52 memocache[noun.ToString()] = operands;
53 return memocache[noun.ToString()];
54 case 2: // 27 :: *[a 2 b c] *[*[a b] *[a c]]
55 if (Noun.IsCell(operands))
57 Noun a = Nock(subject, operands.n1);
58 Noun b = Nock(subject, operands.n2);
59 noun = Noun.CreateNoun(a, b);
61 // return Nock(Nock(subject, operands.n1), Nock(subject, operands.n2));
63 throw new Exception("Atom after operand 2: " + operands.ToString());
64 case 3: // 28 :: *[a 3 b] ?*[a b]
65 memocache[noun.ToString()] = wut(Nock(subject, operands));
66 return memocache[noun.ToString()];
67 case 4: // 29 :: *[a 4 b] +*[a b]
68 memocache[noun.ToString()] = lus(Nock(subject, operands));
69 return memocache[noun.ToString()];
70 case 5: // 30 :: *[a 5 b] =*[a b]
71 memocache[noun.ToString()] = tis(Nock(subject, operands));
72 return memocache[noun.ToString()];
73 case 6: // 32 :: *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
74 if (Noun.IsCell(operands) && Noun.IsCell(operands.n2))
77 Noun c = operands.n2.n1;
78 Noun d = operands.n2.n2;
79 noun = Noun.CreateNoun("[" + subject + " 2 [0 1] 2 [1 " + c + " " + d + "] [1 0] 2 [1 2 3] [1 0] 4 4 " + b + "]");
81 // return Nock(Noun.CreateNoun("[" + subject + " 2 [0 1] 2 [1 " + c + " " + d + "] [1 0] 2 [1 2 3] [1 0] 4 4 " + b + "]"));
83 throw new Exception("Unhandled pattern for operand 6");
84 case 7: // 33 :: *[a 7 b c] *[a 2 b 1 c]
85 if (Noun.IsCell(operands))
89 noun = Noun.CreateNoun("[" + subject + " 2 " + b + " 1 " + c + "]");
91 // return Nock(Noun.CreateNoun("[" + subject + " 2 " + b + " 1 " + c + "]"));
93 throw new Exception("Atom after operand 7: " + operands.ToString());
94 case 8: // 34 :: *[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c]
95 if (Noun.IsCell(operands))
99 noun = Noun.CreateNoun("[" + subject + " 7 [[7 [0 1] " + b + "] 0 1] " + c + "]");
101 // return Nock(Noun.CreateNoun("[" + subject + " 7 [[7 [0 1] " + b + "] 0 1] " + c + "]"));
103 throw new Exception("Atom after operand 8: " + operands.ToString());
104 case 9: // 35 :: *[a 9 b c] *[a 7 c 2 [0 1] 0 b]
105 if (Noun.IsCell(operands))
107 Noun b = operands.n1;
108 Noun c = operands.n2;
109 noun = Noun.CreateNoun("[" + subject + " 7 " + c + " 2 [0 1] 0 " + b + "]");
111 // return Nock(Noun.CreateNoun("[" + subject + " 7 " + c + " 2 [0 1] 0 " + b + "]"));
113 throw new Exception("Atom after operand 9: " + operands.ToString());
115 if (Noun.IsCell(operands))
117 if (Noun.IsCell(operands.n1)) // 36 :: *[a 10 [b c] d] *[a 8 c 7 [0 3] d]
119 Noun b = operands.n1.n1;
120 Noun c = operands.n1.n2;
121 Noun d = operands.n2;
122 noun = Noun.CreateNoun("[" + subject + " 8 " + c + " 7 [0 3] " + d + "]");
124 // return Nock(Noun.CreateNoun("[" + subject + " 8 " + c + " 7 [0 3] " + d + "]"));
126 else // 37 :: *[a 10 b c] *[a c]
128 Noun c = operands.n2;
129 noun = Noun.CreateNoun(subject, c);
131 // return Nock(subject, c);
134 throw new Exception("Atom after operand 10: " + operands.ToString());
136 throw new Exception("Unknown operand: " + op.value);
139 else // 23 :: *[a [b c] d] [*[a b c] *[a d]]
141 memocache[noun.ToString()] = Noun.CreateNoun(Nock(subject, formula.n1), Nock(subject, formula.n2));
142 return memocache[noun.ToString()];
146 throw new Exception("Unhandled pattern");
149 public static Noun Nock(string program)
151 Noun noun = Noun.CreateNoun(program);
155 public static Noun Nock(Noun n1, Noun n2)
157 Noun noun = Noun.CreateNoun(n1, n2);
161 private static Noun tis(Noun noun)
163 if (Noun.IsAtom(noun.ToString()))
164 throw new Exception("Infinite loop tising an atom: " + noun.ToString());
167 Cell cell = (Cell)noun;
169 if (cell.n1.ToString() == cell.n2.ToString())
170 return Noun.CreateNoun("0");
172 return Noun.CreateNoun("1");
176 private static Noun lus(Noun noun)
178 if (Noun.IsAtom(noun.ToString()))
182 return Noun.CreateNoun(v.ToString());
185 throw new Exception("Infinite loop lusing a cell: " + noun.ToString());
188 private static Noun wut(Noun noun)
190 if (Noun.IsAtom(noun.ToString()))
191 return Noun.CreateNoun("1");
193 return Noun.CreateNoun("0");
196 private static Noun fas(Noun n1, Noun n2)
198 Noun noun = Noun.CreateNoun(n1, n2);
202 private static Noun fas(Noun noun)
204 if (Noun.IsAtom(noun.ToString()))
205 throw new Exception("Infinite loop fasing an atom: " + noun.ToString());
209 // If n1 isn't an atom, I assume we throw? This isn't defined in the spec. Confirmed by John B by email. This spins forever.
210 if (Noun.IsCell(c.n1.ToString()))
211 throw new Exception("Axis must be an atom: " + c.ToString());
217 else if (a.value >= 2)
219 if (!Noun.IsCell(c.n2.ToString()))
221 throw new Exception("Only a cell can have an axis of 2 or 3: " + c.n2.ToString());
225 Cell c2 = (Cell)c.n2;
228 else if (a.value == 3)
230 else if (a.value % 2 == 0)
232 int half = a.value / 2;
233 return fas(Noun.CreateNoun("2", fas(Noun.CreateNoun(half.ToString(), c2))));
235 else if (a.value % 2 == 1)
237 int half = a.value / 2;
238 return fas(Noun.CreateNoun("3", fas(Noun.CreateNoun(half.ToString(), c2))));
242 throw new Exception("Infinite loop somewhere in fasing: " + c.n2.ToString());
247 throw new Exception("Infinite loop somewhere in fasing: " + c.n2.ToString());
257 // takes a program, returns a pair of nouns, stringified.
258 public static Tuple<string, string> SplitCell(string program)
263 // split the string right after the first space
264 foreach (char c in program)
274 // if we see a space, and our stack count is at 1, then we've found our split point
277 string a = program.Substring(1, i - 1);
278 string b = program.Substring(i + 1, program.Length - (i + 2));
280 // to implement proper bracket closing, surround b with brackets if it isn't a cell and isn't an atom
281 if (!IsCell(b) && !IsAtom(b))
283 Tuple<string, string> tuple = new Tuple<string, string>(a, b);
289 throw new Exception("Invalid char in cell: " + c);
292 throw new Exception("Invalid cell: " + program);
295 public static bool IsCell(string program)
297 // check if cell is valid, as above but make sure no space after bracket
298 // valid tokens are: space, int, [, ]
300 // from int => space, ], int
301 // from ] => space, ]
302 // from space => int, [
304 // stack count must always be nonzero
305 // first and last elements must be [ and ]
307 int i = 0; // i is the stack count for brackets.
309 char s = '\0'; // s is the last seen character
310 // split the string right after the first space
311 foreach (char c in program)
320 if (!(c == '[' || IsInt(c)))
325 if (!(IsInt(c) || c == ' ' || c == ']'))
330 if (!(c == ']' || c == ' '))
335 if (!(c == '[' || IsInt(c)))
344 if (i <= 0 && counter != program.Length) // stack count can't be zero unless it's the last character
348 // We should end with stack count of zero
355 public static bool IsInt(char c)
372 public static bool IsValidChar(char c)
383 public static bool IsAtom(string program)
386 if (int.TryParse(program, out i))
394 public static bool IsAtom(Noun noun)
396 return IsAtom(noun.ToString());
399 public static bool IsCell(Noun noun)
401 return IsCell(noun.ToString());
404 public static Noun CreateNoun(string program)
407 return new Atom(program);
409 return new Cell(program);
412 public static Noun CreateNoun(Noun n1, Noun n2)
414 return CreateNoun("[" + n1.ToString() + " " + n2.ToString() + "]");
417 public static Noun CreateNoun(string p1, Noun n2)
419 return CreateNoun("[" + p1 + " " + n2.ToString() + "]");
422 public static Noun CreateNoun(Noun n1, string p2)
424 return CreateNoun("[" + n1.ToString() + " " + p2 + "]");
427 public static Noun CreateNoun(string p1, string p2)
429 return CreateNoun("[" + p1 + " " + p2 + "]");
437 public override string ToString()
439 return value.ToString();
442 public Atom(string program)
447 bool result = int.TryParse(program, out i);
451 throw new ArgumentException("Invalid Atom: " + program);
459 public override string ToString()
461 return "[" + n1.ToString() + " " + n2.ToString() + "]";
464 public Cell(string program)
468 Tuple<string, string> split = SplitCell(program);
469 n1 = CreateNoun(split.Item1);
470 n2 = CreateNoun(split.Item2);
473 throw new ArgumentException("Invalid Cell: " + program);
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list