commit 548f9ba9c137354efdae639ba1b389637f2ac97e Author: osmarks Date: Wed Aug 12 19:16:20 2020 +0100 initial commit v2 diff --git a/beep.py b/beep.py new file mode 100644 index 0000000..b6e97b1 --- /dev/null +++ b/beep.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# based on : www.daniweb.com/code/snippet263775.html +# from https://stackoverflow.com/questions/33879523/python-how-can-i-generate-a-wav-file-with-beeps +import math +import wave +import struct + +# Audio will contain a long list of samples (i.e. floating point numbers describing the +# waveform). If you were working with a very long sound you'd want to stream this to +# disk instead of buffering it all in memory list this. But most sounds will fit in +# memory. +audio = [] +sample_rate = 44100.0 + + +def append_silence(duration_milliseconds=500): + num_samples = duration_milliseconds * (sample_rate / 1000.0) + for x in range(int(num_samples)): + audio.append(0.0) + return + + +def append_sinewave( + freq=440.0, + duration_milliseconds=500, + volume=1.0): + global audio # using global variables isn't cool. + num_samples = duration_milliseconds * (sample_rate / 1000.0) + for x in range(int(num_samples)): + audio.append(volume * math.sin(2 * math.pi * freq * ( x / sample_rate ))) + +def append_squarewave( + freq=440.0, + duration_milliseconds=500, + volume=1.0): + global audio + num_samples = duration_milliseconds * (sample_rate / 1000.0) + samples_per_toggle = math.floor(sample_rate / freq) + for x in range(int(num_samples)): + on = math.floor(x / samples_per_toggle) % 2 + audio.append(volume * on) + +def save_wav(file_name): + wav_file=wave.open(file_name,"w") + nchannels = 1 + sampwidth = 2 + nframes = len(audio) + comptype = "NONE" + compname = "not compressed" + wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname)) + for sample in audio: + wav_file.writeframes(struct.pack('h', int( sample * 32767.0 ))) + + wav_file.close() + return + +#for _ in range(8): +# append_sinewave(volume=1.0, freq=1000.0) +# append_silence() +append_sinewave(freq=500, duration_milliseconds=500) +append_sinewave(freq=1000, duration_milliseconds=500) +append_sinewave(freq=2000, duration_milliseconds=500) +append_sinewave(freq=500, duration_milliseconds=500) +save_wav("output.wav") \ No newline at end of file diff --git a/emoji_ternarize.py b/emoji_ternarize.py new file mode 100755 index 0000000..0d23610 --- /dev/null +++ b/emoji_ternarize.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import gmpy2 + +def to_ternary(byte): + return gmpy2.digits(byte, 3).zfill(6) + +def to_emoji(digit): + if digit == "0": return ":cactus:" + if digit == "1": return ":hash:" + if digit == "2": return ":pig:" + +def emojiternarize(string): + out = "" + for byte in string.encode("utf-8"): + out += " ".join([to_emoji(d) for d in to_ternary(byte)]) + " " + return out + +print(emojiternarize(input())) diff --git a/eso-interpreter.py b/eso-interpreter.py new file mode 100644 index 0000000..e5316d1 --- /dev/null +++ b/eso-interpreter.py @@ -0,0 +1,28 @@ +code = input() +l = len(code) +acc = 0 +pos = 0 +incr = 1 +num_lookup = { "zero": 0, "one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6, "seven": 7, "eight": 8, "nine": 9 } +while pos < l: + char = code[pos] + if char == "i": + h, g = list(range(pos + 1, l)), list(range(pos - 1, 0, -1)) + for i in h + g if incr == 1 else g + h: + if code[i] == "i": + pos = (i + 1) % l + break + continue + elif char == "p": pos += incr + elif char == "a": acc += 1 + elif char == "e": acc -= 1 + elif char == "v": incr *= -1 + elif char == "~": + acc = 0 + for x, n in enumerate(reversed(input().split(" "))): acc += 10**x * num_lookup[n] + elif char == "`": print(end=chr(acc)) + elif char == "[": + if acc != 0: + acc = int(str(acc) + bin(acc)[2:]) + else: print("wrong.") + pos += incr \ No newline at end of file diff --git a/esolangs-interpreter-race/hello.ms b/esolangs-interpreter-race/hello.ms new file mode 100644 index 0000000..66cc7a4 --- /dev/null +++ b/esolangs-interpreter-race/hello.ms @@ -0,0 +1,17 @@ +_mulloop := (pop warp new new new new new new new new new new warp _mulloop) +10* := warp new enter warp _mulloop exit pop warp exit send warp enter +[ := new enter +0 := 10* +1 := 10* new +2 := 10* new new +3 := 10* new new new +4 := 10* new new new new +5 := 10* new new new new new +6 := 10* new new new new new new +7 := 10* new new new new new new new +8 := 10* new new new new new new new new +9 := 10* new new new new new new new new new +] := exit +. := ] write [ + +main := [ 7 2 . 1 0 1 . 1 0 8 . 1 0 8 . 1 1 1 . 4 4 . 3 2 . 1 1 9 . 1 1 1 . 1 1 4 . 1 0 8 . 1 0 0 . 3 3 . 1 0 . ] \ No newline at end of file diff --git a/esolangs-interpreter-race/orig.js b/esolangs-interpreter-race/orig.js new file mode 100644 index 0000000..a46f332 --- /dev/null +++ b/esolangs-interpreter-race/orig.js @@ -0,0 +1,178 @@ +const { regex, sequenceOf, char, choice, many1, many, str, coroutine, possibly } = require("arcsecond") +const readline = require("readline-sync") + +const spaces = regex(/^ */) +const whitespace = regex(/^[ \n\t]*/) +const name = regex(/^[^ \n\t():]+/) +const code = many(coroutine(function*() { + yield spaces + return yield choice([ + coroutine(function*() { + yield char("(") + const x = yield code + yield spaces + yield char(")") + return x + }), + name + ]) +})) +const program = sequenceOf([ + many1(coroutine(function*() { + yield whitespace + const n = yield name + yield whitespace + yield str(":=") + const c = yield code + return { code: c, name: n } + })), + possibly(whitespace) +]).map(([x, _]) => x) + +const parsed = program.run(`_mulloop := (pop warp new new new new new new new new new new warp _mulloop) +10* := warp new enter warp _mulloop exit pop warp exit send warp enter +[ := new enter +0 := 10* +1 := 10* new +2 := 10* new new +3 := 10* new new new +4 := 10* new new new new +5 := 10* new new new new new +6 := 10* new new new new new new +7 := 10* new new new new new new new +8 := 10* new new new new new new new new +9 := 10* new new new new new new new new new +] := exit +. := ] write [ + +main := [ 7 2 . 1 0 1 . 1 0 8 . 1 0 8 . 1 1 1 . 4 4 . 3 2 . 1 1 9 . 1 1 1 . 1 1 4 . 1 0 8 . 1 0 0 . 3 3 . 1 0 . ] +`).result +//const parsed = program.run(`main := read write main`).result + +// --------- + +let stackL = {depth: 0, children: []}, stackR = {depth: 0, children: []}; +let currentIsLeft = true; + +function depthDelta(x) { + if(currentIsLeft) + stackL["depth"]+=x; + else + stackR["depth"]+=x; +} + +function currentStack() { + let depth, currentStack; + + if(currentIsLeft) { + depth = stackL["depth"]; + currentStack = stackL["children"]; + } else { + depth = stackR["depth"]; + currentStack = stackR["children"]; + } + + for(let i = 0; i < depth; i++) { + const s = currentStack.length - 1 + currentStack = currentStack[s]; + } + + return currentStack; +} + +// --------- + +function wrap_new() { + currentStack().push([]); +} + +function wrap_pop() { + currentStack().pop(); +} + +function wrap_enter() { + depthDelta(1) +} + +function wrap_exit() { + depthDelta(-1) +} + +function wrap_warp() { + currentIsLeft = !currentIsLeft; +} + +function wrap_send() { + let toMove = currentStack().pop(); + + wrap_warp(); + + currentStack().push(toMove); + + wrap_warp() +} + +function wrap_read(n) { + let thisStack = []; + + for(let i = 0; i < n; i++) { + thisStack.push([]); + } + + currentStack().push(thisStack); +} + +function wrap_write() { + return currentStack().pop().length; +} + +// --------- + +const env = { + warp: wrap_warp, + read: () => { + wrap_read(readline.question("input char: ").codePointAt(0)) + }, + write: () => { + console.log("output char:", String.fromCodePoint(wrap_write())) + }, + send: wrap_send, + exit: wrap_exit, + enter: wrap_enter, + pop: wrap_pop, + new: wrap_new, +} + +for (const def of parsed) { + env[def.name] = def.code +} + +const DEBUG = false + +const execute = code => { + for (const fn of code) { + //console.log("stacks", stackL, stackR) + // is bracketed, run if stack not empty + if (Array.isArray(fn)) { + if (currentStack().length !== 0) { + if (DEBUG) console.log("brackets", fn) + execute(fn) + } + // is a regular function call or whatever, run it + } else { + const v = env[fn] + if (!v) { + throw new Error(fn + " is undefined") + } + if (typeof v === "function") { + if (DEBUG) console.log("builtin", fn) + v() + } else { + if (DEBUG) console.log("normal", fn) + execute(v) + } + } + } +} + +execute(env.main) \ No newline at end of file diff --git a/esolangs-interpreter-race/package-lock.json b/esolangs-interpreter-race/package-lock.json new file mode 100644 index 0000000..eddde0b --- /dev/null +++ b/esolangs-interpreter-race/package-lock.json @@ -0,0 +1,16 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "arcsecond": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/arcsecond/-/arcsecond-2.0.4.tgz", + "integrity": "sha512-7ZJLP7dlS4Qs6eccHQDGZIDGutTjVmpU3GawAHNcBiX3xo3kRC1y5KLlJSU/XIk24ahgmpsWSYVcElW239WDVQ==" + }, + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" + } + } +} diff --git a/esolangs-interpreter-race/thing.js b/esolangs-interpreter-race/thing.js new file mode 100644 index 0000000..dda91ff --- /dev/null +++ b/esolangs-interpreter-race/thing.js @@ -0,0 +1,189 @@ +const { regex, sequenceOf, char, choice, many1, many, str, coroutine, possibly } = require("arcsecond") +const fs = require("fs").promises + +const spaces = regex(/^ */) +const whitespace = regex(/^[ \n\t]*/) +const name = regex(/^[^ \n\t():]+/) +const code = many(coroutine(function*() { + yield spaces + return yield choice([ + coroutine(function*() { + yield char("(") + const x = yield code + yield spaces + yield char(")") + return x + }), + name + ]) +})) +const program = sequenceOf([ + many1(coroutine(function*() { + yield whitespace + const n = yield name + yield whitespace + yield str(":=") + const c = yield code + return { code: c, name: n } + })), + possibly(whitespace) +]).map(([x, _]) => x) + +// --------- + +let stackL = {depth: 0, children: []}, stackR = {depth: 0, children: []}; +let currentIsLeft = true; + +function depthDelta(x) { + if(currentIsLeft) + stackL["depth"]+=x; + else + stackR["depth"]+=x; +} + +function currentStack() { + let depth, currentStack; + + if(currentIsLeft) { + depth = stackL["depth"]; + currentStack = stackL["children"]; + } else { + depth = stackR["depth"]; + currentStack = stackR["children"]; + } + + for(let i = 0; i < depth; i++) { + const s = currentStack.length - 1 + currentStack = currentStack[s]; + } + + return currentStack; +} + +// --------- + +function wrap_new() { + currentStack().push([]); +} + +function wrap_pop() { + currentStack().pop(); +} + +function wrap_enter() { + depthDelta(1) +} + +function wrap_exit() { + depthDelta(-1) +} + +function wrap_warp() { + currentIsLeft = !currentIsLeft; +} + +function wrap_send() { + let toMove = currentStack().pop(); + + wrap_warp(); + + currentStack().push(toMove); + + wrap_warp() +} + +function wrap_read(n) { + let thisStack = []; + + for(let i = 0; i < n; i++) { + thisStack.push([]); + } + + currentStack().push(thisStack); +} + +function wrap_write() { + return currentStack().pop().length; +} + +// --------- + +const stdin = process.stdin +stdin.setRawMode(true) +stdin.resume() +let resolveNext = null +stdin.on("data", key => { + // ctrl+C and ctrl+D + if (key[0] === 3 || key[0] === 4) { + return process.exit() + } + if (resolveNext) { resolveNext(key[0]) } +}) +stdin.on("end", () => process.exit()) +const awaitKeypress = () => new Promise((resolve, reject) => { resolveNext = resolve }) + +const DEBUG = false + +const execute = async (code, env) => { + let fn + let queue = code + while (fn = queue.shift()) { + // is bracketed, run if stack not empty + if (Array.isArray(fn)) { + if (currentStack().length !== 0) { + if (DEBUG) console.log("brackets", fn) + queue = fn.concat(queue) + } + // is a regular function call or whatever, run it + } else { + const v = env[fn] + if (!v) { + throw new Error(fn + " is undefined") + } + if (typeof v === "function") { + if (DEBUG) console.log("builtin", fn) + await v() + } else { + if (DEBUG) console.log("normal", fn) + queue = v.concat(queue) + } + } + } +} + +const run = async () => { + const code = await fs.readFile(process.argv[2], { encoding: "utf8" }) + const parseResult = program.run(code) + if (parseResult.isError) { + console.log(parseResult.error) + process.exit(1) + } + const parsed = parseResult.result + + const env = { + warp: wrap_warp, + read: async () => { + wrap_read(await awaitKeypress()) + }, + write: () => { + //console.log(wrap_write()) + process.stdout.write(Buffer.from([wrap_write()])) + }, + send: wrap_send, + exit: wrap_exit, + enter: wrap_enter, + pop: wrap_pop, + new: wrap_new, + } + + for (const def of parsed) { + env[def.name] = def.code + } + + await execute(env.main, env) +} + +const cleanup = () => { + process.exit(0) +} +run().then(cleanup, cleanup) \ No newline at end of file diff --git a/esolangs-interpreter-race/v2.js b/esolangs-interpreter-race/v2.js new file mode 100644 index 0000000..ece7b65 --- /dev/null +++ b/esolangs-interpreter-race/v2.js @@ -0,0 +1,186 @@ +const { regex, sequenceOf, char, choice, many1, many, str, coroutine, possibly } = require("arcsecond") +const fs = require("fs").promises + +const spaces = regex(/^ */) +const whitespace = regex(/^[ \n\t]*/) +const name = regex(/^[^ \n\t():]+/) +const code = many(coroutine(function*() { + yield spaces + return yield choice([ + coroutine(function*() { + yield char("(") + const x = yield code + yield spaces + yield char(")") + return x + }), + name + ]) +})) +const program = sequenceOf([ + many1(coroutine(function*() { + yield whitespace + const n = yield name + yield whitespace + yield str(":=") + const c = yield code + return { code: c, name: n } + })), + possibly(whitespace) +]).map(([x, _]) => x) + +// --------- + +let stackL = {depth: 0, children: []}, stackR = {depth: 0, children: []}; +let currentIsLeft = true; + +function depthDelta(x) { + if(currentIsLeft) + stackL["depth"]+=x; + else + stackR["depth"]+=x; +} + +function currentStack() { + let depth, currentStack; + + if(currentIsLeft) { + depth = stackL["depth"]; + currentStack = stackL["children"]; + } else { + depth = stackR["depth"]; + currentStack = stackR["children"]; + } + + for(let i = 0; i < depth; i++) { + const s = currentStack.length - 1 + currentStack = currentStack[s]; + } + + return currentStack; +} + +// --------- + +function wrap_new() { + currentStack().push([]); +} + +function wrap_pop() { + currentStack().pop(); +} + +function wrap_enter() { + depthDelta(1) +} + +function wrap_exit() { + depthDelta(-1) +} + +function wrap_warp() { + currentIsLeft = !currentIsLeft; +} + +function wrap_send() { + let toMove = currentStack().pop(); + + wrap_warp(); + + currentStack().push(toMove); + + wrap_warp() +} + +function wrap_read(n) { + let thisStack = []; + + for(let i = 0; i < n; i++) { + thisStack.push([]); + } + + currentStack().push(thisStack); +} + +function wrap_write() { + return currentStack().pop().length; +} + +// --------- + +const stdin = process.stdin +stdin.setRawMode(true) +stdin.resume() +let resolveNext = null +stdin.on("data", key => { + // ctrl+C and ctrl+D + if (key[0] === 3 || key[0] === 4) { + return process.exit() + } + if (resolveNext) { resolveNext(key[0]) } +}) +const awaitKeypress = () => new Promise((resolve, reject) => { resolveNext = resolve }) + +const DEBUG = false + +const execute = async (code, env) => { + for (const fn of code) { + //console.log("stacks", stackL, stackR) + // is bracketed, run if stack not empty + if (Array.isArray(fn)) { + if (currentStack().length !== 0) { + if (DEBUG) console.log("brackets", fn) + await execute(fn, env) + } + // is a regular function call or whatever, run it + } else { + const v = env[fn] + if (!v) { + throw new Error(fn + " is undefined") + } + if (typeof v === "function") { + if (DEBUG) console.log("builtin", fn) + await v() + } else { + if (DEBUG) console.log("normal", fn) + await execute(v, env) + } + } + } +} + +const run = async () => { + const code = await fs.readFile(process.argv[2], { encoding: "utf8" }) + const parseResult = program.run(code) + if (parseResult.isError) { + console.log(parseResult.error) + process.exit(1) + } + const parsed = parseResult.result + + const env = { + warp: wrap_warp, + read: async () => { + wrap_read(await awaitKeypress()) + }, + write: () => { + process.stdout.write(Buffer.from([wrap_write()])) + }, + send: wrap_send, + exit: wrap_exit, + enter: wrap_enter, + pop: wrap_pop, + new: wrap_new, + } + + for (const def of parsed) { + env[def.name] = def.code + } + + await execute(env.main, env) +} + +const cleanup = () => { + process.exit(0) +} +run().then(cleanup, cleanup) \ No newline at end of file diff --git a/generate-tape-image-1.py b/generate-tape-image-1.py new file mode 100644 index 0000000..276fd49 --- /dev/null +++ b/generate-tape-image-1.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import subprocess +import tempfile +import os +import os.path +import collections +import json +import sys + +ProcessedTrack = collections.namedtuple("ProcessedTrack", ["dfpwm_file", "artist", "track"]) + +def convert_wav_dfpwm(infile, outfile): + subprocess.run(["java", "-jar", "LionRay.jar", infile, outfile]) + +def convert_any_wav(infile, outfile): + subprocess.run(["ffmpeg", "-hide_banner", "-i", infile, "-ac", "1", outfile], stderr=subprocess.PIPE) + +def process_file(filename): + parts = list(map(str.strip, os.path.splitext(os.path.basename(filename))[0].split("-"))) + artist = parts[0] + track = parts[1] + wav_dest = tempfile.mktemp(".wav") + convert_any_wav(filename, wav_dest) + dfpwm_dest = tempfile.mktemp(".dfpwm") + convert_wav_dfpwm(wav_dest, dfpwm_dest) + os.remove(wav_dest) + return ProcessedTrack(dfpwm_dest, artist, track) + +def read_binary(filename): + with open(filename, "rb") as f: + return f.read() + +def process_dir(dirname): + tracks = [] + for file in os.listdir(dirname): + tracks.append(process_file(os.path.join(dirname, file))) + tape_image = b"" + tracks_meta = [] + for track in tracks: + track_meta = {} + track_meta["start"] = len(tape_image) + 8193 + data = read_binary(track.dfpwm_file) + os.remove(track.dfpwm_file) + track_meta["end"] = track_meta["start"] + len(data) + track_meta["artist"] = track.artist + track_meta["title"] = track.track + tape_image += data + tracks_meta.append(track_meta) + print(track.track, track.artist) + meta = json.dumps({ "tracks": tracks_meta }).encode("utf-8").ljust(8192, b"\0") + tape_image = meta + tape_image + with open("tape.bin", "wb") as f: + f.write(tape_image) + + +process_dir(sys.argv[1]) \ No newline at end of file diff --git a/generate-tape-image.py b/generate-tape-image.py new file mode 100644 index 0000000..cd265d6 --- /dev/null +++ b/generate-tape-image.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +import subprocess +import tempfile +import os +import os.path +import collections +import json +import sys +import multiprocessing +import struct + +ProcessedTrack = collections.namedtuple("ProcessedTrack", ["dfpwm_file", "metadata"]) + +def convert_wav_dfpwm(infile, outfile): + subprocess.run(["java", "-jar", "LionRay.jar", infile, outfile]) + +def convert_any_wav(infile, outfile): + subprocess.run(["ffmpeg", "-hide_banner", "-i", infile, "-ar", "48000", "-ac", "1", outfile], stderr=subprocess.PIPE) + +def read_meta(path): + proc = subprocess.run(["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", path], stdout=subprocess.PIPE) + data = json.loads(proc.stdout) + meta = {} + # These are the two locations I've found tags in in my not very thorough testing + try: + meta.update(data["format"]["tags"]) + except KeyError: pass + try: + meta.update(data["streams"][0]["tags"]) + except KeyError: pass + # lowercase all keys because in Opus files these seem to be uppercase sometimes + return { k.lower(): v for k, v in meta.items() } + +def process_file(filename): + meta = read_meta(filename) + wav_dest = tempfile.mktemp(".wav") + convert_any_wav(filename, wav_dest) + dfpwm_dest = tempfile.mktemp(".dfpwm") + convert_wav_dfpwm(wav_dest, dfpwm_dest) + os.remove(wav_dest) + print(filename) + return ProcessedTrack(dfpwm_dest, { + "title": meta["title"], + "artist": meta.get("artist", None) or meta.get("artists", None), + "album": meta.get("album", None) + }) + +def read_binary(filename): + with open(filename, "rb") as f: + return f.read() + +def process_dir(dirname): + files = list(map(lambda file: os.path.join(dirname, file), os.listdir(dirname))) + with multiprocessing.Pool(8) as p: + tracks = p.map(process_file, files) + tape_image = b"" + tracks_meta = [] + for track in tracks: + track.metadata["start"] = len(tape_image) + data = read_binary(track.dfpwm_file) + os.remove(track.dfpwm_file) + track.metadata["end"] = track.metadata["start"] + len(data) + tape_image += data + tracks_meta.append(track.metadata) + # dump in a compact format to save space + meta = json.dumps({ "tracks": tracks_meta }, separators=(',', ':')).encode("utf-8") + assert(len(meta) < 65536) + # new format - 0x54 marker byte, then metadata length as 2-byte big endian integer, then metadata, then concatenated DFPWM files + # start is now not an absolute position but just how far after the metadata it is + tape_image = b"\x54" + struct.pack(">H", len(meta)) + meta + tape_image + with open("tape.bin", "wb") as f: + f.write(tape_image) + # Tape lengths are measured in minutes. 6000 bytes are played per second because they use a 48000Hz sample rate and DFPWM is somehow 1 bit per sample. + length_minutes = len(tape_image) / (6000*60) + print(length_minutes, "minute tape required") + +process_dir(sys.argv[1]) diff --git a/heavpoots-game.html b/heavpoots-game.html new file mode 100644 index 0000000..f3754a3 --- /dev/null +++ b/heavpoots-game.html @@ -0,0 +1,87 @@ + + + entitlement + + + + + +
+ + + diff --git a/hello.s b/hello.s new file mode 100644 index 0000000..483a438 --- /dev/null +++ b/hello.s @@ -0,0 +1,16 @@ +BITS 64 +GLOBAL _start +SECTION .text +msg: db "Hello, World!" +len: equ $-msg +_start: + ; initialize stuff for `write` syscall + mov rax, 1 ; write + mov rdi, 1 ; fd 1 (stdout) + mov rsi, $msg ; write from `msg` + mov rdx, $len ; write `len` bytes + syscall + ; exit + mov rax, 60 + mov rdi, 0 + syscall diff --git a/polcomp-visualizer.html b/polcomp-visualizer.html new file mode 100644 index 0000000..b27c2eb --- /dev/null +++ b/polcomp-visualizer.html @@ -0,0 +1,123 @@ +styropyro discord political compass visualizer + + +

