mirror of
https://github.com/osmarks/random-stuff
synced 2024-12-21 07:30:35 +00:00
initial commit v2
This commit is contained in:
commit
548f9ba9c1
64
beep.py
Normal file
64
beep.py
Normal file
@ -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")
|
18
emoji_ternarize.py
Executable file
18
emoji_ternarize.py
Executable file
@ -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()))
|
28
eso-interpreter.py
Normal file
28
eso-interpreter.py
Normal file
@ -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
|
17
esolangs-interpreter-race/hello.ms
Normal file
17
esolangs-interpreter-race/hello.ms
Normal file
@ -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 . ]
|
178
esolangs-interpreter-race/orig.js
Normal file
178
esolangs-interpreter-race/orig.js
Normal file
@ -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)
|
16
esolangs-interpreter-race/package-lock.json
generated
Normal file
16
esolangs-interpreter-race/package-lock.json
generated
Normal file
@ -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=="
|
||||
}
|
||||
}
|
||||
}
|
189
esolangs-interpreter-race/thing.js
Normal file
189
esolangs-interpreter-race/thing.js
Normal file
@ -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)
|
186
esolangs-interpreter-race/v2.js
Normal file
186
esolangs-interpreter-race/v2.js
Normal file
@ -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)
|
56
generate-tape-image-1.py
Normal file
56
generate-tape-image-1.py
Normal file
@ -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])
|
77
generate-tape-image.py
Normal file
77
generate-tape-image.py
Normal file
@ -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])
|
87
heavpoots-game.html
Normal file
87
heavpoots-game.html
Normal file
@ -0,0 +1,87 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>entitlement</title>
|
||||
<meta charset="utf-8" />
|
||||
<style>
|
||||
.hide {
|
||||
opacity:0;
|
||||
}
|
||||
.hide:hover{
|
||||
opacity:1;
|
||||
}
|
||||
button {
|
||||
margin-left: -1px;
|
||||
border: 1px solid black;
|
||||
background: lightgray;
|
||||
padding: 0.5em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>enable js you utter bee</noscript>
|
||||
<div id="o"></div>
|
||||
<script>
|
||||
var state="start"; // SPOILERS SPOILERS OH GOD SPOILERS OH GOD SPOILERS //
|
||||
var game={
|
||||
"start":["hi you are level 3³³ ersearcher in the scp floundation. whatdo?",["173","go to SCP-173s chamber"],["antimemetics","go to the antimemetics division"],["start-2","keep going somewhere"]],
|
||||
"start-2":["ok you go somewhere else. wow",["start","go back"],["174","go to SCP-174s chamber"],["175","go to SCP-175s chamber"],["176","go to SCP-176s chamber"],["dontquestionit","wait, scps arent just contained in the order of their numbering like that"],["start-3","keep going somewhere"]],
|
||||
"start-3":["you keep going for some reason.",["start-2","go back"],["177","go to SCP-177s chamber"],["178","go to SCP-178s chamber"]],
|
||||
"traitor":["youre killed by armed guards lol",["start","rip"]],
|
||||
"178":["its guarded by armed guards and only level 4 researchers can access it.",["pata2","get it anyway"],["start-3","leave"]],
|
||||
"pata2":["ugh, again? no, you cant just use pataphysics for everything",["178","oh, ok. i guess i wont then"],["178opened","use pataphysics anyway","h"]],
|
||||
"178opened":["ok, fine, you win. you put SCP-178 on. you see 3 entities. what now?",["178ent1","look at entity 1"],["178ent2","look at entity 2"],["178ent3","look at entity 3"],["178run","run"],["traitor","take it off"]],
|
||||
"178ent1":["you look at entity 1. it sure is the first entity.",["178opened","stop that"],["lacerated","attempt conversation"],["lacerated","attack"]],
|
||||
"178ent2":["you look at entity 2. it sure is the second entity.",["178opened","stop that"],["lacerated","attempt conversation"],["lacerated","attack"],["dontquestionit","this is dumb","h"]],
|
||||
"178ent3":["you look at entity 3. it sure is the last entity.",["178opened","stop that"],["lacerated","attempt conversation"],["lacerated","attack"]],
|
||||
"178run":["you start running away, still wearing SCP-178",["traitor","go back"],["178run1-remove","remove SCP-178 and keep running"],["178run1-keep","keep SCP-178 and keep running"]],
|
||||
"178run1-keep":["you run into an entity by accident",["lacerated","oh no"]],
|
||||
"178run1-remove":["you run into armed guards",["traitor","oh no"]],
|
||||
"177":["hmm is chessboard yes.",["start-3","leave"],["chess","play"]],
|
||||
"lacerated":["you die from several lacerations",["start","rip"]],
|
||||
"chess":["at some point i might make my own chess thing here or something, but for now, no",["start-3","leave"]],
|
||||
"dontquestionit":["if youre so smart why dont you go enter SCP-7812-1s chamber?",["7812-1","wait what"]],
|
||||
"176":["SCP-176 is contained on-site lol no",["start-2","well im sorry for not reading every series 1 page then"]],
|
||||
"175":["SCP-175 is in a metal safe which you can't open",["start-2","boring"],["cantopen","open it anyway"]],
|
||||
"cantopen":["thats not how it works, when i said 'you can't open' i was directly referring to you",["175","fineeee"],["stillno","utilize pa<span class='hide'>s</span>taphysics to open it"]],
|
||||
"stillno":["while this universe can be manipulated by narrative forces, this one is manipulating you to be unable to open that safe",["175","unfortunate"]],
|
||||
"174":["SCP-174 looks at you, probably",["nope","be manipulated by SCP-174"],["start-2","leave the chamber of containment"]],
|
||||
"nope":["actually you have better things to do than that, so you decide to leave",["start-2","oh"]],
|
||||
"173":["no wtf SCP-173 is like the deadlies apioarachnocognitoteleoinfohazard ever! you died.",["start","start again"]],
|
||||
"antimemetics":["what? there is no antimemetics division.",["start","go back"],["counterconceptual","go to the counterconceptual department"],["55-1","go to SCP-055s chamber","h"]],
|
||||
"counterconceptual":["sorry not done yet lOl",["antimemetics","back to antimemetics division page"],["start","back to start"],["woah","...or is that what they want you to think?","h"]],
|
||||
"55-1":["...",["55-2","…And what have we learned?"]],
|
||||
"55-2":["It takes you a significant amount of time to answer your own question. You speak with a measured, level tone. You are in no hurry.",["55-3","We have learned that there is time missing from our world. Almost a year of extremely recent history. And there are spaces, significant spaces, in every population center, which cannot be perceived or entered. The cities are rerouting around them, like mountains or radiation zones. And along with that time and that space, we have learned that there are enough people missing, without any explanation whatsoever, that if I spent the rest of my considerably augmented lifespan counting them, I could not count to that number."]],
|
||||
"55-3":["...",["55-4","And outside of the Noöspherics Division, no one, not a single person, is even aware of these… thefts. Even those in the Division, who made this discovery, cannot recall what happened during that missing time. And no one can enter that missing space. The gap in reality, itself, can barely be perceived. It is this… shocking, blinding absence. This unknown unknown."]],
|
||||
"55-4":["...",["55-5","We have learned — we have cautiously hypothesized — that three to four years ago an unimaginable anomaly entered our reality. And then, some time later, it left, taking all of that space, and all of that time, and all of those people with it. We do not know what it was, or what it did. We have tried to find out, but the truth evades my best noösphericists. The question fights back, as if it doesn't want to be answered. And we do not know why the anomaly left, though my experts say that in the conceptual realm, there is evidence — traces — of what could have been a conflict. And in the distance, shining down on us, there is a great new star."]],
|
||||
"55-5":["...",["55-6","Even I don't remember what happened. Which I, personally, find... deeply alarming. Because this is recent history. Like nearly everybody alive, I must have been there. In some respect, I must have gone through it."]],
|
||||
"55-6":["...",["55-7","But if we have learned nothing else, we have learned this: humans can walk away from, and forget, anything. Civilization can go back to 'normal' after anything."]],
|
||||
"55-7":["...",["55-8","And I wonder: what was the Foundation's role in this? Were we witness to this anomaly? Were we the ones who defeated it? Did we resist? Negotiate? Participate?"]],
|
||||
"55-8":["...",["55-9","We are here, now. Intact. We are back. To what do we owe that? Did we hide, or run?"]],
|
||||
"55-9":["...",["55-10","Do we deserve to be back? Have we that right? We failed in our stated objective. These people are gone, and it's useless to pretend that they aren't dead. We failed orders of magnitude harder than we've ever failed before. Despite which, we remain clandestine, and unknown to greater humanity. Which means that no one external to the Foundation can ever hold us accountable for our actions, or lack thereof. If what happened at the O5 Council meeting yesterday is any indication, we will certainly never hold ourselves accountable."]],
|
||||
"55-10":["...",["55-11","What happened to those people? My people. Where are they? No one is just dead, no one is merely, passively dead. Death is caused."]],
|
||||
"55-11":["SCP-055 cannot answer you.",["55-12","These things happen. And we say to ourselves, 'Never again.' And a hundred years pass. And they happen. Again."]],
|
||||
"55-12":["...",["55-13","Last time. The time before this one, the time none of us remember, the time for which there is no evidence of any kind, but which I now realise must exist. That time, when we told ourselves and each other, 'We must do better,' what did we do differently, from then on, and why didn't it work?"]],
|
||||
"55-13":["...",["55-14","What does the Foundation need to be? Where does it need to be, and how far is that place from here? Can we see it from here?"]],
|
||||
"55-14":["...",["55-15","Or is this it?"],["truelvl","also, this is an O5s dialogue. arent I a level 3 researcher?","h"]],
|
||||
"truelvl":["obviously not, what kind of level 3 researcher can just wander into random divisions/departments and walk into the rooms of various SCPs?",["55-14","fair point"],["dontquestionit","but i might be just abusing antimemes to do it!"]],
|
||||
"55-15":["You do not know. And after leaving the containment unit, you know, you will not even remember the questions.",["antimemetics","enough of that lol"]],
|
||||
"woah":["you now have access to scps! wait what does this have to do with the counethdfjghkdfjghceuptueal department?",["antimemetics","the what?"],["start","who knows"],["6094","visit SCP-6094"],["7812-1","visit SCP-7812-1"],["7812","visit SCP-7812"]],
|
||||
"6094":["you breathe in some ████████ dust and die, idot",["start","rip"]],
|
||||
"7812-1":["<b>all</b> <i>is</i> <h6>happiness</h6>",["7812-1","futility"]],
|
||||
"7812":["This is it. The source of it all. The SCP designated as 7812 to hide the real truth of SCP-001. What will you do? You can't destroy it. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal. 7812 is eternal.",["7812-1","submit"],["start","self-amnesticize"]],
|
||||
}
|
||||
var o=document.getElementById("o")
|
||||
function btn(cont){
|
||||
return "<button onclick=c(\""+cont[0]+"\")"+(cont[2]=="h"?" class='hide'":"")+">"+cont[1]+"</button>"
|
||||
}
|
||||
function c(st){
|
||||
state=st
|
||||
o.innerHTML="<p>"+game[st][0]+"</p>"
|
||||
for (var i=1;i<game[st].length;i++){
|
||||
o.innerHTML+=btn(game[st][i])
|
||||
}
|
||||
}
|
||||
c(state)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
16
hello.s
Normal file
16
hello.s
Normal file
@ -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
|
123
polcomp-visualizer.html
Normal file
123
polcomp-visualizer.html
Normal file
@ -0,0 +1,123 @@
|
||||
<title>styropyro discord political compass visualizer</title>
|
||||
<meta charset="utf8"/>
|
||||
<style>
|
||||
canvas {
|
||||
border: 1px solid black;
|
||||
/* TODO */
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#selected {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#frame {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
<h1>styropyro discord political compass visualizer</h1>
|
||||
<div id="frame">
|
||||
<canvas></canvas>
|
||||
<div id="selected"></div>
|
||||
</div>
|
||||
<script>
|
||||
const canv = document.querySelector("canvas")
|
||||
const selected = document.querySelector("#selected")
|
||||
canv.height = 500
|
||||
canv.width = 500
|
||||
|
||||
const ctx = canv.getContext("2d")
|
||||
|
||||
const drawRect = (c, x, y, w, h) => {
|
||||
ctx.fillStyle = c
|
||||
ctx.fillRect(x, y, w, h)
|
||||
}
|
||||
|
||||
drawRect("salmon", 0, 0, 250, 250)
|
||||
drawRect("aquamarine", 250, 0, 250, 250)
|
||||
drawRect("lightgreen", 0, 250, 250, 250)
|
||||
drawRect(Math.random() > 0.5 ? "orchid" : "yellow", 250, 250, 250, 250)
|
||||
|
||||
const drawLine = (x1, y1, x2, y2) => {
|
||||
// technically there's a line thing *anyway*
|
||||
ctx.fillRect(x1, y1, x2 - x1, y2 - y1)
|
||||
}
|
||||
|
||||
ctx.fillStyle = "black"
|
||||
for (let x = 1; x < 20; x++) {
|
||||
drawLine(x * 25, 0, x * 25 + 1, 500)
|
||||
}
|
||||
for (let y = 1; y < 20; y++) {
|
||||
drawLine(0, y * 25, 500, y * 25 + 1)
|
||||
}
|
||||
drawLine(0, 248, 500, 252)
|
||||
drawLine(248, 0, 252, 500)
|
||||
|
||||
const results = new Map([
|
||||
["C4M0K41#2507", { x: -8.9, y: -8.9, prog: -6.5, color: "#9a0200" }],
|
||||
["gollark#3909", { x: 2 , y: 6.7 , prog: 12 , color: "#04d9ff" }],
|
||||
["dunnousername#8672", { x: -0.1, y: 5 , prog: 8.5 , color: "#f97306" }],
|
||||
["ThatRedKite#0815", { x: -3.6, y: -0.3, prog: 13.5, color: "#77926f" }], // formerly -3.9, -1.3, 12.5
|
||||
["Billy Mays#5049", { x: -7.2, y: 2.3 , prog: 9 , color: "#0b5509" }],
|
||||
["charizardrekt#0312", { x: -0.3, y: 2.3 , prog: 4.9 , color: "#3675ab" }],
|
||||
["Tiki#9380", { x: 1.6 , y: 0.3 , prog: 9.9 , color: "#00d5dc" }],
|
||||
["0x1c1ean#1489", { x: 1 , y: 1.3 , prog: 6.4 , color: "#21fc0d" }],
|
||||
["Curiosity#5280", { x: -3.3, y: 3.3 , prog: 11 , color: "#fe019a" }],
|
||||
["P-α3#3732", { x: 3.9, y: -7.3, prog: 0.5 , color: "#ff073a" }],
|
||||
["komrad kit#8767", { x: -8 , y: -7.3, prog: 7 , color: "#ffc512" }], // approx - he may have meant +7.3 on y
|
||||
["Armor Plated Meme#2957", { x: -2.3, y: -4 , prog: -2 , color: "#6258c4" }],
|
||||
["Qwerty#1111", { x:3.6 , y: 3 , prog:2.5 , color: "#019529" }],
|
||||
["Lemon_Emu#6143", { x: -1.6, y: -1 , prog: 0.5 , color: "#fff917" }],
|
||||
["Kitty Strafe#3480", { x: -1.3, y: -3 , prog: 8 , color: "#1f0954" }]
|
||||
])
|
||||
|
||||
for (const [k, v] of results) {
|
||||
v.cx = Math.round((v.x * 25) + 250)
|
||||
v.cy = Math.round((v.y * 25) + 250)
|
||||
drawRect(v.color, v.cx - 8, v.cy - 8, 16, 16)
|
||||
}
|
||||
|
||||
const e = (cls, parent, content) => {
|
||||
const element = document.createElement("div")
|
||||
element.classList.add(cls)
|
||||
if (content) { element.appendChild(document.createTextNode(content)) }
|
||||
if (parent) { parent.appendChild(element) }
|
||||
return element
|
||||
}
|
||||
|
||||
const clearSelected = () => { while (selected.firstChild) { selected.removeChild(selected.firstChild) } }
|
||||
|
||||
const updateSelected = info => {
|
||||
e("name", selected, info.name)
|
||||
e("xaxis", selected, `Rightism (X, L/R): ${info.x}`)
|
||||
e("yaxis", selected, `Libertarianism (Y, Auth/Lib): ${info.y}`)
|
||||
e("culturalaxis", selected, `Progressiveness (Conservative/Progressive): ${info.prog}`)
|
||||
}
|
||||
|
||||
const updateFromEvent = (ev, clear) => {
|
||||
const mx = ev.clientX - canv.offsetLeft
|
||||
const my = ev.clientY - canv.offsetTop
|
||||
for (const [k, v] of results) {
|
||||
if (Math.abs(v.cx - mx) < 16 && Math.abs(v.cy - my) < 16) {
|
||||
console.log("selecting", k)
|
||||
clearSelected()
|
||||
updateSelected({ ...v, name: k })
|
||||
return
|
||||
}
|
||||
}
|
||||
if (clear) { clearSelected() }
|
||||
}
|
||||
|
||||
canv.addEventListener("click", ev => {
|
||||
updateFromEvent(ev, true)
|
||||
})
|
||||
|
||||
canv.addEventListener("mousemove", ev => {
|
||||
updateFromEvent(ev, false)
|
||||
})
|
||||
</script>
|
75
whyjit.py
Normal file
75
whyjit.py
Normal file
@ -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)
|
Loading…
Reference in New Issue
Block a user