@ojoxux/typecow 0.1.0
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/LICENSE +21 -0
- package/README.md +79 -0
- package/THIRD_PARTY_NOTICES.md +27 -0
- package/dist/ascii.d.ts +137 -0
- package/dist/index.d.ts +137 -0
- package/package.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 typecow contributors
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# typecow
|
|
2
|
+
|
|
3
|
+
A type level interpreter for the esoteric programming language
|
|
4
|
+
[COW](https://bigzaphod.github.io/COW/) written in TypeScript.
|
|
5
|
+
|
|
6
|
+
The program is evaluated by the TypeScript compiler. The package contains no
|
|
7
|
+
runtime interpreter.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import type { Cow } from "@ojoxux/typecow";
|
|
11
|
+
|
|
12
|
+
type Program = "oom MoO OOM";
|
|
13
|
+
type Input = "41\n";
|
|
14
|
+
type Output = Cow<Program, Input>; // "42\n"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
All twelve COW commands are implemented:
|
|
20
|
+
|
|
21
|
+
| Command | Operation |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `moo` | Search backward for the matching `MOO` |
|
|
24
|
+
| `mOo` | Move the memory pointer left |
|
|
25
|
+
| `moO` | Move the memory pointer right |
|
|
26
|
+
| `mOO` | Execute the current cell as an opcode |
|
|
27
|
+
| `Moo` | Read or write one ASCII character |
|
|
28
|
+
| `MOo` | Decrement the current cell |
|
|
29
|
+
| `MoO` | Increment the current cell |
|
|
30
|
+
| `MOO` | Begin a loop |
|
|
31
|
+
| `OOO` | Set the current cell to zero |
|
|
32
|
+
| `MMM` | Copy through the register |
|
|
33
|
+
| `OOM` | Write the current cell as a decimal integer |
|
|
34
|
+
| `oom` | Read a decimal integer |
|
|
35
|
+
|
|
36
|
+
Text that does not form a command is ignored.
|
|
37
|
+
|
|
38
|
+
## Input and output
|
|
39
|
+
|
|
40
|
+
`Moo` consumes one ASCII character when the current cell is zero. Otherwise it
|
|
41
|
+
appends the ASCII character represented by the cell to the output.
|
|
42
|
+
|
|
43
|
+
`oom` consumes a signed decimal integer through the next newline. `OOM` appends
|
|
44
|
+
the decimal value followed by a newline.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
type Echo = Cow<"Moo Moo", "A">; // "A"
|
|
48
|
+
type AddOne = Cow<"oom MoO OOM", "-2\n">; // "-1\n"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Character I/O supports 7-bit ASCII. Integer cells are represented as signed
|
|
52
|
+
unary tuples, so their practical range is limited by the TypeScript compiler's
|
|
53
|
+
type-instantiation budget. This representation keeps increment, decrement,
|
|
54
|
+
zero checks, dynamic dispatch, and decimal output predictable.
|
|
55
|
+
|
|
56
|
+
Invalid programs and inputs produce a `CowError<...>` type.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import type { Cow, CowError } from "@ojoxux/typecow";
|
|
60
|
+
|
|
61
|
+
type Error = Cow<"mOo">; // CowError<"memory-underflow">
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Development
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
npm install
|
|
68
|
+
npm test
|
|
69
|
+
npm run build
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The recursive evaluator uses the same logarithmic recursion-flattening idea as
|
|
73
|
+
[@susisu/typefuck](https://github.com/susisu/typefuck), which inspired this
|
|
74
|
+
project.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
|
|
78
|
+
MIT. See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for third-party
|
|
79
|
+
copyright and license notices.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
typecowの再帰縮約を実装する`Recurse`と`RecurseSub`は、[@susisu/typefuck](https://github.com/susisu/typefuck)を翻案しています。
|
|
4
|
+
|
|
5
|
+
## @susisu/typefuck
|
|
6
|
+
|
|
7
|
+
The MIT License (http://opensource.org/licenses/mit-license.php)
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2020-2025 Susisu
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
12
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
13
|
+
the Software without restriction, including without limitation the rights to
|
|
14
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
15
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
16
|
+
so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
package/dist/ascii.d.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
type AsciiCharacters = {
|
|
2
|
+
0: "\x00";
|
|
3
|
+
1: "\x01";
|
|
4
|
+
2: "\x02";
|
|
5
|
+
3: "\x03";
|
|
6
|
+
4: "\x04";
|
|
7
|
+
5: "\x05";
|
|
8
|
+
6: "\x06";
|
|
9
|
+
7: "\x07";
|
|
10
|
+
8: "\x08";
|
|
11
|
+
9: "\x09";
|
|
12
|
+
10: "\x0a";
|
|
13
|
+
11: "\x0b";
|
|
14
|
+
12: "\x0c";
|
|
15
|
+
13: "\x0d";
|
|
16
|
+
14: "\x0e";
|
|
17
|
+
15: "\x0f";
|
|
18
|
+
16: "\x10";
|
|
19
|
+
17: "\x11";
|
|
20
|
+
18: "\x12";
|
|
21
|
+
19: "\x13";
|
|
22
|
+
20: "\x14";
|
|
23
|
+
21: "\x15";
|
|
24
|
+
22: "\x16";
|
|
25
|
+
23: "\x17";
|
|
26
|
+
24: "\x18";
|
|
27
|
+
25: "\x19";
|
|
28
|
+
26: "\x1a";
|
|
29
|
+
27: "\x1b";
|
|
30
|
+
28: "\x1c";
|
|
31
|
+
29: "\x1d";
|
|
32
|
+
30: "\x1e";
|
|
33
|
+
31: "\x1f";
|
|
34
|
+
32: " ";
|
|
35
|
+
33: "!";
|
|
36
|
+
34: "\"";
|
|
37
|
+
35: "#";
|
|
38
|
+
36: "$";
|
|
39
|
+
37: "%";
|
|
40
|
+
38: "&";
|
|
41
|
+
39: "'";
|
|
42
|
+
40: "(";
|
|
43
|
+
41: ")";
|
|
44
|
+
42: "*";
|
|
45
|
+
43: "+";
|
|
46
|
+
44: ",";
|
|
47
|
+
45: "-";
|
|
48
|
+
46: ".";
|
|
49
|
+
47: "/";
|
|
50
|
+
48: "0";
|
|
51
|
+
49: "1";
|
|
52
|
+
50: "2";
|
|
53
|
+
51: "3";
|
|
54
|
+
52: "4";
|
|
55
|
+
53: "5";
|
|
56
|
+
54: "6";
|
|
57
|
+
55: "7";
|
|
58
|
+
56: "8";
|
|
59
|
+
57: "9";
|
|
60
|
+
58: ":";
|
|
61
|
+
59: ";";
|
|
62
|
+
60: "<";
|
|
63
|
+
61: "=";
|
|
64
|
+
62: ">";
|
|
65
|
+
63: "?";
|
|
66
|
+
64: "@";
|
|
67
|
+
65: "A";
|
|
68
|
+
66: "B";
|
|
69
|
+
67: "C";
|
|
70
|
+
68: "D";
|
|
71
|
+
69: "E";
|
|
72
|
+
70: "F";
|
|
73
|
+
71: "G";
|
|
74
|
+
72: "H";
|
|
75
|
+
73: "I";
|
|
76
|
+
74: "J";
|
|
77
|
+
75: "K";
|
|
78
|
+
76: "L";
|
|
79
|
+
77: "M";
|
|
80
|
+
78: "N";
|
|
81
|
+
79: "O";
|
|
82
|
+
80: "P";
|
|
83
|
+
81: "Q";
|
|
84
|
+
82: "R";
|
|
85
|
+
83: "S";
|
|
86
|
+
84: "T";
|
|
87
|
+
85: "U";
|
|
88
|
+
86: "V";
|
|
89
|
+
87: "W";
|
|
90
|
+
88: "X";
|
|
91
|
+
89: "Y";
|
|
92
|
+
90: "Z";
|
|
93
|
+
91: "[";
|
|
94
|
+
92: "\\";
|
|
95
|
+
93: "]";
|
|
96
|
+
94: "^";
|
|
97
|
+
95: "_";
|
|
98
|
+
96: "`";
|
|
99
|
+
97: "a";
|
|
100
|
+
98: "b";
|
|
101
|
+
99: "c";
|
|
102
|
+
100: "d";
|
|
103
|
+
101: "e";
|
|
104
|
+
102: "f";
|
|
105
|
+
103: "g";
|
|
106
|
+
104: "h";
|
|
107
|
+
105: "i";
|
|
108
|
+
106: "j";
|
|
109
|
+
107: "k";
|
|
110
|
+
108: "l";
|
|
111
|
+
109: "m";
|
|
112
|
+
110: "n";
|
|
113
|
+
111: "o";
|
|
114
|
+
112: "p";
|
|
115
|
+
113: "q";
|
|
116
|
+
114: "r";
|
|
117
|
+
115: "s";
|
|
118
|
+
116: "t";
|
|
119
|
+
117: "u";
|
|
120
|
+
118: "v";
|
|
121
|
+
119: "w";
|
|
122
|
+
120: "x";
|
|
123
|
+
121: "y";
|
|
124
|
+
122: "z";
|
|
125
|
+
123: "{";
|
|
126
|
+
124: "|";
|
|
127
|
+
125: "}";
|
|
128
|
+
126: "~";
|
|
129
|
+
127: "\x7f";
|
|
130
|
+
};
|
|
131
|
+
type BuildTuple<N extends number, Result extends unknown[] = []> = Result["length"] extends N ? Result : BuildTuple<N, [...Result, unknown]>;
|
|
132
|
+
export type AsciiCharacter = AsciiCharacters[keyof AsciiCharacters];
|
|
133
|
+
export type CharacterOf<Magnitude extends unknown[]> = Magnitude["length"] extends keyof AsciiCharacters ? AsciiCharacters[Magnitude["length"]] : never;
|
|
134
|
+
export type MagnitudeOf<C> = {
|
|
135
|
+
[N in keyof AsciiCharacters]: AsciiCharacters[N] extends C ? BuildTuple<N & number> : never;
|
|
136
|
+
}[keyof AsciiCharacters];
|
|
137
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { AsciiCharacter, CharacterOf, MagnitudeOf } from "./ascii.js";
|
|
2
|
+
type Opcode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
|
|
3
|
+
type Tokenize<Source extends string, Result extends Opcode[] = []> = Source extends `moo${infer Rest}` ? Tokenize<Rest, [...Result, 0]> : Source extends `mOo${infer Rest}` ? Tokenize<Rest, [...Result, 1]> : Source extends `moO${infer Rest}` ? Tokenize<Rest, [...Result, 2]> : Source extends `mOO${infer Rest}` ? Tokenize<Rest, [...Result, 3]> : Source extends `Moo${infer Rest}` ? Tokenize<Rest, [...Result, 4]> : Source extends `MOo${infer Rest}` ? Tokenize<Rest, [...Result, 5]> : Source extends `MoO${infer Rest}` ? Tokenize<Rest, [...Result, 6]> : Source extends `MOO${infer Rest}` ? Tokenize<Rest, [...Result, 7]> : Source extends `OOO${infer Rest}` ? Tokenize<Rest, [...Result, 8]> : Source extends `MMM${infer Rest}` ? Tokenize<Rest, [...Result, 9]> : Source extends `OOM${infer Rest}` ? Tokenize<Rest, [...Result, 10]> : Source extends `oom${infer Rest}` ? Tokenize<Rest, [...Result, 11]> : Source extends `${infer _Character}${infer Rest}` ? Tokenize<Rest, Result> : Result;
|
|
4
|
+
type Positive = "+";
|
|
5
|
+
type Negative = "-";
|
|
6
|
+
type Sign = Positive | Negative;
|
|
7
|
+
type Integer<S extends Sign, M extends unknown[]> = {
|
|
8
|
+
sign: S;
|
|
9
|
+
magnitude: M;
|
|
10
|
+
};
|
|
11
|
+
type Zero = Integer<Positive, []>;
|
|
12
|
+
type Normalize<S extends Sign, M extends unknown[]> = M extends [] ? Zero : Integer<S, M>;
|
|
13
|
+
type Increment<I> = I extends Integer<infer S, infer M extends unknown[]> ? S extends Positive ? Integer<Positive, [...M, unknown]> : M extends [unknown, ...infer Rest] ? Normalize<Negative, Rest> : never : never;
|
|
14
|
+
type Decrement<I> = I extends Integer<infer S, infer M extends unknown[]> ? S extends Negative ? Integer<Negative, [...M, unknown]> : M extends [unknown, ...infer Rest] ? Normalize<Positive, Rest> : Integer<Negative, [unknown]> : never;
|
|
15
|
+
type IsZero<I> = I extends Integer<infer _S, infer M> ? M extends [] ? true : false : false;
|
|
16
|
+
type IntegerString<I> = I extends Integer<infer S, infer M extends unknown[]> ? S extends Negative ? `-${M["length"]}` : `${M["length"]}` : never;
|
|
17
|
+
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
18
|
+
type DigitMagnitude<D extends Digit> = D extends "0" ? [] : D extends "1" ? [unknown] : D extends "2" ? [unknown, unknown] : D extends "3" ? [unknown, unknown, unknown] : D extends "4" ? [unknown, unknown, unknown, unknown] : D extends "5" ? [unknown, unknown, unknown, unknown, unknown] : D extends "6" ? [unknown, unknown, unknown, unknown, unknown, unknown] : D extends "7" ? [unknown, unknown, unknown, unknown, unknown, unknown, unknown] : D extends "8" ? [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown] : [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown];
|
|
19
|
+
type MultiplyByTen<M extends unknown[]> = [
|
|
20
|
+
...M,
|
|
21
|
+
...M,
|
|
22
|
+
...M,
|
|
23
|
+
...M,
|
|
24
|
+
...M,
|
|
25
|
+
...M,
|
|
26
|
+
...M,
|
|
27
|
+
...M,
|
|
28
|
+
...M,
|
|
29
|
+
...M
|
|
30
|
+
];
|
|
31
|
+
type ParseMagnitude<Source extends string, Result extends unknown[] = []> = Source extends "" ? Result : Source extends `${infer D extends Digit}${infer Rest}` ? ParseMagnitude<Rest, [...MultiplyByTen<Result>, ...DigitMagnitude<D>]> : CowError<"invalid-integer-input">;
|
|
32
|
+
type ParseInteger<Source extends string> = Source extends "" ? CowError<"invalid-integer-input"> : Source extends `-${infer Digits}` ? Digits extends "" ? CowError<"invalid-integer-input"> : ParseMagnitude<Digits> extends infer M ? M extends unknown[] ? Normalize<Negative, M> : M : never : Source extends `+${infer Digits}` ? Digits extends "" ? CowError<"invalid-integer-input"> : ParseMagnitude<Digits> extends infer M ? M extends unknown[] ? Normalize<Positive, M> : M : never : ParseMagnitude<Source> extends infer M ? M extends unknown[] ? Normalize<Positive, M> : M : never;
|
|
33
|
+
type ReadLine<Source extends string, Line extends string = ""> = Source extends `\n${infer Rest}` ? [Line, Rest] : Source extends `${infer C}${infer Rest}` ? ReadLine<Rest, `${Line}${C}`> : [Line, ""];
|
|
34
|
+
type Program<Left extends Opcode[], Current extends Opcode | null, Right extends Opcode[]> = {
|
|
35
|
+
left: Left;
|
|
36
|
+
current: Current;
|
|
37
|
+
right: Right;
|
|
38
|
+
};
|
|
39
|
+
type ProgramFrom<Ops extends Opcode[]> = Ops extends [infer Current extends Opcode, ...infer Right extends Opcode[]] ? Program<[], Current, Right> : Program<[], null, []>;
|
|
40
|
+
type Advance<P> = P extends Program<infer Left extends Opcode[], infer Current extends Opcode, infer Right extends Opcode[]> ? Right extends [
|
|
41
|
+
infer Next extends Opcode,
|
|
42
|
+
...infer Rest extends Opcode[]
|
|
43
|
+
] ? Program<[Current, ...Left], Next, Rest> : Program<[Current, ...Left], null, []> : P;
|
|
44
|
+
type Retreat<P> = P extends Program<infer Left extends Opcode[], infer Current extends Opcode | null, infer Right extends Opcode[]> ? Left extends [
|
|
45
|
+
infer Previous extends Opcode,
|
|
46
|
+
...infer Rest extends Opcode[]
|
|
47
|
+
] ? Current extends Opcode ? Program<Rest, Previous, [Current, ...Right]> : Program<Rest, Previous, Right> : CowError<"program-underflow"> : never;
|
|
48
|
+
type Memory<Left extends Integer<Sign, unknown[]>[], Head extends Integer<Sign, unknown[]>, Right extends Integer<Sign, unknown[]>[]> = {
|
|
49
|
+
left: Left;
|
|
50
|
+
head: Head;
|
|
51
|
+
right: Right;
|
|
52
|
+
};
|
|
53
|
+
type InitialMemory = Memory<[], Zero, []>;
|
|
54
|
+
type ReadMemory<M> = M extends Memory<infer _Left, infer Head, infer _Right> ? Head : never;
|
|
55
|
+
type WriteMemory<M, Value extends Integer<Sign, unknown[]>> = M extends Memory<infer Left, infer _Head, infer Right> ? Memory<Left, Value, Right> : never;
|
|
56
|
+
type MoveMemoryLeft<M> = M extends Memory<infer Left, infer Head, infer Right> ? Left extends [
|
|
57
|
+
infer Previous extends Integer<Sign, unknown[]>,
|
|
58
|
+
...infer Rest extends Integer<Sign, unknown[]>[]
|
|
59
|
+
] ? Memory<Rest, Previous, [Head, ...Right]> : CowError<"memory-underflow"> : never;
|
|
60
|
+
type MoveMemoryRight<M> = M extends Memory<infer Left, infer Head, infer Right> ? Right extends [
|
|
61
|
+
infer Next extends Integer<Sign, unknown[]>,
|
|
62
|
+
...infer Rest extends Integer<Sign, unknown[]>[]
|
|
63
|
+
] ? Memory<[Head, ...Left], Next, Rest> : Memory<[Head, ...Left], Zero, []> : never;
|
|
64
|
+
type Register = Integer<Sign, unknown[]> | null;
|
|
65
|
+
type State<P, M, I extends string, O extends string, R extends Register> = {
|
|
66
|
+
program: P;
|
|
67
|
+
memory: M;
|
|
68
|
+
input: I;
|
|
69
|
+
output: O;
|
|
70
|
+
register: R;
|
|
71
|
+
};
|
|
72
|
+
type InitialState<Ops extends Opcode[], Input extends string> = State<ProgramFrom<Ops>, InitialMemory, Input, "", null>;
|
|
73
|
+
export type CowError<Message extends string> = {
|
|
74
|
+
readonly error: Message;
|
|
75
|
+
};
|
|
76
|
+
type WithProgram<S, NextProgram> = S extends State<infer _Program, infer M, infer I, infer O, infer R> ? State<NextProgram, M, I, O, R> : never;
|
|
77
|
+
type AdvanceState<S> = S extends State<infer P, infer M, infer I, infer O, infer R> ? State<Advance<P>, M, I, O, R> : never;
|
|
78
|
+
type WithMemoryAndAdvance<S, NextMemory> = S extends State<infer P, infer _M, infer I, infer O, infer R> ? State<Advance<P>, NextMemory, I, O, R> : never;
|
|
79
|
+
type ContinueBack<P, Depth extends unknown[]> = Retreat<P> extends infer Previous ? Previous extends CowError<string> ? CowError<"unmatched-moo"> : ScanBack<Previous, Depth> : never;
|
|
80
|
+
type ScanBack<P, Depth extends unknown[]> = P extends Program<infer _Left, infer Current, infer _Right> ? Current extends 0 ? ContinueBack<P, [unknown, ...Depth]> : Current extends 7 ? Depth extends [unknown, ...infer Rest] ? Rest extends [] ? P : ContinueBack<P, Rest> : CowError<"unmatched-moo"> : ContinueBack<P, Depth> : CowError<"unmatched-moo">;
|
|
81
|
+
type FindMatchingMooBack<P> = Retreat<P> extends infer Skipped ? Skipped extends CowError<string> ? CowError<"unmatched-moo"> : Retreat<Skipped> extends infer Candidate ? Candidate extends CowError<string> ? CowError<"unmatched-moo"> : ScanBack<Candidate, [unknown]> : never : never;
|
|
82
|
+
type PopDepth<Depth extends unknown[]> = Depth extends [unknown, ...infer Rest] ? Rest : [];
|
|
83
|
+
type CloseForwardDepth<Depth extends unknown[], Previous extends Opcode> = Previous extends 7 ? PopDepth<PopDepth<Depth>> : PopDepth<Depth>;
|
|
84
|
+
type ContinueForward<P, Depth extends unknown[], Previous extends Opcode> = Advance<P> extends infer Next ? Next extends Program<infer _Left, infer Current, infer _Right> ? Current extends Opcode ? ScanForward<Next, Depth, Previous> : CowError<"unmatched-MOO"> : never : never;
|
|
85
|
+
type ScanForward<P, Depth extends unknown[], Previous extends Opcode> = P extends Program<infer _Left, infer Current, infer _Right> ? Current extends Opcode ? Current extends 7 ? ContinueForward<P, [unknown, ...Depth], Current> : Current extends 0 ? CloseForwardDepth<Depth, Previous> extends infer NextDepth extends unknown[] ? NextDepth extends [] ? Advance<P> : ContinueForward<P, NextDepth, Current> : never : ContinueForward<P, Depth, Current> : CowError<"unmatched-MOO"> : CowError<"unmatched-MOO">;
|
|
86
|
+
type FindAfterMatchingMoo<P> = Advance<P> extends infer Skipped ? Skipped extends Program<infer _Left, infer SkippedCurrent, infer _Right> ? SkippedCurrent extends Opcode ? Advance<Skipped> extends infer Candidate ? Candidate extends Program<infer _CandidateLeft, infer CandidateCurrent, infer _CandidateRight> ? CandidateCurrent extends Opcode ? ScanForward<Candidate, [unknown], SkippedCurrent> : CowError<"unmatched-MOO"> : never : never : CowError<"unmatched-MOO"> : never : never;
|
|
87
|
+
type OpcodeFromInteger<I> = I extends Integer<Positive, infer M extends unknown[]> ? M["length"] extends Opcode ? M["length"] : never : never;
|
|
88
|
+
type OutputCharacter<I> = I extends Integer<Positive, infer M extends unknown[]> ? CharacterOf<M> : never;
|
|
89
|
+
type ExecuteMoo<S> = S extends State<infer P, infer _M, infer _I, infer _O, infer _R> ? FindMatchingMooBack<P> extends infer Target ? Target extends CowError<string> ? Target : Execute<7, WithProgram<S, Target>> : never : never;
|
|
90
|
+
type ExecuteMoveLeft<S> = S extends State<infer _P, infer M, infer _I, infer _O, infer _R> ? MoveMemoryLeft<M> extends infer NextMemory ? NextMemory extends CowError<string> ? NextMemory : WithMemoryAndAdvance<S, NextMemory> : never : never;
|
|
91
|
+
type ExecuteMoveRight<S> = S extends State<infer _P, infer M, infer _I, infer _O, infer _R> ? WithMemoryAndAdvance<S, MoveMemoryRight<M>> : never;
|
|
92
|
+
type ExecuteDynamic<S> = S extends State<infer _P, infer M, infer _I, infer O, infer _R> ? OpcodeFromInteger<ReadMemory<M>> extends infer DynamicOpcode ? [DynamicOpcode] extends [never] ? O : DynamicOpcode extends 3 ? O : DynamicOpcode extends Opcode ? Execute<DynamicOpcode, S> : O : never : never;
|
|
93
|
+
type ExecuteCharacterIO<S> = S extends State<infer P, infer M, infer I, infer O, infer R> ? IsZero<ReadMemory<M>> extends true ? I extends `${infer C}${infer Rest}` ? C extends AsciiCharacter ? State<Advance<P>, WriteMemory<M, Integer<Positive, MagnitudeOf<C>>>, Rest, O, R> : CowError<"non-ascii-character-input"> : CowError<"input-exhausted"> : OutputCharacter<ReadMemory<M>> extends infer C ? [C] extends [never] ? CowError<"non-ascii-character-output"> : C extends string ? State<Advance<P>, M, I, `${O}${C}`, R> : never : never : never;
|
|
94
|
+
type ExecuteDecrement<S> = S extends State<infer _P, infer M, infer _I, infer _O, infer _R> ? WithMemoryAndAdvance<S, WriteMemory<M, Decrement<ReadMemory<M>>>> : never;
|
|
95
|
+
type ExecuteIncrement<S> = S extends State<infer _P, infer M, infer _I, infer _O, infer _R> ? WithMemoryAndAdvance<S, WriteMemory<M, Increment<ReadMemory<M>>>> : never;
|
|
96
|
+
type ExecuteMOO<S> = S extends State<infer P, infer M, infer _I, infer _O, infer _R> ? IsZero<ReadMemory<M>> extends true ? FindAfterMatchingMoo<P> extends infer Target ? Target extends CowError<string> ? Target : WithProgram<S, Target> : never : AdvanceState<S> : never;
|
|
97
|
+
type ExecuteZero<S> = S extends State<infer _P, infer M, infer _I, infer _O, infer _R> ? WithMemoryAndAdvance<S, WriteMemory<M, Zero>> : never;
|
|
98
|
+
type ExecuteRegister<S> = S extends State<infer P, infer M, infer I, infer O, infer R> ? R extends Integer<Sign, unknown[]> ? State<Advance<P>, WriteMemory<M, R>, I, O, null> : State<Advance<P>, M, I, O, ReadMemory<M>> : never;
|
|
99
|
+
type ExecuteIntegerOutput<S> = S extends State<infer P, infer M, infer I, infer O, infer R> ? State<Advance<P>, M, I, `${O}${IntegerString<ReadMemory<M>>}\n`, R> : never;
|
|
100
|
+
type ExecuteIntegerInput<S> = S extends State<infer P, infer M, infer I, infer O, infer R> ? ReadLine<I> extends [
|
|
101
|
+
infer Line extends string,
|
|
102
|
+
infer Rest extends string
|
|
103
|
+
] ? ParseInteger<Line> extends infer Value ? Value extends CowError<string> ? Value : Value extends Integer<Sign, unknown[]> ? State<Advance<P>, WriteMemory<M, Value>, Rest, O, R> : never : never : never : never;
|
|
104
|
+
type Execute<Op extends Opcode, S> = Op extends 0 ? ExecuteMoo<S> : Op extends 1 ? ExecuteMoveLeft<S> : Op extends 2 ? ExecuteMoveRight<S> : Op extends 3 ? ExecuteDynamic<S> : Op extends 4 ? ExecuteCharacterIO<S> : Op extends 5 ? ExecuteDecrement<S> : Op extends 6 ? ExecuteIncrement<S> : Op extends 7 ? ExecuteMOO<S> : Op extends 8 ? ExecuteZero<S> : Op extends 9 ? ExecuteRegister<S> : Op extends 10 ? ExecuteIntegerOutput<S> : ExecuteIntegerInput<S>;
|
|
105
|
+
type Step<S> = S extends State<infer P, infer _M, infer _I, infer _O, infer _R> ? P extends Program<infer _Left, infer Current, infer _Right> ? Current extends Opcode ? Execute<Current, S> : S : never : S;
|
|
106
|
+
/**
|
|
107
|
+
* Recursion compaction adapted from @susisu/typefuck.
|
|
108
|
+
* Copyright (c) 2020-2025 Susisu, licensed under the MIT License.
|
|
109
|
+
* See THIRD_PARTY_NOTICES.md for the complete notice.
|
|
110
|
+
*/
|
|
111
|
+
type Recurse<T> = T extends {
|
|
112
|
+
__rec: unknown;
|
|
113
|
+
} ? Recurse<RecurseSub<T>> : T;
|
|
114
|
+
type RecurseSub<T> = T extends {
|
|
115
|
+
__rec: never;
|
|
116
|
+
} ? never : T extends {
|
|
117
|
+
__rec: {
|
|
118
|
+
__rec: infer U;
|
|
119
|
+
};
|
|
120
|
+
} ? {
|
|
121
|
+
__rec: RecurseSub<U>;
|
|
122
|
+
} : T extends {
|
|
123
|
+
__rec: infer U;
|
|
124
|
+
} ? U : T;
|
|
125
|
+
type Run<S> = Recurse<RunSub<S>>;
|
|
126
|
+
type RunSub<S> = S extends CowError<string> ? S : S extends string ? S : S extends State<infer P, infer _M, infer _I, infer O, infer _R> ? P extends Program<infer _Left, infer Current, infer _Right> ? Current extends null ? O : {
|
|
127
|
+
__rec: RunSub<Step<S>>;
|
|
128
|
+
} : never : never;
|
|
129
|
+
/**
|
|
130
|
+
* Evaluates a COW program entirely in the TypeScript type system.
|
|
131
|
+
*
|
|
132
|
+
* `ProgramSource` may contain arbitrary comments. `Input` is a character
|
|
133
|
+
* stream for `Moo`; `oom` consumes a signed decimal integer through the next
|
|
134
|
+
* newline.
|
|
135
|
+
*/
|
|
136
|
+
export type Cow<ProgramSource extends string, Input extends string = ""> = ProgramSource extends unknown ? Input extends unknown ? Run<InitialState<Tokenize<ProgramSource>, Input>> : never : never;
|
|
137
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ojoxux/typecow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A type-level COW interpreter in TypeScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"THIRD_PARTY_NOTICES.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.build.json",
|
|
23
|
+
"prepack": "npm run build",
|
|
24
|
+
"test": "tsc -p tsconfig.test.json"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.9.2"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT"
|
|
30
|
+
}
|