Programming Languages Through The Years

2013 - Dogescript

Dogescript is a language created in 2013 by Zach Bruggeman. It is nothing more than a syntax-replacement for Javascript to make it read like the internal monologues of memetic Shiba Inus.

Hello doge

console dose loge with "Dogescript was made in 2013!"

ASCII Art

such N much N
          much i as 0 next i smaller N next i more 1
              very doge is ("N" + " ".repeat(N-2) + "N").split('')
              s[i] is "N";
              console dose loge with doge.join('')
                              wow
                                      wow

GCD

such gcd_doge much doge, dooge
    rly dooge
              gcd_doge(dooge, doge % dooge)
  but
    rly doge smaller 0
           -doge
    but
          doge
  wow
        wow

2015 - Retina

Retina is a regex-based programming language, which I wrote to be able to compete in PPCG challenges with regex-only answers, without having the unnecessary overhead of calling the regex in some host language. Retina is Turing-complete. To prove it I've implemented a 2-tag system solver as well as Rule 110. It is written in C#, hence it supports both the .NET flavour (by default) and the ECMAScript flavour (via a flag).

Retina can operate in multiple modes, but the most relevant one for computations (and the Turing-complete one) is Replace mode. In Replace mode you give Retina an even number of source files. These are then paired, the first of each pair being a regex, and the second a replacement. These are then executed in order, manipulating the input step by step. The regex can also be preceded by a configuration (delimited with `). The most important option (which makes Retina Turing-complete) is +, which makes Retina apply the replacement in a loop until the result stops changing. In the following examples, I'm also using ;, which suppresses output on intermediate stages.

In each of the following submissions, each line goes in a separate source file. (Alternatively, you can use the new -s option and put all lines into a single file.) Empty files/lines are represented as <empty>. Files/lines containing a single space are represented as <space>.

The explanations are quite long, so I've moved them to the end of the post.

The Programs

"Hello, World!" Variant

<empty>
Retina was made in 2015!

ASCII Art N

This assumes that STDIN is terminated with a newline.

;`^
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
N
;`.(?<=(?=(.*\n)).*)|\n
$1
;`N(?=N\n.*\n.*\n`$)
<space>
;+`N(?=.?(.)+\n.* (?<-1>.)+(?(1)!)\n)
<space>
;`(?<=^.*\n.*\nN)N
S
;+`(?<=\n(?(1)!)(?<-1>.)+S.*\n(.)+N?)N
S
S
<space>

GCD

This requires that STDIN is not terminated with a newline.

;`\b(?=\d)
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
1
;`^(.+)\1* \1+$
$1
;`$
#:0123456789
;+`^(?=1)(1*)\1{9}(#(?=.*(0))|1#(?=.*(?<3>1))|11#(?=.*(?<3>2))|111#(?=.*(?<3>3))|1111#(?=.*(?<3>4))|11111#(?=.*(?<3>5))|111111#(?=.*(?<3>6))|1111111#(?=.*(?<3>7))|11111111#(?=.*(?<3>8))|111111111#(?=.*(?<3>9)))
$1#$3
#|:.*
<empty>

Explanations

"Hello, World!" Variant

This is fairly trivial. It takes no input (i.e. an empty string), matches nothing and replaces it with Retina was made in 2015!. One can also make it work for arbitrary input, by replacing the pattern with [\s\S]* for instance. That would slurp STDIN and replace all of it with the output.

ASCII Art N

This has quite a lot of stages. The idea is to convert the input to unary, create an N x N block of Ns and then "carve out" two triangles. Let's go through the individual stages. Remember that ; merely suppresses intermediate outputs, but + causes the replacement to be applied in a loop.

;`^
#

Simple: prepend a # to the input. This will be used as a marker in the conversion to unary.

;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#

This converts one digit to unary. It takes the digits already converted (\d*) and repeats them 10 times. And then it takes the next digit and appends the appropriate number of digits. The actual value of the digits is irrelevant at this stage. When the # reaches the end of the number, the regex no longer matches, and the conversion is done. As an example, the number 127 will be processed as

#127
1#27
111111111122#7
1111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111221111111111227777777#

where the last line contains exactly 127 digit characters.

;`#
<empty>
;`\d
N

Two simple stages which get rid of that # and then convert all the digits to N. In the following I'll use input 7 as an example. So now we've got

NNNNNNN

The next stage

;`.(?<=(?=(.*\n)).*)|\n
$1

replaces each N with the entire string (remember that it contains a trailing newline), and also removes the trailing newline itself. Hence, this turns the single row into a square grid:

NNNNNNN
NNNNNNN   
NNNNNNN
NNNNNNN
NNNNNNN
NNNNNNN
NNNNNNN

Now the upper triangle. First, we start things off by turning the N in the lower right corner into a space:

;`N(?=N\n.*\n.*\n`$)
<space>

The lookahead ensures that we're modifying the correct N. This gives

NNNNNNN
NNNNNNN   
NNNNNNN
NNNNNNN
NNNNN N
NNNNNNN
NNNNNNN

And now

;+`N(?=.?(.)+\n.* (?<-1>.)+(?(1)!)\n)
<space>

is a regex which matches an N which is above or at the top left corner of a space character, and replaces it with a space. Because the replacement is repeated, this is essentially a flood-fill, which turns the 3rd octant from the initial space into more spaces:

N     N
NN    N   
NNN   N
NNNN  N
NNNNN N
NNNNNNN
NNNNNNN

And finally, we repeat the same thing with the bottom triangle, but we use a different character, so the already existing spaces don't cause a wrong flood fill:

;`(?<=^.*\n.*\nN)N
S

sets the seed:

N     N
NN    N   
NSN   N
NNNN  N
NNNNN N
NNNNNNN
NNNNNNN

Then

;+`(?<=\n(?(1)!)(?<-1>.)+S.*\n(.)+N?)N
S

does the flood-fill.

N     N
NN    N   
NSN   N
NSSN  N
NSSSN N
NSSSSNN
NSSSSSN

And finally

S
<space>

Turns those S into spaces and we're done:

N     N
NN    N   
N N   N
N  N  N
N   N N
N    NN
N     N

GCD

GCD in unary is actually very trivial with regex. Most of this consists of the decimal to unary and unary to decimal conversion. This could be done more compactly, but this isn't a code golf, so...

;`\b(?=\d)
#
;+`(\d*)#(?:(((((((((9)|8)|7)|6)|5)|4)|3)|2)|1)|0)
$1$1$1$1$1$1$1$1$1$1$2$3$4$5$6$7$8$9$10#
;`#
<empty>
;`\d
1

These stages are essentially the same as above, except that both input numbers are converted, and the result uses 1s instead of Ns (not that it matters). So if the input was 18 24, then this would produce

111111111111111111 111111111111111111111111

Now

;`^(.+)\1* \1+$
$1

is the entire GCD computation. We match a common divisor by capturing a number of 1s, and then using backreferences to ensure that both numbers can be written by repeating that string (and nothing else). Due to how backtracking works in the regex engine (i.e. that .+ is greedy), this will always yield the greatest common divisor automatically. Since the match covers the entire string, we simply write back the first capturing group to get our GCD.

Finally, the unary to decimal conversion...

;`$
#:0123456789

Append a marker #, a delimiter : and all digits to the string. This is necessary, because you can't produce new characters conditionally in a regex replacement. If you want conditional replacement, you need to pull the characters from the string itself, so we put them there.

;+`^(?=1)(1*)\1{9}(#(?=.*(0))|1#(?=.*(?<3>1))|11#(?=.*(?<3>2))|111#(?=.*(?<3>3))|1111#(?=.*(?<3>4))|11111#(?=.*(?<3>5))|111111#(?=.*(?<3>6))|1111111#(?=.*(?<3>7))|11111111#(?=.*(?<3>8))|111111111#(?=.*(?<3>9)))
$1#$3

This is the inverse of the unary expansion earlier. We find the largest multiple of 10 that fits into the current string. Then we choose the next digit based on the remainder, and divide the multiple by 10, while moving the marker through the digits.

#|:.*
<empty>

And lastly just a cleanup step to get rid of the marker, delimiter and the helper digits.


2013 - Snap!

Snap! is a language based on Scratch, made at Berkeley University. It is an upgrade to Scratch featuring first-class data and custom blocks (functions). Like Scratch, it is not text based, but rather done by visual "blocks" that snap together.

Snap!, written in JavaScript, is the successor to BYOB, which was written in Squeak Smalltalk. Snap! was beta released for public consumption in March 2013.

Snap! is actually not an esoteric language. It is used as the programming language for the Beauty and Joy of Computing (BJC) AP CS course at Berkeley and others.

I helped out with testing and stuff.

"Hello World" variant

ASCII Art "N"

enter image description here

This uses the stdlib for some of the blocks.

Pretty basic looping here. Takes an input. Then we just add it all together and say it (result for n=5):

enter image description here

I took the liberty here to just use 2 spaces instead of 1, because Snap! doesn't say stuff in monospace.

GCD

The Euclidean algorithm isn't very fast, but it works, and is pretty simple. (Sorry, i made a typo in the block name. Now i closed the tab without saving. It'll just have to stay.)

enter image description here

This function definition will then produce this block:

enter image description here