├── examples ├── 99bottles.fuck ├── helloworld.clean ├── helloworld.fuck ├── hiddenmessage.fuck ├── jumptest.fuck └── response.fuck ├── fuck.lua ├── fuck.php └── readme /examples/99bottles.fuck: -------------------------------------------------------------------------------- 1 | fuck output 2 | fuck temp 3 | fuck index 4 | fuck total 5 | fuck dec 6 | fucking output bottles 7 | fucking temp of 8 | fucked output temp 9 | fucking temp beer 10 | fucked output temp 11 | fucking temp on 12 | fucked output temp 13 | fucking temp the 14 | fucked output temp 15 | fucking temp wall\n 16 | fucked output temp 17 | fucking total 0 18 | fucking index 99 19 | fucking dec -1 20 | motherfuck loop 21 | fucking temp 0 22 | fucked temp index 23 | fucked temp total 24 | motherfucked temp continue 25 | motherfucking quit 26 | motherfuck continue 27 | fuck string 28 | fucked string index 29 | fucked string output 30 | unfucked string 31 | fucked index dec 32 | motherfucking loop 33 | motherfuck quit 34 | -------------------------------------------------------------------------------- /examples/helloworld.clean: -------------------------------------------------------------------------------- 1 | table_init output 2 | table_init temp 3 | table_set output Hello 4 | table_set temp World! 5 | table_mod output temp 6 | table_output output 7 | -------------------------------------------------------------------------------- /examples/helloworld.fuck: -------------------------------------------------------------------------------- 1 | fuck output 2 | fuck temp 3 | fucking output Hello 4 | fucking temp World! 5 | fucked output temp 6 | unfucked output 7 | -------------------------------------------------------------------------------- /examples/hiddenmessage.fuck: -------------------------------------------------------------------------------- 1 | Fuck you_ , Fuck George , what the hell is wrong with you_ man? 2 | Fucking hell, you_ Would do this to me, wouldn't you? 3 | You really fucked up George you_ bastard. 4 | Fucking leave it to you_ you son of a bitch. 5 | I'll make sure you get fucked up so bad George . you_ won't even know 6 | what went through your fucking face. u mind if I just beat you to a pulp? 7 | You fucked me so badly George. you_ know what's going to happen? 8 | Fucking , you_ pick up your teeth off the ground is what's gonna happen. 9 | You fucked everybody George you_ fucking moron. you_ up to no good, I know it 10 | 11 | Super fucked up George you_ asshole. 12 | 13 | No one will ever talk to fucking you_ Pete most of all. 14 | I was fucked before you George you_ know that? 15 | I have no idea what fucking shit you_ on cause when Pete was there 16 | I fucked him up bad, George you_ freak. 17 | 18 | I will enjoy force fucking you_ your own mother won't be able to recognize you 19 | after i've totally fucked with you George you_ ain't going to be happy 20 | 21 | Jesus won't even answer to you fucking hell. And you have no you_ way to get 22 | past this, cause my friends are fucked strong George you_ not cool. 23 | 24 | When will all this fucking stop. Will will this make you_ over? 25 | Crazy fucked up George you_ you crazy. 26 | 27 | Make this unfucked George seriously. 28 | 29 | -------------------------------------------------------------------------------- /examples/jumptest.fuck: -------------------------------------------------------------------------------- 1 | motherfucking test 2 | fuck nevergetshere 3 | fucking nevergetshere SkipMe 4 | unfucked nevergetshere 5 | motherfuck test 6 | fuck awesome 7 | fucking awesome ShowMe 8 | unfucked awesome 9 | -------------------------------------------------------------------------------- /examples/response.fuck: -------------------------------------------------------------------------------- 1 | fuck output 2 | fuck temp 3 | fuck name 4 | fucking output What 5 | fucking temp is 6 | fucked output temp 7 | fucking temp your 8 | fucked output temp 9 | fucking temp name?\n 10 | fucked output temp 11 | unfucked output 12 | unfucking name 13 | fucking output Hello 14 | fucked output name 15 | unfucked output 16 | -------------------------------------------------------------------------------- /fuck.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/lua 2 | 3 | arg_types = { 4 | raw = 1,--"raw", 5 | var = 2,--"var", 6 | label = 3,--"label", 7 | } 8 | 9 | local arg_table = { 10 | table_init = {arg_types.raw}, 11 | table_set = {arg_types.var,arg_types.raw}, 12 | table_mod = {arg_types.var,arg_types.var}, 13 | table_input = {arg_types.var}, 14 | table_output = {arg_types.var}, 15 | label_define = {arg_types.raw}, 16 | label_jump = {arg_types.label}, 17 | label_branch = {arg_types.var,arg_types.label}, 18 | } 19 | 20 | local command_keywords = { 21 | table_init = "fuck", 22 | table_set = "fucking", 23 | table_mod = "fucked", 24 | table_input = "unfucking", 25 | table_output = "unfucked", 26 | label_define = "motherfuck", 27 | label_jump = "motherfucking", 28 | label_branch = "motherfucked", 29 | } 30 | 31 | local commands = { 32 | table_init = { 33 | op = function(args) 34 | vars[string.lower(args[1])] = "" 35 | end, 36 | }, 37 | table_set = { 38 | op = function(args) 39 | assert(vars[args[1]], 40 | "ERROR["..pc.."] var args[0] <"..args[1].."> is not initialized.") 41 | vars[args[1]] = args[2] 42 | end, 43 | }, 44 | table_mod = { 45 | op = function(args) 46 | assert(vars[args[1]], 47 | "ERROR["..pc.."] var args[0] <"..args[1].."> is not initialized.") 48 | assert(vars[args[2]], 49 | "ERROR["..pc.."] var args[1] <"..args[2].."> is not initialized.") 50 | local n0 = tonumber(vars[args[1]]) 51 | local n1 = tonumber(vars[args[2]]) 52 | if n0 and n1 then 53 | vars[args[1]] = vars[args[1]] + vars[args[2]] 54 | else 55 | vars[args[1]] = tostring(vars[args[1]]) .. " " .. tostring(vars[args[2]]) 56 | end 57 | end, 58 | }, 59 | table_input = { 60 | op = function(args) 61 | assert(vars[args[1]], 62 | "ERROR["..pc.."] var args[0] <"..args[1].."> is not initialized.") 63 | vars[args[1]] = io.read() 64 | end, 65 | }, 66 | table_output = { 67 | op = function(args) 68 | assert(vars[args[1]], 69 | "ERROR["..pc.."] var args[0] <"..args[1].."> is not initialized.") 70 | local tmp = string.gsub(vars[args[1]],'\\n', "\n") 71 | io.write(tmp) 72 | end, 73 | 74 | }, 75 | label_define = { 76 | op = function(args) 77 | -- this function has been done pre-emptively 78 | end, 79 | }, 80 | label_jump = { 81 | op = function(args) 82 | assert(labels[args[1]], 83 | "ERROR["..pc.."] label args[0] <"..args[1].."> is not initialized.") 84 | pc = labels[args[1]]+1 85 | end, 86 | }, 87 | label_branch = { 88 | op = function(args) 89 | assert(vars[args[1]], 90 | "ERROR["..pc.."] var args[0] <"..args[1].."> is not initialized.") 91 | assert(labels[args[2]], 92 | "ERROR["..pc.."] label args[1] <"..args[2].."> is not initialized.") 93 | if tonumber(vars[args[1]]) ~= 0 then 94 | pc = labels[args[2]] 95 | end 96 | 97 | end, 98 | }, 99 | } 100 | 101 | function usage() 102 | print("Usage: "..tostring(arg[0]).." [options] input\n") 103 | end 104 | 105 | config = {} 106 | for i,v in pairs(arg) do 107 | if i > 0 then 108 | if v == "-h" or v == "--help" then 109 | usage() 110 | return 111 | elseif v == "-d" or v == "--debug" then 112 | elseif v == "-c" or v == "--clean" then 113 | for keyword,map in pairs(command_keywords) do 114 | command_keywords[keyword] = keyword 115 | end 116 | else 117 | input = v 118 | break 119 | end 120 | end 121 | end 122 | 123 | -- make inverse lookup table 124 | local command_keywords_inv = {} 125 | for i,v in pairs(command_keywords) do 126 | command_keywords_inv[v] = i 127 | end 128 | 129 | -- add keywords to objects for reference 130 | for keyword,command in pairs(commands) do 131 | command.keyword = command_keywords[keyword] 132 | end 133 | 134 | local program = {} 135 | 136 | if input then 137 | input_file = io.open(input,'r') 138 | if input_file then 139 | local current = nil 140 | repeat 141 | local char = input_file:read(1) 142 | if char ~= nil then 143 | if char == "\n" or char == "\r" or char == " " then 144 | table.insert(program,current) 145 | current = nil 146 | else 147 | current = (current or "") .. char 148 | end 149 | else 150 | table.insert(program,current) 151 | current = nil 152 | end 153 | until char == nil 154 | io.close(input_file) 155 | else 156 | print(tostring(arg[0])..": error: "..tostring(input)..": No such file") 157 | end 158 | else 159 | usage() 160 | end 161 | 162 | labels = {} 163 | for pc,word in pairs(program) do 164 | if word == command_keywords.label_define then 165 | --print("Found label:",program[pc+1]) 166 | labels[ program[pc+1] ] = pc 167 | end 168 | end 169 | 170 | pc = 1 171 | vars = {} 172 | local arg_stack = {} 173 | local current_command_keyword = nil 174 | --local current_command = nil 175 | 176 | while pc <= #program do 177 | 178 | local current_line = string.lower(program[pc]) 179 | 180 | --print("current line:",current_line) 181 | 182 | if current_command_keyword then 183 | 184 | --print("current command:",current_command_keyword) 185 | 186 | local var_type = arg_table[current_command_keyword][#arg_stack+1] 187 | 188 | --print("var type:",var_type) 189 | 190 | if var_type == arg_types.raw then 191 | table.insert(arg_stack,program[pc]) 192 | elseif var_type == arg_types.var then 193 | if vars[current_line] then 194 | table.insert(arg_stack,current_line) 195 | end 196 | elseif var_type == arg_types.label then 197 | if labels[current_line] then 198 | table.insert(arg_stack,current_line) 199 | end 200 | end 201 | 202 | --print("#arg_stack",#arg_stack,"#arg_table[current_command_keyword]",#arg_table[current_command_keyword]) 203 | 204 | if #arg_stack == #arg_table[current_command_keyword] then 205 | --print(">call stack") 206 | --for i,v in pairs(arg_stack) do print('>>',i,v) end 207 | commands[current_command_keyword].op(arg_stack) -- this is a function 208 | current_command_keyword = nil 209 | arg_stack = {} 210 | end 211 | 212 | else -- no current command 213 | current_command_keyword = command_keywords_inv[current_line] 214 | --print(">new command",current_command_keyword) 215 | end 216 | 217 | pc=pc+1 218 | 219 | --print("") 220 | 221 | end 222 | io.write("\n") 223 | -------------------------------------------------------------------------------- /fuck.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | "table_init", 35 | "fucking" => "table_set", 36 | "fucked" => "table_mod", 37 | "unfucking" => "table_input", 38 | "unfucked" => "table_output", 39 | "motherfuck" => "label_define", 40 | "motherfucking" => "label_jump", 41 | "motherfucked" => "label_branch", 42 | ); 43 | 44 | // Convert the table to the clean definition. 45 | if($clean){ 46 | $clean_commands = array(); 47 | foreach($commands as $command){ 48 | $clean_commands[$command] = $command; 49 | } 50 | $commands = $clean_commands; 51 | } 52 | 53 | // The argument types of the commands 54 | $argtable = array( 55 | "table_init" => array("raw"), 56 | "table_set" => array("var","raw"), 57 | "table_mod" => array("var","var"), 58 | "table_input" => array("var"), 59 | "table_output" => array("var"), 60 | "label_define" => array("raw"), 61 | "label_jump" => array("label"), 62 | "label_branch" => array("var","label") 63 | ); 64 | 65 | if(is_file($input)){ 66 | // Read the data, remove trailing newline, remove newlines, and then split by 67 | // word into an array. 68 | // TODO: Make this into a preg_match_all(). 69 | $data = explode(" ", 70 | implode(" ", 71 | explode("\n", 72 | rtrim(file_get_contents($input)) 73 | ) 74 | ) 75 | ); 76 | } else { 77 | die("fuck: fatal error: no input files.\nrun terminated.\n"); 78 | } 79 | 80 | // Run through the data once to check for labels 81 | $labels = array(); 82 | foreach($data as $pc => $line){ 83 | // Labels are case insensitive. 84 | $currentline = strtolower($line); 85 | // if the command 86 | if(isset($commands[$currentline]) and 87 | $commands[$currentline] == "label_define"){ 88 | // Find all of the label_define commands, and put argument in an array. 89 | // TODO: Do more debugging to check if by running from this argument, one 90 | // can use a command op as a argument. 91 | // Check label_jump and label_branch too 92 | $labels[$data[$pc+1]]=$pc; 93 | } 94 | } 95 | // Program Counter 96 | $pc = 0; 97 | // Array for variables 98 | $vars = array(); 99 | // Argument stack 100 | $argstack = array(); 101 | // Current Operation 102 | $currentop = null; 103 | 104 | // While program counter is not at the end 105 | while($pc < count($data)){ 106 | // case insensitivity 107 | $currentline = strtolower($data[$pc]); 108 | if($currentop){ // looking for arguments for the current operation. 109 | // Determine type from the argument type table. 110 | $type = $argtable[$currentop][count($argstack)]; 111 | if($type == "raw"){ 112 | // If the argument is raw, then put the next thing on the stack. 113 | // raw arguments are conditionally case insensitive. 114 | $argstack[] = $data[$pc]; 115 | } elseif($type == "var"){ 116 | // If the argument is var, then put the next var on the stack. 117 | if(isset($vars[$currentline])){ 118 | $argstack[] = $currentline; 119 | if($debug){echo "Adding var to argstack.\n";} 120 | } 121 | } elseif($type == "label"){ 122 | // If the argument is label, then put the next label on the stack. 123 | if(isset($labels[$currentline])){ 124 | $argstack[] = $currentline; 125 | if($debug){echo "Adding label to argstack.\n";} 126 | } 127 | } 128 | // If the argument stack is ready for the current operation 129 | if(count($argstack)==count($argtable[$currentop])){ 130 | // Execute the operation, and clear the operation and argument stack. 131 | $currentop($argstack); 132 | $currentop = null; 133 | $argstack = null; 134 | } 135 | } else { // looking for a current operation. 136 | // if a valid command 137 | if(isset($commands[$currentline])){ 138 | $currentop = $commands[$currentline]; 139 | } 140 | } 141 | // increment the program counter. 142 | $pc++; 143 | } 144 | // echo out newline at end of file 145 | echo "\n"; 146 | 147 | // These functions are thoroughly described in the readme file. All functions 148 | // only take in arguments from the argument stack, and do not return anything, 149 | // as they access everything globally. Usually, this would be a bad idea, but 150 | // the language is so small, it really does not matter and lowers the amount of 151 | // overhead being used. 152 | function table_init($args){ 153 | global $vars,$pc,$debug; 154 | if($debug){echo "table_init ".implode(" ",$args)."\n";} 155 | // Specifically using empty string as oppsed to nill to avoid having to check 156 | // with array_key_exists(). 157 | // TODO: Change to array_key_exists() for speed. 158 | // Variable names are case insensitive. 159 | $vars[strtolower($args[0])] = ""; 160 | } 161 | function table_set($args){ 162 | global $vars,$pc,$debug; 163 | if($debug){echo "table_set ".implode(" ",$args)."\n";} 164 | if(!isset($vars[$args[0]])){ 165 | die("ERROR[$pc]: var args[0] <".$args[0]."> is not initialized.\n"); 166 | } 167 | // Raw string data is case sensitive. 168 | $vars[$args[0]] = $args[1]; 169 | } 170 | function table_mod($args){ 171 | global $vars,$pc,$debug; 172 | if($debug){echo "table_mod ".implode(" ",$args)."\n";} 173 | if(!isset($vars[$args[0]])){ 174 | die("ERROR[$pc]: var args[0] <".$args[0]."> is not initialized.\n"); 175 | } 176 | if(!isset($vars[$args[1]])){ 177 | die("ERROR[$pc]: var args[1] <".$args[1]."> is not initialized.\n"); 178 | } 179 | // TODO: Make is_numeric more portable if the language changes to something 180 | // lower level, like C. 181 | // If both arguments are numbers: 182 | if(is_numeric($vars[$args[0]]) and is_numeric($vars[$args[1]])){ 183 | // Treat them as numbers. 184 | $vars[$args[0]] += $vars[$args[1]]; 185 | } else { 186 | // Treat them as strings. 187 | $vars[$args[0]] .= " ".$vars[$args[1]]; 188 | } 189 | } 190 | function table_input($args){ 191 | global $vars,$pc,$debug; 192 | if($debug){echo "table_input ".implode(" ",$args)."\n";} 193 | if(!isset($vars[$args[0]])){ 194 | die("ERROR[$pc]: var args[0] <".$args[0]."> is not initialized.\n"); 195 | } 196 | // using readline over fgets because this script is very linux like. 197 | // TODO: change over to fgets for portability, or, implement the 198 | // readline_history features. 199 | $vars[$args[0]] = readline(""); 200 | } 201 | function table_output($args){ 202 | global $vars,$pc,$debug; 203 | if($debug){echo "table_output ".implode(" ",$args)."\n";} 204 | if(!isset($vars[$args[0]])){ 205 | die("ERROR[$pc]: var args[0] <".$args[0]."> is not initialized.\n"); 206 | } 207 | // The system took in \n as actual data, so it needs to be translated to a 208 | // newline. 209 | echo preg_replace('@\\\\n@',"\n",$vars[$args[0]]); 210 | } 211 | function label_define($args){ 212 | global $labels,$pc,$debug; 213 | if($debug){echo "label_define ".implode(" ",$args)."\n";} 214 | // This function does not actually do anything, but it is important to render 215 | // it so that the system does not treat it or it's argument as a raw 216 | // arguments. 217 | } 218 | function label_jump($args){ 219 | global $labels,$pc,$debug; 220 | if($debug){echo "label_jump ".implode(" ",$args)."\n";} 221 | if(!isset($labels[$args[0]])){ 222 | die("ERROR[$pc]: label args[0] <".$args[0]."> is not initialized.\n"); 223 | } 224 | // Change the program counter to the defined label's argument. 225 | $pc = $labels[$args[0]]+1; 226 | } 227 | function label_branch($args){ 228 | global $labels,$vars,$pc,$debug; 229 | if($debug){echo "label_branch ".implode(" ",$args)."\n";} 230 | if(!isset($vars[$args[0]])){ 231 | die("ERROR[$pc]: var args[0] <".$args[0]."> is not initialized.\n"); 232 | } 233 | if(!isset($labels[$args[1]])){ 234 | die("ERROR[$pc]: label args[1] <".$args[1]."> is not initialized.\n"); 235 | } 236 | // Change the program counter to the defined label if variable does not equal 237 | // zero. 238 | if($vars[$args[0]]!="0"){ 239 | $pc = $labels[$args[1]]+1; 240 | } 241 | } 242 | 243 | function usage(){ 244 | ?> 245 | Usage: fuck [options] input 246 | Options: 247 | -d|--debug Enable debug mode to show how the code is being 248 | rendered. 249 | -c|--clean Run the code using the clean reserved words. 250 | -h|--help Display this information 251 | 262 | * 263 | * @param $raw_flags 264 | * This string represents the flags that should be parsed by this function. 265 | * The flags that this function will look for is seperated by commas. E.g.; 266 | * "-d,--debug,-n!,--name!" 267 | * If flag has an exclamation mark (`!`) at the end, the function will 268 | * assume that the flag is expecting an argument. 269 | * @param $argv|NULL 270 | * This is the argument vector provided when a script is invoked by php-cli. 271 | * By default, it will use the global `$argv`, but can be overridden by 272 | * passing an array of arguments. 273 | * 274 | * @return 275 | * The returned data will consist of a nexted associative array containing: 276 | * - operands: an array of arguments that are not flags or flag operands 277 | * - flags: an associtave array of flags that were found. If the flag is; 278 | * - expecting an argument: the value will be assigned. 279 | * - not expecting an arguement: the value will be null. 280 | */ 281 | 282 | 283 | function yago($raw_flags,$argv=NULL){ 284 | if($argv === NULL){ 285 | global $argv; 286 | } 287 | $stack = array(); 288 | $stack['operands'] = array(); 289 | $stack['flags'] = array(); 290 | $search_flags = explode(",",$raw_flags); 291 | while(!empty($argv)){ 292 | $arg = array_shift($argv); 293 | if(in_array($arg,$search_flags)){ 294 | $stack['flags'][$arg] = NULL; 295 | } elseif(in_array("$arg!",$search_flags)){ 296 | $stack['flags'][$arg] = array_shift($argv); 297 | } elseif(substr($arg,0,1)!="-") { 298 | $stack['operands'][] = $arg; 299 | } 300 | } 301 | return $stack; 302 | } -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | ..... .. 2 | .H8888888x. '`+ < .z@8"` 3 | :888888888888x. ! x. . !@88E 4 | 8~ `"*88888888" .@88k z88u . '888E u 5 | ! . `f"""" ~"8888 ^8888 .udR88N 888E u@8NL 6 | ~:...-` :8L <)88: 8888 888R <888'888k 888E`"88*" 7 | . :888:>X88! 8888 888R 9888 'Y" 888E .dN. 8 | :~"88x 48888X ^` 8888 888R 9888 888E~8888 9 | < :888k'88888X 8888 ,888B . 9888 888E '888& 10 | d8888f '88888X "8888Y 8888" ?8888u../ 888E 9888. 11 | :8888! ?8888> `Y" 'YP "8888P' '"888*" 4888" 12 | X888! 8888~ "P' "" "" 13 | '888 X88f 14 | '%8: .8*" THE ESOTERIC INSULT LANGUAGE 15 | ^----~"` 16 | 17 | Description: 18 | The purpose of "Fuck" (capital F) is to provide a programming language to 19 | insult people, but still allow the recipient to decipher what you're really 20 | trying to say. 21 | 22 | Dependencies: 23 | This language has two implementations. 24 | 25 | Lua: 26 | 27 | This is a linux script pointing to `/usr/bin/lua`. 28 | This script has been tested with lua5.1. 29 | For aptitude users please use: `sudo apt-get install lua5.1` 30 | 31 | PHP: 32 | 33 | This is a linux script pointing to `/usr/bin/php`. 34 | This script has been tested with php5-cli. 35 | For aptitude users please use: `sudo apt-get install php5 php5-cli` 36 | 37 | Operation: 38 | Fuck reads every word until it finds a valid command. 39 | Once it has a command it will read until it finds a valid argument type 40 | (var|label|raw). 41 | 42 | Usage: 43 | fuck [options] input 44 | Options: 45 | -d|--debug Enable debug mode to show how the code is being 46 | rendered. 47 | -c|--clean Run the code using the clean reserved words. 48 | -h|--help Display this information 49 | 50 | Types: 51 | .. A variable as defined with fuck (table_init) 52 | .. A series of characters without a space 53 |