Skip to content

Commit

Permalink
Creatio ex nihilo.
Browse files Browse the repository at this point in the history
  • Loading branch information
munificent committed Jan 3, 2013
0 parents commit bd78a83
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 0 deletions.
79 changes: 79 additions & 0 deletions README.md
@@ -0,0 +1,79 @@
Vigil is a *very safe* programming language, and an entry in the [January 2013 PLT Games competition](http://www.pltgames.com/competition/2013/1).

Many programming language claim to take testing, contracts and safety seriously, but only Vigil is *truly* vigilant about not allowing code that fails to pass programmatic specifications.

## Syntax and semantics

Vigil is very similar to Python with the minor proviso that you must provide a `main()` function which will be automatically called for you.

Infinitely more important than mere syntax and semantics are its addition of **supreme moral vigilance**. This is similar to contracts, but less legal and more medieval.

### The `implore` statement to beseech your needs

Often, a function will require that parameters have certain desireable properties. A function in Vigil can state what it requires by using `implore`:

```
def square_root(n):
implore n >= 0
return math.sqrt(n)
```

If a caller fails to provide valid arguments, it is *wrong* and must be punished.

### The `swear` statement to state what you provide in return

If a good caller meets its obligations, the onus is thus on you to fulfill your end of the bargain. You can state the oaths that you promise to uphold using `swear`:

```
def fib(n):
if n < 2:
result = n
else:
result = fib(n - 1) + fib(n - 2)
# fib() never returns negative number.
swear result >= 0
return result
```

If a function fails to uphold what it has sworn to do, it is *wrong* and must be punished.

### Unhandled exceptions

It goes without saying that any function that throws an exception which isn't caught is *wrong* and must be punished.

## Runtime vigilance

This is where Vigil sets itself apart from weaker languages that lack the courage of their convictions. When a Vigil program is executed, Vigil itself will monitor all oaths (implorations and swears) that have been made. If an oath is broken, the offending function (the called in the case of `implore` and the callee in the case of `swear`) *will be duly punished.*

How?

**Simple: it will be deleted from your source code.**

The only way to ensure your program meets its requirements to absolutely forbid code that fails to do so. With Vigil, it will do this for you *automatically*. After enough runs, Vigil promises that all remaining code meets its oaths.

## Usage

Vigil is a command-line executable. Pass it the path to a file to run:

```
$ ./vigil example/hello.vg
```

The "example" directory has some to get you started.

## FAQ

### Is this serious?

Eternal moral vigilance is no laughing matter.

### But isn't a language that deletes code crazy?

No, wanting to keep code that demonstrably has bugs *according to its own specifications* is crazy. What good could it possibly serve? It is corrupted and must be cleansed from your codebase.

Vigil will do this for you automatically.

### Vigil deleted a function. Won't that cause the functions that call it to fail?

It would seem that those functions appear to be corrupted as well. Run Vigil again and it will take care of that for you. Several invocations may be required to fully excise all bugs from your code.
16 changes: 16 additions & 0 deletions example/failed_implore.vg
@@ -0,0 +1,16 @@
# This shows what happens when a caller fails to keep its oath.
import math

def square_root(n):
"""
Calculates the square root of the given number, which must be non-negative.
"""
implore n >= 0

return math.sqrt(abs(n))

def evil_fn():
square_root(-1)

def main():
evil_fn()
18 changes: 18 additions & 0 deletions example/failed_swear.vg
@@ -0,0 +1,18 @@
# This shows what happens when a function fails to keep its oath.

def bad_abs(n):
"""
Calculates the absolute value of the given number. Always returns a
non-negative number.
"""
result = -n # Oops.

swear result >= 0
return result

def innocent_fn():
print bad_abs(-2) # OK...
print bad_abs(2) # Uh-oh...

def main():
innocent_fn()
22 changes: 22 additions & 0 deletions example/hello.vg
@@ -0,0 +1,22 @@
# This is an innocent program which meets all of its moral obligations.

def fib(n):
"""
Calculates the nth value in the Fibonacci sequence.

"n" must be non-negative, and the result will be as well.
"""
implore n >= 0
if n < 2:
result = n
else:
result = fib(n - 1) + fib(n - 2)

swear result >= 0
return result

def main():
print "Let's see some Fibonacci numbers!"
for n in xrange(0, 10):
print n, ':', fib(n)
print "I feel happy and innocent!"
15 changes: 15 additions & 0 deletions example/unhandled_exception.vg
@@ -0,0 +1,15 @@
# This shows what happens when a function throws an unhandled exception.

def say_hello(who):
"""
Greets 'who'.
"""

print "Hi,", who
raise Exception("ERROR!") # Oops.

def innocent_fn():
say_hello('Bob')

def main():
innocent_fn()
94 changes: 94 additions & 0 deletions vigil
@@ -0,0 +1,94 @@
#!/usr/bin/env python

import re
import sys
import traceback

source_path = sys.argv[1]
source_lines = None
offenders = []

def punish(line, offense):
# No double jeopardy.
for _, _, offend_line in offenders:
if line == offend_line: return

# Walk back to find the beginning of the function containing this line.
start = line
while start >= 0:
if re.match('def ', source_lines[start]):
break
start -= 1

# Walk forward to find the end of the function.
end = line
while end < len(source_lines):
if re.match('^\s*$', source_lines[end]):
break
end += 1

# Duly note those functions which hath caused offence.
offenders.append((source_lines[start].strip(), offense, line))

# Clear the lines, but don't delete them. That way later failures will
# have the right line number.
for i in xrange(start, end + 1):
source_lines[i] = ''

def vigil_implore(ok, expr):
if not ok:
bad_line = traceback.extract_stack()[-3][1]
punish(bad_line,
"Denied the needs of a function which implored '%s'." % expr)

def vigil_swear(ok, expr):
if not ok:
bad_line = traceback.extract_stack()[-2][1]
punish(bad_line, "Swore '%s' and failed to provide such." % expr)

def vigil_done():
# Silent vigil if all is well.
if not offenders:
return

# Strip out the dirty impure lines.
cleansed = filter(len, source_lines)
with open(source_path, 'w') as f:
f.writelines(cleansed)

print ""
print ""
print "------------------------------------------------------------------"
print ""
print "The ever vigilant watchers of your code have found malfeasance in:"
print ""

for fn, offense, _ in offenders:
print fn
print "Crime:", offense
print ""

print "Each has been dealt an appropriate punishment."

def vigil_uncaught():
raise_line = traceback.extract_tb(sys.exc_info()[2])[-1][1]
print "uncaught error from line ", raise_line
punish(raise_line, "Raised '%s' which was not caught." % sys.exc_info()[1])

with open(source_path) as f:
source_lines = f.readlines()

source = ""
for line in source_lines:
line = re.sub(r'(\s*)implore (.*)', r'\1vigil_implore(\2, """\2""")', line)
line = re.sub(r'(\s*)swear (.*)', r'\1vigil_swear(\2, """\2""")', line)
source += line
source += """
try:
main()
except Exception as ex:
vigil_uncaught()
vigil_done()
"""
exec(source)

2 comments on commit bd78a83

@odkq
Copy link

@odkq odkq commented on bd78a83 Jan 3, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:) Why isn't vigil written in vigil?

@joshmarshall
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ex nihilo nihil fit.

Please sign in to comment.