├── LICENSE ├── Makefile ├── README.md ├── life.🙂apl └── 🙂apl.c /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022, Finn Barber 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: 🙂apl.c 2 | $(CC) 🙂apl.c -o 🙂apl 3 | 4 | install: build 5 | cp 🙂apl /usr/bin/🙂apl 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🙂 APL 2 | 3 | This idea has been holding my brain hostage, I hope that implementing it will restore my free will. 4 | 5 | ``` 6 | 🗨️ The canonical game of life function, called LI (Liechtenstein) 7 | 🇱🇮🪧🌜👍👍➊ 🤔🛶🔴🐜➌ ➍⚖️🧮🤰😍🥶➊ ⓿ ➊🤐🔴🤣🥶➊ ⓿ ➊🤐🔴🙃🪺🤔🌛 8 | 9 | 🗨️ An array containing a glider, called GL (Greenland) 10 | 🇬🇱🪧➌ ➌📐➊ ➊ ➊ ➊ ⓿ ⓿ ⓿ ➊ ⓿ 11 | 12 | 🗨️ The 8x8 grid to use, called GR (Greece) 13 | 🇬🇷🪧🥶➑ 🥶➑👍🇬🇱 14 | 15 | 🗨️ Print the first 4 steps to the screen 16 | 🎮🪧🌜🇱🇮😬🤔➡️🇬🇷🌛🍑⓿😍📚➌ 17 | ``` 18 | 19 | ## What? 20 | 21 | It's APL, but instead of the symbols I used emojis. For example ¨ (each) is now 🍑 (peach), ∧ (and) is now 🐜 (ant), and ⌽ (reverse) is 🙃. 22 | 23 | ## How? 24 | 25 | I didn't implement an entire APL for this (thank god), this uses GNU APL under the hood. You will need this installed. I wrote the translator itself in C, because APL didn't seem to like unicode strings much. 26 | 27 | ## Why? 28 | 29 | Why not? 30 | 31 | ## Features 32 | 33 | - Many terrible puns 34 | - Names condense into flags to save space 35 | - Arguably more intuitive symbols than normal APL 36 | - There is no good reason to use this 37 | 38 | ## Character map 39 | 40 | | 🙂APL Emoji | APL Symbol | 41 | |-------------|------------| 42 | | 🇦 | a | 43 | | 🇧 | b | 44 | | 🇨 | c | 45 | | 🇩 | d | 46 | | 🇪 | e | 47 | | 🇫 | f | 48 | | 🇬 | g | 49 | | 🇭 | h | 50 | | 🇮 | i | 51 | | 🇯 | j | 52 | | 🇰 | k | 53 | | 🇱 | l | 54 | | 🇲 | m | 55 | | 🇳 | n | 56 | | 🇴 | o | 57 | | 🇵 | p | 58 | | 🇶 | q | 59 | | 🇷 | r | 60 | | 🇸 | s | 61 | | 🇹 | t | 62 | | 🇺 | u | 63 | | 🇻 | v | 64 | | 🇼 | w | 65 | | 🇽 | x | 66 | | 🇾 | y | 67 | | 🇿 | z | 68 | | ⓿ | 0 | 69 | | ➊ | 1 | 70 | | ➋ | 2 | 71 | | ➌ | 3 | 72 | | ➍ | 4 | 73 | | ➎ | 5 | 74 | | ➏ | 6 | 75 | | ➐ | 7 | 76 | | ➑ | 8 | 77 | | ➒ | 9 | 78 | | 🗨️ | ⍝ | 79 | | ✍️ | ' | 80 | | 🧮 | + | 81 | | 🥖 | - | 82 | | ⚔️ | × | 83 | | 🪓 | ÷ | 84 | | 📈 | ⌈ | 85 | | 📉 | ⌊ | 86 | | 🤯 | * | 87 | | 🪵 | ⍟ | 88 | | 🥧 | ○ | 89 | | 📢 | ! | 90 | | 🎲 | ? | 91 | | 📏 | \| | 92 | | 🐜 | ∧ | 93 | | 🛶 | ∨ | 94 | | 🕷 | ⍲ | 95 | | ⛵ | ⍱ | 96 | | ⚖️ | = | 97 | | 😠 | ≠ | 98 | | 🤝 | ≡ | 99 | | 😡 | ≢ | 100 | | 🔬 | < | 101 | | 🤏 | ≤ | 102 | | 🦣 | ≥ | 103 | | ⛰️ | > | 104 | | ☝️ | ⌷ | 105 | | 👍 | ↑ | 106 | | 👎 | ↓ | 107 | | 📐 | ⍴ | 108 | | 🪺 | ⊂ | 109 | | ⛏️ | ⊃ | 110 | | ⬅️ | ⊣ | 111 | | ➡️ | ⊢ | 112 | | 🦄 | ∪ | 113 | | 🙏 | ∩ | 114 | | 🙅 | ~ | 115 | | 📚 | ⍳ | 116 | | 👀 | ⍸ | 117 | | 📜 | ∊ | 118 | | 🔎 | ⍷ | 119 | | 🤰 | / | 120 | | 🌿 | \ | 121 | | 🧬 | ⌿ | 122 | | 🌱 | ⍀ | 123 | | 🙃 | ⌽ | 124 | | 🤣 | ⊖ | 125 | | 😍 | , | 126 | | ❤️ | ⍪ | 127 | | 🎶 | ⍉ | 128 | | 🔢 | ⊥ | 129 | | 🔡 | ⊤ | 130 | | 🐇 | ⌹ | 131 | | 🏷 | ⍎ | 132 | | 💾 | ⍕ | 133 | | 🧗 | ⍋ | 134 | | ⛷ | ⍒ | 135 | | 🍑 | ¨ | 136 | | 😵 | ⍨ | 137 | | 🚀 | ⌶ | 138 | | 🔑 | ⌸ | 139 | | 🐣 | & | 140 | | 👉 | [ | 141 | | 👈 | ] | 142 | | 🤐 | ∘ | 143 | | 😬 | ⍣ | 144 | | 🔧 | ⍠ | 145 | | ✏️ | ⌺ | 146 | | 😱 | ⍤ | 147 | | 🌍 | @ | 148 | | 🔴 | . | 149 | | 🏁 | → | 150 | | 🚧 | ⋄ | 151 | | 💂 | : | 152 | | 🌜 | { | 153 | | 🌛 | } | 154 | | 🤔 | ⍵ | 155 | | 🥺 | ⍺ | 156 | | 😶 | ⍬ | 157 | | 😳 | ∇ | 158 | | 🌳 | # | 159 | | 🪧 | ← | 160 | | 🎮 | ⎕ | 161 | | ⌨️ | ⍞ | 162 | | 🥶 | ¯ | 163 | | 🤱 | ( | 164 | | 🎅 | ) | 165 | 166 | ## FAQ 167 | 168 | ### Why are the brackets 🤱 and 🎅? 169 | The parens are parents. 170 | 171 | ### Why do identifiers turn into flags? 172 | I don't know. 173 | 174 | ### An Emoji programming language already exists(?) 175 | Yes, but [Emojicode](https://www.emojicode.org) is a traditional programming language, not an APL - where's the fun in that? 176 | 177 | ### How do I install this? 178 | Make sure you have a C compiler and GNU APL, then run `make` and then `sudo make install`. The command to invoke the repl is `🙂apl` and you can pipe output to the repl such as `cat life.🙂apl | 🙂apl`. 179 | -------------------------------------------------------------------------------- /life.🙂apl: -------------------------------------------------------------------------------- 1 | 🗨️ The canonical game of life function, called LI (Lithuania) 2 | 🇱🇮🪧🌜👍👍➊ 🤔🛶🔴🐜➌ ➍⚖️🧮🤰😍🥶➊ ⓿ ➊🤐🔴🤣🥶➊ ⓿ ➊🤐🔴🙃🪺🤔🌛 3 | 4 | 🗨️ An array containing a glider, called GL (Greenland) 5 | 🇬🇱🪧➌ ➌📐➊ ➊ ➊ ➊ ⓿ ⓿ ⓿ ➊ ⓿ 6 | 7 | 🗨️ The 8x8 grid to use, called GR (Greece) 8 | 🇬🇷🪧🥶➑ 🥶➑👍🇬🇱 9 | 10 | 🗨️ Print the first 4 steps to the screen 11 | 🎮🪧🌜🇱🇮😬🤔➡️🇬🇷🌛🍑⓿😍📚➌ 12 | -------------------------------------------------------------------------------- /🙂apl.c: -------------------------------------------------------------------------------- 1 | /* 2 | BSD 2-Clause License 3 | 4 | Copyright (c) 2022, Finn Barber 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define LEN 16192 38 | 39 | char *glyphs[][2] = 40 | { 41 | {"🇦", "a"}, 42 | {"🇧", "b"}, 43 | {"🇨", "c"}, 44 | {"🇩", "d"}, 45 | {"🇪", "e"}, 46 | {"🇫", "f"}, 47 | {"🇬", "g"}, 48 | {"🇭", "h"}, 49 | {"🇮", "i"}, 50 | {"🇯", "j"}, 51 | {"🇰", "k"}, 52 | {"🇱", "l"}, 53 | {"🇲", "m"}, 54 | {"🇳", "n"}, 55 | {"🇴", "o"}, 56 | {"🇵", "p"}, 57 | {"🇶", "q"}, 58 | {"🇷", "r"}, 59 | {"🇸", "s"}, 60 | {"🇹", "t"}, 61 | {"🇺", "u"}, 62 | {"🇻", "v"}, 63 | {"🇼", "w"}, 64 | {"🇽", "x"}, 65 | {"🇾", "y"}, 66 | {"🇿", "z"}, 67 | {"⓿", "0"}, 68 | {"➊", "1"}, 69 | {"➋", "2"}, 70 | {"➌", "3"}, 71 | {"➍", "4"}, 72 | {"➎", "5"}, 73 | {"➏", "6"}, 74 | {"➐", "7"}, 75 | {"➑", "8"}, 76 | {"➒", "9"}, 77 | {"🗨️", "⍝"}, 78 | {"✍️", "'"}, 79 | {"🧮", "+"}, 80 | {"🥖", "-"}, 81 | {"⚔️", "×"}, 82 | {"🪓", "÷"}, 83 | {"📈", "⌈"}, 84 | {"📉", "⌊"}, 85 | {"🤯", "*"}, 86 | {"🪵", "⍟"}, 87 | {"🥧", "○"}, 88 | {"📢", "!"}, 89 | {"🎲", "?"}, 90 | {"📏", "|"}, 91 | {"🐜", "∧"}, 92 | {"🛶", "∨"}, 93 | {"🕷", "⍲"}, 94 | {"⛵", "⍱"}, 95 | {"⚖️", "="}, 96 | {"😠", "≠"}, 97 | {"🤝", "≡"}, 98 | {"😡", "≢"}, 99 | {"🔬", "<"}, 100 | {"🤏", "≤"}, 101 | {"🦣", "≥"}, 102 | {"⛰️", ">"}, 103 | {"☝️", "⌷"}, 104 | {"👍", "↑"}, 105 | {"👎", "↓"}, 106 | {"📐", "⍴"}, 107 | {"🪺", "⊂"}, 108 | {"⛏️", "⊃"}, 109 | {"⬅️", "⊣"}, 110 | {"➡️", "⊢"}, 111 | {"🦄", "∪"}, 112 | {"🙏", "∩"}, 113 | {"🙅", "~"}, 114 | {"📚", "⍳"}, 115 | {"👀", "⍸"}, 116 | {"📜", "∊"}, 117 | {"🔎", "⍷"}, 118 | {"🤰", "/"}, 119 | {"🌿", "\\"}, 120 | {"🧬", "⌿"}, 121 | {"🌱", "⍀"}, 122 | {"🙃", "⌽"}, 123 | {"🤣", "⊖"}, 124 | {"😍", ","}, 125 | {"❤️", "⍪"}, 126 | {"🎶", "⍉"}, 127 | {"🔢", "⊥"}, 128 | {"🔡", "⊤"}, 129 | {"🐇", "⌹"}, 130 | {"🏷", "⍎"}, 131 | {"💾", "⍕"}, 132 | {"🧗", "⍋"}, 133 | {"⛷", "⍒"}, 134 | {"🍑", "¨"}, 135 | {"😵", "⍨"}, 136 | {"🚀", "⌶"}, 137 | {"🔑", "⌸"}, 138 | {"🐣", "&"}, 139 | {"👉", "["}, 140 | {"👈", "]"}, 141 | {"🤐", "∘"}, 142 | {"😬", "⍣"}, 143 | {"🔧", "⍠"}, 144 | {"✏️", "⌺"}, 145 | {"😱", "⍤"}, 146 | {"🌍", "@"}, 147 | {"🔴", "."}, 148 | {"🏁", "→"}, 149 | {"🚧", "⋄"}, 150 | {"💂", ":"}, 151 | {"🌜", "{"}, 152 | {"🌛", "}"}, 153 | {"🤔", "⍵"}, 154 | {"🥺", "⍺"}, 155 | {"😶", "⍬"}, 156 | {"😳", "∇"}, 157 | {"🌳", "#"}, 158 | {"🪧", "←"}, 159 | {"🎮", "⎕"}, 160 | {"⌨️", "⍞"}, 161 | {"🥶", "¯"}, 162 | {"🤱", "("}, 163 | {"🎅", ")"}, 164 | }; 165 | 166 | // Unfortunately, this is the last comment you're getting 167 | 168 | void throw_error(char *fmt, ...) 169 | { 170 | fputs("\n\033[31;1m", stderr); 171 | va_list args; 172 | va_start(args, fmt); 173 | vfprintf(stderr, fmt, args); 174 | fputs("\033[0m\n", stderr); 175 | } 176 | 177 | int main(int argc, char **argv) 178 | { 179 | char* string_delim = strdup("✍️"); 180 | char* comment_delim = strdup("🗨️"); 181 | puts(" ___ ___, , __ _\n" 182 | "/ (_) o o / | /|/ \\\\_|_)\n" 183 | "\\__ _ _ _ __ | | |___/ |\n" 184 | "/ / |/ |/ | / \\_| | | | | _|\n" 185 | "\\___/ | | |_/\\__/ |/|_/ \\__/\\_/| (/\\___/\n" 186 | " /|\n" 187 | " Copyright 2022 \\| Finn Barber\n"); 188 | if (!setlocale(LC_ALL, "")) 189 | throw_error("cannot set locale"); 190 | for (size_t i = 0; i < sizeof glyphs / sizeof glyphs[0]; ++i) 191 | { 192 | glyphs[i][0] = strdup(glyphs[i][0]); 193 | glyphs[i][0][mblen(glyphs[i][0], MB_CUR_MAX)] = '\0'; 194 | } 195 | string_delim[mblen(string_delim, MB_CUR_MAX)] = '\0'; 196 | comment_delim[mblen(comment_delim, MB_CUR_MAX)] = '\0'; 197 | static char buf[LEN]; 198 | int apl_in[2]; 199 | pipe(apl_in); 200 | if (!fork()) 201 | { 202 | close(0); 203 | dup(apl_in[0]); 204 | char *aplargs[argc + 3]; 205 | aplargs[0] = argv[0]; 206 | aplargs[1] = "-s"; 207 | aplargs[2] = "--"; 208 | for (int i = 1; i < argc; ++i) 209 | aplargs[i + 2] = argv[i]; 210 | aplargs[argc + 2] = NULL; 211 | int apl_out[2]; 212 | pipe(apl_out); 213 | if (!fork()) 214 | { 215 | close(0); 216 | dup(apl_out[0]); 217 | static char buf[LEN]; 218 | while (fgets(buf, sizeof buf, stdin)) printf("► %s", buf); 219 | } 220 | close(1); 221 | dup(apl_out[1]); 222 | return execvp("apl", aplargs); 223 | } 224 | int out = apl_in[1]; 225 | while (fgets(buf, sizeof buf, stdin)) 226 | { 227 | _Bool string = 0; 228 | _Bool comment = 0; 229 | char *line = buf; 230 | while (*line) 231 | { 232 | int sz = mblen(line, MB_CUR_MAX); 233 | char chr[sz + 1]; 234 | memcpy(chr, line, sz); 235 | chr[sz] = '\0'; 236 | if (!strcmp(string_delim, chr)) string = !string; 237 | else if (string || comment || isspace(*chr)) 238 | { 239 | write(out, chr, sz); 240 | goto next_char; 241 | } 242 | if (!strcmp(comment_delim, chr)) comment = 1; 243 | for (int i = 0; i < (sizeof glyphs / sizeof glyphs[0]); ++i) 244 | { 245 | if (!strcmp(glyphs[i][0], chr)) 246 | { 247 | write(out, glyphs[i][1], strlen(glyphs[i][1])); 248 | goto next_char; 249 | } 250 | } 251 | if (!isgraph(*chr)) goto next_char; 252 | throw_error("invalid glyph '%s' (0x%lx)", chr, *(long *)chr, strlen(chr)); 253 | goto next_line; 254 | next_char: 255 | line += sz; 256 | } 257 | if (string) throw_error("unterminated string"); 258 | next_line:; 259 | } 260 | write(out, "\n", 1); 261 | } 262 | --------------------------------------------------------------------------------