
Vigil: A programming language with eternal moral vigilance - factorialboy
https://github.com/munificent/vigil
======
Locke1689
The underlying idea here is a contract system, first pioneered by Bertrand
Meyer in the programming language Eiffel[1] and then augmented with the
ability to describe higher-order functions by Robby Findler[2]. PLT also
strongly advocated the use of blame with contracts -- the ability to blame the
responsible party (function) when a contract fails. My Masters thesis under
Robby Findler was on guided random testing using higher-order contracts.

I should note that an ordinary contract system does not delete your code...

[1]
[http://en.wikipedia.org/wiki/Eiffel_(programming_language)#D...](http://en.wikipedia.org/wiki/Eiffel_\(programming_language\)#Design_by_Contract)

[2] [http://www.eecs.northwestern.edu/~robby/pubs/papers/ho-
contr...](http://www.eecs.northwestern.edu/~robby/pubs/papers/ho-contracts-
techreport.pdf)

~~~
fogus
> I should note that an ordinary > contract system does not delete your
> code...

Much to my dismay.

~~~
webjprgm
git commit before running, then git diff to see what code was bad.

~~~
prezjordan
Or comment out code.

------
eslaught
I rather enjoyed reading about the language, but was a bit disappointed that
they made no attempt at static analysis, especially with such a rich set of
assertions that the language enforces. I'd really like to see my entire
program get deleted at compile-time rather than having to run it a bunch of
times to delete all the faulty nested function calls one at a time.

~~~
a3_nm
Agreed. The "deletes the function from your source code" part is amusing, but
"swear" and "implore" are just like Python's "assert".

~~~
Cogito
Not quite.

Implore asserts that a test passes (prototypically on a passed in parameter),
but if that test fails the blame is on the calling function.

Swear on the other hand will assign blame to the current function if the test
fails.

------
ot
I hope someone makes a C/C++ compiler that deletes functions from the source
code when they trigger undefined behaviour.

It would still be compliant with the standard.

~~~
qznc
This compiler would probably delete all the code. See
<http://blog.regehr.org/archives/761>

~~~
bcoates
I think that website is confused about undefined behavior, they accuse LLVM
and GCC of "executing undefined behavior" for the minimal empty-main C99
program because the default headers included in the compiler have UB code in
them.

But only user code is required to be well-formed and have defined behavior,
system headers could just as well be written in Forth as long as the actual
behavior under the compiler they come with is correct.

~~~
scott_s
John Regehr is an expert in undefined behavior in C compilers, so rather than
assume his understanding is mistaken, I would first assume mine is.

He is not accusing the compilers of _executing_ undefined behavior. He is
accusing them of _exploiting_ undefined behavior to "optimize" code.

His points are:

1\. Current compilers will perform optimizations based on undefined behavior.
That is, during the optimization phase, they will say "Aha! That's not
defined! I'll instead do this much, much faster thing as an optimization."

2\. Lots of real code has undefined behavior.

3\. The programs that result from these codes still produce the answers we
expect, mostly.

4\. If we take point 1 to its logical conclusion, then point 2 means that
point 3 will no longer be true. That is, if compilers aggressively and
thoroughly sought out to find all instances of undefined behavior in C code,
and just optimized it away, many (most?) programs would cease to do much at
all.

~~~
Elrac
Ironically enough, point #4 sounds very similar to how Vigil claims to work.

~~~
scott_s
I don't think it's irony, I think that's the very reason that qznc linked to
it.

------
pcwalton
Supposedly an unreleased version of the GHC Haskell compiler had this feature
first: <https://twitter.com/bos31337/status/116372971509121025>

~~~
oftenwrong
GHC Haskell compiler = Glasgow Haskell Compiler Haskell compiler

~~~
ot
Typical case of "redundant acronym syndrome syndrome"

<http://en.wikipedia.org/wiki/RAS_syndrome>

~~~
dllthomas
Slightly more severe than typical - two words are duplicated.

~~~
kybernetikos
Worst I ever saw was an advertisement proclaiming that the car in question had
"Advanced ABS Braking System".

I consider that an example of "Maximally Redundant MRAS Acronym Syndrome".

~~~
dllthomas
Isn't the A in ABS "Anti-lock"? In which case, it's comparable. I like your
syndrome name, though!

------
CurtHagenlocher
Eternal moral vigilance is the price of coding liberty!

This project clearly needs to be amended to integrate with version control.

~~~
jerf
Source control allows one to bypass the moral purity of Vigil by recovering
arbitrary sinful code from the past. Moral purity can not be advanced while
the sins of the past remain with us forever, uncleansed. One can only properly
use Vigil without any sort of source control. Even copying files before the
compiler tries to run it is an attempt to cheat the system; for that, Vigil
would be justified in deleting your entire code base and all the copies it
could find.

Or perhaps justified in deleting you instead, as it is you who has sinned, not
the source code.

...

Certainly this approach leads to a more pure universe, but, I suspect, a
rather sparsely populated one.

(Eliezer, do me a favor and keep munificent away from AI development....)

~~~
CurtHagenlocher
I was thinking that it would remove the offending source code from history --
a revisionist source control system, if you will, to show that we have always
been at war with Eastasia.

~~~
bernardom
You just have to set Damnatio_Memoriae = TRUE

<http://en.wikipedia.org/wiki/Damnatio_memoriae>

~~~
eli_gottlieb
If you push networked updates of the source tree, you can pull off a full
Amalek on a function: "Blot out the name and memory of `class Amalek` from
under the heavens!"

------
brudgers
If Vigil fails to punish a function, does it delete itself?

Or is it a Hobbesian sovereign?

~~~
saidajigumi
> If Vigil fails to punish a function, does it delete itself?

1\. It is _wrong_ not to punish immoral code. 2\. You cannot punish all
immoral code without a solution to the Halting Problem. 3\. You cannot solve
the Halting Problem.

∴ Vigil must delete itself. QED.

~~~
munificent
I'm working on getting Vigil to be self-hosted. There's a bit of a "who
watches the watchers" problem involved.

But, remember, Vigil only holds you to the oaths you yourself have sworn. If
Vigil swears to punish a function, then it should be punished for failing to
do so. But if it's given no oath to that effect, then it's off the hook.

You may reasonably ask yourself, "well, what oaths does Vigil swear to
uphold?" The answer is a frightening "none", since Vigil is not currently
written in Vigil (nor is the README, which is in Markdown, a decidedly sinful
format).

~~~
brudgers
This is the essence of the Hobbesian approach - Vigil is has unlimited power
over the programmer's code. The programmer has no claim upon Vigil other than
that it enforce morality upon their code.

I don't think you can have turtles all the way down.

~~~
tomrod
Because chances are four of them are teenaged ninjas?

------
p4bl0
This is a submission to this month PLT Games "Testing the Waters" [1] which
goal "is to create a language that is somehow related to automated testing". I
hope we'll see more interresting stuff coming from this!

[1] <https://news.ycombinator.com/item?id=5001504> (full disclosure: I'm the
submitter of this link)

