Repository: mame/quine-relay Branch: master Commit: c2aa5098d3e9 Files: 45 Total size: 231.7 KB Directory structure: gitextract_2_dvvpj1/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── main.yml ├── .gitignore ├── Dockerfile ├── Makefile ├── QR.rb ├── README.md ├── SHA256SUMS ├── src/ │ ├── Dockerfile.gen.rb │ ├── Makefile.gen.rb │ ├── QR.rb.gen.rb │ ├── README.md.gen.rb │ ├── Rakefile │ ├── SHA256SUMS.gen.rb │ ├── blc-boot.dat.gen.rb │ ├── code-gen-pool.rb │ ├── code-gen.rb │ ├── dot.github.workflows.main.yml.gen.rb │ ├── grass-boot.dat.gen.rb │ ├── langs.png.gen.rb │ ├── lazyk-boot.dat.gen.rb │ ├── test.rb │ ├── thumbnail.png.gen.rb │ ├── uroboros.txt │ └── wasm-tmpl.dat.gen.rb └── vendor/ ├── .gitignore ├── Makefile ├── README ├── aheui.rb ├── ante.rb ├── bf.rb ├── blc.rb ├── cfunge-0.9.0.tar.bz2 ├── dummy-wasi-runtime.c ├── false.rb ├── golfscript.rb ├── grass.rb ├── lazyk.c ├── ook-to-bf.rb ├── subleq.rb ├── thue.rb ├── unlambda.rb ├── wasi-runtime.js └── whitespace.rb ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ /Dockerfile linguist-generated /Makefile linguist-generated /QR.rb linguist-generated linguist-language=prose /README.md linguist-generated /SHA256SUMS linguist-generated /langs.png linguist-generated /thumbnail.png linguist-generated /vendor linguist-vendored ================================================ FILE: .github/FUNDING.yml ================================================ github: mame ================================================ FILE: .github/workflows/main.yml ================================================ name: CI on: - push - pull_request - workflow_dispatch jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: docker build run: | sudo docker build -t quine-relay . - name: docker run run: | sudo docker run --privileged --name qr -e CI=true -t quine-relay - name: push spoiler run: | git clone https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git spoiler --branch spoiler git -C spoiler rm --quiet -r '*' sudo docker cp qr:/usr/local/share/quine-relay/QR.rb spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.rs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.scala spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.scm spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.sci spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.sed spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.spl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.sl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.nut spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.sml spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.sq spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ss spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.swift spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.tcl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.tcsh spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.t spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ts spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.unl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.vala spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.mid spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.v spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.vim spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.vb spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.wasm spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.wat spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ws spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.xslt spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.yab spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.yorick spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.azm spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.zsh spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.+ spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/qr.adb spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.als spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.aheui spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.a68 spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ante spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.aj spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.asy spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.dats spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.awk spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.bash spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.bc spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.bsh spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.bef spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.Blc spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.bf spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.c spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.cpp spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.cs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.chef spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.clj spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.cmake spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.cob spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.coffee spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.lisp spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.cr spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.d spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.dc spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.dhall spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.exs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.el spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.erl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.e spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.fsx spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.false spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.fl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.fish spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.fs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.f spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.f90 spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gbs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.g spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gdb spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gel spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.plt spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.go spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gpt spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.grass spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.groovy spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gz spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.hs spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.hx spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.icn spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.i spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.j spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.java spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.js spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.jq spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.jsfuck spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.kt spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ksh spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.lazy spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ls spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ll spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.lol spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.lua spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.m4 spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.mk spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.mzn spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.mod spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.il spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.mustache spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.asm spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.neko spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.5c spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.nim spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.m spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ml spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.octave spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ook spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.gp spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.p spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.pas spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.pl spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.pl6 spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.php spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.png spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.pike spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ps spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.prolog spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.pr spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.py spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.R spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.ratfor spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.rc spoiler/ sudo docker cp qr:/usr/local/share/quine-relay/QR.rexx spoiler/ cd spoiler git add . GIT_AUTHOR_NAME="$(git show -s --format=%an "$GITHUB_SHA")" \ GIT_AUTHOR_EMAIL="$(git show -s --format=%ae "$GITHUB_SHA")" \ GIT_AUTHOR_DATE="$(git show -s --format=%ad "$GITHUB_SHA")" \ GIT_COMMITTER_NAME='GitHub Actions' \ GIT_COMMITTER_EMAIL='actions@github.com' \ TZ=UTC \ git commit --allow-empty -m "spoiler: $(git show -s --format=%s "$GITHUB_SHA")" git push --quiet origin spoiler echo The intermediate sources are available: https://github.com/${GITHUB_REPOSITORY}/tree/spoiler if: github.event_name == 'push' && github.ref == 'refs/heads/master' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .gitignore ================================================ /QR* /qr* /tmp /nimcache /.curry !QR.rb gst.im /src/lazyk-boot.dat /src/blc-boot.dat /src/grass-boot.dat *.sw* tmp.*proj ================================================ FILE: Dockerfile ================================================ FROM ubuntu:25.10 ENV DEBIAN_FRONTEND noninteractive RUN apt-get update && apt-get upgrade -y RUN apt-get -qq install -y apt-utils > /dev/null RUN apt-get -qq install -y moreutils RUN chronic apt-get -qq install -y afnix algol68g aplus-fsf aspectj && chronic apt-get clean RUN chronic apt-get -qq install -y asymptote ats2-lang bash bc && chronic apt-get clean RUN chronic apt-get -qq install -y bison bsh clisp clojure && chronic apt-get clean RUN chronic apt-get -qq install -y cmake coffeescript crystal curl && chronic apt-get clean RUN chronic apt-get -qq install -y dc dhall dotnet8 elixir && chronic apt-get clean RUN chronic apt-get -qq install -y emacs-nox erlang execline f2c && chronic apt-get clean RUN chronic apt-get -qq install -y fish flex fp-compiler g++ && chronic apt-get clean RUN chronic apt-get -qq install -y gambas3-gb-pcre gambas3-scripter gap gawk && chronic apt-get clean RUN chronic apt-get -qq install -y gcc gdb gdc genius && chronic apt-get clean RUN chronic apt-get -qq install -y gforth gfortran ghc ghostscript && chronic apt-get clean RUN chronic apt-get -qq install -y gm2 gnat gnucobol4 gnuplot && chronic apt-get clean RUN chronic apt-get -qq install -y gobjc golang gpt groff && chronic apt-get clean RUN chronic apt-get -qq install -y groovy guile-3.0 gzip haxe && chronic apt-get clean RUN chronic apt-get -qq install -y icont iconx intercal iverilog && chronic apt-get clean RUN chronic apt-get -qq install -y jasmin-sable jq kotlin ksh && chronic apt-get clean RUN chronic apt-get -qq install -y libevent-dev libgd-dev libpng-dev libpolyml-dev && chronic apt-get clean RUN chronic apt-get -qq install -y livescript llvm lua5.3 m4 && chronic apt-get clean RUN chronic apt-get -qq install -y make minizinc mono-devel nasm && chronic apt-get clean RUN chronic apt-get -qq install -y neko nickle nim node-typescript && chronic apt-get clean RUN chronic apt-get -qq install -y nodejs ocaml octave openjdk-11-jdk && chronic apt-get clean RUN chronic apt-get -qq install -y pari-gp parser3-cgi perl php-cli && chronic apt-get clean RUN chronic apt-get -qq install -y pike8.0 polyml python3 r-base && chronic apt-get clean RUN chronic apt-get -qq install -y rakudo ratfor rc regina-rexx && chronic apt-get clean RUN chronic apt-get -qq install -y ruby ruby-mustache rustc scala && chronic apt-get clean RUN chronic apt-get -qq install -y scilab-cli sed slsh spin && chronic apt-get clean RUN chronic apt-get -qq install -y squirrel3 surgescript swi-prolog swiftlang && chronic apt-get clean RUN chronic apt-get -qq install -y tcl tcsh valac vim && chronic apt-get clean RUN chronic apt-get -qq install -y wabt xsltproc yabasic yorick && chronic apt-get clean RUN chronic apt-get -qq install -y zoem zsh && chronic apt-get clean ADD . /usr/local/share/quine-relay WORKDIR /usr/local/share/quine-relay RUN make -C vendor CMD make check -j 10000 ================================================ FILE: Makefile ================================================ MAKEFLAGS += --no-print-directory PATH := $(CURDIR)/vendor/local/bin:/usr/games:$(PATH) CLASSPATH := . find_any0 = $(firstword $(foreach x,$(1),$(if $(shell which $(x) 2>/dev/null),$(x),))) check = $(if $(2),$(2),$(error $(1) interpreter not found!)) find_any = $(call check,$(1),$(call find_any0,$(2))) JAVASCRIPT := $(call find_any,JavaScript,nodejs node js) SCHEME := $(call find_any,Scheme,guile csi gosh) GBS := $(call find_any,Gambas script,gbs3 gbs2 gba3) WASI_RUNTIME := $(call find_any,WASI runtime,wasmtime node) ifeq ($(SCHEME),csi) SCHEME := csi -s endif ifeq ($(WASI_RUNTIME),node) WASI_RUNTIME := node --experimental-wasi-unstable-preview1 vendor/wasi-runtime.js endif .DELETE_ON_ERROR: all: QR2.rb @echo @echo "#############" @echo "## CHECK ##" @echo "#############" @echo diff -s QR.rb QR2.rb check: all @sha256sum --quiet -c SHA256SUMS QR.rs: QR.rb @echo @echo "#######################" @echo "## 1: Ruby -> Rust ##" @echo "#######################" @echo ruby QR.rb > QR.rs QR.scala: QR.rs @echo @echo "########################" @echo "## 2: Rust -> Scala ##" @echo "########################" @echo rustc QR.rs ./QR > QR.scala QR.scm: QR.scala @echo @echo "##########################" @echo "## 3: Scala -> Scheme ##" @echo "##########################" @echo scalac QR.scala scala QR > QR.scm QR.sci: QR.scm @echo @echo "###########################" @echo "## 4: Scheme -> Scilab ##" @echo "###########################" @echo $(SCHEME) QR.scm > QR.sci QR.sed: QR.sci @echo @echo "########################" @echo "## 5: Scilab -> sed ##" @echo "########################" @echo scilab-cli -nb -f QR.sci > QR.sed QR.spl: QR.sed @echo @echo "#############################" @echo "## 6: sed -> Shakespeare ##" @echo "#############################" @echo sed -E -f QR.sed QR.sed > QR.spl QR.sl: QR.spl @echo @echo "################################" @echo "## 7: Shakespeare -> S-Lang ##" @echo "################################" @echo spl2c < QR.spl > QR.spl.c gcc -z muldefs -o QR -I ./vendor/local/include -L ./vendor/local/lib QR.spl.c -lspl -lm ./QR > QR.sl QR.nut: QR.sl @echo @echo "#############################" @echo "## 8: S-Lang -> Squirrel ##" @echo "#############################" @echo slsh QR.sl > QR.nut QR.sml: QR.nut @echo @echo "##################################" @echo "## 9: Squirrel -> Standard ML ##" @echo "##################################" @echo squirrel QR.nut > QR.sml QR.sq: QR.sml @echo @echo "#################################" @echo "## 10: Standard ML -> Subleq ##" @echo "#################################" @echo polyc -o QR QR.sml ./QR > QR.sq QR.ss: QR.sq @echo @echo "#################################" @echo "## 11: Subleq -> SurgeScript ##" @echo "#################################" @echo ruby vendor/subleq.rb QR.sq > QR.ss QR.swift: QR.ss @echo @echo "################################" @echo "## 12: SurgeScript -> Swift ##" @echo "################################" @echo surgescript QR.ss > QR.swift QR.tcl: QR.swift @echo @echo "########################" @echo "## 13: Swift -> Tcl ##" @echo "########################" @echo swiftc QR.swift ./QR > QR.tcl QR.tcsh: QR.tcl @echo @echo "#######################" @echo "## 14: Tcl -> tcsh ##" @echo "#######################" @echo tclsh QR.tcl > QR.tcsh QR.t: QR.tcsh @echo @echo "########################" @echo "## 15: tcsh -> Thue ##" @echo "########################" @echo tcsh QR.tcsh > QR.t QR.ts: QR.t @echo @echo "##############################" @echo "## 16: Thue -> TypeScript ##" @echo "##############################" @echo ruby vendor/thue.rb QR.t > QR.ts QR.unl: QR.ts @echo @echo "##################################" @echo "## 17: TypeScript -> Unlambda ##" @echo "##################################" @echo tsc --outFile QR.ts.js QR.ts $(JAVASCRIPT) QR.ts.js > QR.unl QR.vala: QR.unl @echo @echo "############################" @echo "## 18: Unlambda -> Vala ##" @echo "############################" @echo ruby vendor/unlambda.rb QR.unl > QR.vala QR.mid: QR.vala @echo @echo "##########################" @echo "## 19: Vala -> Velato ##" @echo "##########################" @echo valac QR.vala ./QR > QR.mid QR.v: QR.mid @echo @echo "#############################" @echo "## 20: Velato -> Verilog ##" @echo "#############################" @echo mono vendor/local/bin/Vlt.exe /s QR.mid mono QR.exe > QR.v QR.vim: QR.v @echo @echo "################################" @echo "## 21: Verilog -> Vimscript ##" @echo "################################" @echo iverilog -o QR QR.v ./QR -vcd-none > QR.vim QR.vb: QR.vim @echo @echo "#####################################" @echo "## 22: Vimscript -> Visual Basic ##" @echo "#####################################" @echo vim -EsS QR.vim > QR.vb QR.wasm: QR.vb @echo @echo "#######################################################" @echo "## 23: Visual Basic -> WebAssembly (Binary format) ##" @echo "#######################################################" @echo echo 'Exenet8.0false' > tmp.vbproj DOTNET_NOLOGO=1 dotnet run --project tmp.vbproj > QR.wasm QR.wat: QR.wasm @echo @echo "####################################################################" @echo "## 24: WebAssembly (Binary format) -> WebAssembly (Text format) ##" @echo "####################################################################" @echo $(WASI_RUNTIME) QR.wasm > QR.wat QR.ws: QR.wat @echo @echo "###################################################" @echo "## 25: WebAssembly (Text format) -> Whitespace ##" @echo "###################################################" @echo wat2wasm QR.wat -o QR.wat.wasm $(WASI_RUNTIME) QR.wat.wasm > QR.ws QR.xslt: QR.ws @echo @echo "##############################" @echo "## 26: Whitespace -> XSLT ##" @echo "##############################" @echo ruby vendor/whitespace.rb QR.ws > QR.xslt QR.yab: QR.xslt @echo @echo "###########################" @echo "## 27: XSLT -> Yabasic ##" @echo "###########################" @echo xsltproc QR.xslt > QR.yab QR.yorick: QR.yab @echo @echo "#############################" @echo "## 28: Yabasic -> Yorick ##" @echo "#############################" @echo yabasic QR.yab > QR.yorick QR.azm: QR.yorick @echo @echo "##########################" @echo "## 29: Yorick -> Zoem ##" @echo "##########################" @echo yorick -batch QR.yorick > QR.azm QR.zsh: QR.azm @echo @echo "#######################" @echo "## 30: Zoem -> zsh ##" @echo "#######################" @echo zoem -i QR.azm > QR.zsh QR.+: QR.zsh @echo @echo "#####################" @echo "## 31: zsh -> A+ ##" @echo "#####################" @echo zsh QR.zsh > QR.+ qr.adb: QR.+ @echo @echo "#####################" @echo "## 32: A+ -> Ada ##" @echo "#####################" @echo a+ QR.+ > qr.adb QR.als: qr.adb @echo @echo "########################" @echo "## 33: Ada -> AFNIX ##" @echo "########################" @echo gnatmake qr.adb ./qr > QR.als QR.aheui: QR.als @echo @echo "##########################" @echo "## 34: AFNIX -> Aheui ##" @echo "##########################" @echo LANG=C LD_LIBRARY_PATH=/usr/lib/afnix axi QR.als > QR.aheui QR.a68: QR.aheui @echo @echo "#############################" @echo "## 35: Aheui -> ALGOL 68 ##" @echo "#############################" @echo ruby vendor/aheui.rb QR.aheui > QR.a68 QR.ante: QR.a68 @echo @echo "############################" @echo "## 36: ALGOL 68 -> Ante ##" @echo "############################" @echo a68g QR.a68 > QR.ante QR.aj: QR.ante @echo @echo "###########################" @echo "## 37: Ante -> AspectJ ##" @echo "###########################" @echo ruby vendor/ante.rb QR.ante > QR.aj QR.asy: QR.aj @echo @echo "################################" @echo "## 38: AspectJ -> Asymptote ##" @echo "################################" @echo ajc QR.aj java QR > QR.asy QR.dats: QR.asy @echo @echo "############################" @echo "## 39: Asymptote -> ATS ##" @echo "############################" @echo asy QR.asy > QR.dats QR.awk: QR.dats @echo @echo "######################" @echo "## 40: ATS -> Awk ##" @echo "######################" @echo patscc -o QR QR.dats ./QR > QR.awk QR.bash: QR.awk @echo @echo "#######################" @echo "## 41: Awk -> bash ##" @echo "#######################" @echo awk -f QR.awk > QR.bash QR.bc: QR.bash @echo @echo "######################" @echo "## 42: bash -> bc ##" @echo "######################" @echo bash QR.bash > QR.bc QR.bsh: QR.bc @echo @echo "###########################" @echo "## 43: bc -> BeanShell ##" @echo "###########################" @echo BC_LINE_LENGTH=4000000 bc -q QR.bc > QR.bsh QR.bef: QR.bsh @echo @echo "################################" @echo "## 44: BeanShell -> Befunge ##" @echo "################################" @echo bsh QR.bsh > QR.bef @stty echo QR.Blc: QR.bef @echo @echo "###########################" @echo "## 45: Befunge -> BLC8 ##" @echo "###########################" @echo cfunge QR.bef > QR.Blc QR.bf: QR.Blc @echo @echo "#############################" @echo "## 46: BLC8 -> Brainfuck ##" @echo "#############################" @echo ruby vendor/blc.rb < QR.Blc > QR.bf QR.c: QR.bf @echo @echo "##########################" @echo "## 47: Brainfuck -> C ##" @echo "##########################" @echo ruby vendor/bf.rb QR.bf > QR.c QR.cpp: QR.c @echo @echo "####################" @echo "## 48: C -> C++ ##" @echo "####################" @echo $(CC) -o QR QR.c ./QR > QR.cpp QR.cs: QR.cpp @echo @echo "#####################" @echo "## 49: C++ -> C# ##" @echo "#####################" @echo $(CXX) -o QR QR.cpp ./QR > QR.cs QR.chef: QR.cs @echo @echo "######################" @echo "## 50: C# -> Chef ##" @echo "######################" @echo echo 'Exenet8.0false' > tmp.csproj DOTNET_NOLOGO=1 dotnet run --project tmp.csproj > QR.chef QR.clj: QR.chef @echo @echo "###########################" @echo "## 51: Chef -> Clojure ##" @echo "###########################" @echo PERL5LIB=vendor/local/lib/perl5 compilechef QR.chef QR.chef.pl perl QR.chef.pl > QR.clj QR.cmake: QR.clj @echo @echo "############################" @echo "## 52: Clojure -> CMake ##" @echo "############################" @echo clojure QR.clj > QR.cmake QR.cob: QR.cmake @echo @echo "##########################" @echo "## 53: CMake -> Cobol ##" @echo "##########################" @echo cmake -P QR.cmake > QR.cob QR.coffee: QR.cob @echo @echo "#################################" @echo "## 54: Cobol -> CoffeeScript ##" @echo "#################################" @echo cobc -O2 -x QR.cob ./QR > QR.coffee QR.lisp: QR.coffee @echo @echo "#######################################" @echo "## 55: CoffeeScript -> Common Lisp ##" @echo "#######################################" @echo coffee --nodejs --stack_size=100000 QR.coffee > QR.lisp QR.cr: QR.lisp @echo @echo "##################################" @echo "## 56: Common Lisp -> Crystal ##" @echo "##################################" @echo clisp QR.lisp > QR.cr QR.d: QR.cr @echo @echo "########################" @echo "## 57: Crystal -> D ##" @echo "########################" @echo crystal QR.cr > QR.d QR.dc: QR.d @echo @echo "###################" @echo "## 58: D -> dc ##" @echo "###################" @echo gdc -o QR QR.d ./QR > QR.dc QR.dhall: QR.dc @echo @echo "#######################" @echo "## 59: dc -> Dhall ##" @echo "#######################" @echo dc QR.dc > QR.dhall || true QR.exs: QR.dhall @echo @echo "###########################" @echo "## 60: Dhall -> Elixir ##" @echo "###########################" @echo dhall text --file QR.dhall > QR.exs QR.el: QR.exs @echo @echo "################################" @echo "## 61: Elixir -> Emacs Lisp ##" @echo "################################" @echo elixir QR.exs > QR.el QR.erl: QR.el @echo @echo "################################" @echo "## 62: Emacs Lisp -> Erlang ##" @echo "################################" @echo emacs -Q --script QR.el > QR.erl QR.e: QR.erl @echo @echo "##############################" @echo "## 63: Erlang -> Execline ##" @echo "##############################" @echo escript QR.erl > QR.e QR.fsx: QR.e @echo @echo "##########################" @echo "## 64: Execline -> F# ##" @echo "##########################" @echo execlineb QR.e > QR.fsx QR.false: QR.fsx @echo @echo "#######################" @echo "## 65: F# -> FALSE ##" @echo "#######################" @echo echo 'Exenet8.0false' > tmp.fsproj DOTNET_NOLOGO=1 dotnet run --project tmp.fsproj > QR.false QR.fl: QR.false @echo @echo "#########################" @echo "## 66: FALSE -> Flex ##" @echo "#########################" @echo ruby vendor/false.rb QR.false > QR.fl QR.fish: QR.fl @echo @echo "########################" @echo "## 67: Flex -> Fish ##" @echo "########################" @echo flex -o QR.fl.c QR.fl gcc -o QR QR.fl.c ./QR > QR.fish QR.fs: QR.fish @echo @echo "#########################" @echo "## 68: Fish -> Forth ##" @echo "#########################" @echo fish QR.fish > QR.fs QR.f: QR.fs @echo @echo "##############################" @echo "## 69: Forth -> FORTRAN77 ##" @echo "##############################" @echo gforth QR.fs > QR.f QR.f90: QR.f @echo @echo "##################################" @echo "## 70: FORTRAN77 -> Fortran90 ##" @echo "##################################" @echo @mv QR.c QR.c.bak gfortran -o QR QR.f ./QR > QR.f90 @mv QR.c.bak QR.c QR.gbs: QR.f90 @echo @echo "######################################" @echo "## 71: Fortran90 -> Gambas script ##" @echo "######################################" @echo gfortran -o QR QR.f90 ./QR > QR.gbs QR.g: QR.gbs @echo @echo "################################" @echo "## 72: Gambas script -> GAP ##" @echo "################################" @echo $(GBS) QR.gbs > QR.g QR.gdb: QR.g @echo @echo "######################" @echo "## 73: GAP -> GDB ##" @echo "######################" @echo gap -q QR.g > QR.gdb QR.gel: QR.gdb @echo @echo "###############################" @echo "## 74: GDB -> GEL (Genius) ##" @echo "###############################" @echo gdb -q -x QR.gdb > QR.gel QR.plt: QR.gel @echo @echo "###################################" @echo "## 75: GEL (Genius) -> Gnuplot ##" @echo "###################################" @echo genius QR.gel > QR.plt QR.go: QR.plt @echo @echo "#########################" @echo "## 76: Gnuplot -> Go ##" @echo "#########################" @echo gnuplot QR.plt > QR.go QR.gs: QR.go @echo @echo "############################" @echo "## 77: Go -> GolfScript ##" @echo "############################" @echo go run QR.go > QR.gs QR.gpt: QR.gs @echo @echo "####################################" @echo "## 78: GolfScript -> G-Portugol ##" @echo "####################################" @echo ruby vendor/golfscript.rb QR.gs > QR.gpt QR.grass: QR.gpt @echo @echo "###############################" @echo "## 79: G-Portugol -> Grass ##" @echo "###############################" @echo mv QR.c QR.c.bak gpt -t QR.c QR.gpt gcc -o QR QR.c ./QR > QR.grass mv QR.c.bak QR.c QR.groovy: QR.grass @echo @echo "###########################" @echo "## 80: Grass -> Groovy ##" @echo "###########################" @echo ruby vendor/grass.rb QR.grass > QR.groovy QR.gz: QR.groovy @echo @echo "##########################" @echo "## 81: Groovy -> Gzip ##" @echo "##########################" @echo groovy QR.groovy > QR.gz QR.hs: QR.gz @echo @echo "###########################" @echo "## 82: Gzip -> Haskell ##" @echo "###########################" @echo gzip -cd QR.gz > QR.hs QR.hx: QR.hs @echo @echo "###########################" @echo "## 83: Haskell -> Haxe ##" @echo "###########################" @echo rm -f QR.o ghc QR.hs ./QR > QR.hx QR.icn: QR.hx @echo @echo "########################" @echo "## 84: Haxe -> Icon ##" @echo "########################" @echo haxe -main QR -neko QR.n neko QR.n > QR.icn QR.i: QR.icn @echo @echo "############################" @echo "## 85: Icon -> INTERCAL ##" @echo "############################" @echo icont -s QR.icn ./QR > QR.i QR.j: QR.i @echo @echo "##############################" @echo "## 86: INTERCAL -> Jasmin ##" @echo "##############################" @echo @mv QR.c QR.c.bak ick -bfOc QR.i gcc -std=c99 -static QR.c -I /usr/include/ick-* -o QR -lick ./QR > QR.j @mv QR.c.bak QR.c QR.java: QR.j @echo @echo "##########################" @echo "## 87: Jasmin -> Java ##" @echo "##########################" @echo jasmin QR.j java QR > QR.java QR.js: QR.java @echo @echo "##############################" @echo "## 88: Java -> JavaScript ##" @echo "##############################" @echo javac QR.java java QR > QR.js QR.jq: QR.js @echo @echo "############################" @echo "## 89: JavaScript -> Jq ##" @echo "############################" @echo $(JAVASCRIPT) QR.js > QR.jq QR.jsfuck: QR.jq @echo @echo "########################" @echo "## 90: Jq -> JSFuck ##" @echo "########################" @echo jq -r -n -f QR.jq > QR.jsfuck QR.kt: QR.jsfuck @echo @echo "############################" @echo "## 91: JSFuck -> Kotlin ##" @echo "############################" @echo ulimit -s unlimited && $(JAVASCRIPT) --stack_size=100000 QR.jsfuck > QR.kt QR.ksh: QR.kt @echo @echo "#########################" @echo "## 92: Kotlin -> ksh ##" @echo "#########################" @echo kotlinc QR.kt -include-runtime -d QR.jar kotlin QR.jar > QR.ksh QR.lazy: QR.ksh @echo @echo "#########################" @echo "## 93: ksh -> Lazy K ##" @echo "#########################" @echo ksh QR.ksh > QR.lazy QR.ls: QR.lazy @echo @echo "################################" @echo "## 94: Lazy K -> LiveScript ##" @echo "################################" @echo lazyk QR.lazy > QR.ls QR.ll: QR.ls @echo @echo "##################################" @echo "## 95: LiveScript -> LLVM asm ##" @echo "##################################" @echo @mv QR.c QR.c.bak lsc QR.ls > QR.ll @mv QR.c.bak QR.c QR.lol: QR.ll @echo @echo "###############################" @echo "## 96: LLVM asm -> LOLCODE ##" @echo "###############################" @echo @mv QR.bc QR.bc.bak llvm-as QR.ll lli QR.bc > QR.lol @mv QR.bc.bak QR.bc QR.lua: QR.lol @echo @echo "##########################" @echo "## 97: LOLCODE -> Lua ##" @echo "##########################" @echo lci QR.lol > QR.lua QR.m4: QR.lua @echo @echo "#####################" @echo "## 98: Lua -> M4 ##" @echo "#####################" @echo lua5.3 QR.lua > QR.m4 QR.mk: QR.m4 @echo @echo "##########################" @echo "## 99: M4 -> Makefile ##" @echo "##########################" @echo m4 QR.m4 > QR.mk QR.mzn: QR.mk @echo @echo "#################################" @echo "## 100: Makefile -> MiniZinc ##" @echo "#################################" @echo make -f QR.mk > QR.mzn QR.mod: QR.mzn @echo @echo "#################################" @echo "## 101: MiniZinc -> Modula-2 ##" @echo "#################################" @echo minizinc --solver COIN-BC --soln-sep '' QR.mzn > QR.mod QR.il: QR.mod @echo @echo "#############################" @echo "## 102: Modula-2 -> MSIL ##" @echo "#############################" @echo gm2 -fiso QR.mod -o QR ./QR > QR.il QR.mustache: QR.il @echo @echo "#############################" @echo "## 103: MSIL -> Mustache ##" @echo "#############################" @echo ilasm QR.il mono QR.exe > QR.mustache QR.asm: QR.mustache @echo @echo "#############################" @echo "## 104: Mustache -> NASM ##" @echo "#############################" @echo mustache QR.mustache QR.mustache > QR.asm QR.neko: QR.asm @echo @echo "#########################" @echo "## 105: NASM -> Neko ##" @echo "#########################" @echo nasm -felf QR.asm ld -m elf_i386 -o QR QR.o ./QR > QR.neko QR.5c: QR.neko @echo @echo "###########################" @echo "## 106: Neko -> Nickle ##" @echo "###########################" @echo nekoc QR.neko neko QR.n > QR.5c QR.nim: QR.5c @echo @echo "##########################" @echo "## 107: Nickle -> Nim ##" @echo "##########################" @echo nickle QR.5c > QR.nim QR.m: QR.nim @echo @echo "###############################" @echo "## 108: Nim -> Objective-C ##" @echo "###############################" @echo nim compile QR.nim ./QR > QR.m QR.ml: QR.m @echo @echo "#################################" @echo "## 109: Objective-C -> OCaml ##" @echo "#################################" @echo gcc -o QR QR.m ./QR > QR.ml QR.octave: QR.ml @echo @echo "############################" @echo "## 110: OCaml -> Octave ##" @echo "############################" @echo ocaml QR.ml > QR.octave QR.ook: QR.octave @echo @echo "###########################" @echo "## 111: Octave -> Ook! ##" @echo "###########################" @echo mv QR.m QR.m.bak octave -qf QR.octave > QR.ook mv QR.m.bak QR.m QR.gp: QR.ook @echo @echo "############################" @echo "## 112: Ook! -> PARI/GP ##" @echo "############################" @echo ruby vendor/ook-to-bf.rb QR.ook QR.ook.bf ruby vendor/bf.rb QR.ook.bf > QR.gp QR.p: QR.gp @echo @echo "################################" @echo "## 113: PARI/GP -> Parser 3 ##" @echo "################################" @echo gp -f -q QR.gp > QR.p QR.pas: QR.p @echo @echo "###############################" @echo "## 114: Parser 3 -> Pascal ##" @echo "###############################" @echo parser3 QR.p > QR.pas QR.pl: QR.pas @echo @echo "#############################" @echo "## 115: Pascal -> Perl 5 ##" @echo "#############################" @echo fpc QR.pas ./QR > QR.pl QR.pl6: QR.pl @echo @echo "#############################" @echo "## 116: Perl 5 -> Perl 6 ##" @echo "#############################" @echo perl QR.pl > QR.pl6 QR.php: QR.pl6 @echo @echo "##########################" @echo "## 117: Perl 6 -> PHP ##" @echo "##########################" @echo perl6 QR.pl6 > QR.php QR.png: QR.php @echo @echo "########################" @echo "## 118: PHP -> Piet ##" @echo "########################" @echo php QR.php > QR.png QR.pike: QR.png @echo @echo "#########################" @echo "## 119: Piet -> Pike ##" @echo "#########################" @echo npiet QR.png > QR.pike QR.ps: QR.pike @echo @echo "###############################" @echo "## 120: Pike -> PostScript ##" @echo "###############################" @echo pike QR.pike > QR.ps QR.prolog: QR.ps @echo @echo "#################################" @echo "## 121: PostScript -> Prolog ##" @echo "#################################" @echo gs -dNODISPLAY -q QR.ps > QR.prolog QR.pr: QR.prolog @echo @echo "#####################################" @echo "## 122: Prolog -> Promela (Spin) ##" @echo "#####################################" @echo swipl -q -t qr -f QR.prolog > QR.pr QR.py: QR.pr @echo @echo "#####################################" @echo "## 123: Promela (Spin) -> Python ##" @echo "#####################################" @echo spin -T QR.pr > QR.py QR.R: QR.py @echo @echo "########################" @echo "## 124: Python -> R ##" @echo "########################" @echo python3 QR.py > QR.R QR.ratfor: QR.R @echo @echo "########################" @echo "## 125: R -> Ratfor ##" @echo "########################" @echo R --slave -f QR.R > QR.ratfor QR.rc: QR.ratfor @echo @echo "#########################" @echo "## 126: Ratfor -> rc ##" @echo "#########################" @echo ratfor -o QR.ratfor.f QR.ratfor gfortran -o QR QR.ratfor.f ./QR > QR.rc QR.rexx: QR.rc @echo @echo "#######################" @echo "## 127: rc -> REXX ##" @echo "#######################" @echo rc QR.rc > QR.rexx QR2.rb: QR.rexx @echo @echo "#########################" @echo "## 128: REXX -> Ruby ##" @echo "#########################" @echo rexx ./QR.rexx > QR2.rb clean: @mv QR.rb quine-relay.rb rm -f qr QR qr.* QR.* QR2.rb *.class gst.im @mv quine-relay.rb QR.rb ================================================ FILE: QR.rb ================================================ eval$s=%q(eval(%w(B=92.chr;g=32.chr;puts(eval(%q(N=10.chr;n=0;e=->s{Q[Q[s,B],?"].K(N,B+?n)};E=->s{'("'+e[s]+'")'};d=->s,t=?"{s.K(t){t+t}};def~f(s,n)s.K(/.{1,#{n*255}}/m){yield$S=E[$s=$&]}end;Q=->s,t=?${s.K(t){B+$&}};R=";return~0;";V=->s,a,z{s.K(/( #{B*4})+/){a+"#{$&.size/2}"+z}};C=%w(System.Console~Write);$C=C*?.;$D="program~QR";$G="~contents~of"+$F="~the~mix!g~bowl";$L="public~static";$W="s.WriteByte";rp=->s,r{v="";[r.!ject(s){|s,j|o={};m=n=0;s.size.times{|i|o[f=s[i,2]]||=0;c=o[f]+=1;m(p(3+ord~c);Z"-1~0~";c))#{E[~~~~~~%(object"Application"{state"ma!"{foreach(s~![#{f("Z#{E[%(puts~"#{Q[e[%(echo~'a::=`x7e#{Q[Q["let~s=#{E[%(void~p(!t[]c){foreach(!t~v~!~c)stdout.Zf("%c%c ",v/256,v%256);}void~mX{!t[]a;p({19796,26724,0,6,0,1,480,19796,29291,#{s=%(module~QR;!itial~beg!~#{f((%(Module~QR`nSub~MX`nDim~c,n:Dim~s~As~Object=#{C[0]}.OpenStandardOutput():Dim~t()As~Short={26,34,86,127,148,158,200}:For~Each~d~!"BasmCBBBCRE`x60 F<<<D`x21BE@ABRCABRCABRCA`x4a`x21CE@~B-BB~CACk:CvACqRC~COBMADRCACRCADRCABRCABRC~BACj:B-BBOBMADRCADRCADRCAFRCMM}CBABM`x7e#{ 40.chr}BBBCBBB,BBBDBBB0BBBDBBB4BBB=BBB?BBB;BBB~...^t..^n..(module(import~:wasi_snapshot_preview1:~:fd_H:~(func(param~i32~i32~i32~i32)(result~i32)))(memory(export~:memory:)(data~:^08^00^00^00$:))(func(export~:_start:)i32.const~1~i32.const~0~i32.con st~1~i32.const~0~call~0~drop))":c=Asc(d):If~c=36:For~c=0To~11:#$W(If(c~Mod~3,Asc(#{s="<#{U="xsl:template"}~match='/'><`x21[CDATA[#{%(su b~f(s$,n) Z(s$);:for~i=1to~n~Z("Y");:next:end~sub:f("#{V[e[%(H,format="#{y="";f("^H{-}{txt}{#{Q["echo~-E~$'#{Q[Q[E[%(with~Ada.Text_Io;procedure~qr~is~beg!~Ada.Text_Io.Put("#{d[%(trans ~B(Buffer)`ntrans~O(n){`nB:add(Byte(+~128~n))}`ntra ns~f(v ~n){ `nO(+(/~ n~64)107)`nO(n:mod~64)`nO~v}`ntrans~D(n){if(<~n~4){f(+(*~6~n)9)48}{if(n:odd-p){D(-~n~3)`nf~27~48`nf~36~11}{D(/~n~2)`nf~21~48`nf~48~20}}}`ntrans~S(Buffer"#{e[%W[ST RINGz:=~226+~153,a:=z+~166,b:=a+"2"+z+~160,c:=b+" 8"+ z +~165,t:="#{d[%(class~QR{#$L~void~ma!(SJ[]a){a=#{E["H('#{Q[e["implement~ma!0()=Z"+E[ "BEGIN{Z#{E[%(echo~'#{%(f(s){System.out.Z(s);}s="389**6+44*6+00 p45*,";for(c:#{E[(s="#!clude`n!t~mX{s td ::cout<<#{E[%(class~Program{#$L~void~MX{#$C("Qu!e~Relay~Coffee. ^n^nIngredients.^n");for(!t~i=9;i++<126;)#$C($"{i}~g~ca ffe!e~{i}^n");#$C("^nMethod.^n");foreach(char ~c~!#{E[%((doseq[s(lazy-cat["IDENTIFICATION~DIVISION.""PROGR AM-ID.~QR.""PROCEDURE~DIVISION."'DISPLA`x59](map~# (str"~~~~^""(.replace~%1"^"""^"^"")"^"")(re- seq~#".{1,45}""#{e["(f=(n)->Array(n+1).jo!~'Y');c onsole.log('%s',#{V[E[%((H-l!e"#{e["puts#{E["i mport~std.stdio;void~mX{H(`x60#{"['']p[#{"I O.puts"+E[%((pr!c~"#{e["`nma!(_)->`nio:fH# {d[E[%(echo~"#{e['Zfn("""'+d[?"+"%option~no yywrap`n%%`n%%`n!t~mX{puts#{E["echo~'#{Q[ Q[%(~:~A~."#{g*9}"~;~:~B~A~."~WRITE(*,*)' "~A~;~:~C~B~T`x59PE~."~'"~CR~;~:~D~S"~#$ D"~C~S^"~Z~^"(&"~C~S^"~#{e[%(Z"#{e["s:= Outp utTextUser();WriteAll(s,#{E[%(Zf"# {e[d[f('set~Z" -";Z'+E[%(package~ma!;import"fmt";fun c~mX{fmt.Pr!t#{E[%(236:j;{119:i;{206i- :i;.4 8<{71+}{[i]^48-*}if}%}:t;"al goritmo~QR;!"[195][173]++'ci o~imprima("'"013141"t"/12131"t~6*"/1 :1918151:??6271413/4=3626612/2/353251 215/ `x5a0`x5a0R"t"#{e[%(z=new~j ava.util.zip.G`x5aIPOutputStream(Syste m.out);z.H('#{"ma!=putStr"+E["clas s~QR{#$L~function~mX{neko.Lib.Z#{E[%( procedure~mX;i:=c:=0;s :=#{E[%(.class~public~ QR`n.super~#{$T="java/io/Pr!tStream"}`n.meth od~#$L~ma!([L#{S="java/lang/S"}J ;)V~;]`n.limit~stack~2`ngetstatic~#{S }yst em/out~L#$T;`nldc~"#{e[%(class~QR{ #$L~void~ma!(SJ[] v){SJ~c[]=new~SJ[99999],y="",z=y,s="#{z=t=(0..r=q= 126).map{|n|[n,[]]};a="";b=->n{ a<<(n%78+55)%84+42};(%(P={0:'[+[]]',m:' ((+[])'+(C="['constructor']")+"+[])['11']"};for(R ~!~B=('`x21[] @`x21`x21[]@[][[]]@'+(A="[]['fill']")+"@([]+[])['fontc olor']([])@(+('11e20')+[])['s plit']([])@"+A+C+"('return~escape')( )("+A+')').split('@'))for(E~!~D=eval(G='('+B[R]+'+[ ])'))P[T=D[E ]]=P[T]||G+"['"+E+"']";for(G='[',B=0;++B<36;)P[D=B.toSJ(36 )]=B<10?(G+='+`x21+[]')+']': P[D]||"(+('"+B+"'))['to'+([]+[])" +C+"['name']]('36')";A+=C+"('console.log(unescape(^"";fo r(E~!~G= #{E["fun~ma!(a:Array){Z#{Q[E[%(p(){~echo~-n~$1;};f(){~for ~x~!~$(p~"$1"|od~-An~-tu1~- v);do;p~$4;for((j=$3;j--;));do;h ~$2~$x~$j;done;done;};p~k^`x60;h(){~p~^`x60${1:$(($2>>$3&1)) :2}; };f~'console.log#{Q[E[%(@s=global[#{i=(s=%(`x48AI~1.2`nVISIBLE~"# {"x=sJ.K(#{V[E["changequot e(<@,@>)`ndef!e(p,<@#{"all:`n` t@echo~'#{d["solve~satisfy;output~[#{E["MODULE~QR;FROM~StrIO~IM PO RT~WriteSJ;BEGIN~#{(%(.assembly~t{}.method~#$L~void~MX{.entrypo!t~ldstr"#{e["m{ {`x21:~x`nqr:~|-`n~:db`x60 #{e[s="$Z#{E["Zf#{E["echo#{E ["#import#{N}!t~mX{puts#{E["Z_sJ"+E["s=double#{E["Z#{E["$c onsole :l!e[#{"#$D(output);beg!~H(#{f((p="eval";%($_="#{s,v=rp["$_='#{ Q[%($z)&&$i/$z<($c< $w?ord($s[(!t)($c/3)]):$c--%3+2)?$t[2].$t[$c%3%2].$t[$c%3]:"^0^0^0":"^0")$c =$i%$z;foreach(array("I`x48DR".pack("NNCV ",$w+2,128,8,2),"IDAT".g zcompress($m),"IEND")as$d )echo~pack("NA*N",strlen($d)-4,$d,crc32($d));).K(B,"`x7f"),?']}';s:g/^x7f/Y/ ;Z~$_",128..287];s="$_='#{Q[s,c=/['Y] /]}';$n=32;$s='#{Q[v,c]} ';$s=`x7es{..}{$a=$&;$b= chr(--$n&255);`x7es/$b/$a/g;}eg;Z";(s+N*(-s.size%6)).unpack("B*")[0].K(/.{6}/){ n=$&.to_i~2;((n+14)/26*6+n+47).chr }}";s|.|$n=ord$&;substr ~unpack(B8,chr$n-!t($n/3 2)*6-41),2|eg;eval~pack'B*',$_).scan(/[~,-:A-z]+|(.)/){p="s++#{$1?"chr~#{$1.ord} +e":$&+?+};"+p};p),1){"'#$s',"} }'')end.".K(/[:;()]/){? `x5e+$&}}]"]};quit"]};t =num2cell(b=11-ceil(s/13));for~n=1:9m={};for~i=1:141f=@(x,y,n)repmat(['Ook'~char(x )~'~Ook'~char(y)~'~'],[1~ab s(n)]);m(i)=[f(z=46,63, n)~f(q=z-(i<13)*13,q,i- 13)~f(33,z,1)~f(63,z,n)];end;t(x=b==n)=m(diff([0~s(x)])+13);end;Zf('%%s',t{:})"]]+R }}"]}"]}`n"]};"]}`x60`n~ global~_start`n~_start:m ov~edx,#{s.size}`n~mov~ ecx,m`n~mov~ebx,1`n~mov~eax,4`n~!t~128`n~mov~ebx,0`n~mov~eax,1`n~!t~128`nx:~|`n~}} { {{qr}}}"]}"call~void~ [mscorlib]#{C*"::"}(sJ)r et})).K(/()[#{i=94.chr} "]+|[#{i}']+/){["WriteSJ(",$&,");"]*($1??":?')}}END~QR."]}];",?$].K(?'){"'^''"}} '" }@>)`np"], ?&,? &]},'&(%d+)&',func tion(s)return~sJ.rep('Y' ,tonumber(s))end);Z(x)" .K(/[:"]/,":^0")}"`n`x4bT`x48`x58B`x59E~B`x59E)).size+1}x~i8]c"#{s.K(/[^"`n`t]/ ) {"^%02`x58"%$ &.ord}}^00" declare~i32@put s(i8*)def!e~i32@mX{%1=cal l~i32@puts(i8*getelement ptr([#{i}x~i8],[#{i}x~i8]*@s,i32~0,i32~0))ret~i32~0})],?#].K(?',%('"'"'))}'~k k i~7~'`x60`x60s `x60`x60s`x60` x60s` x60`x60s`x60 `x60s`x60`x60s`x60`x60s`x 60`x60si';h(){~p~${1:$(( (($2%83-10)>>((2-$3)*2))%4)):1};};f~'AG-`x48-`x48Fy.IlD==;=jdlAy=;=jldltld lt l{lAulAy=jtlldlAyFy=?=jdlAyGFyF yG2AFy>zlAFF BCjldGyGF y>GFy.AGy=G==n`x48==nlldC= j@=jtlldltldlAut11'~ski^` x60~3)]]}~}"]})A+="'+`x21[]+'"+G.charCodeAt(E).toSJ(16);for(A+="^".repla ce(/ '+`x21[]+'/g,^"%^")))')()",R=0;R <9;R++)A=A.repla ce(/'. *?'/g,function(B){T=[];for( E=1;B[E+1];)T.push(P[B[E++ ]]);return~T.jo!('+')});console.log('"'+A+'"'))).bytes{|n|r,z=z[n]||( b[r/78]; b[r];q<6083&&z[n]=[q+=1,[]];t[n] )};b[r/78];b[r]}";! t~i =0,n=0,q=0;for(;++n<126;)c[n ]=""+(char)n;for(;i<#{a.si ze};){q=q*78+(s.charAt(i)-13)%84;if(i++%2>0){y=qn{L<<(n+62)%92+35;D};s.by tes{|c|n>0?n-=1:(t[c]=(t[c]||[ ]).reject{|j|j4&&x<<[k,j]};x=x.max)?(n,j=x;x=b. size;(u=[x,3999 ].m!;D[u%87][u/87];L<0;x=4001+i-j;D[x%87][x/87][n-5]):b<< c;t[c]+=[i+=1]};"#!clude`nchar*p= #{E[L]},s[999999],*q=s;!t~mX{!t~n,m;for(;*p;){n=(* p-5)%92+(p[1]-5)%92*87;p+=2;if(n>3999)for(m=(*p ++-5)%92+6;m--;q++)*q=q[4000-n];else~for(;n-- ;)*q++=*p++;}puts(s)#{R}}")]}){s+="00g,";for(m=1;m<256;m* =2)s+="00g,4,:"+(c/m%2>0?"4+":"")+",";f(s);s="4,:," ;}f(s+s);for(c:Base64.getDecoder().decode("kaARERE `x58/I0ALn3n5ef6l/Pz8+fnz58/BOf5/7/hE`x58/O`x5azM5mC`x58/Oczm`x5a zBPn5+`x58/OczMznBL/nM5m`x5azBPu++fPPOc5zngnnO`x5azO`x5 agnBMGAW7A==")){c=c<0?256+c:c;for(i=0;i++<3;c/=8)f(c%8); f("8*+8*+,");}f("@");).K(?',%('"'"'))}'|sed~-e's/Y/YY/g'~-e's/"/Yq/g'~-e's/.*/Z ~"&"^nquit/')]}}"]],?']}');".K(/^+/){"`x5e#{$&.size}`x5e"}]}.s plit("Y`x5e");for(!t~i=1;i#{U}>";s.size*16+3}.ToSJ("x8")(1`x58or~7-c*2^3)),92)):Next:Else:n=(c>124)*(8*c-#{s.size+1294}):Do~While~n>127:#$W(128+(127And~n)):n^=128:Loop:#$W(If(c<125,If((c-1)^7-8,c+66*(c>65And~c<91),t(c-57)),n)):End~If:Next:For~Each~c~!"#{d [s].K~N,'"&~VbLf~&"'}":#$W(Asc(c)):Next:End~Sub:End~Module)).l!es.map{|s|"let~s=#{E[s]}`nput=s`nZ`n"}.jo!+"qa`x21",3){%($H("%s",#$S);)+N}}end~endmodule);W=s.size*72+4;"%d,%d"%[W/65536,W%65536]}});foreach(!t~c~!#{E[s]}.data)foreach(!t~v~!~a={0,9,7, 4,5,c/100*7/6+1,c%100/10*7/6+1,c%10*7/6+1,7})p({144,v=15450+v*256,384,v});p({255,12032});})]},i=0,t='k';while(s[i])t='^x60.'+s[i++]+t;console.log(t)",B],?`x21].K(?',%('"'"'))}'"^n::=^na")],/[`[`]$]/]}")]}",4){$S+?,}}])Console.H(s);Application.exit ();}})]};Z"0~0~-1");)],127..255];f(%(variable~s=`x60#{s.K(/.{1,234}/){$&.K("`x60",%(`x60+"`x60"+`x60))+"`x60+`n`x60"}}`x60,i;for(i=0;i<129;i++)s=strreplace(s,pack("C",255-i),substrbytes(`x60#{v[0,99]}`x60+`n`x60#{v[99..-1]}`x60,i*2+1,2));Zf("%s",s )),7){"f('%s')`n"%$s.unpack("`x48*")}}Zf("^n#[Exeunt]");quit)]}")),196){%(Z#$S;)}}}"]});})).gsub(/[!HJKXYZ^`~]/){[B*2,:write,B,:tring,:gsub,"ain()",B*4,:print,g,:in][$&.ord%47%12]})))*"")#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_ #_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffe #################################################################################### Quine Relay -- Copyright (c) 2013, 2014 Yusuke Endoh (@mametter), @hirekoke ###################################################################################) ================================================ FILE: README.md ================================================ # Quine Relay [](https://github.com/mame/quine-relay/actions?query=workflow%3ACI) ## What this is [QR.rb](https://github.com/mame/quine-relay/blob/master/QR.rb) is a Ruby program that generates a Rust program that generates a Scala program that generates ...(through 128 languages in total)... a REXX program that generates the original Ruby code again. ![Language Uroboros][langs] [langs]: langs.png (If you want to see the old 50-language version, see the [50](https://github.com/mame/quine-relay/tree/50) branch.) ## Usage ### Ubuntu If you are using Ubuntu 25.10 (Questing Quokka), you can follow these steps. #### 1. Install all the interpreters/compilers. First, you need to type the following apt-get command to install them all. $ sudo apt-get install afnix algol68g aplus-fsf aspectj asymptote \ ats2-lang bash bc bsh clisp clojure cmake coffeescript crystal dc \ dhall dotnet8 elixir emacs-nox erlang execline f2c fish flex \ fp-compiler g++ gambas3-gb-pcre gambas3-scripter gap gawk gcc gdb gdc \ genius gforth gfortran ghc ghostscript gm2 gnat gnucobol4 gnuplot \ gobjc golang gpt groovy guile-3.0 gzip haxe icont iconx intercal \ iverilog jasmin-sable jq kotlin ksh libevent-dev libpolyml-dev \ livescript llvm lua5.3 m4 make minizinc mono-devel nasm neko nickle \ nim node-typescript nodejs ocaml octave openjdk-11-jdk pari-gp \ parser3-cgi perl php-cli pike8.0 polyml python3 r-base rakudo ratfor \ rc regina-rexx ruby ruby-mustache rustc scala scilab-cli sed slsh spin \ squirrel3 surgescript swi-prolog swiftlang tcl tcsh valac vim wabt \ xsltproc yabasic yorick zoem zsh Then, build the bundled interpreters. $ sudo apt-get install cmake libpng-dev libgd-dev groff bison curl $ make -C vendor #### 2. Run each program on each interpreter/compiler. $ ulimit -s unlimited $ ruby QR.rb > QR.rs $ rustc QR.rs && ./QR > QR.scala $ scalac QR.scala && scala QR > QR.scm $ guile QR.scm > QR.sci $ scilab-cli -nb -f QR.sci > QR.sed $ sed -E -f QR.sed QR.sed > QR.spl $ spl2c < QR.spl > QR.spl.c && gcc -z muldefs -o QR -I ./vendor/local/include -L ./vendor/local/lib QR.spl.c -lspl -lm && ./QR > QR.sl $ slsh QR.sl > QR.nut $ squirrel QR.nut > QR.sml $ polyc -o QR QR.sml && ./QR > QR.sq $ ruby vendor/subleq.rb QR.sq > QR.ss $ surgescript QR.ss > QR.swift $ swiftc QR.swift && ./QR > QR.tcl $ tclsh QR.tcl > QR.tcsh $ tcsh QR.tcsh > QR.t $ ruby vendor/thue.rb QR.t > QR.ts $ tsc --outFile QR.ts.js QR.ts && nodejs QR.ts.js > QR.unl $ ruby vendor/unlambda.rb QR.unl > QR.vala $ valac QR.vala && ./QR > QR.mid $ mono vendor/local/bin/Vlt.exe /s QR.mid && mono QR.exe > QR.v $ iverilog -o QR QR.v && ./QR -vcd-none > QR.vim $ vim -EsS QR.vim > QR.vb $ echo 'Exenet8.0false' > tmp.vbproj && DOTNET_NOLOGO=1 dotnet run --project tmp.vbproj > QR.wasm $ $(WASI_RUNTIME) QR.wasm > QR.wat $ wat2wasm QR.wat -o QR.wat.wasm && $(WASI_RUNTIME) QR.wat.wasm > QR.ws $ ruby vendor/whitespace.rb QR.ws > QR.xslt $ xsltproc QR.xslt > QR.yab $ yabasic QR.yab > QR.yorick $ yorick -batch QR.yorick > QR.azm $ zoem -i QR.azm > QR.zsh $ zsh QR.zsh > QR.+ $ a+ QR.+ > qr.adb $ gnatmake qr.adb && ./qr > QR.als $ LANG=C LD_LIBRARY_PATH=/usr/lib/afnix axi QR.als > QR.aheui $ ruby vendor/aheui.rb QR.aheui > QR.a68 $ a68g QR.a68 > QR.ante $ ruby vendor/ante.rb QR.ante > QR.aj $ ajc QR.aj && java QR > QR.asy $ asy QR.asy > QR.dats $ patscc -o QR QR.dats && ./QR > QR.awk $ awk -f QR.awk > QR.bash $ bash QR.bash > QR.bc $ BC_LINE_LENGTH=4000000 bc -q QR.bc > QR.bsh $ bsh QR.bsh > QR.bef $ cfunge QR.bef > QR.Blc $ ruby vendor/blc.rb < QR.Blc > QR.bf $ ruby vendor/bf.rb QR.bf > QR.c $ gcc -o QR QR.c && ./QR > QR.cpp $ g++ -o QR QR.cpp && ./QR > QR.cs $ echo 'Exenet8.0false' > tmp.csproj && DOTNET_NOLOGO=1 dotnet run --project tmp.csproj > QR.chef $ PERL5LIB=vendor/local/lib/perl5 compilechef QR.chef QR.chef.pl && perl QR.chef.pl > QR.clj $ clojure QR.clj > QR.cmake $ cmake -P QR.cmake > QR.cob $ cobc -O2 -x QR.cob && ./QR > QR.coffee $ coffee --nodejs --stack_size=100000 QR.coffee > QR.lisp $ clisp QR.lisp > QR.cr $ crystal QR.cr > QR.d $ gdc -o QR QR.d && ./QR > QR.dc $ dc QR.dc > QR.dhall || true $ dhall text --file QR.dhall > QR.exs $ elixir QR.exs > QR.el $ emacs -Q --script QR.el > QR.erl $ escript QR.erl > QR.e $ execlineb QR.e > QR.fsx $ echo 'Exenet8.0false' > tmp.fsproj && DOTNET_NOLOGO=1 dotnet run --project tmp.fsproj > QR.false $ ruby vendor/false.rb QR.false > QR.fl $ flex -o QR.fl.c QR.fl && gcc -o QR QR.fl.c && ./QR > QR.fish $ fish QR.fish > QR.fs $ gforth QR.fs > QR.f $ gfortran -o QR QR.f && ./QR > QR.f90 $ gfortran -o QR QR.f90 && ./QR > QR.gbs $ gbs3 QR.gbs > QR.g $ gap -q QR.g > QR.gdb $ gdb -q -x QR.gdb > QR.gel $ genius QR.gel > QR.plt $ gnuplot QR.plt > QR.go $ go run QR.go > QR.gs $ ruby vendor/golfscript.rb QR.gs > QR.gpt $ mv QR.c QR.c.bak && gpt -t QR.c QR.gpt && gcc -o QR QR.c && ./QR > QR.grass && mv QR.c.bak QR.c $ ruby vendor/grass.rb QR.grass > QR.groovy $ groovy QR.groovy > QR.gz $ gzip -cd QR.gz > QR.hs $ rm -f QR.o && ghc QR.hs && ./QR > QR.hx $ haxe -main QR -neko QR.n && neko QR.n > QR.icn $ icont -s QR.icn && ./QR > QR.i $ ick -bfOc QR.i && gcc -std=c99 -static QR.c -I /usr/include/ick-* -o QR -lick && ./QR > QR.j $ jasmin QR.j && java QR > QR.java $ javac QR.java && java QR > QR.js $ nodejs QR.js > QR.jq $ jq -r -n -f QR.jq > QR.jsfuck $ nodejs --stack_size=100000 QR.jsfuck > QR.kt $ kotlinc QR.kt -include-runtime -d QR.jar && kotlin QR.jar > QR.ksh $ ksh QR.ksh > QR.lazy $ lazyk QR.lazy > QR.ls $ lsc QR.ls > QR.ll $ llvm-as QR.ll && lli QR.bc > QR.lol $ lci QR.lol > QR.lua $ lua5.3 QR.lua > QR.m4 $ m4 QR.m4 > QR.mk $ make -f QR.mk > QR.mzn $ minizinc --solver COIN-BC --soln-sep '' QR.mzn > QR.mod $ gm2 -fiso QR.mod -o QR && ./QR > QR.il $ ilasm QR.il && mono QR.exe > QR.mustache $ mustache QR.mustache QR.mustache > QR.asm $ nasm -felf QR.asm && ld -m elf_i386 -o QR QR.o && ./QR > QR.neko $ nekoc QR.neko && neko QR.n > QR.5c $ nickle QR.5c > QR.nim $ nim compile QR.nim && ./QR > QR.m $ gcc -o QR QR.m && ./QR > QR.ml $ ocaml QR.ml > QR.octave $ mv QR.m QR.m.bak && octave -qf QR.octave > QR.ook && mv QR.m.bak QR.m $ ruby vendor/ook-to-bf.rb QR.ook QR.ook.bf && ruby vendor/bf.rb QR.ook.bf > QR.gp $ gp -f -q QR.gp > QR.p $ parser3 QR.p > QR.pas $ fpc QR.pas && ./QR > QR.pl $ perl QR.pl > QR.pl6 $ perl6 QR.pl6 > QR.php $ php QR.php > QR.png $ npiet QR.png > QR.pike $ pike QR.pike > QR.ps $ gs -dNODISPLAY -q QR.ps > QR.prolog $ swipl -q -t qr -f QR.prolog > QR.pr $ spin -T QR.pr > QR.py $ python3 QR.py > QR.R $ R --slave -f QR.R > QR.ratfor $ ratfor -o QR.ratfor.f QR.ratfor && gfortran -o QR QR.ratfor.f && ./QR > QR.rc $ rc QR.rc > QR.rexx $ rexx ./QR.rexx > QR2.rb You will see that `QR.rb` is the same as `QR2.rb`. $ diff QR.rb QR2.rb Alternatively, just type `make`. $ make Note: It may take a lot of memory to compile some files. ### Docker Simply build the image and run a container as follows: $ docker build -t qr . $ docker run --privileged --rm -e CI=true qr Note: You must run in privileged mode, otherwise the `maxima` command will fail. If you want to check the generated files, you can mount the local directory in the Docker container (but still use the `vendor` directory of the container), as follows: $ docker run --privileged --rm -e CI=true -v $(pwd):/usr/local/share/quine-relay -v /usr/local/share/quine-relay/vendor qr ### Other platforms You may find [instructions for other platforms in the wiki](https://github.com/mame/quine-relay/wiki/Installation). If you do not use these Linux distributions, please find your own way. If you manage it, please let me know. I wish you good luck. ## Interpreter/compiler versions tested I used the following Ubuntu deb packages to test this program. \# |language |ubuntu package |version ----|----------------------------|----------------------------------|-------------------------------- 1 |Ruby |ruby |1:3.3 2 |Rust |rustc |1.85.1ubuntu1 3 |Scala |scala |2.11.12-6 4 |Scheme |guile-3.0 |3.0.10+really3.0.10-5 5 |Scilab |scilab-cli |2024.1.0+dfsg-7ubuntu1 6 |sed |sed |4.9-2build2 7 |Shakespeare |*N/A* |- 8 |S-Lang |slsh |2.3.3-5 9 |Squirrel |squirrel3 |3.1-8.2 10 |Standard ML |polyml, libpolyml-dev |5.7.1-5build1 11 |Subleq |*N/A* |- 12 |SurgeScript |surgescript |0.5.4.4-1.1 13 |Swift |swiftlang |6.0.3-2build1 14 |Tcl |tcl |8.6.16 15 |tcsh |tcsh |6.24.13-2 16 |Thue |*N/A* |- 17 |TypeScript |node-typescript |5.0.4+ds1-2 18 |Unlambda |*N/A* |- 19 |Vala |valac |0.56.18-2 20 |Velato |*N/A* |- 21 |Verilog |iverilog |12.0-2build2 22 |Vimscript |vim |2:9.1.0967-1ubuntu6 23 |Visual Basic |dotnet8 |8.0.120-8.0.20-0ubuntu1 24 |WebAssembly (Binary format) |wabt |1.0.36+dfsg+\~cs1.0.36-2ubuntu1 25 |WebAssembly (Text format) |wabt |1.0.36+dfsg+\~cs1.0.36-2ubuntu1 26 |Whitespace |*N/A* |- 27 |XSLT |xsltproc |1.1.43-0.1 28 |Yabasic |yabasic |1:2.91.4-1 29 |Yorick |yorick |2.2.04+dfsg1-14 30 |Zoem |zoem |21-341-2 31 |zsh |zsh |5.9-8ubuntu2 32 |A+ |aplus-fsf |4.22.1-13 33 |Ada |gnat |14.1ubuntu1 34 |AFNIX |afnix |3.8.0-1.1ubuntu1 35 |Aheui |*N/A* |- 36 |ALGOL 68 |algol68g |3.1.2-1 37 |Ante |*N/A* |- 38 |AspectJ |aspectj |1.9.6-1 39 |Asymptote |asymptote |3.05+ds-2 40 |ATS |ats2-lang |0.4.2-3 41 |Awk |gawk |1:5.3.2-1build1 42 |bash |bash |5.2.37-2ubuntu5 43 |bc |bc |1.07.1-4 44 |BeanShell |bsh |2.0b4-20 45 |Befunge |*N/A* |- 46 |BLC8 |*N/A* |- 47 |Brainfuck |*N/A* |- 48 |C |gcc |4:15.2.0-4ubuntu1 49 |C++ |g++ |4:15.2.0-4ubuntu1 50 |C# |dotnet8 |8.0.120-8.0.20-0ubuntu1 51 |Chef |*N/A* |- 52 |Clojure |clojure |1.12.0-1 53 |CMake |cmake |3.31.6-2ubuntu6 54 |Cobol |gnucobol4 |4.0\~early\~20200606-8 55 |CoffeeScript |coffeescript |2.7.0+dfsg1-2 56 |Common Lisp |clisp |1:2.49.20250504.gitf662209-1 57 |Crystal |crystal, libevent-dev |1.14.0+dfsg-1 58 |D |gdc |4:15.2.0-4ubuntu1 59 |dc |dc |1.07.1-4 60 |Dhall |dhall |1.42.1-1build2 61 |Elixir |elixir |1.18.3.dfsg-1 62 |Emacs Lisp |emacs-nox |1:30.1+1-9ubuntu1 63 |Erlang |erlang |1:27.3.4.1+dfsg-1build1 64 |Execline |execline |2.9.6.1-1 65 |F# |dotnet8 |8.0.120-8.0.20-0ubuntu1 66 |FALSE |*N/A* |- 67 |Flex |flex |2.6.4-8.2build1 68 |Fish |fish |4.0.6-0ubuntu1 69 |Forth |gforth |0.7.3+dfsg-9build4.1 70 |FORTRAN77 |f2c |20240504-1 71 |Fortran90 |gfortran |4:15.2.0-4ubuntu1 72 |Gambas script |gambas3-scripter, gambas3-gb-pcre |3.20.4-1build1 73 |GAP |gap |4.15.0-1 74 |GDB |gdb |16.3-1ubuntu2 75 |GEL (Genius) |genius |1.0.27-1build4 76 |Gnuplot |gnuplot |6.0.2+dfsg1-2ubuntu1 77 |Go |golang |2:1.24\~2 78 |GolfScript |*N/A* |- 79 |G-Portugol |gpt |1.1-8 80 |Grass |*N/A* |- 81 |Groovy |groovy |2.4.21-10 82 |Gzip |gzip |1.13-1ubuntu4 83 |Haskell |ghc |9.6.6-4 84 |Haxe |haxe |1:4.3.7-1 85 |Icon |icont, iconx |9.5.25a-1 86 |INTERCAL |intercal |30:0.30-6 87 |Jasmin |jasmin-sable |2.5.0-3 88 |Java |openjdk-11-jdk |11.0.28+6-1ubuntu1 89 |JavaScript |nodejs |20.19.4+dfsg-1 90 |Jq |jq |1.8.1-3ubuntu1 91 |JSFuck |nodejs |20.19.4+dfsg-1 92 |Kotlin |kotlin |1.3.31+ds1-3 93 |ksh |ksh |20240113-1.0.10-2 94 |Lazy K |*N/A* |- 95 |LiveScript |livescript |1.6.1+dfsg-3 96 |LLVM asm |llvm |1:20.0-63ubuntu1 97 |LOLCODE |*N/A* |- 98 |Lua |lua5.3 |5.3.6-2build2 99 |M4 |m4 |1.4.19-8 100 |Makefile |make |4.4.1-2 101 |MiniZinc |minizinc |2.9.2+dfsg1-1 102 |Modula-2 |gm2 |4:15.2.0-4ubuntu1 103 |MSIL |mono-devel |6.12.0.199+dfsg-6 104 |Mustache |ruby-mustache |1.1.1-2 105 |NASM |nasm |2.16.03-1 106 |Neko |neko |2.4.1-1 107 |Nickle |nickle |2.103 108 |Nim |nim |2.2.4-1 109 |Objective-C |gobjc |4:15.2.0-4ubuntu1 110 |OCaml |ocaml |5.3.0-3 111 |Octave |octave |9.4.0-1 112 |Ook! |*N/A* |- 113 |PARI/GP |pari-gp |2.17.2-1 114 |Parser 3 |parser3-cgi |3.5.1-3 115 |Pascal |fp-compiler |3.2.2+dfsg-46 116 |Perl 5 |perl |5.40.1-6build1 117 |Perl 6 |rakudo |2024.09-4 118 |PHP |php-cli |2:8.4+96ubuntu1 119 |Piet |*N/A* |- 120 |Pike |pike8.0 |8.0.1956-1 121 |PostScript |ghostscript |10.05.0dfsg1-0ubuntu4 122 |Prolog |swi-prolog |9.2.9+dfsg-1 123 |Promela (Spin) |spin |6.5.2+dfsg-2 124 |Python |python3 |3.13.7-1 125 |R |r-base |4.5.1-1 126 |Ratfor |ratfor |1.07-1 127 |rc |rc |1.7.4+97.gceb59bb-6 128 |REXX |regina-rexx |3.9.5+dfsg1-0.2 Note that some languages are not available in Ubuntu (marked as *N/A*). This repository contains their implementations in `vendor/`. See also `vendor/README` for detail. ## Frequently asked questions ### Q. Why? A. [Take your pick](https://github.com/mame/quine-relay/issues/11). ### Q. How? A. Good news: I have published a book, ["The World of Obfuscated, Esoteric, Artistic Programming"](http://gihyo.jp/book/2015/978-4-7741-7643-7). It explains how to write a quine, an ascii-art quine, and an uroboros quine like this quine-relay. You can buy my book on [amazon.co.jp](http://www.amazon.co.jp/dp/4774176435). (It also contains my almost all of my (about forty) works, including [alphabet-only Ruby program](http://www.slideshare.net/mametter/ruby-esoteric-obfuscated-ruby-programming-5088683), [radiation-hardened quine](https://github.com/mame/radiation-hardened-quine), etc., and explains many techniques for writing such programs.) Bad news: It is written in Japanese. I hope you can translate it into English and help me earn royalties. ### Q. Language XXX is missing! A. See [the language inclusion criteria][criteria] in detail. (In short, please create a deb package and contribute it to Ubuntu.) See also [:heart:][sponsors]. [criteria]: https://github.com/mame/quine-relay/wiki/Language-inclusion-criteria [sponsors]: https://github.com/sponsors/mame ### Q. Does it really work? A. [](https://github.com/mame/quine-relay/actions?query=workflow%2ACI) ### Q. How long did it take you? A. [Are you trying to cross the world line?](https://github.com/mame/quine-relay/issues/60) ### Q. The code does not fit in my screen! A. [Here you go][thumbnail]. [thumbnail]: thumbnail.png ### Q. How was the code generated? A. $ sudo apt-get install rake ruby-cairo ruby-rsvg2 ruby-gdk-pixbuf2 \ optipng advancecomp ruby-chunky-png $ cd src $ rake clobber $ rake ## History ## for Ubuntu 13.04 [50 languages](https://github.com/mame/quine-relay/tree/ad3f8222c796969db8cfb1bae015a46c2387b3d6) Added: Ruby, Scala, Scheme, bash, Smalltalk, Unlambda, Tcl, Whitespace, Verilog, Vala, Ada, ALGOL 68, Awk, Brainfuck, Boo, C, C++, C#, Cobol, Clojure, Fortran90, FORTRAN77, Forth, Common Lisp, CoffeeScript, Groovy, Go, INTERCAL, Icon, Haskell, Jasmin, Java, LLVM asm, Logo, Lua, Makefile, MSIL, Objective-C, JavaScript, OCaml, Octave, Parrot asm, Pascal, Perl, PHP, Pike, Prolog, Python, R, REXX ## for Ubuntu 13.10 [50 languages](https://github.com/mame/quine-relay/tree/ea4d39fb1ebc7ee23ec6f60ca7bfa0d465b5806a) ## for Ubuntu 14.04 [50 languages](https://github.com/mame/quine-relay/tree/d16bf072e3063dc476dc440c8f3e33d7426e98db) ## for Ubuntu 14.10 [64 languages](https://github.com/mame/quine-relay/tree/e449baba456d4885102482cbd365335be59241b2) Added: Scilab, S-Lang, SPL, LOLCODE, Maxima, NASM, Neko, Nickle, Ook!, PARI/GP, Piet, PPT (Punched tape), PostScript, Ratfor ## for Ubuntu 15.04 [100 languages](https://github.com/mame/quine-relay/tree/7749715289ca162eb1c1eb1ff1ed1393edc41630) Added: Subleq, Standard ML, Thue, Visual Basic, XSLT, Yorick, Zoem, A+, AFNIX, Ante, Asymptote, ATS, BLC8, Befunge, bc, Chef, CDuce, D, dc, eC, Emacs Lisp, Erlang, F#, Falcon, FALSE, Gambas script, GAP, GEL (Genius), Gnuplot, G-Portugol, Gri, Haxe, Julia, Lisaac, Lazy K, Kaya ## for Ubuntu 15.10 [100 languages](https://github.com/mame/quine-relay/tree/f45035f867c7c8f7b4e12fa63e7c8eef9aabecad) Removed: Boo, Falcon, Kaya Added: Elixir, Jq, Nim ## for Ubuntu 16.04 [100 languages](https://github.com/mame/quine-relay/tree/233ba8b4e1d7e4c59a46d64481048a8ea7f4400e) ## for Ubuntu 17.04 [100 languages](https://github.com/mame/quine-relay/tree/e65a798da23df0367d9eb5e4d46f00d87e6cb342) Removed: SPL, Gri, Logo, Parrot asm Added: Squirrel, Dafny, Grass, MiniZinc ## for Ubuntu 17.10 [100 languages](https://github.com/mame/quine-relay/tree/943b83801a1bd019ebf348adc78df2cdfde06513) Removed: CDuce Added: Rust ## for Ubuntu 18.04 [128 languages](https://github.com/mame/quine-relay/tree/6e173d76e972e1da7992b84768bf9f4c788949ed) Removed: Gambas script, Perl Added: Shakespeare, sed, tcsh, TypeScript, Velato, Vimscript, Yabasic, zsh, Aheui, AspectC++, AspectJ, BeanShell, CMake, Flex, Fish, GDB, GolfScript, Gzip, Gri, JSFuck, ksh, LiveScript, M4, Mustache, nesC, Parser 3, Perl 5, Perl 6, Promela (Spin), rc ## for Ubuntu 19.04 [128 languages](https://github.com/mame/quine-relay/tree/c8898351500682cea02219313e9203da7eca5505) Removed: Scilab, G-Portugol, nesC Added: Curry, Gambas script, GeneratorScriptingLanguage ## for Ubuntu 19.10 [128 languages](https://github.com/mame/quine-relay/tree/13041dbf3f80a90c9221ef94f8e8bc385800b6fd) Removed: Gri Added: Scilab ## for Ubuntu 20.04 [128 languages](https://github.com/mame/quine-relay/tree/62e2cc2d61d99719328094d185d899bc03a851fb) ## for Ubuntu 20.10 [128 languages](https://github.com/mame/quine-relay/tree/114f44fefd610812d2f5e3032603762752ed51b2) Removed: AspectC++, eC Added: SurgeScript, Dhall ## for Ubuntu 21.04 [128 languages](https://github.com/mame/quine-relay/tree/d8df33bad3693afd0bd3bf1c2b1cedd5753325dc) Removed: Curry Added: G-Portugol ## for Ubuntu 21.10 [128 languages](https://github.com/mame/quine-relay/tree/158b6251d36a48122ec0006feaf759d8b1973b0f) ## for Ubuntu 22.04 [128 languages](https://github.com/mame/quine-relay/tree/7b81d8704549d31814499c5300be2be9568467c8) Removed: Julia, Nim, Pike Added: WebAssembly (Text format), WebAssembly (Binary format), Kotlin ## for Ubuntu 22.10 [128 languages](https://github.com/mame/quine-relay/tree/362962dd2d55d7c36dd9fa3e0d4c0c52c0e6a18f) ## for Ubuntu 23.04 [128 languages](https://github.com/mame/quine-relay/tree/5dfdada5aa58f6a97ae85b84f86c7eb091225a8c) Removed: Squirrel, GeneratorScriptingLanguage Added: Crystal, Nim ## for Ubuntu 23.10 [128 languages](https://github.com/mame/quine-relay/tree/74c4cc7d79fccbb1c8315070b9efea03cb787755) Removed: Smalltalk Added: Modula-2 ## for Ubuntu 24.04 [128 languages](https://github.com/mame/quine-relay/tree/20d7f437c053b8e0b301ba996d124a4b812e3571) Removed: PPT (Punched tape) Added: Pike ## for Ubuntu 24.10 [128 languages](https://github.com/mame/quine-relay/tree/2ed61a62c9d31121b39e740c89107085c122f478) Removed: Dafny, Maxima Added: Execline, Squirrel ## for Ubuntu 25.04 [128 languages](https://github.com/mame/quine-relay/tree/b9c8056cad4589fe650163a3fd0cea4b3055fce4) ## for Ubuntu 25.10 [128 languages](https://github.com/mame/quine-relay/tree/5298413382ea707061e04aa077f99872d159a7b8) Removed: Lisaac Added: Swift ## License The MIT License applies to all resources *except* the files in the `vendor/` directory. The files in the `vendor/` directory are from third-parties and are distributed under different licenses. See `vendor/README` in detail. --- The MIT License (MIT) Copyright (c) 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Yusuke Endoh (@mametter), @hirekoke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: SHA256SUMS ================================================ 12623f713c91a8a66799c2c48fc6d69b5c8e667534e6ba0f6456eb874076c081 *QR.rb 9df1959f513e14e295e338bd60324068555aa69f9a39d70f24e789f494d0a82c *QR.rs 7099d0b66ce499616935a8f40948421faade9fa32f3ade5e61b112fbf90c7b67 *QR.scala 9e8be7aa29be0373379ce94135a4f3eb3dfb7d13eadf9217f92fdea2aae42bec *QR.scm 6d765ab621adc206990eeb6b56de0c5fb04ef82b8d927e7b4016f289fdffe4e3 *QR.sci b2a6f25d27c2ec1331d64cde25397a6f3ad279664634b5625397c4fa072abf50 *QR.sed 8960c90239ca53a093cd169c36b82096ffd5e861554023ac9a71c4865d43776e *QR.spl 1f5a84b47ce3806a97094d2ccb19f598c0cd65be90bbb9860e2c2c6dd9c1490f *QR.sl c9e148f618bb8ce458cf105b894ac6dc5c88ab35003998a126bdacc5c1060c07 *QR.nut 6ec2a8743395bcaa0449aef53561ce3cfedcf043d241ac2309406f5d4bd21f38 *QR.sml 7e9d0dfa4b902adebc72111b1dc9d820bcacfad059930c01085ac7b3f81e2a1e *QR.sq 62a990a76ac114ebc67e45382a6dce8bbbbddd550b3a87bc6f3c3fc9233134b1 *QR.ss 16e55ff01e922ccdd8f8f60588b0ca520835c7962ba4bba78cadc17768295234 *QR.swift 414a439517704a14dd257be4d9cceeee411a94fceffd8f67808bbd5beb7c8e17 *QR.tcl afd18299f737e2b106aa34d937affb01e09a00be66488f2598942791224ad8b4 *QR.tcsh de3f2b463d6c24fb873b73bf33e4c64c1fa05b77d001641f6b95ed26ec9c720f *QR.t c046065994ea12c8e3d79c2f22db10d7bc4b467f6bd5497e17b94e03252d285f *QR.ts c1f686f2e5e28135ebe443443a2e42aa919e9d211d40271c6b75b5b536df0333 *QR.unl dfa15a63952a7b401935bdb529c01cbe5c09a4cb2f8f40ca504abdf575662b8d *QR.vala 21a09c188ce2b7e6a207572ec4e8b5b0ad019d7a7205f362c0d4b7a840897026 *QR.mid 5f17ee6f8b2c9071220edd280e2e36924a4986c5035b97a79306cd802e509e21 *QR.v 5c62c705bdc929fc7948abe930e9a9c6ad424e8e0ba39d2e87dec145216d2286 *QR.vim 45056322828773f4a0d5d20c54be4b846bf0203af201eaac51cf14d539d2d060 *QR.vb 43790b395321678896f721d8da7fab91a784d0d5c69b1dae9f745f8afc56e036 *QR.wasm 67a51a505f0f37e6f2ea6f47eabdd0fce42effc4b950d75158ada64459361edd *QR.wat aaec5d6e1cf79681ef6dfc04fe7796afc568eb4283ae209c43670083a3cbb174 *QR.ws 5368d3e1658d37b0dfb75a14ed23250a35bc7311301b91450cbc1a7d73eff891 *QR.xslt 4b426b6364d3b759f321d29737ab0b8bed4e6b1dbff6276afedccd85b129c5af *QR.yab 310af9cf037708d18f99580d96af2c949f9a536715ebc1b3edcb33b71b2fa478 *QR.yorick aba3b8abecce9ad46c14597e47d8c7acae5e54069b09b59a001ff04bf9cc2000 *QR.azm 6b437b52493d214197d834282b7b07d60e6a126689be4f2c7fdca43e27de6e45 *QR.zsh bf00ee4220495a50727cc37e345d641202c0a372a6c31ceb522d835b885fba3d *QR.+ 89dba8652bfa4c9e56508c5981258503b49091a8641c40a1b1cc683ad63fdfff *qr.adb cf1c668b168e26a401581389c08d41560ed3c0b5e37c35e21552e671a872c524 *QR.als c502a439d37b41518368dd277033d335f6ebb54d61d6b17496ba29caea132c34 *QR.aheui e0d785bd6bcbae22956ab50265413b8535458896303d7ab9470fdec60db9c6e4 *QR.a68 8fabf20d41561d2876ff024f550f2c19edda0009579643468a0277fbbd403d28 *QR.ante 0ad2978a1a2f8aa60929c895557031ce201edd6cb56993735d2e48e3d1947c30 *QR.aj ac615a877bb6f8434cdec39813a4e052c514a6d3fe0304f0c4b32f9de195772b *QR.asy 5cd48139791b9f32140664deb448108c97d8aae3578d795ed0a365f8922f9d98 *QR.dats a21fdb1bc5cc1f8468defac905921156b642cea98f9bd82147b8c7c28b111514 *QR.awk dca132455085f2745bacd50cbb9cc8a57a4cf8d1a5de99de8222ff705e3aaaf5 *QR.bash d802710fb2ce4af4abf8b6749ed5f66f2e96964f2238c4ef387b030407372efd *QR.bc 49f6bbf2ad1b3540da516aefa5e12ad866a08b0d3886e36b1e809bcfe244376a *QR.bsh de30728cc7125000e0e6cf6f6640538e536c3ff39178a5290e0b67008969c27a *QR.bef 04fb756bf661fae309465e04d86b030832b45f21969f13a39ca4a37e1f244bd0 *QR.Blc fb520c3323b946fc6026179e2312d6e345dd44a384b1dfd38280aadba472c728 *QR.bf 2f90d2915d01b7d4f5eb01e38efa4f9174551e5e1803dfa1e41aa14dc4d19670 *QR.c 0b9a14819367894121cb7ac096179c48a5142531a29c05c49892eb51638d7a84 *QR.cpp e638911ea743a293eb031011c0099e3749fc01d7d211ef755dc93bdf6616edb8 *QR.cs 56f4e86a9306260a0b04e5fa33e2b2629ba5a35263ccba2d7e23ec9353835e3f *QR.chef 0b37f015a5bc532e9a98c308181851ae6881fd47d87eaa969b47050c396a1717 *QR.clj e2d787d27bf447a41e42b1a56e6f12036650ba1f28a45d81e0332b8c22be04cd *QR.cmake f042e6896aec32247ff3e83b78ed946e34cf88861acf44de0d822568b66a845e *QR.cob 026db578fb2d1a4df22bc2b2a573cdc96886be831a042ec4a3a1e78e114ed3ef *QR.coffee 8ae17e1600f94c49604758fd947630b6742bf4d75d5674068e20af80a0e88c6c *QR.lisp 6065e90fbc5390d7aff7794cc5f0722cd8317704809b2916be4426938b9e4055 *QR.cr 9c4e3a3e80bff9ba0ffc7584e217e9c279158823870e3d1eb6c6e83053a4282f *QR.d 1d779f095d0c2b033fb543b20a21f23e4fabaf67b1ef8a8509eb553b58d7eb98 *QR.dc 589b275a368d00943eef8153d420cb7e45c61072176f5f019abaf47e69a3f871 *QR.dhall f78a791439f3855552c8403823e879936fcb5aab24430fddad4ffbe2e2749512 *QR.exs be237d208d1d2cc397adc15e4e2e6b9b5006a487f27b2e3cd449c237ff6fea19 *QR.el aac501df84bed42ab741cc045a8adf8f789c2edb6ec165de31657acebf02781f *QR.erl d916525e98362d3d6f52b9054de1b517147b0c21a5b491137ab960b3fc136226 *QR.e 971320ceddf347f91b105992aa0714bf1588c61b19fcebe55b86baec25c73db7 *QR.fsx 86c6dd5a0d58ec1e68b1ed21332a7a4b5bd4e46acf8958a90011d2c2ed996d5e *QR.false c9e193115153ce16773ba8837fb935bfa93e24709e5ffb32d85236076daa0d92 *QR.fl e9f759f28ecbfeebf7b7b3248074244de4d0043f7a9d7cb86ac7dd5fef5fdb40 *QR.fish 1657cfafda71d29987615f79c8fd82cbc36b34d56718d4a1d7f51baccebf5c34 *QR.fs 10f6b1742f4372ee4d054e02a2a10d31e8079270664f77620fc827a1e09fdcdc *QR.f f7a2bbdec2bc47162966d206b7b85c6d51a00ab04d8231e90575015153b7c891 *QR.f90 f56167c040a8fa8ae35db8041e48f1e0c15b8da6222dea044ab27ec06acfa9ca *QR.gbs 39beb2f88d9289944cd784f674db09bde2054213023e0a1bbe095051024add92 *QR.g 0fdb573c2c19b7b50c5fbe8b0d69ea607e80eaef1041dd553dbef08fe1685fb9 *QR.gdb 381830f625dc5359177d3a15dfad69848fdbe705ae83087e6b748ddc8b1c71df *QR.gel 418cdd7f990d1f019ab8687645d1a4f4252f17bb3c8b838fb2d8b45ec06e3170 *QR.plt c603a7a903c99d4ac7098831f31a4601046b88bbb61efbd909f0c2c7b2816183 *QR.go 94251e39c4e0a7acc1c10904d5eb1080ced2588d96ff0f05cda6e116ff40f6f4 *QR.gs c49dc6ccb84103de4d881e2a109fa6bad80b1fb8c6f1e59cc031835f5f135fa4 *QR.gpt 389faf61261586ec08c209ffe78239ede67f91955a6df12a8fd447025cac36b4 *QR.grass 6b17989e98a11754c741f7d462bddba17d6c0795294510277aa237053c595c01 *QR.groovy f57be29f963e19e54cfc558722b5d8023a66409619c9a00407b44c77a291db88 *QR.gz 4b5aa836e0e8c7e4a82763e948f66d6bf969474c37176104f1018ca4c9a9207b *QR.hs 18e31dac4491412fa5b600bf269ebcbbf6084c80540599608370bdcd482ee671 *QR.hx 33726b852a2b3a55319ea8f764410f2dbe7d2960a06b91e200b4d923a861b2e7 *QR.icn a53f3bb0269f323e284bbd4007af41a261d9fd9420004806c6ce5e153c1543cc *QR.i 74c9a0dfe67d4a89b97ee54bf24704d7215b48862d03c80151214269b38c09d6 *QR.j 1d692da0ba8c6b04a60aefc87ac7da1cb937bab8b1f501a34b1a7013e9688305 *QR.java 8039f166ab0ce892e0bcdd78fc5f203bb115f94748f374a63cf241f6a33776fb *QR.js 83e07ba7dff9a8db351a0449e6ef4a1b08b5a069fb357c1e05599fa6bf50e672 *QR.jq 944b6cf24bf7ddc4a1ce1e40130dacf60b5999d6914f8efa047c1188bdd2ce06 *QR.jsfuck ad65cf3eda51297f6665d6c14b0b5d3676611f4d595ab07e52a74133f58ef4a2 *QR.kt e4955fd14ec9af1409c3c930fa2d26b378cc5a439fb68873698e044cd2f6789f *QR.ksh 633b7936c4981d8a0e7d75a3f5ee72f17f65c0fc750084e2fe923b4de7d0e06b *QR.lazy 358ec5fb72e695845036595aef0b0a7c98bdb6c8e0c365faafc898d8b15926a1 *QR.ls 1d50d0deeeca335bb589f27dfbfe4214ec87cf075268e2822f17ce019d4df930 *QR.ll 7ad8bfd091fef07608038101557e10454eaf71b1aa0d05ac07904121acf2a1e2 *QR.lol a0207688cdd56e2a3061a000230affc8de557ae34d77287b62bea1ee8fae1b9f *QR.lua d17ae7faca6eedce73d2cad23166eb6b6e55c2a3675c1a9119fd7eea48ee9251 *QR.m4 4eeffb7c5c3a20a26dfd66fe5ccbbe2bbe0ced830e0ddcab63cc3cf8f2f4eeb9 *QR.mk ca4359361ae7702db6f816a8e7482ae5b419af8b69be866765164de3acfaceff *QR.mzn af97b86c1721993b8476ad2cc9b0aa78880e48588144f099108e52b10e8f7c3d *QR.mod 2497238e2b1f7977b22e67277c6279921e871b0c2804a9a32212e710d8f85f11 *QR.il 4af6900b554510b99b8e922ca55871a1783ad4b9f77dd48ef7ea767fdca477fe *QR.mustache 923564cbf178e5c2025fb8a7e06652f40931bdb4100d3488aaa956bd999f672d *QR.asm 0a4d3bf1bc0b619e7de55a684788372178450eb4d5eeb9fb7e637fbc45d00eaa *QR.neko 8d0f55a65ee193fe742b580927c3c71366fa2d386a9fcd52c3660e9435509ad7 *QR.5c a8a6a3bb228d60182e6855266b77c6f7d43fc28a6d321ee7541511bcc6e86b42 *QR.nim b1ccccd92cf89f33119be28a63b536bccaa1789a50ff73d20b1252a2a5af0ef5 *QR.m c4d62f4ed17c8734bd9d33e1312fc4b357e0503ab67a25f98c42975a2b6bfaf3 *QR.ml 1e98dddc2dcf041ed95b44b786772447151bd0dafd52049964b193b11324f9ce *QR.octave d855fad9b90051da6e46928f1dc550d014701e2924b138f65214e3a9367266f0 *QR.ook adb0980458098bc1a168858461d840242109e9e900cb883ab0d9516a99a0e9c3 *QR.gp 0b0e2b15a611acd8e2ef03dfb107de9dbea67e04afcf4dc75ce5f6bf33b2ea80 *QR.p f76ca81f5cd8f8bf13cc578a051b2268cd422dabe0c755bde02dba75567ce83e *QR.pas e73c69d99568d5293561b198933dac0ca1f255258c936c8cf63824794eb8821a *QR.pl e5bd8ac748f20dae70c4792280e95fc477a03cbe34696ace3a10c85ebcca0a25 *QR.pl6 cee0abe37b1f2ee044d18934dba7f2af43287e1a1ed3ae8ab7304f6c41c61c94 *QR.php 18f3abe96e38466c31969fb5ceea480170f1f9d7089d6620a2a08d5b913386c4 *QR.png 7639f1d7c80abc8d8c44f3effe72158e2dc8d8d1c0624c68c81f0a8225dcca22 *QR.pike cbd418d7d572ceaccd8856bf5153e8f8c3740dc55d47bbd1dbdae55e83285888 *QR.ps 5a0456754a1f2f5c87b82ca83cf35ddaca605057ba675c758744dc5bf1f8d9f4 *QR.prolog e8252e383bcc102cbcb51f0b6d35e44890c70ff0fc2cef6ac0cbe604e7a88a0b *QR.pr 83ec85f8784ee7765e2679616962250891b99a9d98d42f6300b622a1e52bd56f *QR.py 3ca5fa842d5ce951ee7a287ea578f63401e8e9e64b8fdec8040abbc0b6df2dd5 *QR.R db14c6a8343fa742e3056f6882f0f024458bcf431b546e9af4d4edf28c34fce8 *QR.ratfor ea356e5891386571c753178d30d2e86cb59cf7612e925cd1262c87869b849ae9 *QR.rc 5b74c101ae27ab30e67cb070d25cdadf1436a6f11593edc16320d960a468ae67 *QR.rexx ================================================ FILE: src/Dockerfile.gen.rb ================================================ require_relative "code-gen" apts = RunSteps.flat_map {|s| s.apt } other_packages = %w(libpng-dev libgd-dev groff flex bison curl) apts = [*apts.flatten.compact.uniq, *other_packages].uniq.sort dockerfile = [] dockerfile << "FROM ubuntu:#{ `bash -c 'source /etc/os-release && echo $VERSION_ID'`.chomp }" dockerfile << "ENV DEBIAN_FRONTEND noninteractive" dockerfile << "RUN apt-get update && apt-get upgrade -y" dockerfile << "RUN apt-get -qq install -y apt-utils > /dev/null" dockerfile << "RUN apt-get -qq install -y moreutils" apts.each_slice(4) do |apt| dockerfile << "RUN chronic apt-get -qq install -y #{ apt.join(" ") } && chronic apt-get clean" end dockerfile << "ADD . /usr/local/share/quine-relay" dockerfile << "WORKDIR /usr/local/share/quine-relay" dockerfile << "RUN make -C vendor" dockerfile << "CMD make check -j 10000" File.write("../Dockerfile", dockerfile.join("\n") + "\n") ================================================ FILE: src/Makefile.gen.rb ================================================ require_relative "code-gen" OUT = [] def banner(s1, s2=nil, i=nil) s = "## #{ "#{ i + 1 }: " if i }#{ s1 }#{ ' -> ' + s2 if s2 } ##" OUT << "\t@echo" OUT << "\t@echo \"#{ "#" * s.size }\"" OUT << "\t@echo \"#{ s }\"" OUT << "\t@echo \"#{ "#" * s.size }\"" OUT << "\t@echo" end OUT << <<-END MAKEFLAGS += --no-print-directory PATH := $(CURDIR)/vendor/local/bin:/usr/games:$(PATH) CLASSPATH := . find_any0 = $(firstword $(foreach x,$(1),$(if $(shell which $(x) 2>/dev/null),$(x),))) check = $(if $(2),$(2),$(error $(1) interpreter not found!)) find_any = $(call check,$(1),$(call find_any0,$(2))) JAVASCRIPT := $(call find_any,JavaScript,nodejs node js) SCHEME := $(call find_any,Scheme,guile csi gosh) GBS := $(call find_any,Gambas script,gbs3 gbs2 gba3) WASI_RUNTIME := $(call find_any,WASI runtime,wasmtime node) ifeq ($(SCHEME),csi) SCHEME := csi -s endif ifeq ($(WASI_RUNTIME),node) WASI_RUNTIME := node --experimental-wasi-unstable-preview1 vendor/wasi-runtime.js endif .DELETE_ON_ERROR: END OUT << "all: QR2.rb" banner("CHECK") OUT << "\tdiff -s QR.rb QR2.rb" OUT << "" OUT << "check: all" OUT << "\t@sha256sum --quiet -c SHA256SUMS" [*RunSteps, RunStep["Ruby", "QR2.rb"]].each_cons(2).with_index do |(s1, s2), i| cmd = s1.cmd_make.gsub("OUTFILE", s2.src) OUT << "" OUT << "#{ s2.src }: #{ s1.src }" banner(s1.name, s2.name, i) if s1.backup if s1.backup.is_a?(String) OUT << "\t@mv #{ s1.backup } #{ s1.backup }.bak" else OUT << "\t@#{ s1.backup[0] }" end end cmd.split("&&").each {|c| OUT << "\t" + c.strip.gsub(/^!/, "ulimit -s unlimited && ") } if s1.name == "BeanShell" # workaround; bsh disables terminal echo OUT << "\t@stty echo" end if s1.backup if s1.backup.is_a?(String) OUT << "\t@mv #{ s1.backup }.bak #{ s1.backup }" else OUT << "\t@#{ s1.backup[1] }" end end end OUT << <<-END clean: \t@mv QR.rb quine-relay.rb \trm -f qr QR qr.* QR.* QR2.rb *.class gst.im \t@mv quine-relay.rb QR.rb END File.write("../Makefile", OUT.join("\n")) ================================================ FILE: src/QR.rb.gen.rb ================================================ require_relative "code-gen" gen_prologue_1 = GenPrologue.split(?;)[0, 2].join(?;) gen_prologue_2 = GenPrologue.split(?;)[2..-1].join(?;) s = gen_prologue_2 + ?; + GenSteps[0..-2].inject('"eval$s=%q(#$s)"') {|code, s| s.code.sub("PREV"){ code }.chomp } if false # search characters rarely used h = {} 32.upto(126) {|c| h[c.chr] = 0 } s.chars.group_by {|c| c }.map do |c, a| h[c] = a.size end %w(( ) [ ] { } \ \\ \").each {|c| h.delete(c) } p *h.sort_by {|k, v| v } exit end if false # search sequences that often appear h = Hash.new(0) 2.upto(10) do |n| s.chars.each_cons(n) do |a| h[a.join] += n-1 end end p *h.sort_by {|k, v| v }.reverse exit end # a table of short-hand character for sequences that often appear ABBREV = { ?~ => " ", ?` => "\\", ?^ => "``", ?Z => "print", ?X => "ain()", ?J => "tring", ?H => "write", ?K => "gsub", ?! => "in", ?Y => "^^", } s = s.gsub(/[#{ ABBREV.keys.join }]/){"\\x%02x" % $&.ord} # search perfect and simplest hash a = ABBREV.keys.join.bytes max = 1000 a.size.upto(90) do |n| a.size.upto(90) do |m| b = a.map {|c| c%n%m } if b.uniq.size >= a.size&&b.max#{ TEMPLATE.count("#") - width }" end PADDING = "".ljust(width, "#_buffer_for_future_bug_fixes_") COPYRIGHT = " Quine Relay -- Copyright (c) 2013, 2014 Yusuke Endoh (@mametter), @hirekoke ". center(width, "#")[0..-2] code = TEMPLATE.gsub(/#+/) { w = $&.size; code.slice!(0, w).ljust(w, PADDING) }.chomp code[-1] = ")" code[-1 - COPYRIGHT.size, COPYRIGHT.size] = COPYRIGHT File.write("../QR.rb", code + "\n") ================================================ FILE: src/README.md.gen.rb ================================================ require_relative "code-gen" require "erb" require "cairo" other_packages = %w(cmake libpng-dev libgd-dev groff bison curl) other_packages.each do |package| `dpkg -s #{ package }` # just check the packages end pkg_versions = {} apts = RunSteps.map {|s| s.apt } `which apt-get >/dev/null && dpkg -s #{ apts.join(" ") }`.b.split("\n\n").each do |s| name = s[/^Package: (.*)$/, 1] version = s[/^Version: (.*)$/, 1] pkg_versions[name] = version if name && version end rows = [["\\#", "language", "ubuntu package", "version"]] rows += RunSteps.map.with_index do |s, idx| if s.apt.is_a?(Array) apt = s.apt.join(", ") ver = pkg_versions.values_at(*s.apt) #raise if ver.uniq.size > 1 ver = ver.first else apt = s.apt || "*N/A*" ver = pkg_versions[apt] end ver = ver.gsub("~") { "\\~" } if ver [(idx + 1).to_s, s.name, apt, ver || "-"] end ws = rows.transpose.map {|row| row.map {|s| s.size }.max + 1 } rows[1, 0] = [ws.map {|w| "-" * w }] rows = rows.map do |col| (col.zip(ws).map {|s, w| s.ljust(w) } * "|").rstrip end apt_get = "sudo apt-get install #{ [*apts.flatten.compact.uniq].sort * " " }" apt_get.gsub!(/.{,70}( |\z)/) do $&[-1] == " " ? $& + "\\\n " : $& end cmds = [*RunSteps, RunStep["Ruby", "QR2.rb"]].each_cons(2).map do |s1, s2| cmd = s1.cmd_raw src = s2.src cmd = cmd.gsub("OUTFILE", src) cmd = cmd.gsub(/^!/, "") cmd = cmd.gsub(/.{60,}?&&/, "\\0\n ") cmd end File.write("../README.md", ERB.new(DATA.read, trim_mode: "%").result(binding)) __END__ # Quine Relay [](https://github.com/mame/quine-relay/actions?query=workflow%3ACI) ## What this is [QR.rb](https://github.com/mame/quine-relay/blob/master/QR.rb) is a <%= RunSteps[0].name %> program that generates a <%= RunSteps[1].name %> program that generates a <%= RunSteps[2].name %> program that generates ...(through <%= RunSteps.size %> languages in total)... a <%= RunSteps[-1].name %> program that generates the original <%= RunSteps[0].name %> code again. ![Language Uroboros][langs] [langs]: langs.png (If you want to see the old 50-language version, see the [50](https://github.com/mame/quine-relay/tree/50) branch.) ## Usage ### Ubuntu If you are using Ubuntu <%= `bash -c 'source /etc/os-release && echo $VERSION'`.chomp %>, you can follow these steps. #### 1. Install all the interpreters/compilers. First, you need to type the following apt-get command to install them all. $ <%= apt_get %> Then, build the bundled interpreters. $ sudo apt-get install <%= other_packages.join(" ") %> $ make -C vendor #### 2. Run each program on each interpreter/compiler. $ ulimit -s unlimited % cmds.each do |cmd| $ <%= cmd %> % end You will see that `QR.rb` is the same as `QR2.rb`. $ diff QR.rb QR2.rb Alternatively, just type `make`. $ make Note: It may take a lot of memory to compile some files. ### Docker Simply build the image and run a container as follows: $ docker build -t qr . $ docker run --privileged --rm -e CI=true qr Note: You must run in privileged mode, otherwise the `maxima` command will fail. If you want to check the generated files, you can mount the local directory in the Docker container (but still use the `vendor` directory of the container), as follows: $ docker run --privileged --rm -e CI=true -v $(pwd):/usr/local/share/quine-relay -v /usr/local/share/quine-relay/vendor qr ### Other platforms You may find [instructions for other platforms in the wiki](https://github.com/mame/quine-relay/wiki/Installation). If you do not use these Linux distributions, please find your own way. If you manage it, please let me know. I wish you good luck. ## Interpreter/compiler versions tested I used the following Ubuntu deb packages to test this program. % rows.each do |row| <%= row %> % end Note that some languages are not available in Ubuntu (marked as *N/A*). This repository contains their implementations in `vendor/`. See also `vendor/README` for detail. ## Frequently asked questions ### Q. Why? A. [Take your pick](https://github.com/mame/quine-relay/issues/11). ### Q. How? A. Good news: I have published a book, ["The World of Obfuscated, Esoteric, Artistic Programming"](http://gihyo.jp/book/2015/978-4-7741-7643-7). It explains how to write a quine, an ascii-art quine, and an uroboros quine like this quine-relay. You can buy my book on [amazon.co.jp](http://www.amazon.co.jp/dp/4774176435). (It also contains my almost all of my (about forty) works, including [alphabet-only Ruby program](http://www.slideshare.net/mametter/ruby-esoteric-obfuscated-ruby-programming-5088683), [radiation-hardened quine](https://github.com/mame/radiation-hardened-quine), etc., and explains many techniques for writing such programs.) Bad news: It is written in Japanese. I hope you can translate it into English and help me earn royalties. ### Q. Language XXX is missing! A. See [the language inclusion criteria][criteria] in detail. (In short, please create a deb package and contribute it to Ubuntu.) See also [:heart:][sponsors]. [criteria]: https://github.com/mame/quine-relay/wiki/Language-inclusion-criteria [sponsors]: https://github.com/sponsors/mame ### Q. Does it really work? A. [](https://github.com/mame/quine-relay/actions?query=workflow%2ACI) ### Q. How long did it take you? A. [Are you trying to cross the world line?](https://github.com/mame/quine-relay/issues/60) ### Q. The code does not fit in my screen! A. [Here you go][thumbnail]. [thumbnail]: thumbnail.png ### Q. How was the code generated? A. $ sudo apt-get install rake ruby-cairo ruby-rsvg2 ruby-gdk-pixbuf2 \ optipng advancecomp ruby-chunky-png $ cd src $ rake clobber $ rake ## History ## for Ubuntu 13.04 [50 languages](https://github.com/mame/quine-relay/tree/ad3f8222c796969db8cfb1bae015a46c2387b3d6) Added: Ruby, Scala, Scheme, bash, Smalltalk, Unlambda, Tcl, Whitespace, Verilog, Vala, Ada, ALGOL 68, Awk, Brainfuck, Boo, C, C++, C#, Cobol, Clojure, Fortran90, FORTRAN77, Forth, Common Lisp, CoffeeScript, Groovy, Go, INTERCAL, Icon, Haskell, Jasmin, Java, LLVM asm, Logo, Lua, Makefile, MSIL, Objective-C, JavaScript, OCaml, Octave, Parrot asm, Pascal, Perl, PHP, Pike, Prolog, Python, R, REXX ## for Ubuntu 13.10 [50 languages](https://github.com/mame/quine-relay/tree/ea4d39fb1ebc7ee23ec6f60ca7bfa0d465b5806a) ## for Ubuntu 14.04 [50 languages](https://github.com/mame/quine-relay/tree/d16bf072e3063dc476dc440c8f3e33d7426e98db) ## for Ubuntu 14.10 [64 languages](https://github.com/mame/quine-relay/tree/e449baba456d4885102482cbd365335be59241b2) Added: Scilab, S-Lang, SPL, LOLCODE, Maxima, NASM, Neko, Nickle, Ook!, PARI/GP, Piet, PPT (Punched tape), PostScript, Ratfor ## for Ubuntu 15.04 [100 languages](https://github.com/mame/quine-relay/tree/7749715289ca162eb1c1eb1ff1ed1393edc41630) Added: Subleq, Standard ML, Thue, Visual Basic, XSLT, Yorick, Zoem, A+, AFNIX, Ante, Asymptote, ATS, BLC8, Befunge, bc, Chef, CDuce, D, dc, eC, Emacs Lisp, Erlang, F#, Falcon, FALSE, Gambas script, GAP, GEL (Genius), Gnuplot, G-Portugol, Gri, Haxe, Julia, Lisaac, Lazy K, Kaya ## for Ubuntu 15.10 [100 languages](https://github.com/mame/quine-relay/tree/f45035f867c7c8f7b4e12fa63e7c8eef9aabecad) Removed: Boo, Falcon, Kaya Added: Elixir, Jq, Nim ## for Ubuntu 16.04 [100 languages](https://github.com/mame/quine-relay/tree/233ba8b4e1d7e4c59a46d64481048a8ea7f4400e) ## for Ubuntu 17.04 [100 languages](https://github.com/mame/quine-relay/tree/e65a798da23df0367d9eb5e4d46f00d87e6cb342) Removed: SPL, Gri, Logo, Parrot asm Added: Squirrel, Dafny, Grass, MiniZinc ## for Ubuntu 17.10 [100 languages](https://github.com/mame/quine-relay/tree/943b83801a1bd019ebf348adc78df2cdfde06513) Removed: CDuce Added: Rust ## for Ubuntu 18.04 [128 languages](https://github.com/mame/quine-relay/tree/6e173d76e972e1da7992b84768bf9f4c788949ed) Removed: Gambas script, Perl Added: Shakespeare, sed, tcsh, TypeScript, Velato, Vimscript, Yabasic, zsh, Aheui, AspectC++, AspectJ, BeanShell, CMake, Flex, Fish, GDB, GolfScript, Gzip, Gri, JSFuck, ksh, LiveScript, M4, Mustache, nesC, Parser 3, Perl 5, Perl 6, Promela (Spin), rc ## for Ubuntu 19.04 [128 languages](https://github.com/mame/quine-relay/tree/c8898351500682cea02219313e9203da7eca5505) Removed: Scilab, G-Portugol, nesC Added: Curry, Gambas script, GeneratorScriptingLanguage ## for Ubuntu 19.10 [128 languages](https://github.com/mame/quine-relay/tree/13041dbf3f80a90c9221ef94f8e8bc385800b6fd) Removed: Gri Added: Scilab ## for Ubuntu 20.04 [128 languages](https://github.com/mame/quine-relay/tree/62e2cc2d61d99719328094d185d899bc03a851fb) ## for Ubuntu 20.10 [128 languages](https://github.com/mame/quine-relay/tree/114f44fefd610812d2f5e3032603762752ed51b2) Removed: AspectC++, eC Added: SurgeScript, Dhall ## for Ubuntu 21.04 [128 languages](https://github.com/mame/quine-relay/tree/d8df33bad3693afd0bd3bf1c2b1cedd5753325dc) Removed: Curry Added: G-Portugol ## for Ubuntu 21.10 [128 languages](https://github.com/mame/quine-relay/tree/158b6251d36a48122ec0006feaf759d8b1973b0f) ## for Ubuntu 22.04 [128 languages](https://github.com/mame/quine-relay/tree/7b81d8704549d31814499c5300be2be9568467c8) Removed: Julia, Nim, Pike Added: WebAssembly (Text format), WebAssembly (Binary format), Kotlin ## for Ubuntu 22.10 [128 languages](https://github.com/mame/quine-relay/tree/362962dd2d55d7c36dd9fa3e0d4c0c52c0e6a18f) ## for Ubuntu 23.04 [128 languages](https://github.com/mame/quine-relay/tree/5dfdada5aa58f6a97ae85b84f86c7eb091225a8c) Removed: Squirrel, GeneratorScriptingLanguage Added: Crystal, Nim ## for Ubuntu 23.10 [128 languages](https://github.com/mame/quine-relay/tree/74c4cc7d79fccbb1c8315070b9efea03cb787755) Removed: Smalltalk Added: Modula-2 ## for Ubuntu 24.04 [128 languages](https://github.com/mame/quine-relay/tree/20d7f437c053b8e0b301ba996d124a4b812e3571) Removed: PPT (Punched tape) Added: Pike ## for Ubuntu 24.10 [128 languages](https://github.com/mame/quine-relay/tree/2ed61a62c9d31121b39e740c89107085c122f478) Removed: Dafny, Maxima Added: Execline, Squirrel ## for Ubuntu 25.04 [128 languages](https://github.com/mame/quine-relay/tree/b9c8056cad4589fe650163a3fd0cea4b3055fce4) ## for Ubuntu 25.10 [128 languages](https://github.com/mame/quine-relay/tree/5298413382ea707061e04aa077f99872d159a7b8) Removed: Lisaac Added: Swift ## License The MIT License applies to all resources *except* the files in the `vendor/` directory. The files in the `vendor/` directory are from third-parties and are distributed under different licenses. See `vendor/README` in detail. --- The MIT License (MIT) Copyright (c) 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Yusuke Endoh (@mametter), @hirekoke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: src/Rakefile ================================================ require "rake/clean" CLEAN.include("../QR.*") CLEAN.include("../qr.*") CLEAN.include("../QR$*") CLEAN.include("../QR") CLEAN.include("../qr") CLEAN.include("../QR2.rb") CLEAN.include("../README.md") CLEAN.include("../langs.png") CLEAN.include("../Makefile") LIBS = %w(code-gen.rb code-gen-pool.rb lazyk-boot.dat blc-boot.dat grass-boot.dat wasm-tmpl.dat) file "lazyk-boot.dat" => "lazyk-boot.dat.gen.rb" do ruby "lazyk-boot.dat.gen.rb" end file "blc-boot.dat" => "blc-boot.dat.gen.rb" do ruby "blc-boot.dat.gen.rb" end file "grass-boot.dat" => "grass-boot.dat.gen.rb" do ruby "grass-boot.dat.gen.rb" end file "wasm-tmpl.dat" => "wasm-tmpl.dat.gen.rb" do ruby "wasm-tmpl.dat.gen.rb" end file "../QR.rb" => ["QR.rb.gen.rb", *LIBS, "uroboros.txt"] do ruby "QR.rb.gen.rb" end file "../README.md" => ["README.md.gen.rb", *LIBS] do ruby "README.md.gen.rb" end file "../langs.png" => ["langs.png.gen.rb", "uroboros.svg", *LIBS] do ruby "langs.png.gen.rb" end file "../thumbnail.png" => ["thumbnail.png.gen.rb", "../QR.rb"] do ruby "thumbnail.png.gen.rb" end file "../Makefile" => ["Makefile.gen.rb", *LIBS] do ruby "Makefile.gen.rb" end file "../.github/workflows/main.yml" => ["dot.github.workflows.main.yml.gen.rb", *LIBS] do ruby "dot.github.workflows.main.yml.gen.rb" end file "../Dockerfile" => ["Dockerfile.gen.rb", *LIBS] do ruby "Dockerfile.gen.rb" end task :test do ruby "test.rb" end task :default => %w( ../QR.rb ../README.md ../langs.png ../thumbnail.png ../Makefile ../.github/workflows/main.yml ../Dockerfile ) task "../SHA256SUMS" => ["SHA256SUMS.gen.rb", *LIBS] do ruby "SHA256SUMS.gen.rb" end task :run => :default do sh "make -C .." end task :gen => [:run, "../SHA256SUMS"] ================================================ FILE: src/SHA256SUMS.gen.rb ================================================ require_relative "code-gen" Dir.chdir("..") do system("sha256sum", "-b", *RunSteps.map {|s| s.src }, out: "SHA256SUMS") end ================================================ FILE: src/blc-boot.dat.gen.rb ================================================ def dump(e, env) if e.is_a?(Symbol) ?1 * (env.index(e) + 1) + ?0 elsif e[0] == :abs! vs = [*e[1]].reverse "00" * vs.size + dump(e[2], vs + env) else "01" * (e.size - 1) + e.map {|x| dump(x, env) } * "" end end L = -> x, y { [:abs!, x, y] } Let = -> v, x, y { [L[v, y], x] } Cons = -> x, y { L[:f, [:f, x, y]] } False = L[[:x, :y], :y] True = L[[:x, :y], :x] Num = -> n { [n[7] == 1 ? :ConsFalse : :ConsTrue, [n[6] == 1 ? :ConsFalse : :ConsTrue, [n[5] == 1 ? :ConsFalse : :ConsTrue, [n[4] == 1 ? :ConsFalse : :ConsTrue, [n[3] == 1 ? :ConsFalse : :ConsTrue, [n[2] == 1 ? :ConsFalse : :ConsTrue, [n[1] == 1 ? :ConsFalse : :ConsTrue, [n[0] == 1 ? :ConsFalse : :ConsTrue, False]]]]]]]] } OutBF = -> tl { [:Cons, Num[?..ord], [:ConsGt, tl]] } DblBF = # [->++<]> L[:tl, Let[:ConsTrue, :ConsTrue, Let[:ConsFalse, :ConsFalse, [:Cons, Num[?[.ord], [:Cons, Num[?-.ord], [:ConsGt, [:ConsPlus, [:ConsPlus, [:Cons, Num[?<.ord], [:Cons, Num[?].ord], [:ConsGt, :tl]]]]]]]]]]] # each_bit bit tl = # ("[->++<]>" concat (tl each_bit)) EachBit = [L[:x, [:x, :x]], # recursive L[[:self, :bit, :tl, :next], [:tl, [:self, :self], [:DblBF, [:bit, [:ConsPlus, :next], :next]]]]] # each_byte byte tl = # (byte each_bit ".>") concat (tl each_byte) EachByte = [L[:x, [:x, :x]], # recursive L[[:self, :byte, :tl], Let[:Cons, L[[:x, :y, :f], [:f, :x, :y]], Let[:ConsTrue, [:Cons, True], Let[:ConsFalse, [:Cons, False], Let[:ConsPlus, [:Cons, Num[?+.ord]], Let[:ConsGt, [:Cons, Num[?>.ord]], Let[:DblBF, DblBF, [:byte, EachBit, OutBF[[:tl, [:self, :self]]]]]]]]]]]] tree = EachByte boot = "10" + dump(tree, []) # 20 x ? boot = 00010100 x ? boot = \a (\b x) ? boot = \a x boot # 22 x y = 00010110 x y = \a a x y = cons x y # 4 222 = 00000100 11011110 = \a \b (\c b) (????) = \a \b b = false # 4 226 = 00000100 11100010 = \a \b (\c a) (\c c) = \a \b a = true if ARGV[0] $stderr.puts(boot.size, (boot.size + 7) / 8) a = [20] ("foo" * 100 + "\n").each_byte do |b| a << 22 0.upto(7) do |i| a << 22 << 4 << 222 + b[i] * 4 end a << 4 << 222 end a << 4 << 222 print a.pack("C*") + [boot].pack("B*") else File.write("blc-boot.dat", [boot].pack("B*")) end ================================================ FILE: src/code-gen-pool.rb ================================================ original_list_size = CodeGen::List.size #class NesC < CodeGen # Name = "nesC" # File = "QR.nc" # Cmd = "nescc -o QR QR.nc && ./QR > OUTFILE" # Apt = "nescc" # def code # <<-'END'.lines.map {|l| l.strip }.join # %( # #include\n # module QR{}implementation{ # int main()__attribute__((C,spontaneous)){ # puts#{E[PREV]}; # return 0; # } } # ) # END # # avoid "}}" because of Mustache # end #end #class Nim_NVSPL2 < CodeGen # After = Nim # Obsoletes = Nim # File = ["QR.nim", "QR.nvspl2"] # Cmd = ["nim c QR.nim && ./QR > OUTFILE", "ruby vendor/nvspl2.rb QR.nvspl2 > OUTFILE"] # Apt = ["nim", nil] # Code = %q(%((for i, c in#{E[PREV]}:echo ",",int(c),"CO");echo "Q")) #end CodeGen::List.slice!(original_list_size..-1).each do |s| i = CodeGen::List.find_index(s::After) CodeGen::List.insert(i, s) [*s::Obsoletes].each {|s_| CodeGen::List.delete(s_) } if defined?(s::Obsoletes) end CodeGen::List.delete(GeneratorScriptingLanguage) class Zig < CodeGen File = "QR.zig" Cmd = "zig run QR.zig > OUTFILE" Apt = "zig" Code = %q(%(pub fn main()!void{_=try @import("std").io.getStdOut().write#{E[PREV]};})) end # aribas # elvish # hare # raku # snek # storm-lang ================================================ FILE: src/code-gen.rb ================================================ # A source for generating Quine Relay GenStep = Struct.new(:name, :code, :run_steps) RunStep = Struct.new(:name, :src, :cmd_make, :cmd_raw, :backup, :apt) # A class that generates Ruby code that generates a code (in a language X) that prints PREV. class CodeGen # File = source file name of X # Cmd = command for execution/compilation # Apt = ubuntu package name of the interpreter/compiler of X List = [] def self.inherited(c) List << c end def self.gen_step GenStep[name, new.code, run_steps] end def code self.class::Code end def self.run_steps a = [] a << (defined?(self::Name) ? [*self::Name] : self.to_s.split("_")) a << [*self::File] a << [*self::Cmd] a << (defined?(self::Backup) ? [*self::Backup] : [*self::Cmd].map { nil }) a << [*self::Apt] a.transpose.map do |name, src, cmd_make, backup, apt| cmd_raw = cmd_make cmd_raw = cmd_raw.gsub("$(SCHEME)", "guile") cmd_raw = cmd_raw.gsub("$(JAVASCRIPT)", "nodejs") cmd_raw = cmd_raw.gsub("$(CC)", "gcc") cmd_raw = cmd_raw.gsub("$(CXX)", "g++") cmd_raw = cmd_raw.gsub("$(GBS)", "gbs3") RunStep[name, src, cmd_make, cmd_raw, backup, apt] end end end # Common part GenPrologue = <<-'END'.lines.map {|l| l.strip }.join B=92.chr; g=32.chr; N=10.chr; n=0; e=->s{Q[Q[s,B],?"].gsub(N,B+?n)}; E=->s{'("'+e[s]+'")'}; d=->s,t=?"{s.gsub(t){t+t}}; def f(s,n)s.gsub(/.{1,#{n*255}}/m){yield$S=E[$s=$&]}end; Q=->s,t=?${s.gsub(t){B+$&}}; R=";return 0;"; V=->s,a,z{s.gsub(/(#{B*4})+/){a+"#{$&.size/2}"+z}}; C=%w(System.Console Write); $C=C*?.; $D="program QR"; $G=" contents of"+$F=" the mixing bowl"; $L="public static"; $W="s.WriteByte"; rp=->s,r{ v=""; [r.inject(s){|s,j| o={}; m=n=0; s.size.times{|i| o[f=s[i,2]]||=0; c=o[f]+=1; m OUTFILE", "R --slave -f QR.R > OUTFILE", "ratfor -o QR.ratfor.f QR.ratfor && gfortran -o QR QR.ratfor.f && ./QR > OUTFILE", "rc QR.rc > OUTFILE", "rexx ./QR.rexx > OUTFILE" ] Apt = ["python3", "r-base", "ratfor", "rc", "regina-rexx"] def code <<-'END'.lines.map {|l| l.strip }.join %( print('cat("')\n for c in"".join(["echo 'say ''%s'''\\n"%l for l in#{E[d[d[PREV,?'],?']]}.split("\\n")]): print('r=fput(char(%d))'%ord(c))\n print('end\\n")')# ) END end end class Promela < CodeGen Name = "Promela (Spin)" File = "QR.pr" Cmd = "spin -T QR.pr > OUTFILE" Apt = "spin" Code = %q("init{#{f(PREV,6){"printf#{d[$S,?%]};"}}}") end class Prolog < CodeGen File = "QR.prolog" Cmd = "swipl -q -t qr -f QR.prolog > OUTFILE" Apt = "swi-prolog" Code = %q("qr:-write('#{Q[e[PREV],?']}').") end class PostScript < CodeGen Name = "PostScript" File = "QR.ps" Cmd = "gs -dNODISPLAY -q QR.ps > OUTFILE" Apt = "ghostscript" Code = %q("(#{Q[PREV,B]})print quit") end class Pike < CodeGen File = "QR.pike" Cmd = "pike QR.pike > OUTFILE" Apt = "pike8.0" Code = %q("int main(){write#{E[PREV]+R}}") end class PHP_Piet < CodeGen File = ["QR.php", "QR.png"] Cmd = ["php QR.php > OUTFILE", "npiet QR.png > OUTFILE"] Apt = ["php-cli", nil] def code <<-'END'.lines.map {|l| l.strip }.join %( $z)&&$i/$z<($c<$w?ord($s[(int)($c/3)]):$c--%3+2)? $t[2].$t[$c%3%2].$t[$c%3]:"\\0\\0\\0":"\\0" ) $c=$i%$z; foreach(array( "IHDR".pack("NNCV",$w+2,128,8,2), "IDAT".gzcompress($m), "IEND" )as$d) echo pack("NA*N",strlen($d)-4,$d,crc32($d)); ) END end end class Perl6 < CodeGen Name = "Perl 6" File = "QR.pl6" Cmd = "perl6 QR.pl6 > OUTFILE" Apt = "rakudo" Code = %q("$_='#{Q[PREV.gsub(B,"\x7f"),?']}';s:g/\\\\x7f/\\\\\\\\/;print $_") end class Perl5 < CodeGen Name = "Perl 5" File = "QR.pl" Cmd = "perl QR.pl > OUTFILE" Apt = "perl" def code <<-'END'.lines.map {|l| l.strip }.join ( p="eval"; %( $_="#{ s,v=rp[PREV,128..287]; s=" $_='#{Q[s,c=/['\\\\]/]}'; $n=32; $s='#{Q[v,c]}'; $s=~s{..}{ $a=$&; $b=chr(--$n&255); ~s/$b/$a/g; }eg; print "; (s+N*(-s.size%6)).unpack("B*")[0]. gsub(/.{6}/){n=$&.to_i 2;((n+14)/26*6+n+47).chr} }"; s|.|$n=ord$&;substr unpack(B8,chr$n-int($n/32)*6-41),2|eg; eval pack'B*',$_ ).scan(/[ ,-:A-z]+|(.)/){p="s++#{$1?"chr #{$1.ord}+e":$&+?+};"+p}; p ) END end end class Pascal < CodeGen File = "QR.pas" Cmd = "fpc QR.pas && ./QR > OUTFILE" Apt = "fp-compiler" Code = %q("#$D(output);begin write(#{f(PREV,1){"'#$s',"}}'')end.") end class Parser3 < CodeGen Name = "Parser 3" File = "QR.p" Cmd = "parser3 QR.p > OUTFILE" Apt = "parser3-cgi" Code = %q("$console:line[#{PREV.gsub(/[:;()]/){?^+$&}}]") end class PARIGP < CodeGen Name = "PARI/GP" File = "QR.gp" Cmd = "gp -f -q QR.gp > OUTFILE" Apt = "pari-gp" Code = %q("print#{E[PREV]};quit") end class Octave_Ook < CodeGen Name = ["Octave", "Ook!"] File = ["QR.octave", "QR.ook"] Cmd = [ "mv QR.m QR.m.bak && octave -qf QR.octave > OUTFILE && mv QR.m.bak QR.m", "ruby vendor/ook-to-bf.rb QR.ook QR.ook.bf && ruby vendor/bf.rb QR.ook.bf > OUTFILE" ] Apt = ["octave", nil] def code <<-'END'.lines.map {|l| l.strip }.join " s=double#{E[PREV]}; t=num2cell(b=11-ceil(s/13)); for n=1:9 m={}; for i=1:141 f=@(x,y,n)repmat(['Ook' char(x) ' Ook' char(y) ' '],[1 abs(n)]); m(i)=[f(z=46,63,n) f(q=z-(i<13)*13,q,i-13) f(33,z,1) f(63,z,n)]; end; t(x=b==n)=m(diff([0 s(x)])+13); end; printf('%%s',t{:}) " END # NOTE: %% is a hack for Nickle printf escaping. end end class OCaml < CodeGen File = "QR.ml" Cmd = "ocaml QR.ml > OUTFILE" Apt = "ocaml" Code = %q("print_string"+E[PREV]) end class ObjC < CodeGen Name = "Objective-C" File = "QR.m" Cmd = "gcc -o QR QR.m && ./QR > OUTFILE" Apt = "gobjc" Code = %q("#import#{N}int main(){puts#{E[PREV]+R}}") end class Nim < CodeGen File = "QR.nim" Cmd = "nim compile QR.nim && ./QR > OUTFILE" Apt = "nim" Code = %q("echo#{E[PREV]}") end class Nickle < CodeGen File = "QR.5c" Cmd = "nickle QR.5c > OUTFILE" Apt = "nickle" Code = %q("printf#{E[PREV]}\\n") end class Neko < CodeGen File = "QR.neko" Cmd = "nekoc QR.neko && neko QR.n > OUTFILE" Apt = "neko" Code = %q("$print#{E[PREV]};") end class Mustache_NASM < CodeGen File = ["QR.mustache", "QR.asm"] Cmd = [ "mustache QR.mustache QR.mustache > OUTFILE", "nasm -felf QR.asm && ld -m elf_i386 -o QR QR.o && ./QR > OUTFILE", ] Apt = ["ruby-mustache", "nasm"] def code <<-'END'.lines.map {|l| l.strip.gsub("^^^", " ") }.join("\\n") "m{{!: x qr: |- ^^^:db\x60#{e[s=PREV]}\x60 ^^^global _start ^^^_start:mov edx,#{s.size} ^^^mov ecx,m ^^^mov ebx,1 ^^^mov eax,4 ^^^int 128 ^^^mov ebx,0 ^^^mov eax,1 ^^^int 128 x: | ^^^}}{{{qr}}}" END end end class MSIL < CodeGen File = "QR.il" Cmd = "ilasm QR.il && mono QR.exe > OUTFILE" Apt = "mono-devel" def code <<-'END'.lines.map {|l| l.strip }.join %( .assembly t{} .method #$L void Main() { .entrypoint ldstr"#{e[PREV]}" call void [mscorlib]#{C*"::"}(string) ret } ) END end end class Modula2 < CodeGen Name = "Modula-2" File = "QR.mod" Cmd = "gm2 -fiso QR.mod -o QR && ./QR > OUTFILE" Apt = "gm2" def code <<-'END'.lines.map {|l| l.strip }.join " MODULE QR; FROM StrIO IMPORT WriteString; BEGIN #{ (PREV).gsub(/()[#{i=94.chr}"]+|[#{i}']+/){ ["WriteString(",$&,");"]*($1??":?') } }END QR. " END end end class MiniZinc < CodeGen File = "QR.mzn" Cmd = "minizinc --solver COIN-BC --soln-sep '' QR.mzn > OUTFILE" Apt = "minizinc" Code = %q("solve satisfy;output [#{E[PREV]}];") end class Makefile < CodeGen File = "QR.mk" Cmd = "make -f QR.mk > OUTFILE" Apt = "make" Code = %q("all:\n\t@echo '#{d[PREV,?$].gsub(?'){"'\\\\''"}}'") end class M4 < CodeGen File = "QR.m4" Cmd = "m4 QR.m4 > OUTFILE" Apt = "m4" Code = %q("changequote(<@,@>)\ndefine(p,<@#{PREV}@>)\np") end class Lua < CodeGen File = "QR.lua" Cmd = "lua5.3 QR.lua > OUTFILE" Apt = "lua5.3" Code = %q("x=string.gsub(#{V[E[PREV],?&,?&]},'&(%d+)&',function(s)return string.rep('\\\\\\\\',tonumber(s))end);print(x)") end class LOLCODE < CodeGen File = "QR.lol" Cmd = "lci QR.lol > OUTFILE" Apt = [nil] def code <<-'END'.lines.map {|l| l.strip }.join %( HAI 1.2\n VISIBLE "#{ PREV.gsub(/[:"]/,":\\0") }"\n KTHXBYE BYE ) END end end class LLVMAsm < CodeGen Name = "LLVM asm" File = "QR.ll" Cmd = "llvm-as QR.ll && lli QR.bc > OUTFILE" Apt = "llvm" Backup = "QR.bc" def code <<-'END'.lines.map {|l| l.strip }.join %( @s=global[#{i=(s=PREV).size+1}x i8] c"#{s.gsub(/[\\"\n\t]/){"\\%02X"%$&.ord}}\\00" declare i32@puts(i8*) define i32@main(){ %1=call i32@puts(i8*getelementptr([#{i}x i8],[#{i}x i8]*@s,i32 0,i32 0)) ret i32 0 } ) END end end class Ksh_LazyK_LiveScript < CodeGen Name = ["ksh", "Lazy K", "LiveScript"] File = ["QR.ksh", "QR.lazy", "QR.ls"] Cmd = [ "ksh QR.ksh > OUTFILE", "lazyk QR.lazy > OUTFILE", "lsc QR.ls > OUTFILE", ] Apt = ["ksh", nil, "livescript"] Backup = [nil, nil, "QR.c"] def code lazyk = ::File.read(::File.join(__dir__, "lazyk-boot.dat")) lazyk = lazyk.tr("ski`","0123").scan(/.{1,3}/).map do |n| n = n.reverse.to_i(4) [*93..124,*42..73][n] end.pack("C*") lazyk = lazyk.gsub(/[ZHJK\^`~X]/) {|c| "\\x%02x" % c.ord } <<-'END'.lines.map {|l| l.strip }.join.sub("LAZYK"){lazyk} %( p(){ echo -n $1;}; f(){ for x in $(p "$1"|od -An -tu1 -v);do; p $4; for((j=$3;j--;));do; h $2 $x $j; done; done; }; p k\\`; h(){ p \\`${1:$(($2>>$3&1)):2};}; f 'console.log#{Q[E[PREV],?#].gsub(?',%('"'"'))}' kki 7 '``s``s``s``s``s``s``s``si'; h(){ p ${1:$(((($2%83-10)>>((2-$3)*2))%4)):1};}; f 'LAZYK' ski\\` 3 ) END end end class Kotlin < CodeGen File = "QR.kt" Cmd = "kotlinc QR.kt -include-runtime -d QR.jar && kotlin QR.jar > OUTFILE" Apt = "kotlin" Code = %q("fun main(a:Array){print#{Q[E[PREV]]} }") end class JavaScript_Jq_JSFuck < CodeGen File = ["QR.js", "QR.jq", "QR.jsfuck"] Cmd = [ "$(JAVASCRIPT) QR.js > OUTFILE", "jq -r -n -f QR.jq > OUTFILE", "!$(JAVASCRIPT) --stack_size=100000 QR.jsfuck > OUTFILE", ] Apt = ["nodejs", "jq", "nodejs"] def code <<-'END'.lines.map {|l| l.strip }.join %( P={0:'[+[]]',m:'((+[])'+(C="['constructor']")+"+[])['11']"}; for(R in B= ( '![]@!![]@[][[]]@'+ (A="[]['fill']")+ "@([]+[])['fontcolor']([])@(+('11e20')+[])['split']([])@"+ A+C+"('return escape')()("+A+')' ).split('@') ) for(E in D=eval(G='('+B[R]+'+[])')) P[T=D[E]]=P[T]||G+"['"+E+"']"; for(G='[',B=0;++B<36;) P[D=B.toString(36)]= B<10? (G+='+!+[]')+']' : P[D]||"(+('"+B+"'))['to'+([]+[])"+C+"['name']]('36')"; A+=C+"('console.log(unescape(\\""; for(E in G=#{E[PREV]}) A+="'+![]+'"+G.charCodeAt(E).toString(16); for(A+="\\".replace(/'+![]+'/g,\\"%\\")))')()",R=0;R<9;R++) A=A.replace(/'.*?'/g,function(B){ T=[]; for(E=1;B[E+1];) T.push(P[B[E++]]); return T.join('+') }); console.log('"'+A+'"') ) END end end class Java_ < CodeGen Name = "Java" File = "QR.java" Cmd = "javac QR.java && java QR > OUTFILE" Apt = "openjdk-11-jdk" def code # LZ78-like compression <<-'END'.lines.map {|l| l.strip }.join %( class QR{ #$L void main(String[]v){ String c[]=new String[99999],y="",z=y,s="#{ z=t=(0..r=q=126).map{|n|[n,[]]}; a=""; b=->n{a<<(n%78+55)%84+42}; (PREV).bytes{|n| r,z=z[n]||( b[r/78];b[r]; q<6083&&z[n]=[q+=1,[]]; t[n]) }; b[r/78];b[r] }"; int i=0,n=0,q=0; for(;++n<126;)c[n]=""+(char)n; for(;i<#{a.size};){ q=q*78+(s.charAt(i)-13)%84; if(i++%2>0){ y=q OUTFILE", "ick -bfOc QR.i && gcc -std=c99 -static QR.c -I /usr/include/ick-* -o QR -lick && ./QR > OUTFILE" ] Backup = [nil, "QR.c"] Apt = [["icont", "iconx"], "intercal"] def code <<-'END'.lines.map {|l| l.strip }.join %( procedure main(); i:=c:=0; s:=#{E[PREV+N]}; write("DO,1<-#"||*s); s?while t:=ord(move(1))do{ i+:=1; u:=-i; every 0to 7do{u:=u*2+t%2;t/:=2}; write("PLEASE")\\(i%4/3); write("DO,1SUB#"||i||"<-#"||((c-u)%256)); c:=u; }; write("PLEASEREADOUT,1\\nPLEASEGIVEUP"); end ) END end end class Haxe < CodeGen File = "QR.hx" Cmd = "haxe -main QR -neko QR.n && neko QR.n > OUTFILE" Apt = "haxe" Code = %q("class QR{#$L function main(){neko.Lib.print#{E[PREV]};}}") end class Haskell < CodeGen File = "QR.hs" Cmd = "rm -f QR.o && ghc QR.hs && ./QR > OUTFILE" Apt = "ghc" Code = %q("main=putStr"+E[PREV]) end class Groovy_Gzip < CodeGen File = ["QR.groovy", "QR.gz"] Cmd = ["groovy QR.groovy > OUTFILE", "gzip -cd QR.gz > OUTFILE"] Apt = ["groovy", "gzip"] def code <<-'END'.lines.map {|l| l.strip }.join %( z=new java.util.zip.GZIPOutputStream(System.out); z.write('#{PREV.tr(?"+B,"!~")}'.tr('~!','\\\\\u0022')as byte[]); z.close() ) END end end class GolfScript_GPortugol_Grass < CodeGen Name = ["GolfScript", "G-Portugol", "Grass"] File = ["QR.gs", "QR.gpt", "QR.grass"] Cmd = ["ruby vendor/golfscript.rb QR.gs > OUTFILE", "mv QR.c QR.c.bak && gpt -t QR.c QR.gpt && gcc -o QR QR.c && ./QR > OUTFILE && mv QR.c.bak QR.c", "ruby vendor/grass.rb QR.grass > OUTFILE"] Apt = [nil, "gpt", nil] def code r = <<-'END'.lines.map {|l| l.strip }.join %( @@BASE@@:j; { 119:i; { 206i-:i; .48<{71+}{[i]\\48-*}if }% }:t; "algoritmo QR;in"[195][173]++'cio imprima("' @@PROLOGUE@@ "#{e[PREV]}" { "W""w"@j 1+:j\\- @@MOD@@%1+* }% @@EPILOGUE@@ '");fim' ) END mod, prologue, epilogue = ::File.read(::File.join(__dir__, "grass-boot.dat")).lines prologue += "t" epilogue += "t" prologue = prologue.gsub(/(\/12131)+/) { "\"t\"/12131\"t #{ $&.size / 6 }*\"" } mod = mod.to_i r.gsub(/@@\w+@@/, { "@@PROLOGUE@@" => prologue.chomp, "@@EPILOGUE@@" => epilogue.chomp, "@@BASE@@" => 119 + mod - 1, "@@MOD@@" => mod, }) end end class Go < CodeGen File = "QR.go" Cmd = "go run QR.go > OUTFILE" Apt = "golang" def code <<-'END'.lines.map {|l| l.strip }.join %( package main; import"fmt"; func main(){ fmt.Print#{E[PREV]}; } ) END end end class Gnuplot < CodeGen File = "QR.plt" Cmd = "gnuplot QR.plt > OUTFILE" Apt = "gnuplot" Code = %q('set print"-";print'+E[PREV]) end class GEL < CodeGen Name = "GEL (Genius)" File = "QR.gel" Cmd = "genius QR.gel > OUTFILE" Apt = "genius" Code = %q(f(PREV,61){"printn#$S\n"}) end class GDB < CodeGen File = "QR.gdb" Cmd = "gdb -q -x QR.gdb > OUTFILE" Apt = "gdb" Code = %q(%(printf"#{e[d[PREV,?%]]}"\nquit)) end class GAP < CodeGen File = "QR.g" Cmd = "gap -q QR.g > OUTFILE" Apt = "gap" Code = %q("s:=OutputTextUser();WriteAll(s,#{E[PREV]});CloseStream(s);QUIT;") end class Gambas < CodeGen Name = "Gambas script" File = "QR.gbs" Cmd = "$(GBS) QR.gbs > OUTFILE" Apt = [["gambas3-scripter", "gambas3-gb-pcre"]] Code = %q(%(print"#{e[PREV]}")) end class Forth_FORTRAN77_Fortran90 < CodeGen File = ["QR.fs", "QR.f", "QR.f90"] Cmd = [ "gforth QR.fs > OUTFILE", "gfortran -o QR QR.f && ./QR > OUTFILE", "gfortran -o QR QR.f90 && ./QR > OUTFILE" ] Backup = [nil, "QR.c", nil] Apt = ["gforth", "f2c", "gfortran"] def code # assuming that PREV has no ' <<-'END'.lines.map {|l| l.strip }.join(" ") %( : A ."#{g*9}" ; : B A ." WRITE(*,*)'" A ; : C B TYPE ." '" CR ; : D S" #$D" C S\\" print \\"(&" C S\\" #{e[PREV]}" DUP A ." DO 10 I=1," . CR S" &A,&" C ." 10 CONTINUE" CR S\\" &A)\\",&" C 0 DO B ." &char(" COUNT . ." ),&'" CR LOOP S\\" &\\"\\"" C S" end #$D" C A ." STOP" CR A ." END" CR BYE ; D ) END end end class Fish < CodeGen File = "QR.fish" Cmd = "fish QR.fish > OUTFILE" Apt = "fish" Code = %q("echo '#{Q[Q[PREV,B],?!].gsub(?',%('"'"'))}'") end class Flex < CodeGen File = "QR.fl" Cmd = "flex -o QR.fl.c QR.fl && gcc -o QR QR.fl.c && ./QR > OUTFILE" Apt = "flex" Code = %q("%option noyywrap\n%%\n%%\nint main(){puts#{E[PREV]};}") end class FALSELang < CodeGen Name = "FALSE" File = "QR.false" Cmd = "ruby vendor/false.rb QR.false > OUTFILE" Apt = [nil] Code = %q(?"+PREV.gsub(?"){'"34,"'}.gsub(N){'"10,"'}+?") end class FSharp < CodeGen Name = "F#" File = "QR.fsx" fsproj = <<-END Exe net8.0 false END Cmd = %(echo '#{ fsproj.lines.map {|s| s.strip }.join }' > tmp.fsproj && DOTNET_NOLOGO=1 dotnet run --project tmp.fsproj > OUTFILE) Apt = "dotnet8" Code = %q('printfn("""'+d[PREV,?%]+' """)') end class Execline < CodeGen File = "QR.e" Cmd = "execlineb QR.e > OUTFILE" Apt = "execline" Code = %q(%(echo "#{e[PREV]}")) end class Erlang < CodeGen File = "QR.erl" Cmd = "escript QR.erl > OUTFILE" Apt = "erlang" Code = %q("\nmain(_)->\nio:fwrite#{d[E[PREV],?~]}.") end class EmacsLisp < CodeGen Name = "Emacs Lisp" File = "QR.el" Cmd = "emacs -Q --script QR.el > OUTFILE" Apt = "emacs-nox" Code = %q(%((princ "#{e[PREV]}"))) end class Elixir < CodeGen File = "QR.exs" Cmd = "elixir QR.exs > OUTFILE" Apt = "elixir" Code = %q("IO.puts"+E[PREV]) end #class Dhall < CodeGen # Name = "dhall" # File = "QR.dhall" # Cmd = "dhall text --file QR.dhall > OUTFILE" # Apt = "dhall" # Code = %q(E[PREV]) #end # #class Dc < CodeGen # Name = "dc" # File = "QR.dc" # Cmd = "dc QR.dc > OUTFILE || true" # XXX # Apt = "dc" # Code = %q("[#{PREV}]pq") #end class Dc_Dhall < CodeGen Name = ["dc", "Dhall"] File = ["QR.dc", "QR.dhall"] Cmd = [ "dc QR.dc > OUTFILE || true", # XXX "dhall text --file QR.dhall > OUTFILE", ] Apt = ["dc", "dhall"] Code = %q("['']p[#{PREV}]p['']pq") end class D < CodeGen File = "QR.d" Cmd = "gdc -o QR QR.d && ./QR > OUTFILE" Apt = "gdc" Code = %q("import std.stdio;void main(){write(`#{PREV}`);}") end # pakcs package is broken in Ubuntu 20.10; I guess it will be fixed in Ubuntu 21.04 # it was fixed since 21.04, but it is broken again in Ubuntu 22.04 #class Curry < CodeGen # Disabled = true # File = "QR.curry" # Cmd = "pakcs --nocypm :load QR.curry :save :quit && ./QR > OUTFILE" # Apt = "pakcs" # Code = %q("main=putStr"+E[PREV]) #end class Crystal < CodeGen Name = "Crystal" File = "QR.cr" Cmd = "crystal QR.cr > OUTFILE" Apt = [["crystal", "libevent-dev"]] Code = %q("puts#{E[PREV]}") end class CommonLisp < CodeGen Name = "Common Lisp" File = "QR.lisp" Cmd = "clisp QR.lisp > OUTFILE" Apt = "clisp" Code = %q(%((write-line"#{e[PREV]}"))) end class CoffeeScript < CodeGen File = "QR.coffee" Cmd = "coffee --nodejs --stack_size=100000 QR.coffee > OUTFILE" Apt = "coffeescript" def code <<-'END'.lines.map {|l| l.strip }.join " (f=(n)->Array(n+1).join '\\\\'); console.log('%s',#{V[E[PREV].gsub(?`,"\\\\x60"),'#{f(',')}']}) " END end end class Clojure_CMake_Cobol < CodeGen File = ["QR.clj", "QR.cmake", "QR.cob"] Cmd = [ "clojure QR.clj > OUTFILE", "cmake -P QR.cmake > OUTFILE", "cobc -O2 -x QR.cob && ./QR > OUTFILE", ] Apt = ["clojure", "cmake", "gnucobol4"] def code <<-'END'.lines.map {|l| l.strip }.join %( (doseq[s (lazy-cat ["IDENTIFICATION DIVISION." "PROGRAM-ID. QR." "PROCEDURE DIVISION." 'DISPLAY] (map #(str " \\"" (.replace %1"\\"""\\"\\"") "\\"") (re-seq #".{1,45}" "#{e[PREV]}")) [" \\" \\"." "STOP RUN."])] (println(str "message(STATUS \\" " (.replace(.replace(str s)"\\\\""\\\\\\\\")"\\"""\\\\\\"") "\\")"))) ) END end end class CSharp_Chef < CodeGen Name = ["C#", "Chef"] File = ["QR.cs", "QR.chef"] csproj = <<-END Exe net8.0 false END Cmd = [ %(echo '#{ csproj.lines.map {|s| s.strip }.join }' > tmp.csproj && DOTNET_NOLOGO=1 dotnet run --project tmp.csproj > OUTFILE), "PERL5LIB=vendor/local/lib/perl5 compilechef QR.chef QR.chef.pl && perl QR.chef.pl > OUTFILE" ] Apt = ["dotnet8", nil] def code <<-'END'.lines.map {|l| l.strip }.join %( class Program{ #$L void Main(){ #$C("Quine Relay Coffee.\\n\\nIngredients.\\n"); for(int i=9;i++<126;)#$C($"{i} g caffeine {i}\\n"); #$C("\\nMethod.\\n"); foreach(char c in#{E[PREV.reverse]})#$C($"Put caffeine {(int)c} into#$F.\\n"); #$C("Liquify#$G.\\nPour#$G into the baking dish.\\n\\nServes 1.\\n"); } } ) END end end class Cplusplus < CodeGen Name = "C++" File = "QR.cpp" Cmd = "$(CXX) -o QR QR.cpp && ./QR > OUTFILE" Apt = "g++" def code <<-'END'.lines.map {|l| l.strip }.join " #include\n int main(){ std::cout<<#{E[PREV]}; }/****//****/ " END end end class C < CodeGen File = "QR.c" Cmd = "$(CC) -o QR QR.c && ./QR > OUTFILE" Apt = "gcc" def code # LZ77-like compression <<-'END'.lines.map {|l| l.strip.gsub(/^_+/) { " " * $&.size } }.join ( s=PREV; t={};b="";L="";n=i=0;D=->n{L<<(n+62)%92+35;D}; s.bytes{|c| n>0? n-=1: (t[c]=(t[c]||[]).reject{|j|j4&&x<<[k,j] }; x=x.max)? ( n,j=x; x=b.size;(u=[x,3999].min;D[u%87][u/87];L<0; x=4001+i-j;D[x%87][x/87][n-5] ):b<\n char*p=#{E[L]},s[999999],*q=s; int main(){ int n,m; for(;*p;){ n=(*p-5)%92+(p[1]-5)%92*87; p+=2; if(n>3999) for(m=(*p++-5)%92+6;m--;q++)*q=q[4000-n]; else for(;n--;)*q++=*p++; } puts(s)#{R} } " ) END end end class BeanShell_Befunge_BLC8_Brainfuck < CodeGen Name = ["BeanShell", "Befunge", "BLC8", "Brainfuck"] File = ["QR.bsh", "QR.bef", "QR.Blc", "QR.bf"] Cmd = [ "bsh QR.bsh > OUTFILE", "cfunge QR.bef > OUTFILE", "ruby vendor/blc.rb < QR.Blc > OUTFILE", "ruby vendor/bf.rb QR.bf > OUTFILE", ] Apt = ["bsh", nil, nil, nil] def code blc = ::File.read(::File.join(__dir__, "blc-boot.dat")) <<-'END'.lines.map {|l| l.strip }.join.sub("BLC", [blc].pack("m0")) %( f(s){System.out.print(s);} s="389**6+44*6+00p45*,"; for(c:#{E[PREV]}){ s+="00g,"; for(m=1;m<256;m*=2) s+="00g,4,:"+(c/m%2>0?"4+":"")+","; f(s); s="4,:,"; } f(s+s); for(c:Base64.getDecoder().decode("BLC")){ c=c<0?256+c:c; for(i=0;i++<3;c/=8)f(c%8); f("8*+8*+,"); } f("@"); ) END end end class Bash_Bc < CodeGen Name = ["bash", "bc"] File = ["QR.bash", "QR.bc"] Cmd = [ "bash QR.bash > OUTFILE", "BC_LINE_LENGTH=4000000 bc -q QR.bc > OUTFILE", ] Apt = ["bash", "bc"] def code <<-'END'.lines.map {|l| l.strip }.join %(echo '#{PREV.gsub(?',%('"'"'))}'|sed -e's/\\\\/\\\\\\\\/g' -e's/"/\\\\q/g' -e's/.*/print "&"\\nquit/') END end end class Awk < CodeGen Name = "Awk" File = "QR.awk" Cmd = "awk -f QR.awk > OUTFILE" Apt = "gawk" Code = %q("BEGIN{print#{E[PREV]}}") end class ATS < CodeGen File = "QR.dats" Cmd = "patscc -o QR QR.dats && ./QR > OUTFILE" Apt = "ats2-lang" Code = %q("implement main0()=print"+E[PREV]) end class Asymptote < CodeGen File = "QR.asy" Cmd = "asy QR.asy > OUTFILE" Apt = "asymptote" Code = %q("write('#{Q[e[PREV],?']}');") end class AspectJ < CodeGen File = "QR.aj" Cmd = "ajc QR.aj && java QR > OUTFILE" Apt = "aspectj" def code <<-'END'.lines.map {|l| l.strip }.join %( class QR{ #$L void main(String[]a){ a=#{E[PREV.gsub(/\\+/){"^#{$&.size}^"}]}.split("\\\\^"); for(int i=1;i OUTFILE", "ruby vendor/ante.rb QR.ante > OUTFILE", ] Apt = ["algol68g", nil] def code <<-'end'.lines.map {|l| l.strip }.join %W[ STRINGz:= 226+ 153,a:=z+ 166,b:=a+"2"+z+ 160,c:=b+"8"+z+ 165,t:="#{d[PREV]}"; FORiTO\ UPBtDO\ INTn:=ABSt[i]; print( (50+n%64)+c+ (50+n%8MOD8)+c+ (50+nMOD8)+b+"J"+a) OD ]*"REPR" end end end class AFNIX_Aheui < CodeGen File = ["QR.als", "QR.aheui"] Cmd = ["LANG=C LD_LIBRARY_PATH=/usr/lib/afnix axi QR.als > OUTFILE", "ruby vendor/aheui.rb QR.aheui > OUTFILE"] Apt = ["afnix", nil] def code <<-'END'.lines.map {|l| l.strip }.join %( trans B(Buffer)\n trans O(n){\n B:add(Byte(+ 128 n)) }\n trans f(v n){\n O(+(/ n 64)107)\n O(n:mod 64)\n O v }\n trans D(n){ if(< n 4){ f(+(* 6 n)9)48 }{ if(n:odd-p){ D(- n 3)\n f 27 48\n f 36 11 }{ D(/ n 2)\n f 21 48\n f 48 20 } } }\n trans S(Buffer"#{e[PREV]}")\n while(!=(S:length)0){\n trans c(S:read)\n D(c:to-integer)\n f 35 39 }\n f 24 149\n interp:library"afnix-sio"\n trans o(afnix:sio:OutputTerm)\n o:write B ) END end end class Ada < CodeGen File = "qr.adb" Cmd = "gnatmake qr.adb && ./qr > OUTFILE" Apt = "gnat" def code <<-'END'.lines.map {|l| l.strip }.join.gsub("$$$", " ") %( with Ada.Text_Io; procedure qr is$$$ begin$$$ Ada.Text_Io.Put("#{d[PREV].gsub(N,'"&Character'+?'+'Val(10)&"')}"); end; ) END #<<-'END'.lines.map {|l| l.strip }.join.gsub("$$$", " ") # %( # with Ada.Text_Io; # procedure qr is$$$ # begin$$$ # #{f(PREV,120){ # %(Ada.Text_Io.Put("#{d[$s].gsub(N,'"&Character'+?'+'Val(10)&"')}");\n) # }} # Ada.Text_Io.Put_Line(""); # end; # ) #END end end class Aplus < CodeGen Name = "A+" File = "QR.+" Cmd = "a+ QR.+ > OUTFILE" Apt = "aplus-fsf" Code = %q(E[PREV]+"\nsys.exit 0") end class Zsh < CodeGen Name = "zsh" File = "QR.zsh" Cmd = "zsh QR.zsh > OUTFILE" Apt = "zsh" Code = %q("echo -E $'#{Q[Q[PREV,B],?']}'") end class Zoem < CodeGen File = "QR.azm" Cmd = "zoem -i QR.azm > OUTFILE" Apt = "zoem" Code = %q("\\\\write{-}{txt}{#{Q[PREV,/[\\\\{}]/]}}") end class Yorick < CodeGen File = "QR.yorick" Cmd = "yorick -batch QR.yorick > OUTFILE" Apt = "yorick" Code = %q(%(write,format="#{y="";f(PREV,35){y<<",\\n"+$S;"%s"}}")+y) end class Yabasic < CodeGen File = "QR.yab" Cmd = "yabasic QR.yab > OUTFILE" Apt = "yabasic" def code <<-'END'.lines.map {|l| l.strip }.join %( sub f(s$,n) print(s$);: for i=1to n print("\\\\");: next: end sub: f("#{V[e[PREV],'",','):f("']}",0) ) END end end class XSLT < CodeGen File = "QR.xslt" Cmd = "xsltproc QR.xslt > OUTFILE" Apt = "xsltproc" def code <<-'END'.lines.map {|l| l.strip }.join.gsub("$$$", "\n") " $$$ $$$ <#{U="xsl:template"} match='/'> #{U}> " END end end class VisualBasic_WebAssemblyBinary_WebAssemblyText_Whitespace < CodeGen Name = ["Visual Basic", "WebAssembly (Binary format)", "WebAssembly (Text format)", "Whitespace"] File = ["QR.vb", "QR.wasm", "QR.wat", "QR.ws"] vbproj = <<-END Exe net8.0 false END Cmd = [ %(echo '#{ vbproj.lines.map {|s| s.strip }.join }' > tmp.vbproj && DOTNET_NOLOGO=1 dotnet run --project tmp.vbproj > OUTFILE), "$(WASI_RUNTIME) QR.wasm > OUTFILE", "wat2wasm QR.wat -o QR.wat.wasm && $(WASI_RUNTIME) QR.wat.wasm > OUTFILE", "ruby vendor/whitespace.rb QR.ws > OUTFILE" ] Apt = ["dotnet8", "wabt", "wabt", nil] def code r = <<-'END'.lines.map {|l| l.strip }.join(?:) %(Module QR\nSub Main()\nDim c,n:Dim s As Object=#{C[0]}.OpenStandardOutput():Dim t()As Short={@@TBL@@} For Each d in"@@DATA1@@}@@DATA2@@~@@DATA3@@$@@DATA4@@" c=Asc(d) If c=36 For c=0To 11 #$W(If(c Mod 3,Asc(#{s=PREV;s.size*16+3}.ToString("x8")(1Xor 7-c*2\\3)),92)) Next Else n=(c>124)*(@@CONST1@@*c-#{s.size+@@CONST2@@}) Do While n>127 #$W(128+(127And n)) n\\=128 Loop #$W(If(c<125,If((c-1)\\7-8,c+66*(c>65And c<91),t(c-57)),n)) End If Next For Each c in"#{d[s].gsub N,'"& VbLf &"'}" #$W(Asc(c)) Next End Sub End Module) END tbl, data1, data2, data3, data4 = ::File.read(::File.join(__dir__, "wasm-tmpl.dat")).lines.map {|s| s.chomp } raise unless data3[0] == '(' r.gsub(/@@\w+@@/, { "@@TBL@@" => tbl, "@@DATA1@@" => data1.gsub("\\"){"\\\\"}, "@@DATA2@@" => data2.gsub("\\"){"\\\\"}, "@@DATA3@@" => '#{40.chr}'+data3[1..].gsub("\\"){"\\\\"}, "@@DATA4@@" => data4.gsub("\\"){"\\\\"}, # precompute some expressions by assuming that 2**14 <= (292+s.size) < 2**21 # "@@CONST1@@" => '#{6+((292+s.size).bit_length-1)/7}', "@@CONST1@@" => "8", # "@@CONST2@@" => '292+125*6+126*(((292+s.size).bit_length-1)/7)', "@@CONST2@@" => "1294" }) end end class VimScript < CodeGen Name = ["Vimscript"] Apt = "vim" File = "QR.vim" Cmd = "vim -EsS QR.vim > OUTFILE" def code <<-'END'.lines.map {|l| l.strip }.join (PREV).lines.map{|s|"let s=#{E[s]}\nput=s\nprint\n"}.join+"qa!" END end end class Verilog < CodeGen File = "QR.v" Cmd = "iverilog -o QR QR.v && ./QR -vcd-none > OUTFILE" Apt = "iverilog" Code = %q(%(module QR;initial begin #{f(PREV,3){%($write("%s",#$S);)+N}}end endmodule)) end class Vala_Velato < CodeGen File = ["QR.vala", "QR.mid"] Cmd = [ "valac QR.vala && ./QR > OUTFILE", "mono vendor/local/bin/Vlt.exe /s QR.mid && mono QR.exe > OUTFILE", ] Apt = ["valac", nil] def code <<-'END'.lines.map {|l| l.strip }.join %( void p(int[]c){ foreach(int v in c) stdout.printf("%c%c",v/256,v%256); } void main(){ int[]a; p({19796,26724,0,6,0,1,480,19796,29291,#{s=PREV;W=s.size*72+4;"%d,%d"%[W/65536,W%65536]}}); foreach(int c in#{E[s]}.data) foreach(int v in a={0,9,7,4,5,c/100*7/6+1,c%100/10*7/6+1,c%10*7/6+1,7}) p({144,v=15450+v*256,384,v}); p({255,12032}); } ) END end end class TypeScript_Unlambda < CodeGen File = ["QR.ts", "QR.unl"] Cmd = ["tsc --outFile QR.ts.js QR.ts && $(JAVASCRIPT) QR.ts.js > OUTFILE", "ruby vendor/unlambda.rb QR.unl > OUTFILE"] Apt = ["node-typescript", nil] def code <<-'END'.lines.map {|l| l.strip }.join "let s=#{E[PREV]},i=0,t='k';while(s[i])t='\\x60.'+s[i++]+t;console.log(t)" END end end class Tcsh_Thue < CodeGen Name = ["tcsh", "Thue"] File = ["QR.tcsh", "QR.t"] Cmd = ["tcsh QR.tcsh > OUTFILE", "ruby vendor/thue.rb QR.t > OUTFILE"] Apt = ["tcsh", nil] Code = %q(%(echo 'a::=~#{Q[Q[PREV,B],?!].gsub(?',%('"'"'))}'"\\\\n::=\\\\na")) end class Tcl < CodeGen File = "QR.tcl" Cmd = "tclsh QR.tcl > OUTFILE" Apt = "tcl" Code = %q(%(puts "#{Q[e[PREV],/[\[\]$]/]}")) end class Swift < CodeGen File = "QR.swift" Cmd = "swiftc QR.swift && ./QR > OUTFILE" Apt = "swiftlang" Code = %q("print#{E[PREV]}") end class SurgeScript < CodeGen File = "QR.ss" Cmd = "surgescript QR.ss > OUTFILE" Apt = "surgescript" def code <<-'END' %(object"Application"{state"main"{foreach(s in[#{f(PREV,4){$S+?,}}])Console.write(s);Application.exit();}}) END end end class StandardML_Subleq < CodeGen Name = ["Standard ML", "Subleq"] File = ["QR.sml", "QR.sq"] Cmd = ["polyc -o QR QR.sml && ./QR > OUTFILE", "ruby vendor/subleq.rb QR.sq > OUTFILE"] Apt = [["polyml", "libpolyml-dev"], nil] def code <<-'END'.lines.map {|l| l.strip }.join %( fun p n=print(Int.toString n^" "); fun main()=( p 0;p 0;p 130; List.tabulate(127,p); String.map(fn c=>(p(3+ord c);print"-1 0 ";c))#{E[PREV]}; print"0 0 -1" ); ) END end end class Squirrel < CodeGen File = "QR.nut" Cmd = "squirrel QR.nut > OUTFILE" Apt = "squirrel3" Code = %q("print"+E[PREV]) end class Scilab_Sed_Shakespeare_SLang < CodeGen Name = ["Scilab", "sed", "Shakespeare", "S-Lang"] File = ["QR.sci", "QR.sed", "QR.spl", "QR.sl"] Cmd = [ "scilab-cli -nb -f QR.sci > OUTFILE", "sed -E -f QR.sed QR.sed > OUTFILE", "spl2c < QR.spl > QR.spl.c && gcc -z muldefs -o QR -I ./vendor/local/include -L ./vendor/local/lib QR.spl.c -lspl -lm && ./QR > OUTFILE", "slsh QR.sl > OUTFILE", ] Apt = ["scilab-cli", "sed", nil, "slsh"] def code # NOTE: This code does not work for a short or simple text. # This assumes the input is so complex enough that # the compressed result won't be one character. # # * The Scheme program generates the encoded Shakespeare code. # * sed program decodes and completes Shakespeare code. # * The S-Lang program includes 8-bit characters and decompress the compression. <<-'END'.lines.map {|l| l.strip }.join %( printf(" 1d; s/.//; s/1/ the sum of a son and0/g; s/0/ twice/g; s/2/You are as bad as/g; s/3/ a son!Speak your mind!/g\\n #The Relay of Quine.\\n #Ajax, a man.\\n #Ford, a man.\\n #Act i: Quine.\\n #Scene i: Relay.\\n #[Enter Ajax and Ford]\\n #Ajax:\\n #"); function[]=f(s); for i=1:2:length(s), printf("2%s3",part(dec2bin(hex2dec(part(s,i:i+1))),$:-1:2)), end; endfunction\n #{ s,v=rp[PREV,127..255]; f( %( variable s=`#{s.gsub(/.{1,234}/){$&.gsub("`",%(`+"`"+`))+"`+\n`"}}`,i; for(i=0;i<129;i++) s=strreplace( s, pack("C",255-i), substrbytes(`#{v[0,99]}`+\n`#{v[99..-1]}`,i*2+1,2)); printf("%s",s) ),7 ){ "f('%s')\n"%$s.unpack("H*") } } printf("\\n#[Exeunt]"); quit ) END end end class Scheme < CodeGen File = "QR.scm" Cmd = "$(SCHEME) QR.scm > OUTFILE" Apt = "guile-3.0" Code = %q(%((display "#{e[PREV]}"))) end class Scala < CodeGen File = "QR.scala" Cmd = "scalac QR.scala && scala QR > OUTFILE" Apt = "scala" def code <<-'END'.lines.map {|l| l.strip }.join " object QR extends App{ #{f(PREV,196){%(print#$S;)}} } " END end end class Rust < CodeGen File = "QR.rs" Cmd = "rustc QR.rs && ./QR > OUTFILE" Apt = "rustc" Code = %q(%(fn main(){print!("{}",#{E[PREV]});})) end class Ruby_ < CodeGen Name = "Ruby" File = "QR.rb" Cmd = "ruby QR.rb > OUTFILE" Apt = "ruby" Code = nil end load "code-gen-pool.rb" if ENV["ALL"] GenSteps = CodeGen::List.map {|s| s.gen_step } RunSteps = CodeGen::List.reverse.flat_map {|s| s.run_steps } ================================================ FILE: src/dot.github.workflows.main.yml.gen.rb ================================================ require "yaml" require_relative "code-gen" apts = RunSteps.flat_map {|s| s.apt } apts = apts.flatten.map {|apt| apt }.compact apts.delete("ruby2.1") srcs = RunSteps.flat_map {|s| s.src } cp_cmds = srcs.map do |s| " sudo docker cp qr:/usr/local/share/quine-relay/#{ s } spoiler/" end.join("\n") File.write(File.join(__dir__, "../.github/workflows/main.yml"), <" % self.object_id) @name = name.to_s end def inspect @name end def [](*others) prev = self others.each do |other| sym = Sym.new $prog << [:app, sym, prev, other] prev = sym end prev end end w = Sym.new(:W) succ = Sym.new(:Succ) out = Sym.new(:Out) def fn(name, &blk) params = blk.parameters.map {|_, param_name| Sym.new(param_name) } sym = Sym.new(name) $prog << [:abs, sym, params] blk[*params] $prog << [:ret] sym end $result = [] [10, 32].each do |smallest_char| $prog = [] succ2 = fn(:succ2) {|n| succ[succ[n]] } succ4 = fn(:succ4) {|n| succ2[succ2[n]] } succ8 = fn(:succ8) {|n| succ4[succ4[n]] } succ16 = fn(:succ16) {|n| succ8[succ8[n]] } succ32 = fn(:succ32) {|n| succ16[succ16[n]] } succ64 = fn(:succ64) {|n| succ32[succ32[n]] } succ128 = fn(:succ128) {|n| succ64[succ64[n]] } add_num = ->(n, v) do ary = [succ128, succ64, succ32, succ16, succ8, succ4, succ2, succ] until v == 0 f = ary.pop n = f[n] if v % 2 == 1 v /= 2 end n end next_char = fn(:next_char) do |n| sc = add_num[n, 129 + smallest_char] # n == 127 ? c10 : succ[n] add_num[w, 8][n, sc, add_num[n, 1]] end sub = fn(:sub) do |magic, n, _, m| out[n] magic[magic, next_char[m]] end # http://d.hatena.ne.jp/kikx/20080914 app23 = fn(:app23) {|x, y| y } magic = fn(:magic) {|magic_, n, g| g[app23, sub[magic_], n] } #main = fn(:main) do |n120,n121,n122,n123,n124,n125,n126,n127,n10,n11,n12,n13,n14,n15,n16,n17,n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n33,n34,n35,n36,n37,n38,n39,n40,n41,n42,n43,n44,n45,n46,n47,n48,n49,n50,n51,n52,n53,n54,n55,n56,n57,n58,n59,n60,n61,n62,n63,n64,n65,n66,n67,n68,n69,n70,n71,n72,n73,n74,n75,n76,n77,n78,n79,n80,n81,n82,n83,n84,n85,n86,n87,n88,n89,n90,n91,n92,n93,n94,n95,n96,n97,n98,n99,n100,n101,n102,n103,n104,n105,n106,n107,n108,n109,n110,n111,n112,n113,n114,n115,n116,n117,n118,n119| # $prog << [:raw, "!"] # n120 = n119[n33] # n121 = n120[n33] # n122 = n121[n33] # n123 = n122[n33] # n124 = n123[n33] # n125 = n124[n33] # n126 = n125[n33] #end main = Sym.new(:main) $prog << [:abs, main, (smallest_char..127).map { Sym.new }] $prog << [:raw, "!"] $prog << [:ret] start = fn(:start) do |start_, main_, n| m = main_[magic[magic, n]] w[n, start_, start_[start_, m]][next_char[n]] end fn(:kick) {|_kick| start[start, main, next_char[w]] } stacks = [] stack = [out, succ, w] a = [] $prog[0..-2].each do |type, *args| case type when :abs new_sym, params = args a << "w" * params.size stacks << ([new_sym] + stack) stack = params.reverse + stack when :app new_sym, sym0, sym1 = args a << " " + "W" * (stack.index(sym0) + 1) + "w" * (stack.index(sym1) + 1) stack.unshift(new_sym) when :ret stack = stacks.pop a << "v" when :raw a << args.first end end prologue, epilogue = a.join.split.join.split("!") def dump(s) aa = [*"0".."Z"] a = "" s.scan(/(v|W*)(w{1,#{aa.size-1}})/) do |s1, s2| a << (s1 == "v" ? "/" : aa[s1.size]) << aa[s2.size] end "#{ a.dump }" end epilogue = dump(epilogue) prologue = dump(prologue) $result << 128 - smallest_char $result << prologue $result << epilogue end open("grass-boot.dat", "w") do |f| $result.each do |e| f.puts e end end ================================================ FILE: src/langs.png.gen.rb ================================================ require_relative "code-gen" require "cairo" require "rsvg2" # You need to install the two fonts: Raleway and UnifrakturCook. # * https://www.google.com/fonts/specimen/Raleway # * https://www.google.com/fonts/specimen/UnifrakturCook %w(Raleway UnifrakturCook).each do |font| if `fc-list #{ font }`.strip.empty? && !ENV["SKIP_FONT_CHECK"] raise "Font `#{ font }' is not available; to skip this check, set SKIP_FONT_CHECK=1" end end W = H = 750 surface = Cairo::ImageSurface.new(W, H) ctx = Cairo::Context.new(surface) ctx.line_width = 1 ctx.set_source_rgb(1, 1, 1) ctx.rectangle(0, 0, W, H) ctx.fill ctx.set_source_rgb(0, 0, 0) ctx.translate(W / 2, H / 2) ctx.select_font_face("Raleway") ctx.antialias = Cairo::Antialias::GRAY BaseFontSize = 13 SubFontSize = 10 Radius = 210.0 RunSteps.each_with_index do |s, i| ctx.save do angle = i / (RunSteps.size / 4.0) dir = 1 < angle && angle <= 3 ? 1 : -1 ctx.rotate(Math::PI / 2 * (dir < 0 ? -angle : 2 - angle + 0.02)) s.name =~ /^(.*?)(\(.*\))?$/ name, sub_name = $1, $2 || "" ctx.font_size = BaseFontSize; e1 = ctx.text_extents(name) ctx.font_size = SubFontSize ; e2 = ctx.text_extents(sub_name) ctx.move_to(dir * (Radius + 10) - (dir < 0 ? e1.x_advance + e2.x_advance : 0), 0) ctx.font_size = BaseFontSize; ctx.show_text(name) ctx.font_size = SubFontSize ; ctx.show_text(sub_name) end end ArrowCount = 7 ArrowCount.times do |i| ctx.save do ctx.rotate(Math::PI * (2 * i) / ArrowCount - Math::PI + 0.1) ctx.line_width = 2 ctx.line_cap = Cairo::LineCap::SQUARE ctx.new_path ctx.arc(0, 0, Radius, 0.0, Math::PI * 2 / ArrowCount - 0.1) ctx.stroke ctx.line_width = 1 ctx.move_to(Radius , -8) ctx.line_to(Radius - 6, 2) ctx.line_to(Radius + 6, 2) ctx.fill end end Uroboros = 350.0 ctx.select_font_face("UnifrakturCook") ctx.font_size = 25 Title = "#{ RunSteps.size }-Language Uroboros Quine" e = ctx.text_extents(Title) height = Uroboros / 2 + e.height + 20 ctx.move_to(-e.width / 2, height / 2) ctx.show_text(Title) ctx.save do svg = RSVG::Handle.new_from_file("uroboros.svg") ctx.translate(-Uroboros / 2, -height / 2) ctx.scale(Uroboros / svg.width, Uroboros / svg.width) ctx.render_rsvg_handle(svg) end surface.write_to_png("../langs.png") unless ENV["NO_PNG_OPT"] system 'optipng -fix -i0 -o7 -strip all ../langs.png' system 'advdef -z4 ../langs.png' system 'advpng -z4 ../langs.png' end # convert svg to template # #require "cairo" #require "rsvg2" #H = 52.0 #W = H * 4 #surface = Cairo::ImageSurface.new(W, H) #ctx = Cairo::Context.new(surface) #svg = RSVG::Handle.new_from_file("uroboros2.svg") #ctx.translate(4, 2) #ctx.rotate(-0.014) #ctx.scale((W - 8) / svg.width, (H - 4) / svg.height) #ctx.render_rsvg_handle(svg) #data = surface.data.unpack("C*") #M = (0...H).map do |y| # (0...W).map do |x| # idx = y * surface.stride + x * 4 # data[idx] < 40 && data[idx + 3] > 48 ? " " : "#" # end.join #end #puts *M ================================================ FILE: src/lazyk-boot.dat.gen.rb ================================================ Var = Struct.new(:name) Abs = Struct.new(:var, :exp) App = Struct.new(:exp1, :exp2) Comb = Struct.new(:type) S, K, I = Comb[:S], Comb[:K], Comb[:I] class Var def fvs { name => 1 } end def remove_abs self end def remove_var(n) if n == name I else App[K, self] end end def inspect(need_paren = true) name.to_s end end class Abs def fvs @fvs ||= ( s = exp.fvs.dup s.delete(var) s ) end def remove_abs exp.remove_abs.remove_var(var) end def remove_var(v) if exp.fvs[v] exp.remove_abs.remove_var(v) else App[K, self] end end def inspect(need_paren = true) vs, e = [var], exp while e.is_a?(Abs) vs << e.var e = e.exp end "(\\#{ vs * " " }. #{ e.inspect(false) })" end end class App def fvs @fvs ||= ( s = exp1.fvs.dup exp2.fvs.each do |v, n| s[v] ||= 0 s[v] += n end s ) end def remove_abs App[exp1.remove_abs, exp2.remove_abs] end def remove_var(v) if fvs[v] if exp2.is_a?(Var) && exp2.name == v && !exp1.fvs[v] exp1 else App[App[S, exp1.remove_var(v)], exp2.remove_var(v)] end else App[K, self] end end def inspect(need_paren = true) s = "%s %s" % [exp1.inspect(false), exp2.inspect(true)] s = "(#{ s })" if need_paren s end def to_unlambda "`" + exp1.to_unlambda + exp2.to_unlambda end def simplify if exp1 == I exp2.simplify # I x -> x elsif exp1.is_a?(App) if exp1.exp1 == K exp1.simplify # K x y -> x elsif exp1.exp1.is_a?(App) && exp1.exp1.exp1 == S if exp1.exp1.exp2.is_a?(App) && exp1.exp1.exp2.exp1 == K App[exp1.exp1.exp2.exp2, App[exp1.exp2, exp2]].simplify # S (K x) y z -> x (y z) elsif exp1.exp2.is_a?(App) && exp1.exp2.exp1 == K App[App[exp1.exp1.exp2, exp2], exp1.exp2.exp2].simplify # S x (K y) z -> x z y else App[exp1.simplify, exp2.simplify] end else App[exp1.simplify, exp2.simplify] end else App[exp1.simplify, exp2.simplify] end end end class Comb def fvs {} end def remove_abs self end def remove_var(v) App[K, self] end def inspect(need_paren = true) type.to_s end def to_unlambda type.to_s.downcase end def simplify self end end def ary2app(exp) if exp.is_a?(Array) exp = exp.map {|e| ary2app(e) } e1 = App[*exp.shift(2)] exp.each {|e2| e1 = App[e1, e2] } e1 elsif exp.is_a?(Abs) Abs[exp.var, ary2app(exp.exp)] else exp end end def to_unlambda(exp) ary2app(exp).remove_abs.simplify.to_unlambda end def abs(&b) vars = b.parameters.map {|type, name| name } exp = yield(*vars.map {|name| Var[name] }) vars.reverse_each {|v| exp = Abs[v, exp] } exp end Zero = abs {|s, z| z } One = abs {|s, z| [s, z] } Two = abs {|s, z| [s, [s, z]] } Three = abs {|s, z| [s, [s, [s, z]]] } Six = abs {|s| [Two, [Three, s]] } N256 = [abs {|n| [n, n] }, [abs {|n| [n, n] }, abs {|s, z| [s, [s, z]] }]] Inc = abs {|n, s, z| [s, [[n, s], z]] } Dbl = abs {|n, s| [n, abs {|x| [s, [s, x]] }] } Cons = abs {|hd, tl| abs {|f| [f, hd, tl] } } Pow = abs {|n, m| [m, n] } IfLE6 = -> m, t, e { [[m, Pow, [K, t]], [Six, Pow, [K, e]]] } Main = [ abs {|x| [x, x, Zero, Zero] }, abs {|main, count, num, code| IfLE6[count, [main, main, [Inc, count], [code, I, Inc, [Dbl, num]]], [Cons, num, code] ] } ] if ARGV[0] puts "k`" "foobar\n".bytes do |c| print "``s" * 8 + "i" 6.downto(0) {|j| print "`" + "kki"[c[j], 2] } puts end puts "`k`k" + to_unlambda(N256) + to_unlambda(Main) else File.write("lazyk-boot.dat", "`k`k" + to_unlambda(N256) + to_unlambda(Main)) end ================================================ FILE: src/test.rb ================================================ # usage: # ruby test.rb # test all Steps # ruby test.rb Perl # test only Perl Step require_relative "code-gen" ENV["PATH"] = "vendor/local/bin:#{ ENV["PATH"] }" dir = File.join(File.dirname(__dir__), "tmp") Dir.mkdir(dir) unless File.directory?(dir) Dir.chdir(dir) File.symlink("../vendor", "vendor") unless File.symlink?("vendor") gens = ARGV[0] ? [eval(ARGV[0]).gen_step] : GenSteps[0..-2] text = ARGV[1] || "Hello" all_check = true gens.each do |gen_step| puts "test: %s" % gen_step.name code = Object.new.instance_eval(GenPrologue + gen_step.code.sub("PREV") { text.dump }) + "\n" code.sub!("%%", "%") if gen_step.name == "Octave_Ook" steps = [*gen_step.run_steps, RunStep[nil, "QR.txt"]] File.write(steps.first.src, code) steps.each_cons(2) do |src, dst| cmd = src.cmd_raw.gsub("OUTFILE", dst.src) puts "cmd: " + cmd system(cmd) || raise("failed") end check = File.read("QR.txt").strip == text all_check &&= check puts "result: #{ check ? "OK" : "NG" }" puts end puts all_check ? "all ok" : "something wrong" ================================================ FILE: src/thumbnail.png.gen.rb ================================================ require "chunky_png" # zcat /usr/share/fonts/X11/misc/4x6.pcf.gz | # pcf2bdf | # ruby -e '$<.each("") {|s| (n = $1.to_i; puts " %3d => 0x%s," % [n, $2.split.map {|n| n[0] }.join] if 32 <= n && n <= 126) if s =~ /ENCODING (\d+).*BITMAP(.*)ENDCHAR/m }' FONT = { 32 => 0x000000, 33 => 0x444040, 34 => 0xAA0000, 35 => 0xAFAFA0, 36 => 0x4EC2E4, 37 => 0x824820, 38 => 0x4A4A50, 39 => 0x440000, 40 => 0x244442, 41 => 0x844448, 42 => 0xA4E4A0, 43 => 0x44E440, 44 => 0x000048, 45 => 0x00E000, 46 => 0x000040, 47 => 0x224880, 48 => 0x4AEA40, 49 => 0x4C44E0, 50 => 0x4A24E0, 51 => 0xE242C0, 52 => 0xAAE220, 53 => 0xE8C2C0, 54 => 0x68CA40, 55 => 0xE24880, 56 => 0x6A4AC0, 57 => 0x4A62C0, 58 => 0x040040, 59 => 0x040048, 60 => 0x248420, 61 => 0x0E0E00, 62 => 0x842480, 63 => 0xC24040, 64 => 0x6AA860, 65 => 0x4AEAA0, 66 => 0xCACAC0, 67 => 0x4A8A40, 68 => 0xCAAAC0, 69 => 0xE8C8E0, 70 => 0xE8C880, 71 => 0x68AA60, 72 => 0xAAEAA0, 73 => 0xE444E0, 74 => 0x222A40, 75 => 0xAACAA0, 76 => 0x8888E0, 77 => 0xAEEAA0, 78 => 0x2AEA80, 79 => 0x4AAA40, 80 => 0xCAC880, 81 => 0x4AAA42, 82 => 0xCACAA0, 83 => 0x6842C0, 84 => 0xE44440, 85 => 0xAAAAE0, 86 => 0xAAAE40, 87 => 0xAAEEA0, 88 => 0xAA4AA0, 89 => 0xAA4440, 90 => 0xE248E0, 91 => 0x644460, 92 => 0x884220, 93 => 0xC444C0, 94 => 0x4A0000, 95 => 0x00000E, 96 => 0x420000, 97 => 0x06AA60, 98 => 0x8CAAC0, 99 => 0x068860, 100 => 0x26AA60, 101 => 0x04AC60, 102 => 0x24E440, 103 => 0x06A62C, 104 => 0x8CAAA0, 105 => 0x40C4E0, 106 => 0x20222C, 107 => 0x8ACAA0, 108 => 0xC444E0, 109 => 0x0AEAA0, 110 => 0x0CAAA0, 111 => 0x04AA40, 112 => 0x0CAC88, 113 => 0x06AA62, 114 => 0x0AC880, 115 => 0x06C2C0, 116 => 0x4E4420, 117 => 0x0AAA60, 118 => 0x0AAA40, 119 => 0x0AAEA0, 120 => 0x0A44A0, 121 => 0x0AA62C, 122 => 0x0E24E0, 123 => 0x24C442, 124 => 0x444440, 125 => 0x846448, 126 => 0x5A0000 } src = File.foreach("../QR.rb").to_a w = src.map {|line| line.chomp.size }.max h = src.size png = ChunkyPNG::Image.new(w * 4, h * 8, :black) src.each_with_index do |line, j| line.chomp.chars.each_with_index do |ch, i| 6.times do |y| 4.times do |x| png[i * 4 + 3 - x, j * 8 + y + 1] = [:black, :white][FONT[ch.ord][x + (5 - y) * 4]] end end end end png.save('../thumbnail.png') ================================================ FILE: src/uroboros.txt ================================================ ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ############################################ ######### ########################################################################################################################################################### ################################# ###### #### ######## ################################################################################################################################################ ############################### ### # #################################################################################### ############################################# ############################# ## ############################################################### ##################################### ########################### ############################################################ ################################ ########################## ################################################# ############################ ######################### ########################################## ######################### ####################### ######################################### ###################### ##################### #### ################################## ############## ################### #################### ##### ############################ ############################ ################## ################### #### ########################### ###################################### ################ ################### ###################### ###################### ############################################ ############## ################### #### ################################## ################# ################################################## ############# ##################### ################################################# ############# ###################################################### ########### ################## ################################################### ############ ########################################################## ########## ############### ######################################################## ######## ############################################################# ######### ############## ############################################################ #### ################################################################# ######## ############ ############################################################### ## ############################################################################### ######## ########## ################################################################### ###### ############################################################### ####### ######### ###################################################################### ################################################### ###### ######## ######################################################################## ############################################## ###### ####### ########################################################################### ######################################### ###### ####### ############################################################################ ##################################### ###### ###### ############################################################################### ################################## ##### ###### ################################################################################ ############################### ##### ##### ################################################################################## ########################### ##### ##### ################################################################################### ######################## ###### ##### ################################################################################## # ##################### ###### ##### ################################################################################ ## ########## #### ################## ###### ##### ############################################################################### # ############# ########### ############### ####### ###### ############################################################################# # ############## ############## ##### ############ ####### ###### ########################################################################## ## ############################### ############ ######### ######## ####### ######################################################################## #### ################################ ################ ###### ######### ######## ##################################################################### ######## ################################ ################### ### ########## ######## ################################################################## ########## #################################################### # ########### ######### ############################################################### ############## ################################################# ############ ########## ############################################################ ################## ############################################# ############## ############ ####################################################### ##################### ####################################### ############### ############# ################################################### ######################## ############################### ################# ############### ############################################# ############################ ################## ################### ################# ####################################### ################################## ##################### ################### ############################## ###################################### ####################### ##################### ############### ############################################ ########################## ######################## ################################################## ############################# ########################### ######################################################### ################################# ################################ ################################################################# ##################################### ###################################### ############################################################################### ############################################ ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ################################################################################################################################################################################################################### ================================================ FILE: src/wasm-tmpl.dat.gen.rb ================================================ def f(s) enc = -> n { [n].pack("V").unpack1("H*").gsub(/../){"\\"+$&} } esc = -> s { s.gsub(?\\){'\\\\'}.gsub(?"){'\\"'} } wasm_txt_pre = <<-'END'.lines.map {|s| s.strip }.join + enc[s.size * 16 + 3] (module (import "wasi_snapshot_preview1" "fd_write" (func(param i32 i32 i32 i32)(result i32))) (memory(export "memory")(data "\08\00\00\00 END raise unless wasm_txt_pre.size % 4 == 0 wasm_txt_post = <<-'END'.lines.map {|s| s.strip }.join ")) (func(export "_start")i32.const 1 i32.const 0 i32.const 1 i32.const 0 call 0 drop) ) END txt = <<-END (module (import "wasi_snapshot_preview1" "fd_write"(func $fd_write(param i32 i32 i32 i32)(result i32))) (memory 64) (export "memory"(memory 0)) (data(i32.const 0)"#{ enc[8*5]+enc[1] # " " }#{ enc[8*5+4]+enc[2] # "\t" }#{ enc[8*5+8]+enc[2] # "\n" }#{ enc[8*5+12]+enc[wasm_txt_pre.size] }#{ enc[8*5+12+wasm_txt_pre.size]+enc[wasm_txt_post.size] } ...\\\\t..\\\\n..#{ esc[wasm_txt_pre] }#{ esc[wasm_txt_post] }#{ s }") (func $out(param i32) i32.const 1 local.get 0 i32.const 8 i32.mul i32.const 1 i32.const #{ 8 * 5 + 12 } call $fd_write drop ) (func(export "_start") (local $idx i32) (local $shift i32) i32.const 3 call $out i32.const #{ 8*5+12+wasm_txt_pre.size+wasm_txt_post.size } local.set $idx (loop i32.const 0 call $out (; out << 32 ;) i32.const 0 call $out (; out << 32 ;) i32.const 0 call $out (; out << 32 ;) i32.const 8 local.set $shift (loop local.get $idx i32.load8_u local.get $shift i32.const 1 i32.sub local.tee $shift i32.shr_u i32.const 1 i32.and call $out (; out << 32 - c[7-i] * 23 ;) local.get $shift br_if 0 ) i32.const 2 call $out (; out << 10 ;) i32.const 1 call $out (; out << 9 ;) i32.const 2 call $out (; out << 10 ;) i32.const 0 call $out (; out << 32 ;) i32.const 0 call $out (; out << 32 ;) local.get $idx i32.const 1 i32.add local.tee $idx i32.load8_u br_if 0 ) i32.const 2 call $out (; out << 10 ;) i32.const 2 call $out (; out << 10 ;) i32.const 2 call $out (; out << 10 ;) i32.const 4 call $out ) ) END end File.write("ABCD.wat", f("abcd")) File.write("ABCDE.wat", f("abcde")) system("wat2wasm ABCD.wat", exception: true) system("wat2wasm ABCDE.wat", exception: true) abcd = File.binread("ABCD.wasm") abcde = File.binread("ABCDE.wasm") i = (0..).find {|i| abcd[i] != abcde[i] } j = (abcd.size - 4).downto(0).find {|i| abcd[i] != abcde[i] } data1 = abcd[0, i] raise unless data1 == abcde[0, i] data2 = abcd[i + 2, 5] raise unless data2 == abcde[i + 2, 5] data3 = abcd[i + 2 + 5 + 2...j-1] raise unless data3 == abcde[i + 2 + 5 + 2...j-1] data4 = abcd[j + 12-1...-4] # wasm template: # data1 + LSB128(length+const) + data2 + LSB128(length+const) + data3 + Hexdump(length) + data4 A = [26, 34, 86, 127, 148, 158, 200] def e(data) enc = "".b data.bytes do |n| case when n < 0x1a enc << [n + ?B.ord].pack("C*") when ?9.ord <= n && n < ?9.ord + A.size raise when n < 32 || n == ?".ord || (?B.ord <= n && n <= ?Z.ord) || n >= 127 enc << [?9.ord + A.index(n)].pack("C*") else enc << n end end enc end def d(data) data.gsub(/./) { "9" <= $& && $& < "@" ? [A[$&.ord - ?9.ord]].pack("C*") : "A" < $& && $& < "Z" ? [$&.ord - ?B.ord].pack("C*") : $& } end [data1, data2, data3, data4].each do |data| raise unless data == d(e(data)) end File.open("wasm-tmpl.dat", "w") do |f| f.puts A.join(",") f.puts e(data1) f.puts e(data2) f.puts e(data3) f.puts e(data4) end d=->s,t=?"{s.gsub(t){t+t}}; out = "ABCDE" # test code raise if data3.size + data4.size + 18 != 292 n = 292+out.size m = (n.bit_length - 1) / 7 puts <124)*(#{6+m}*c-#{m+n+125*(6+m)}) Do While n>127 s.WriteByte(128+(127And n)) n\\=128 Loop s.WriteByte(If(c<125,If((c-1)\\7-8,c+66*(c>65And c<91),t(c-57)),n)) End If Next For Each c in"#{d[out]}" s.WriteByte(Asc(c)) Next End Sub End Module END ================================================ FILE: vendor/.gitignore ================================================ Spl/ goaheui/ lci-*/ npiet-*/ cfunge-*/ Acme-Chef-*/ local/ spl-*/ ================================================ FILE: vendor/Makefile ================================================ LCI := lci-0.10.5 NPIET := npiet-1.3e CFUNGE := cfunge-0.9.0 ACME_CHEF := Acme-Chef-1.03 SPL := spl-1.2.1 LOCAL := $(CURDIR)/local .NOTPARALLEL: all: $(LOCAL)/bin/lci $(LOCAL)/bin/npiet $(LOCAL)/bin/cfunge $(LOCAL)/bin/compilechef $(LOCAL)/bin/lazyk $(LOCAL)/bin/spl2c $(LOCAL)/bin/Vlt.exe $(LOCAL)/bin/lci: unzip -q $(LCI).zip (cd $(LCI) && cmake -DCMAKE_INSTALL_PREFIX=$(LOCAL) . && make && make install) $(LOCAL)/bin/npiet: tar xzf $(NPIET).tar.gz (cd $(NPIET) && ./configure CC="gcc -std=c99 -Wno-implicit-function-declaration -Wno-int-conversion" --prefix=$(LOCAL) && make && make install) $(LOCAL)/bin/cfunge: tar xjf $(CFUNGE).tar.bz2 (cd $(CFUNGE) && cmake -DCMAKE_INSTALL_PREFIX=$(LOCAL) . && make && make install) $(LOCAL)/bin/compilechef: tar xzf $(ACME_CHEF).tar.gz (cd $(ACME_CHEF) && perl Makefile.PL INSTALL_BASE=$(LOCAL) && make && make install) $(LOCAL)/bin/lazyk: $(CC) lazyk.c -o $@ $(LOCAL)/bin/spl2c: tar xzf $(SPL).tar.gz (cd $(SPL) && ln -s ../local spl && make spl2c CCFLAGS="-O0 -g -Wall" && make install) $(LOCAL)/bin/Vlt.exe: unzip -d $(LOCAL)/bin -q Velato_0_1.zip clean: rm -rf $(LOCAL)/ $(LCI)/ $(NPIET)/ $(CFUNGE)/ $(ACME_CHEF)/ $(SPL)/ ================================================ FILE: vendor/README ================================================ Unlambda: unlambda.rb * self-made * License: MIT Whitespace: whitespace.rb * self-made * License: MIT Subleq: subleq.rb * self-made * License: MIT Thue: thue.rb * self-made * License: MIT Ook!: ook-to-bf.rb * self-made * License: MIT BLC8: blc.rb * self-made * License: MIT FALSE: false.rb * self-made * License: MIT Aheui: aheui.rb * self-made * License: MIT ante: ante.rb * https://github.com/michaeldv * License: MIT Befunge: cfunge-0.9.0.tar.bz2 * http://sourceforge.net/projects/cfunge/ * License: GPL3 Chef: Acme-Chef-1.03.tar.gz * https://metacpan.org/pod/Acme::Chef * License: the same terms as Perl (Artistic License) Grass: grass.rb * http://www.blue.sky.or.jp/grass/ * License: BSD 2-Clause * slightly modified for Ruby 2+ GolfScript: golfscript.rb * http://www.golfscript.com/golfscript/ * License: MIT LOLCODE: lci-0.10.5.zip * http://lolcode.org/ * License: GPL3+ Piet: npiet-1.3e.tar.gz * http://www.bertnase.de/npiet/ * License: GPL2 Lazy K: lazyk.c * https://github.com/irori/lazyk * License: GPL2+ Shakespeare: spl-1.2.1.tar.gz * http://shakespearelang.sourceforge.net/ * License: GPL Velato: Velato_0_1.zip * http://velato.net/ * License: freeware ================================================ FILE: vendor/aheui.rb ================================================ # https://aheui.readthedocs.io/en/latest/specs.en.html code = $<.each_line.map do |s| s.chomp.unpack("U*").map do |c| if 0xac00 <= c && c <= 0xd7a3 c -= 0xac00 # Hangul initial consonant, vowel, final consonant [c / 21 / 28, c / 28 % 21, c % 28] end end end def read_int s = "" while true ch = $stdin.getc case ch when /\d+/ then s << ch when /\s+/ then break else raise "Integer expected" end end s.to_i end STROKE_TABLE = [0,2,4,4,2,5,5,3,5,7,9,9,7,9,9,8,4,4,6,2,4,nil,3,4,3,4,4,nil] x, y, dx, dy, s = 0, 0, 0, 1, 0 ss = (0..27).map { [] } def (ss[21]).pop; shift; end # queue ss[27] = nil # extension protocol check_size = -> n do if ss[s].size >= n true else dx, dy = -dx, -dy false end end while true ic, vo, fc = code[y][x] case ic when 11 # null when 18 then exit # terminate when 3 then check_size[2] && (a, b = ss[s].pop, ss[s].pop; ss[s] << b + a) when 4 then check_size[2] && (a, b = ss[s].pop, ss[s].pop; ss[s] << b * a) when 2 then check_size[2] && (a, b = ss[s].pop, ss[s].pop; ss[s] << b / a) when 16 then check_size[2] && (a, b = ss[s].pop, ss[s].pop; ss[s] << b - a) when 5 then check_size[2] && (a, b = ss[s].pop, ss[s].pop; ss[s] << b % a) when 6 # pop if check_size[1] v = ss[s].pop case fc when 21 then puts v when 27 then print v.chr("UTF-8") end end when 7 # push case fc when 21 then ss[s] << read_int when 27 then ss[s] << $stdin.getc.ord else ss[s] << STROKE_TABLE[fc] end when 8 then check_size[1] && ss[s] << ss[s][s != 21 ? -1 : 0] # duplicate when 17 # swap if check_size[2] r = s != 21 ? (-2..-1) : (0..1) ss[s][r] = ss[s][r].reverse end when 9 then s = fc # select when 10 then check_size[1] && ss[fc] << ss[s].pop # transfer when 12 # compare check_size[2] && ss[fc] << (ss[s].pop <= ss[s].pop ? 1 : 0) when 14 # fork dx, dy = -dx, -dy if check_size[1] && ss[fc].pop != 0 end case vo when 0 then dx, dy = 1, 0 when 2 then dx, dy = 2, 0 when 4 then dx, dy = -1, 0 when 6 then dx, dy = -2, 0 when 8 then dx, dy = 0, -1 when 12 then dx, dy = 0, -2 when 13 then dx, dy = 0, 1 when 17 then dx, dy = 0, 2 when 18 then dy = -dy when 19 then dx, dy = -dx, -dy when 20 then dx = -dx end x, y = x + dx, y + dy end ================================================ FILE: vendor/ante.rb ================================================ #!/usr/bin/env ruby # encoding: utf-8 # # Copyright (c) 2013 Michael Dvorkin # # Ante is an esoteric programming language where all you've got is # a deck of cards. # # 95% of this code was developed on the way back from RubyConf 2013 # during 5-hour flight from Miami to San Francisco. # ### require "awesome_print" class Array def rank; self[0] end def suit; self[1] end def rank=(value); self[0] = value end def suit=(value); self[1] = value end end class Ante def initialize() @♦, @♥, @♠, @♣ = 0, 0, 0, 0 @line, @pc = 0, 0 @code, @labels = [], {} end def run(source) parse(source) ### ap @code; ap @labels while card = @code[@pc] @pc += 1 case card.rank when nil then newline(card) when "K" then jump(card) when "Q" then next when "J" then dump(card, :char) when 10 then dump(card) else assign(card) end end end def parse(source) lines = source.split("\n").map { |line| line.sub(/#.*$/, "").strip } ### ap lines # Turn source file into array of cards. Each card is 2-item # array of rank and suit. lines.each_with_index do |line, i| @code += [[ nil, i + 1 ]] # <-- Line number cards have nil rank. @code += line.scan(/(10|[2-9JQKA])([♦♥♠♣])/) end # A pass to convert ranks to Fixnum and extract labels. pc = 0 while card = @code[pc] pc += 1 if card.rank =~ /\d/ card.rank = card.rank.to_i elsif card.rank == "Q" queen = card.suit while @code[pc] && @code[pc].rank == "Q" && @code[pc].suit == card.suit queen += card.suit pc += 1 end @labels[queen] = pc end end end def newline(card) # puts "newline #{card}" @line = card.suit end def assign(card) # puts "assign #{card.inspect}" operands = remaining(card) expression(operands) end def jump(card) # puts "jump #{card.inspect}, pc: #{@pc.inspect}, #{@labels.inspect}" suit = card.suit while @code[@pc] && @code[@pc].rank == "K" && @code[@pc].suit == card.suit suit += card.suit @pc += 1 end if instance_variable_get("@#{suit[0]}") != 0 # puts "jumping to " << "Q#{suit[0]}" * suit.size if @labels[suit] @pc = @labels[suit] else exception("can't find " << "Q#{suit[0]}" * suit.size << " to go to") end end end def dump(card, char = nil) # puts "dump #{card.inspect} => " value = instance_variable_get("@#{card.suit}") if char if value.between?(0, 255) print value.chr else exception("character code #{value} is out of 0..255 range") end else print value end end # Fetch the rest of the assignment expression. def remaining(card) operands = [ card ] while card = @code[@pc] break if card.rank.nil? || card.rank.to_s =~ /[KQJ]/ operands += [ card ] @pc += 1 end ### ap "remaining: #{operands.inspect}" operands end def expression(operands) initial, target = operands.shift initial = instance_variable_get("@#{target}") if initial == "A" operands.each do |rank, suit| # puts "rank: #{rank.inspect}, suit: #{suit.inspect}" rank = instance_variable_get("@#{suit}") if rank == "A" case suit when "♦" then initial += rank when "♥" then initial *= rank when "♠" then initial -= rank when "♣" then if rank != 0 initial /= rank else exception("division by zero") end end end instance_variable_set("@#{target}", initial) # dump_registers end def exception(message) abort("Ante exception: #{message} on line #{@line} (pc:#{@pc})") end def dump_registers instance_variables.each do |i| puts " #{i}: " + instance_variable_get("#{i}").to_s if i.size == 2 end end end if ARGV[0] Ante.new.run(IO.read(ARGV[0], encoding: "UTF-8")) else puts "usage: ante filename.ante" end ================================================ FILE: vendor/bf.rb ================================================ code = File.read($*[0]).unpack("C*") data = [0] i = j = 0 while code[i] case code[i] when 60 # < j -= 1 when 62 # > j += 1 data[j] ||= 0 when 43 # + data[j] += 1 when 45 # - data[j] -= 1 when 91 # [ if data[j] == 0 d = 0 i += 1 until d == 0 && code[i] == 93 # ] case code[i] when 91 # [ d += 1 when 93 # ] d -= 1 end i += 1 end end when 93 # ] d = 0 i -= 1 until d == 0 && code[i] == 91 # [ case code[i] when 91 # [ d -= 1 when 93 # ] d += 1 end i -= 1 end next when 46 # . putc(data[j]) when 44 # , data[j] = $stdin.getc end i += 1 end ================================================ FILE: vendor/blc.rb ================================================ # Binary lambda calculus interpreter # # (C) Copyright 2014, 2015, Yusuke Endoh # License: MIT # # See in detail: http://tromp.github.io/cl/cl.html # BLC8 or not binary_mode = ARGV.empty? $stdout.sync = true # abstract syntax tree Var = -> v { [:var, v] } Abs = -> e { [:abs, e] } App = -> e1, e2 { [:app, e1, e2] } # bit stream current_byte, bit_offset = nil, 0 get_byte = -> do bit_offset = binary_mode ? 8 : 1 current_byte = $stdin.getbyte end get_bit = -> do get_byte[] if bit_offset == 0 bit_offset -= 1 current_byte ? current_byte[bit_offset] == 0 : false end # parse stack, acc = [:exp], nil until stack.empty? v = stack.pop acc = case v when :exp if get_bit[] stack << (get_bit[] ? :abs : :app1) << :exp nil else v = 0 v += 1 until get_bit[] Var[v] end when :abs then Abs[acc] when :app1 then stack << acc << :exp; nil else App[v, acc] # parsing two exps of app finished end end bit_offset = 0 # force to align bit offset # I/O cons = -> a, b { Abs[App[App[Var[0], a], b]] } bool = -> b { Abs[Abs[Var[b ? 1 : 0]]] } if binary_mode read = -> i { i > 0 ? cons[bool[get_bit[]], read[i - 1]] : bool[false] } in_ = [:in, -> { get_byte[] ? cons[read[8], in_] : bool[false] }] outc = 0 out0, out1 = [0, 1].map {|n| [:out, -> { outc = (2 * outc + n) & 255 }] } out0[2] = out1[2] = App[Var[0], cons[out0, out1]] outn = [:out, -> { putc(outc) }] out_ = outn[2] = App[Var[0], cons[cons[out0, out1], outn]] else in_ = [:in, -> { get_byte[] ? cons[bool[get_bit[]], in_] : bool[false] }] out0, out1 = [0, 1].map {|n| [:out, -> { print(n) }] } out_ = out0[2] = out1[2] = App[Var[0], cons[out0, out1]] end # eval-loop exp = App[Abs[out_], App[acc, in_]] env, stack = [], [[nil, nil]] while true case exp[0] when :var exp[1].times { env = env[2] } if env.frozen? valexp, valenv = env # already forced else # not forced yet stack.last << env exp, env = env[0], env[1] next end when :app stack << [exp[2], env] next exp = exp[1] when :abs valexp, valenv = exp[1], env when :in then next exp = exp[1][] when :out then exp[1][]; valexp, valenv = exp[2], env end env = stack.pop until env.size == 2 th = env.pop th[0] = valexp # force th[1] = valenv th.freeze end break unless env[0] exp = valexp env[2] = valenv end ================================================ FILE: vendor/dummy-wasi-runtime.c ================================================ #include #include #define/* f = ARGV[0] system("wasm2c", f, "-o", f + ".c", exception: true) system("gcc", "-DWASM_RT_MODULE_PREFIX=Z_" + File.basename(f, ".wasm").gsub(".", "Z2E"), "-o", "dummy-wasi-exec", f + ".c", __FILE__, "-include", f + ".h", "-lwasm-rt-impl", "-I.", exception: true) exec("./dummy-wasi-exec") __END__ */DUMMY #ifndef WASM_RT_ADD_PREFIX #define WASM_RT_PASTE_(x, y) x ## y #define WASM_RT_PASTE(x, y) WASM_RT_PASTE_(x, y) #define WASM_RT_ADD_PREFIX(x) WASM_RT_PASTE(WASM_RT_MODULE_PREFIX, x) #endif // This is a dummy WASI implementation based on wasm2c. // It supports only "wasi_snapshot_preview1.fd_write" for stdout. // This should be replaced if a proper WASI implementation // (such as wasmtime) becomes available. // // Usage: // ruby dummy-wasi-runtime.c foo.wasm u32 fd_write(u32 fd, u32 iovs, u32 iovsLen, u32 size) { if (fd != 1) abort(); u32 total_len = 0; u8 *mem = WASM_RT_ADD_PREFIX(Z_memory)->data; for (; iovsLen--; iovs += 8) { u32 ptr = *(u32*)&mem[iovs]; u32 len = *(u32*)&mem[iovs + 4]; fwrite(&mem[ptr], 1, len, stdout); total_len += len; } *(u32*)&mem[size] = total_len; return 0; } u32 (*Z_wasi_snapshot_preview1Z_fd_write)(u32, u32, u32, u32) = fd_write; int main() { WASM_RT_ADD_PREFIX(_init)(); WASM_RT_ADD_PREFIX(Z__start)(); WASM_RT_ADD_PREFIX(_free)(); return 0; } ================================================ FILE: vendor/false.rb ================================================ code = File.read($*[0]) stack = [] pos = 0 parse = ->(re) do m = code.match(re, pos) pos = m.end(0) - 1 m[1] end while code[pos] case code[pos] when /\d/ then s = parse[/(\d+)/]; stack << s.to_i when /[a-z]/ then stack << code[pos].to_sym when ?+ then a, b = stack.pop, stack.pop; stack << b + a when ?- then a, b = stack.pop, stack.pop; stack << b - a when ?* then a, b = stack.pop, stack.pop; stack << b * a when ?/ then a, b = stack.pop, stack.pop; stack << b / a when ?& then a, b = stack.pop, stack.pop; stack << b & a when ?| then a, b = stack.pop, stack.pop; stack << b | a when ?_ then stack << -stack.pop when ?~ then stack << ~stack.pop when ?= then a, b = stack.pop, stack.pop; stack << (b == a ? -1 : 0) when ?> then a, b = stack.pop, stack.pop; stack << (b > a ? -1 : 0) when ?% then stack.pop when ?$ then stack << stack.last when ?\\ then a, b = stack.pop, stack.pop; stack << a << b when ?@ then a, b, c = stack.pop, stack.pop, stack.pop; stack << b << a << c when ?O then a = stack.pop; stack << stack[-1 - a] when ?: then a, b = stack.pop, stack.pop; vars[a] = b when ?; then a = stack.pop; stack << vars[a] when ?. then print "%d" % stack.pop when ?, then print stack.pop.chr when ?^ then stack << $stdin.getc when ?B then $stdin.flush; $stdout.flush when ?" then s = parse[/"(.*?)"/]; print s when ?{ then s = parse[/\}/] when ?' then stack << code[pos += 1].ord when ?` then raise when ?[ stack << [:func, pos] m = code.match(/(?\[(\g|\{.*?\}|\".*?\"|[^\{\}\"\[\]])*\])/) pos = m.end(0) - 1 when ?] case npos = ret.pop when :det if stack.pop == 0 pos = ret.pop ret.pop; ret.pop else ret << :body pos = ret[-3] end when :body stack << :det pos = ret[-4] else pos = npos end when ?! then ret << pos; pos = stack.pop[1] when ?? tpos = stack.pop[1]; b = stack.pop; (ret << pos; pos = tpos) if b when ?# body = stack.pop[1] det = stack.pop[1] ret << det << body << pos << :det pos = det when /\A\s\z/ else raise "unknown symbol: %p" % code[pos] end pos += 1 end ================================================ FILE: vendor/golfscript.rb ================================================ #!/usr/bin/ruby #(c) Copyright 2008 Darren Smith. All Rights Reserved. $lb = [] class Gtype def go $stack<(rhs) @val<=>rhs.val end end class Gint < Gtype def initialize(i) @val = case i when true then 1 when false then 0 else;i end end def factory(a) Gint.new(a) end def to_gs Gstring.new(@val.to_s) end def to_int #for pack @val end def ginspect to_gs end def class_id; 0; end def coerce(b) [if b.class == Garray Garray.new([self]) elsif b.class == Gstring to_gs else #Gblock to_gs.to_s.compile end,b] end def ~ Gint.new(~@val) end def notop Gint.new(@val == 0) end '*/%<>'.each_byte{|i| eval'def %c(rhs) Gint.new(@val %c rhs.val) end'%[i,i] } def equalop(rhs) Gint.new(@val == rhs.val) end def question(b) Gint.new(@val**b.val) end def base(a) if Garray===a r=0 a.val.each{|i| r*=@val r+=i.val } Gint.new(r) else i=a.val.abs r=[] while i!=0 r.unshift Gint.new(i%@val) i/=@val end Garray.new(r) end end def leftparen Gint.new(@val-1) end def rightparen Gint.new(@val+1) end end class Garray < Gtype def initialize(a) @val = a || [] end def factory(a) Garray.new(a) end def to_gs @val.inject(Gstring.new("")){|s,i|s+i.to_gs} end def flatten #maybe name to_a ? # Garray.new(@val.inject([]){|s,i|s+case i # when Gstring then i.val # when Gint then [i] # when Garray then i.flatten.val # when Gblock then i.val # end # }) # end #use Peter Taylor's fix to avoid quadratic flatten times Garray.new(flatten_append([])) end def flatten_append(prefix) @val.inject(prefix){|s,i|case i when Gint then s<(b) if b.class == Gint factory(@val[[b.val,-@val.size].max..-1]) else Gint.new(@val>b.val) end end def sort factory(@val.sort) end def zip r=[] @val.size.times{|x| @val[x].val.size.times{|y| (r[y]||=@val[0].factory([])).val<<@val[x].val[y] } } Garray.new(r) end def ~ val end end class Gstring < Garray def initialize(a) @val=case a when NilClass then [] when String then a.unpack('C*').map{|i|Gint.new(i)} when Array then a when Garray then a.flatten.val end end def factory(a) Gstring.new(a) end def to_gs self end def ginspect factory(to_s.inspect) end def to_s @val.pack('C*') end def class_id; 2; end def coerce(b) if b.class == Gblock [to_s.compile,b] else b.coerce(self).reverse end end def question(b) if b.class == Gstring Gint.new(to_s.index(b.to_s)||-1) elsif b.class == Garray b.question(self) else Gint.new(@val.index(b)||-1) end end def ~ to_s.compile.go nil end end class Gblock < Garray def initialize(_a,_b=nil) @val=Gstring.new(_b).val @native = eval("lambda{#{_a}}") end def go @native.call end def factory(b) Gstring.new(b).to_s.compile end def class_id; 3; end def to_gs Gstring.new("{"+Gstring.new(@val).to_s+"}") end def ginspect to_gs end def coerce(b) b.coerce(self).reverse end def +(b) if b.class != self.class a,b=coerce(b) a+b else Gstring.new(@val+Gstring.new(" ").val+b.val).to_s.compile end end def *(b) if b.class == Gint b.val.times{go} else gpush b.val.first (b.val[1..-1]||[]).each{|i|$stack<','gpush a>b'.order var'!','gpush a.notop'.cc1 var'?','gpush a.question(b)'.order var'$','gpush (a.class==Gint ? $stack[~a.val] : a.sort)'.cc1 var',','gpush case a when Gint then Garray.new([*0...a.val].map{|i|Gint.new(i)}) when Gblock then a.select(gpop) when Garray then Gint.new(a.val.size) end'.cc1 var')','gpush a.rightparen'.cc1 var'(','gpush a.leftparen'.cc1 var'rand','gpush Gint.new(rand([1,a.val].max))'.cc1 var'abs','gpush Gint.new(a.val.abs)'.cc1 var'print','print a.to_gs'.cc1 var'if',"#{var'!'}.go;(gpop.val==0?a:b).go".cc2 var'do',"loop{a.go; #{var'!'}.go; break if gpop.val!=0}".cc1 var'while',"loop{a.go; #{var'!'}.go; break if gpop.val!=0; b.go}".cc2 var'until',"loop{a.go; #{var'!'}.go; break if gpop.val==0; b.go}".cc2 var'zip','gpush a.zip'.cc1 var'base','gpush b.base(a)'.cc2 '"\n":n; {print n print}:puts; {`puts}:p; {1$if}:and; {1$\if}:or; {\!!{!}*}:xor; '.compile.go code.compile.go gpush Garray.new($stack) 'puts'.compile.go ================================================ FILE: vendor/grass.rb ================================================ #!/usr/bin/ruby -Ku # # grass.rb - Grass interpreter # http://www.blue.sky.or.jp/grass/ # # Copyright (C) 2006, 2007 UENO Katsuhiro. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # History: # # 2007-10-02 # - Follow the latest changes of the definition of Grass. # 2007-09-20 # - First version. # require 'pp' class Grass RELEASE_DATE = '2007-10-02' class Error < StandardError ; end class RuntimeError < Error ; end class IllegalState < Error ; end Machine = Struct.new(:code, :env, :dump) class Value def char_code raise RuntimeError, "not a char" end def app(m, arg) raise RuntimeError, "app undefined" end end class Insn end class App < Insn def initialize(m, n) @m, @n = m, n end def eval(m) f, v = m.env[-@m], m.env[-@n] raise "out of bound" unless f and v f.app m, v end def pretty_print(q) q.text 'App' q.group(4, '(', ')') { q.seplist([@m,@n]) { |i| q.text "#{i}" } } end alias inspect pretty_print_inspect end class Abs < Insn def initialize(body) @body = body end def eval(m) m.env.push Fn.new(@body, m.env.dup) end def pretty_print(q) q.text 'Abs' q.group(4, '(', ')') { @body.pretty_print(q) } end alias inspect pretty_print_inspect end class Fn < Value def initialize(code, env) @code, @env = code, env end def app(m, arg) m.dump.push [m.code, m.env] m.code, m.env = @code.dup, @env.dup m.env.push arg end end ChurchTrue = Fn.new([Abs.new([App.new(3,2)])], [Fn.new([],[])]) ChurchFalse = Fn.new([Abs.new([])], []) class CharFn < Value def initialize(char_code) @char_code = char_code end attr_reader :char_code def app(m, arg) ret = @char_code == arg.char_code ? ChurchTrue : ChurchFalse m.env.push ret end end class Succ < Value def app(m, arg) m.env.push CharFn.new((arg.char_code + 1) & 255) end end class Out < Value def app(m, arg) $stdout.print arg.char_code.chr $stdout.flush m.env.push arg end end class In < Value def app(m, arg) ch = $stdin.getc ret = ch ? CharFn.new(ch) : arg m.env.push ret end end private def eval(m) while true insn = m.code.shift if insn then insn.eval m else break if m.dump.empty? ret = m.env.last raise IllegalState, "no return value" unless ret m.code, m.env = m.dump.pop m.env.push ret end end raise IllegalState, "illegal final machine state" unless m.env.size == 1 m.env.first end InitialEnv = [In.new, CharFn.new(?w.ord), Succ.new, Out.new] InitialDump = [[[], []], [[App.new(1, 1)], []]] def start(code) eval Machine.new(code, InitialEnv, InitialDump) end def parse(src) code = [] src = src.sub(/\A[^ww]*/, '').gsub(/[^wwWWvv]/, '') src.split(/[vv]+/).each { |s| a = s.scan(/[ww]+|[WW]+/).map { |i| i.split(//).size } arity = 0 arity = a.shift if /\A[ww]/ =~ s raise "parse error at app" unless a.size % 2 == 0 body = [] 0.step(a.size - 1, 2) { |i| body.push App.new(a[i], a[i+1]) } insn = (0...arity).inject(body) { |body,| [Abs.new(body)] } code.concat insn } code end public def run(src) start parse(src) end end if $0 == __FILE__ then $stderr.puts "Grass #{Grass::RELEASE_DATE}" if $VERBOSE Grass.new.run $<.read end # Local Variables: # coding: utf-8 # End: ================================================ FILE: vendor/lazyk.c ================================================ /* * Lazy K interpreter * * Copyright 2008 irori * This code is licensed under the MIT License (see LICENSE file for details). */ #include #include #include #include #include #include #include #include #define VERSION "1.0.0" #define INITIAL_HEAP_SIZE 128*1024 #define RDSTACK_SIZE 100000 // Verbosity levels enum { V_NONE, V_STATS, V_GC, } verbosity = V_NONE; /********************************************************************** * Storage management **********************************************************************/ /* TAG STRUCTURE * * -------- -------- -------- ------00 Pair * -------- -------- -------- ------01 Int * -------- -------- -------- ------10 Combinator * -------- -------- -------- -----011 Character * -------- -------- -------- -----111 Miscellaneous */ struct tagPair; typedef struct tagPair *Cell; #define CELL(x) ((Cell)(x)) #define TAG(c) ((intptr_t)(c) & 0x03) /* pair */ typedef struct tagPair { Cell car; Cell cdr; } Pair; #define ispair(c) (TAG(c) == 0) #define car(c) ((c)->car) #define cdr(c) ((c)->cdr) #define SET(c,fst,snd) ((c)->car = (fst), (c)->cdr = (snd)) /* integer */ #define isint(c) (TAG(c) == 1) #define mkint(n) CELL(((n) << 2) + 1) #define intof(c) ((intptr_t)(c) >> 2) /* combinator */ #define iscomb(c) (TAG(c) == 2) #define mkcomb(n) CELL(((n) << 2) + 2) #define combof(c) ((intptr_t)(c) >> 2) #define COMB_S mkcomb(0) #define COMB_K mkcomb(1) #define COMB_I mkcomb(2) #define COMB_IOTA mkcomb(3) #define COMB_KI mkcomb(4) #define COMB_READ mkcomb(5) #define COMB_WRITE mkcomb(6) #define COMB_INC mkcomb(7) #define COMB_CONS mkcomb(8) /* character */ #define ischar(c) (((intptr_t)(c) & 0x07) == 0x03) #define mkchar(n) CELL(((n) << 3) + 0x03) #define charof(c) ((intptr_t)(c) >> 3) /* immediate objects */ #define isimm(c) (((intptr_t)(c) & 0x07) == 0x07) #define mkimm(n) CELL(((n) << 3) + 0x07) #define NIL mkimm(0) #define COPIED mkimm(1) #define UNUSED_MARKER mkimm(2) Pair *heap_area, *free_ptr; int heap_size, next_heap_size; double total_gc_time = 0.0; void gc_run(Cell *save1, Cell *save2); void rs_copy(void); Cell copy_cell(Cell c); void errexit(char *fmt, ...) { va_list arg; va_start(arg, fmt); vfprintf(stderr, fmt, arg); va_end(arg); exit(1); } void storage_init(int size) { heap_size = size; heap_area = malloc(sizeof(Pair) * heap_size); if (heap_area == NULL) errexit("Cannot allocate heap storage (%d cells)\n", heap_size); assert(((intptr_t)heap_area & 3) == 0 && (sizeof(Pair) & 3) == 0); free_ptr = heap_area; heap_area += heap_size; next_heap_size = heap_size * 3 / 2; } Cell pair(Cell fst, Cell snd) { Cell c; if (free_ptr >= heap_area) gc_run(&fst, &snd); assert(free_ptr < heap_area); c = free_ptr++; car(c) = fst; cdr(c) = snd; return c; } Cell alloc(int n) { Cell p; if (free_ptr + n > heap_area) gc_run(NULL, NULL); assert(free_ptr + n <= heap_area); p = free_ptr; free_ptr += n; return p; } void gc_run(Cell *save1, Cell *save2) { static Pair* free_area = NULL; int num_alive; Pair *scan; clock_t start = clock(); if (free_area == NULL) { free_area = malloc(sizeof(Pair) * next_heap_size); if (free_area == NULL) errexit("Cannot allocate heap storage (%d cells)\n", next_heap_size); } free_ptr = scan = free_area; free_area = heap_area - heap_size; heap_area = free_ptr + next_heap_size; rs_copy(); if (save1) *save1 = copy_cell(*save1); if (save2) *save2 = copy_cell(*save2); while (scan < free_ptr) { car(scan) = copy_cell(car(scan)); cdr(scan) = copy_cell(cdr(scan)); scan++; } num_alive = free_ptr - (heap_area - next_heap_size); if (verbosity >= V_GC) fprintf(stderr, "GC: %d / %d\n", num_alive, heap_size); if (heap_size != next_heap_size || num_alive * 8 > next_heap_size) { heap_size = next_heap_size; if (num_alive * 8 > next_heap_size) next_heap_size = num_alive * 8; free(free_area); free_area = NULL; } total_gc_time += (clock() - start) / (double)CLOCKS_PER_SEC; } Cell copy_cell(Cell c) { Cell r; if (!ispair(c)) return c; if (car(c) == COPIED) return cdr(c); r = free_ptr++; car(r) = car(c); if (car(c) == COMB_I) { Cell tmp = cdr(c); while (ispair(tmp) && car(tmp) == COMB_I) tmp = cdr(tmp); cdr(r) = tmp; } else cdr(r) = cdr(c); car(c) = COPIED; cdr(c) = r; return r; } /********************************************************************** * Reduction Machine **********************************************************************/ typedef struct { Cell *sp; Cell stack[RDSTACK_SIZE]; } RdStack; RdStack rd_stack; void rs_init(void) { int i; rd_stack.sp = rd_stack.stack + RDSTACK_SIZE; for (i = 0; i < RDSTACK_SIZE; i++) rd_stack.stack[i] = UNUSED_MARKER; } void rs_copy(void) { Cell *c; for (c = rd_stack.stack + RDSTACK_SIZE - 1; c >= rd_stack.sp; c--) *c = copy_cell(*c); } int rs_max_depth(void) { int i; for (i = 0; i < RDSTACK_SIZE; i++) { if (rd_stack.stack[i] != UNUSED_MARKER) break; } return RDSTACK_SIZE - i; } void rs_push(Cell c) { if (rd_stack.sp <= rd_stack.stack) errexit("runtime error: stack overflow\n"); *--rd_stack.sp = c; } #define TOP (*rd_stack.sp) #define POP (*rd_stack.sp++) #define POP_ (rd_stack.sp++) #define PUSH(c) rs_push(c) #define PUSHED(n) (*(rd_stack.sp+(n))) #define DROP(n) (rd_stack.sp += (n)) #define ARG(n) cdr(PUSHED(n)) #define APPLICABLE(n) (bottom - rd_stack.sp > (n)) /********************************************************************** * Loader **********************************************************************/ Cell read_one(FILE *fp, int i_is_iota); Cell read_many(FILE *fp, int closing_char); Cell load_program(const char *fname) { FILE *fp; Cell c; if (fname == NULL) fp = stdin; else { fp = fopen(fname, "r"); if (fp == NULL) errexit("cannot open %s\n", fname); } c = read_many(fp, EOF); if (fname != NULL) fclose(fp); return c; } int next_char(FILE *fp) { int c; do { c = fgetc(fp); if (c == '#') { while (c = fgetc(fp), c != '\n' && c != EOF) ; } } while (isspace(c)); return c; } Cell read_many(FILE *fp, int closing_char) { int c; Cell obj; c = next_char(fp); if (c == closing_char) return COMB_I; ungetc(c, fp); PUSH(read_one(fp, 0)); while ((c = next_char(fp)) != closing_char) { ungetc(c, fp); obj = read_one(fp, 0); obj = pair(TOP, obj); TOP = obj; } return POP; } Cell read_one(FILE *fp, int i_is_iota) { int c; Cell obj; c = next_char(fp); switch (c) { case '`': case '*': PUSH(read_one(fp, c == '*')); obj = read_one(fp, c == '*'); obj = pair(TOP, obj); POP_; return obj; case '(': obj = read_many(fp, ')'); return obj; case 's': case 'S': return COMB_S; case 'k': case 'K': return COMB_K; case 'i': return i_is_iota ? COMB_IOTA : COMB_I; case 'I': return COMB_I; case '0': case '1': { obj = COMB_I; do { if (c == '0') obj = pair(pair(obj, COMB_S), COMB_K); else obj = pair(COMB_S, pair(COMB_K, obj)); c = next_char(fp); } while (c == '0' || c == '1'); ungetc(c, fp); return obj; } case EOF: errexit("parse error: unexpected EOF\n"); return NULL; default: errexit("parse error: %c\n", c); return NULL; } } /********************************************************************** * Reducer **********************************************************************/ int reductions; void eval(Cell root) { Cell *bottom = rd_stack.sp; PUSH(root); for (;;) { while (ispair(TOP)) PUSH(car(TOP)); if (TOP == COMB_I && APPLICABLE(1)) { /* I x -> x */ POP_; TOP = cdr(TOP); } else if (TOP == COMB_S && APPLICABLE(3)) { /* S f g x -> f x (g x) */ Cell a = alloc(2); SET(a+0, ARG(1), ARG(3)); /* f x */ SET(a+1, ARG(2), ARG(3)); /* g x */ DROP(3); SET(TOP, a+0, a+1); /* f x (g x) */ } else if (TOP == COMB_K && APPLICABLE(2)) { /* K x y -> I x */ Cell x = ARG(1); DROP(2); SET(TOP, COMB_I, x); TOP = cdr(TOP); /* shortcut reduction of I */ } else if (TOP == COMB_IOTA && APPLICABLE(1)) { /* IOTA x -> x S K */ Cell xs = pair(ARG(1), COMB_S); POP_; SET(TOP, xs, COMB_K); } else if (TOP == COMB_KI && APPLICABLE(2)) { /* KI x y -> I y */ DROP(2); car(TOP) = COMB_I; } else if (TOP == COMB_CONS && APPLICABLE(3)) { /* CONS x y f -> f x y */ Cell fx, y; fx = pair(ARG(3), ARG(1)); y = ARG(2); DROP(3); SET(TOP, fx, y); } else if (TOP == COMB_READ && APPLICABLE(2)) { /* READ NIL f -> CONS CHAR(c) (READ NIL) f */ intptr_t c = getchar(); Cell a = alloc(2); SET(a+0, COMB_CONS, mkchar(c == EOF ? 256 : c)); SET(a+1, COMB_READ, NIL); POP_; SET(TOP, a+0, a+1); } else if (TOP == COMB_WRITE && APPLICABLE(1)) { /* WRITE x -> putc(eval((car x) INC NUM(0))); WRITE (cdr x) */ Cell a = alloc(3); SET(a+0, ARG(1), COMB_K); /* (car x) */ SET(a+1, a+0, COMB_INC); /* (car x) INC */ SET(a+2, a+1, mkint(0)); /* (car x) INC NUM(0) */ POP_; eval(a+2); if (!isint(TOP)) errexit("invalid output format (result was not a number)\n"); if (intof(TOP) >= 256) return; putchar(intof(TOP)); POP_; a = pair(cdr(TOP), COMB_KI); cdr(TOP) = a; } else if (TOP == COMB_INC && APPLICABLE(1)) { /* INC x -> eval(x)+1 */ Cell c = ARG(1); POP_; eval(c); c = POP; if (!isint(c)) errexit("invalid output format (attempted to apply inc to a non-number)\n"); SET(TOP, COMB_I, mkint(intof(c) + 1)); } else if (ischar(TOP) && APPLICABLE(2)) { intptr_t c = charof(TOP); if (c <= 0) { /* CHAR(0) f z -> z */ Cell z = ARG(2); DROP(2); SET(TOP, COMB_I, z); } else { /* CHAR(n+1) f z -> f (CHAR(n) f z) */ Cell a = alloc(2); Cell f = ARG(1); SET(a+0, mkchar(c-1), f); /* CHAR(n) f */ SET(a+1, a+0, ARG(2)); /* CHAR(n) f z */ DROP(2); SET(TOP, f, a+1); /* f (CHAR(n) f z) */ } } else if (isint(TOP) && APPLICABLE(1)) errexit("invalid output format (attempted to apply a number)\n"); else return; reductions++; } } void eval_print(Cell root) { eval(pair(COMB_WRITE, pair(root, pair(COMB_READ, NIL)))); } /********************************************************************** * Main **********************************************************************/ void help(const char *progname) { printf("Usage: %s [options] sourcefile\n", progname); printf(" -h print this help and exit\n"); printf(" -u disable stdout buffering\n"); printf(" -v print version and exit\n"); printf(" -v[0-2] set verbosity level (default: 0)\n"); } int main(int argc, char *argv[]) { Cell root; clock_t start; char *prog_file = NULL; int i; for (i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == 'v' && isdigit(argv[i][2])) { verbosity = argv[i][2] - '0'; } else if (strcmp(argv[i], "-h") == 0) { help(argv[0]); return 0; } else if (strcmp(argv[i], "-u") == 0) { setbuf(stdout, NULL); } else if (strcmp(argv[i], "-v") == 0) { printf("Lazy K interpreter " VERSION " by irori\n"); return 0; } else if (argv[i][0] == '-') { fprintf(stderr, "bad option %s (Try -h for more information).\n", argv[i]); return 1; } else { prog_file = argv[i]; } } storage_init(INITIAL_HEAP_SIZE); rs_init(); root = load_program(prog_file); start = clock(); eval_print(root); if (verbosity >= V_STATS) { double evaltime = (clock() - start) / (double)CLOCKS_PER_SEC; printf("\n%d reductions\n", reductions); printf(" total eval time --- %5.2f sec.\n", evaltime - total_gc_time); printf(" total gc time --- %5.2f sec.\n", total_gc_time); printf(" max stack depth --- %d\n", rs_max_depth()); } return 0; } ================================================ FILE: vendor/ook-to-bf.rb ================================================ RE = /\G(?:\s*Ook(?.)\s*Ook(?.)|(?)\s*\z|(?))/ T = { ".?" => ">", "?." => "<", ".." => "+", "!!" => "-", ".!" => ",", "!." => ".", "!?" => "[", "?!" => "]", } if $*.size != 2 $stderr.puts "usage: #$0 in.ook out.bf" exit 1 end c = "" File.read($*[0]).scan(RE) do if $~[:c1] c << T[$~[:c1] + $~[:c2]] elsif $~[:error] raise "Ook? Ook? Ook?" end end File.write($*[1], c) ================================================ FILE: vendor/subleq.rb ================================================ IN_ADDR = -1 OUT_ADDR = -1 mem = File.read(ARGV[0]).split.map do |v| if v.start_with?(?#) case v when "#IN" then IN_ADDR when "#OUT" then OUT_ADDR else raise "Unresolved register: #{ v }" end else v.to_i end end ip = 0 while 0 <= ip && ip < mem.size a, b, c = mem[ip], mem[ip + 1], mem[ip + 2] ip += 3 if a == IN_ADDR ma = -($stdin.getc || -1).ord else ma = mem[a] end if b == OUT_ADDR putc ma else mb = mem[b] -= ma ip = c if mb <= 0 end end ================================================ FILE: vendor/thue.rb ================================================ RE = /^\s*::=.*\n(?(?m:.*))|^(?.+?)::=(?.*)$/ rules, body = {}, "" File.binread($*[0]).scan(RE) do $~[:lhs] ? rules[$~[:lhs]] = $~[:rhs] : body = $~[:body].delete("\n") end loop do #puts body targets = [] rules.each do |lhs, rhs| pos = 0 while npos = body.index(lhs, pos) targets << [npos, lhs, rhs] pos = npos + 1 end end break if targets.empty? pos, lhs, rhs = targets.sample case rhs when ":::" then rhs = gets when /^~/ then print $'; rhs = "" end body[pos, lhs.size] = rhs end ================================================ FILE: vendor/unlambda.rb ================================================ tokens = [] File.read($*[0]).scan(/\.(?.)|(?[r`ikscd])|#.*/) do if $~[:out] tokens << [:o, $~[:out]] elsif $~[:insn] case $~[:insn] when ?r then tokens << [:o, ?\n] when ?` then tokens << :a else tokens << $~[:insn].to_sym end end end tokens.reverse! stack = [nil, :S] acc = nil while stack stack, cmd = stack acc = if cmd == :S stack = [stack, acc] if acc insn, arg = tokens.pop case insn when :o then [:o, arg] when :a then stack = [[stack, :S], :S]; nil when nil then raise "EOF" else [insn] end else [:a, cmd, acc] end end stack = [nil, :E, acc] acc = nil while stack stack, cmd, cls = stack acc = if cmd == :E if acc && acc[0] == :d [:d1, cls] else stack = [stack, :A, acc] if acc cls[0] == :a ? (stack = [[stack, :E, cls[2]], :E, cls[1]]; nil) : cls end else type, x, y = cls case type when :o then print x; acc when :i then acc when :k then [:k1, acc] when :k1 then x when :s then [:s1, acc] when :s1 then [:s2, x, acc] when :s2 then stack = [stack, :E, [:a, [:a, x, acc], [:a, y, acc]]]; nil when :c then stack = [stack, :A, acc]; [:c1, stack[0]] when :c1 then stack = x; acc when :d then acc when :d1 then stack = [stack, :E, [:a, x, acc]]; nil end end end ================================================ FILE: vendor/wasi-runtime.js ================================================ 'use strict'; const fs = require('fs'); const { WASI } = require('wasi'); const wasi = new WASI({ version: "preview1" }); const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; (async () => { const wasm = await WebAssembly.compile(fs.readFileSync(process.argv[2])); const instance = await WebAssembly.instantiate(wasm, importObject); wasi.start(instance); })(); ================================================ FILE: vendor/whitespace.rb ================================================ RE = /\G(?[01]+){0}(?[01]*){0} ( 00 (? )\g2 | 010 (? )\g2 | 012 (?)\g2 | 020 (?) | 021 (?) | 022 (?) | 1000(?) | 1001(?) | 1002(?) | 1010(?) | 1011(?) | 110 (?) | 111 (?) | 1200(?) | 1201(?) | 1210(?) | 1211(?) | 200 (?)\g2 | 201 (?)\g2 | 202 (?)\g2 | 210 (?)\g2 | 211 (?)\g2 | 212 (?) | 222 (?) | (?)\z | (?) )/x names = RE.names.map {|n| n.to_sym } - [:num, :label] code, labels = [], {} File.read($*[0]).gsub(/[^ \t\n]/m, "").tr(" \t\n", "012").scan(RE) do insn = names.find {|n| $~[n] } arg = $~[:num] arg = arg[1..-1].to_i(2) * (arg[0] == ?0 ? 1 : -1) if arg arg = $~[:label] if $~[:label] raise "Unrecognised input" if insn == :error insn == :mark ? labels[arg] = code.size : code << [insn, arg] end def read_int s = "" while true ch = $stdin.getc case ch when /\d+/ then s << ch when /\s+/ then break else raise "Integer expected" end end s.to_i end pc, call, stack, heap = 0, [], [], Hash.new(0) loop do insn, arg = code[pc] pc += 1 case insn when :push then stack << arg when :dup then stack << stack.last when :copy then stack << stack[-arg - 1] when :slide then n = stack.pop; stack.pop(arg); stack << n when :swap then n = stack.pop; m = stack.pop; stack << n << m when :pop then stack.pop when :add then n = stack.pop; stack << stack.pop + n when :sub then n = stack.pop; stack << stack.pop - n when :mul then n = stack.pop; stack << stack.pop * n when :div then n = stack.pop; stack << stack.pop / n when :mod then n = stack.pop; stack << stack.pop % n when :set then n = stack.pop; heap[stack.pop] = n when :get then stack << heap[stack.pop] when :outc then putc stack.pop when :readc then heap[stack.pop] = $stdin.getc.ord when :outn then print stack.pop when :readn then heap[stack.pop] = read_int when :call then call << pc; pc = labels[arg] when :jump then pc = labels[arg] when :jz then pc = labels[arg] if stack.pop == 0 when :jn then pc = labels[arg] if stack.pop < 0 when :ret then pc = call.pop when :end then break when :eof then raise("Reached EOF") end end