styropyro discord political compass visualizer

+
+ +
+
+ diff --git a/whyjit.py b/whyjit.py new file mode 100644 index 0000000..9dd60af --- /dev/null +++ b/whyjit.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +import argparse +import subprocess +import random +import string + +parser = argparse.ArgumentParser(description="Compile a WHY program using WHYJIT.") +parser.add_argument("input", help="File containing WHY source code") +parser.add_argument("-o", "--output", help="Filename of the output executable to make", default="./a.why") +parser.add_argument("-O", "--optimize", help="Optimization level", type=int, default="0") +args = parser.parse_args() + +def randomword(length): + letters = string.ascii_lowercase + return ''.join(random.choice(letters) for i in range(length)) + +def which(program): + proc = subprocess.run(["which", program], stdout=subprocess.PIPE) + if proc.returncode == 0: + return proc.stdout.replace(b"\n", b"") + else: + return None + +def find_C_compiler(): + compilers = ["gcc", "clang", "tcc", "cc"] + for compiler in compilers: + path = which(compiler) + if path != None: + return path + +def build_output(code, mx): + C_code = f""" +#define QUITELONG long long int +const QUITELONG max = {mx}; + +int main() {{ + volatile QUITELONG i = 0; // disable some "optimizations" that RUIN OUR BEAUTIFUL CODE! + while (i < max) {{ + i++; + }} + {code} +}} + """ + + heredoc = randomword(100) + devnull = "2>/dev/null" + shell_script = f"""#!/bin/sh +TMP1=/tmp/ignore-me +TMP2=/tmp/ignore-me-too +TMP3=/tmp/dont-look-here + cat << {heredoc} > $TMP1 +{C_code} +{heredoc} +sed -e '1,/^exit \$?$/d' "$0" > $TMP3 +chmod +x $TMP3 +$TMP3 -x c -o $TMP2 $TMP1 +chmod +x $TMP2 +$TMP2 +exit $? +""".encode("utf-8") + + with open(find_C_compiler(), "rb") as f: + return shell_script + f.read() + +input = args.input +output = args.output +with open(input, "r") as f: + contents = f.read() + looplen = max(1000, (2 ** -args.optimize) * 1000000000) + code = build_output( + contents, + looplen + ) + with open(output, "wb") as out: + out.write(code)