------
aslakhellesoy
This reminds me of Guantanamo [1] - a tool I created 9 years ago. It removes
code that isn't covered by tests.

[1] <http://docs.codehaus.org/display/ASH/Guantanamo>

------
steveklabnik
If you need a similar level of assurance in Ruby,
<https://github.com/fxn/i-told-you-it-was-private> can do something almost the
same.

------
angersock
Code for the code gods, scrum for the scrum throne.

Seriously, this is some Imperium of Man PL research.

------
wodow
Looks like Python, but it doesn't interpret... it executes.

------
ArchD
To make this actually useful, instead of deleting bad functions, it's probably
better to make the offending functions throw a special exception when they are
called, signaling the calling of a function known to be bad. This way, you can
still inspect the code for the offending functions and fix the bugs.

Otherwise, the original code could just totally disappear after multiple runs.
What good is non-buggy code if it does nothing? Failure to perform the user's
requirement at all is also a bug. Not having the original code that you can at
least edit to fix is rather pointless, especially when vigil doesn't indicate
the callers of the offending functions, because next time you run vigil, those
will get deleted. Besides, if foo()'s failure is completely due to bar()'s
failure to fulfill its 'swear', it's foo()'s failure is not really its bug.

~~~
ConstantineXVI
How will functions learn to stay in line if the compiler doesn't make an
example every now and then?

