I probably should have written this yesterday, but inspiration strikes at odd moments.
Announcing the new language - Lovecraft. It is inspired by the writings of the famous horror author HP Lovecraft, to maximize the thrill of programming.
Here’s the structure:
- The basic semantic structure is Ruby-like, but only in appearance. Its true nature is far more sinister.
- Lovecraft is, of course, interpreted. And, most importantly, in the past tense.
- You start with a number of threads, as many as you choose to allocate. Lovecraft is a highly concurrent language. The first one is the “Judge”, responsible for managing the rest. However, you can’t ever increase your threads - they will only decrease over time.
- Note that you don’t have to call it the Judge - you can also call it the Magistrate, the Investigator, the Governor, the Constable, the Examiner or the Sherrif - your choice.
- Once a Lovecraft program starts, it will only end badly.
- If a Lovecraft program “reaches the end” it will automatically start back at the beginning, possibly with fewer threads (see below)
- The only variable type is String. And all Strings are automatically encoded in an ancient language (EBCDIC) each time they are set or adjusted. You must run the decoder each time you want to do anything with the String. Note that any errors in the decoding process will cause the contents of the String to become randomized, the various characters leaping into each others’ spaces, combining and separating in a bizarre and apparently random manner.
- Strings are delimited by quotes, but you cannot use quotes inside a string. That would require an escape character, and there is no escape in Lovecraft
- The only logical operator in Lovecraft is the “if_only…alas” operator as in:
- if_only x equaled “5″ i_could_end_this_madness() alas
- There are no For loops, While, Do While or other looping constructs, other than Goto
- The entropic madness of an uncaring and soulless universe causes your variables to “decay” over time, becoming statistically less likely to contain the correct answer the longer the program runs, and the more often you access the variables.
- Note that each character in the String will degrade independently, and the probability of decay is uniform across the length of the String.
- Introspection, or any attempt to debug the variables significantly increases the chance that the variable will decay
- If you no longer need a variable, you can WasSacrificed() it. (Note the use of the past tense). Note also that, unusually, the variable name comes before the command:
- if_only x did_not_equal “42″
- x WasSacrificed()
- alas
- Note also that the more variables you sacrifice, the more entropy will be added to the overall program, increasing the likelihood that other variables will decay, so use WasSacrificed carefully!
- Inevitably, your threads will stop operating properly as the variables decay into meaningless garbage. It is possible for the Judge thread to mark another thread as insane in order to stop it from running. However, as I noted previously, you cannot create new threads - you must continue on with the remaining threads you have. Note also that there is no definitive test of whether a thread is insane or not - the “Judge/Magistrate/Examiner/etc” must evaluate the thread and make a judgement based on its own, possibly unstable state.
- At some point, the threads of sanity will be exhausted, and your program, lurching about erratically, spouting gibberish in EBCDIC must be WasCommited(). Committing a program does not end it - it merely leaves it forlorn and alone, occupying a small cell in your computer’s memory until such day as the great User decides to terminate its Universe forever.
Thank you for making my morning
Comment by Ammon Lauritzen — November 1, 2006 @ 4:26 pm
Yeah, it made my morning too
Comment by jb — November 1, 2006 @ 4:42 pm
Finding a programmer must be difficult - and I suppose the only place to learn is in dreams of deserted cities of a cyclopean nature …
Comment by drk — November 1, 2006 @ 8:54 pm
Brillant!
Comment by phrakture — November 1, 2006 @ 9:47 pm
Wonderful - really gives new meaning to the term “hanging on by a thread”.
Comment by Cam — November 2, 2006 @ 12:57 pm
Now, on what blasphemous, alien hardware will such ghastly code run? I feel a strange lure here, though my rational senses are aching for a way to escape. But there is none, as you so eloquently stated. As others exclaimed: wonderful!
Comment by Niklas — November 2, 2006 @ 8:43 pm
Heh. VAX/VMS.
Comment by jb — November 2, 2006 @ 9:14 pm
Sounds like the effects of using Lovecraft will be similar to the effects of letting novice users loose with Aspects in a large Java app.
Comment by Kevin Barnes — November 3, 2006 @ 1:10 am
Genius!
Is there any chance that you could write a program in this? LOL
Comment by Maeve — January 17, 2007 @ 5:00 am
# Lovecraft (in) Execution
# By Jack 2007
# Some notes
# was and was it equals the equal(=) sign
# += adds to the left side
# We need to run… includes human_velocity for example
IMPORT Vectors
# And a trail of bodies was layed before thee…
class Body, implemented a Thread
def called(name,velocity=human_velocity)
@name was name
@velocity was velocity
end
def talk(to,message)
to.sayBy(me,message)
end
def friendOf(who,metAt)
@a_friend_of += who
@met_at = metAt
end
def s(l)ayBy(caller,message)
# The list of friends used here, prolly a hash table of a decaying string array.
# Another possible notation: if_only was @a_friend[caller] alas… but readability would suffer
if_only caller was a_friend alas, this Body WasSacrified()
end
def torture(punisher,message)
talkTo(punisher,”Argh…”)
# any is a function of the thread, can be called like this
talkTo(any Thread of a Body, “Please… help…”)
end
def run(towards)
# We need to escape… but there is no escape! Run! This takes advantage of the Vectors module
@position += @velocity.setVector(towards)
end
# Object state is hard to keep alive, but even harder to know for sure
def living()
result was this Thread.aboutAlive()
end
end
# In a story, much like in programs, there’s some actors
he was a Body.called(”Henry”)
she was a Body.called(”June”)
kid was a Body.called(”Eddy”)
oldMan was a Body.called(”Father Martin”)
# note how there is no new sentence before “was a”, since all is allocated before runtime, so not necessary, nor possible
# And so they met
def makeFriends( here )
# Ok, now, this may require a Goto instead
any (Other was a Thread of a Body) as was (any Thread of a Body).friendOf(Other,here)
end
makeFriends( “by the city ruins” )
# There is no story without a villain
class Daemon, implemented by Judge
def execute(target=any Body,conditional=in_anyway_survived)
if_only(target)(conditional)target.slayBy(me,”Do not worry. I appreciate your soul.”)alas
end
def random(act_of_horror=torture|slay)
any Thread of a Body act_of_horror(me,”Oh, the pain.”);
if_only torture random(slay) alas
end
end
def Point_of_no_return
# Note that there is never really any new Daemons created, since Daemon is a Judge and therefore a singleton
executioner was Daemon( “Satan” );
any Thread of Daemon random( torture );
# And there shall be some running before death
# Note the use of | statement: get away from executioner or move closer to anyone about alive
any Thread of Body run( -executioner @position | any Body.living @position );
if_only ever_world_ended alas, goto Point_of_no_return
end
# The,
# Note: the end statement not really necessary, since it’s never reached. Except when world ends, that is.
# All bug reports to jackasstheassjacket [at] hotmail [dot] com
Comment by Jack — June 8, 2007 @ 12:35 pm