On a serious note, what you're thinking of is contracts, like so[0]

[0] <http://disnetdev.com/contracts.coffee/>

~~~
phpnode
projects like this are why coffeescript needs to support macros. There are so
many coffeescript dialects out there that make minor changes to the language
to accomodate one or two extra features, e.g. IcedCoffee. I don't want to have
to use a separate, presumably less well supported language for this kind of
stuff, just let me plug it in!

~~~
ConstantineXVI
> The golden rule of CoffeeScript is: "It's just JavaScript"[0]

Macros would be deviating from core JS too much to fit with CoffeeScript's
goal. Just happens that the compiler is nicely hackable to allow for these
projects.

Not to say I object to the idea of an expanded CoffeeScript, just that it
should be a fork.

[0] <http://coffeescript.org/>

~~~
gtrak
Macros will eventually be in core JS, see:

[http://disnetdev.com/blog/2012/10/14/hygienic-macros-for-
jav...](http://disnetdev.com/blog/2012/10/14/hygienic-macros-for-javascript/)

and <http://brendaneich.github.com/Strange-Loop-2012/#/40>
<http://www.infoq.com/presentations/State-JavaScript>

------
JasonFruit
Developed with mutual antagonism by the Ayn Rand Institute and the Atlas
Society under the special supervision of Leonard Peikoff.

~~~
andyjohnson0
That would be objectivist-c: <http://fdiv.net/2012/04/01/objectivist-c>

~~~
davesims
I award you one Internet.

------
mas644
I think this is a fantastic concept with lots of potential! I especially loved
the tongue-in-cheek humor -- "Eternal moral vigilance is no laughing matter."

In my opinion, deleting code is fine...however you should 1) be warned that it
will happen in the near future if you do nothing about it and 2) it should be
tied to some version control system (e.g. GitHub) where it pushes the deletes
(maybe even creating a branch and remerging it so the changes are clear) so
that code can be recovered if need be.

Vigil can maybe even have some logic built in if you revert deleted code it
gets "angrier" and starts more aggressively purging code in the future :P

------
conanbatt
Punished code deserves to be shamed and be made an example of. Vigil should
make an image with the deleted code, such as it cannot be copy pasted and has
to be rewritten in shame.

This idea seems actually quite awesome for a competition. Its truly a dungeon-
crawler of programming.

Suggested extra hard-mode for short competitions: deletes all code.

~~~
andrewflnr
It should also upload the image to imgur or some such site.

~~~
mst
Or submit it to thedailywtf

------
scrumper
Excellent idea. Looks like it was co-designed by Kim Jong Un and the Taliban.

~~~
LVB
Failing to include mandatory ASCII art of the Dear Leader atop each source
file is a punishable offence.

~~~
scrumper
The Dear Leader himself, of course, is such a Real Programmer that the
butterflies flap their wings without even needing to be directed.

Vigil reminds me a little bit of Intercal, with its "Programmer is
insufficiently polite" errors.

------
md224
As the creator of FuckItJS, I heartily approve of this destructive approach.

~~~
munificent
You're my inspiration! You are the wind beneath my wings.

------
frozenport
Code deletion reminds me of it <https://github.com/mattdiamond/fuckitjs>

------
MichaelAza
You know, I don't think this is a half bad idea. I mean, deleting offending
code is a bit much, but shouldn't a code-by-contract language not allow code
that failed a contract to be compiled until it changes? That would seem to
make sense.

~~~
derefr
To explicate this, it would make sense that when you pass a source file to the
compiler, it would:

1\. Parse the code into an AST (to strip away any pre-parse differences, like
formatting or syntactic sugar usage), then hash that AST (recursively--replace
any non-primitive function references with hashes of their own current ASTs)

2\. Run unit tests, fuzz, etc--taking the AST hashes of each function of the
testing code as well (though using symbolic, rather than "hard", references to
the implementation-code, so it can change without making the test's hash
change)

3\. If a piece of code fails a test, add the pair (test AST hash, code AST
hash) to some database (preferably an online, global database).

4\. From then on, before anything is allowed to be compiled, perform a lookup
in said database, and refuse to compile anything if the database finds any
known (test, failed code) pairs in your code.

\---

The interesting thing is that this system is very _conservative_ \--if a piece
of code depended on by the code you wrote changes, then your code is given
another chance (because maybe your code was just failing because it was
expecting something of that other code, and that other code was wrong, and
then it was fixed.)

Likewise, if you change the requirements, your code must be re-evaluated for
conformance--code shouldn't be barred because it fails a "wrong test" like
assert_equal(add_two_plus_two(), 5);.

But on the other hand, if you _add_ tests, the old barrings based on previous
tests stay in effect as well--this actually incentivizes breaking unit tests
into small, orthogonal functions that pass or fail separately.

I don't think there would actually be any problem doing real development under
this "restriction". In practice, given the way we currently do software
engineering, it would only catch problems within your own project that had
been seen+caught before--because those would be the only tests you had
included.

In theory, though, you could also import, say, a global "test set"--basically,
AST hashes for every test of the current stable branch of all major open
source projects, or something similar--and check your code against that as
well, just in case you happened to write, say, an incorrect date-handling
function that someone else had ever written in an AST-identical way.

------
rthomas6
Someone should combine this with some kind of fast mutating genetic algorithm.
Presto, procedurally generated solutions.

------
rcbarnes
Wow, I'm seriously considering adapting this for my shell scripts (with code
recovery via mercurial, since I'm weak of will...). Actually, I bet there are
already others doing the same, because code deletion in personal shell scripts
probably turns out to be an unalloyed good.

Consider this: you've got some script that does a sequence of operations using
the standard tools. Somewhere you change between imagemagick and
graphicsmagick and some image doesn't get made thanks to syntax differences;
after this you've used some clever shell filename expansion expression or
regex to move/delete files, but the missing image changed your working context
enough that suddenly you're in $HOME doing an rm -rf .! The environment is
just too fragile and powerful to completely automate everything you might need
without setting up enough safety mechanisms, confirmations, and sanity checks
to largely nullify the value of scripting as a nearly zero development
programming toolchain.

But if shell code were trivially spec'd for pre-/post- conditions and
misbehaving code gets noisily deleted (noisily so everything isn't packed away
into code versioning purgatory by cascading failures when a tool like rename
is accidentally uninstalled)---especially if the shell of pre-and post
conditions were left around stub code... Imagine the beauty of your scripts
directory!

Replacing some slain block of code is trivial since the tools you need are
already mostly written, and you've done something close to what you need
before---plus the whole point of shell scripting is that it should be
effortless and fast to produce.

If you've built a massive, multi-purpose utility, it deserves to live only as
long as it runs flawlessly---after which, you should slice it down or replace
it with an inevitably more reliable equivalent that was written for the same
purpose years (or decades) ago.

Best of all the conditions that deleted your broken cruft even remind you
exactly what you needed to do when you're re-implementing something, but often
without pre-studying the entire system to ascertain what world state you are
getting and what you need to produce. Brilliant!

This may have started out somewhat tongue-in-cheek (since most programming
environments are at least somewhat stable and feature significant error
detection and recovery facilities), but I think there's some dead serious
application in the quick-and-dirty, often unchecked and fluid environment of
traditional shell scripting. The more I think about it, the more I'm amazed my
quarter million keystrokes of live scripts woven into my every task on my
Linux desktop haven't produced more catastrophes (or any meaningful accidental
data loss) or left a trail of silent failures for me to find only long after
the causal bugs had manifested.

~~~
munificent
> somewhat tongue-in-cheek

Somewhat?

~~~
rcbarnes
Well, from what I gather, the overarching criteria of the contest for which
this was develped is "Does it do something novel to advance understanding and
execution of software development?" While that kind of focus tends to bring
out all kinds of wacky ideas, don't confuse defiance of the status quo for
casting off all reason. When there's no shame in it, experimenters needen't
rationalize or smooth over their deviation from expected norms.

~~~
munificent
> "Does it do something novel to advance understanding and execution of
> software development?"

Shit, I probably should have read the rules before I entered.

------
eli_gottlieb
CONSTANT NEVER-CEASING VIGILANCE!

~~~
gmaslov
Burn the heretic. Kill the mutant. Purge the unclean.

~~~
eli_gottlieb
That sounds like Death Eater talk to me.

~~~
saraid216

      "Harry James Potter-Evans-Verres!
      Harry James Potter-Evans-Verres!
      HARRY JAMES POTTER-EVANS-VERRES!"

------
torial
I like python-like languages, but the deleting of code seems rather extreme
(and unlike the personality I'd expect from a python-like language). Boo
provided a super extensible compiler pipeline and metaprogramming
(<http://boo.codehaus.org/>), while Cobra provided built in unit test support
and contracts (with keywords of ensure and require) (<http://cobra-
language.com/>) -- neither destroy your work (even if it is WIP).

------
agentultra
This is the greatest thing ever... except... can it solve the halting problem?

~~~
jerf
Well, with probability 1 - epsilon, any non-trivial Vigil program halts, and
_never runs again_. In theory this is not a solution to the halting problem,
in practice it pretty much is. A very definitive solution.

~~~
gabriel34
Should thou neither swearest nor implorest thou shan't be punished

------
downey
Even better when you listen to this while coding:
<http://www.youtube.com/watch?v=w097Q0fZE-A>

:)

------
cpdean
How are the `implore` and `swear` keywords different from python's `assert`?

Even the implementation looks like it's just custom error text for `assert`.

~~~
cpdean
Oh.

"If an oath is broken, the offending function (the caller in the case of
implore and the callee in the case of swear) will be duly punished. ... it
will be deleted from your source code"

Hahah, awesome.

Outsource-proof.

------
eli_gottlieb
As a friend of mine put it, run an office pool on how long such a contract-
testing system will take to delete _all_ your code!

------
maxbaroi
Proposal for the next release: Any code that gives a warning should either a)
Print so many hail marys or b) Be half deleted

------
zeeboo
Oops, I called fib(-1) on the example page :(

------
saidajigumi
Wow. Vigil needs its own LLVM compiler. We'll call it House of Cards. :-P

------
mikecane
IDK. Implore? Shouldn't there also be beg, cajole, plead, and grovel?

~~~
RyanMcGreal
There is nothing morally upright about begging, cajoling, pleading or
grovelling.

~~~
kybernetikos
Imploring isn't really right either, because it seems too subservient to
enforce a requirement on calling code.

It's more like the feudal lords obligation to his vassal - that he provide
them with the use of the fief and protect them from others. If the function is
the fief, then you provide the use of it only to those other functions that
will swear fealty to you.

------
sgt101
I was with it until the delete bit. Refuse point blank to run : I like this.
Raise exceptions : ok (bit weak). But delete... esh imagine the cost!

~~~
pc86
You are apparently not aware that the author himself created it as satire as
part of a programming competition/game.

------
chrismealy
Nobody tell management about this.

------
RyanZAG
Good God, why would anybody try to re-invent COBOL?!

------
pjungwir

        illa 'quis et me' inquit 'miseram et te perdidit, Orpheu,
        quis tantus furor? en iterum crudelia retro
        fata vocant, conditque natantia lumina somnus.
        iamque vale: feror ingenti circumdata nocte
        invalidasque tibi tendens, heu non tua, palmas.'
        dixit et ex oculis subito, ceu fumus in auras
        commixtus tenuis, fugit diversa, neque illum
        prensantem nequiquam umbras et multa volentem
        dicere praeterea vidit; nec portitor Orci
        amplius obiectam passus transire paludem.

~~~
tnorthcutt
Virgil != Vigil

~~~
pjungwir
Oops, sure enough. Somehow I read "r"s into that whole Github page! I guess
you see what you expect to see. You have to admit though that all its moral
language sounds a lot like Aeneas. :-)

