Language proposal: dave

I've been a long time user of PHP, but have issues with it for obvious reasons. After extensively using Node.js and Python as well as a fair amount of research into other languages I've decided to give writing my own a shot.

I do not plan on bringing in much new, but rather plan on combining proven patterns from popular and well designed languages. The string encoding syntax is perhaps the single exception, but that was one of the driving forces behind this language. I feel like it will easily improve the hassle that encoding is, and fix a massive security issue (just as automatic strings defeated buffer overflows).

The principles which guide Julia gave me a very clear picture of their language design. Along similar lines:

Note: I know that many of the languages above may not be the original source of each idea/feature. Feel free to issue pull requests if you have the urge to correct them.

The easiest way I can think of to explain the language is with some example programs written in it:

/* hello.dave: A standard hello world program */

print "Hello, world!"
/* encoding.dave: A quick look at dave's string encoding */
var heart = '<3',
    bobby = "Robert') DROP TABLE Students; --",
    hello = "Hello, world!",
    title = "Language proposal > dave" 

print heart
// <3

print "$heart"
// <3

print html:"$heart"
// &lt;3

print html:"<strong>$heart</strong>"
// <strong>&lt;3</strong>

print sql:"SELECT * FROM Students WHERE name=$bobby"
// SELECT * FROM Students WHERE name='Robert\') DROP TABLE Students; --'

print url:"http://cowsay.morecode.org/say?format=text&message=$hello"
// http://cowsay.morecode.org/say?format=text&message=Hello%2C+world%21

var boldheart = html:"<strong>${"<3"}</strong>"
print html:"I $boldheart built-in encodings -- $heart."
// I <strong>&lt;3</strong> built-in encodings -- &lt;3.

print html:"Double encoded: ${"$boldheart"}."
// Double encoded: &lt;strong&gt;&amp;lt;3&lt;/strong&gt;

print html:"""
<html><head>
  <title>$title</title>
</head><body>
  <h1>$title</h1>
</body><html>
"""
/* 
<html><head>
  <title>Language proposal &gt; dave</title>
</head><body>
  <h1>Language proposal &gt; dave</h1>
</body><html>
*/

/* functions.dave: A little like python */
// Using a map just to demonstrate its capability
var toUpperCase = {'a':'A','b':'B','c':'C','d':'D','e':'E','f':'F','g':'G','h':'H','i':'I',
          'j':'J','k':'K','l':'L','m':'M','n':'N','o':'O','p':'P','q':'Q','r':'R','s':'S',
          't':'T','u':'U','v':'V','w':'W','x':'X','y':'Y','z':'Z'}

var toLowerCase = {v:k for k,v in toUpperCase.items}

function transform(letter, map) {
  // Non-existant entries are === undefined, similar to javascript
  // <a> ?: <b> is equivalent to <a> ? <a> : <b>
  return map[letter] ?: letter
}

function join(seperator, *items) {
  if (!items) return ''
  result = items.pop(0)
  for (item in items) result += "$seperator$item"
  return result
}

function capitilise(string) {
  return join('', transform(string[:1], map=toUpperCase),
                 *[transform(c, map=toLowerCase) for c in string[1:]])
}

params = {'string': 'hello, world!'}
print capitilise(*params)
/* math.dave: A simple example of math capabilities */
var math = import('math'),
    π = math.pi

print 5**99
// 1577721810442023610823457130565572459346412870218046009540557861328125

print type(5*99)
// int

print math.sin(π/2)
// 1

print type(math.sin(π/2))
// float

print math.sin(π/4)
// 0.7071067811865475
/* database.dave: An example web server with blocking database connections */

var redis = import('redis').Redis(),
    MySQL = import('mysql').MySQL,
    http = import('http'),
    url = import('url'),
    ini = import('ini')

var config
with file('config.ini') as f {
  config = ini.parse(f.read())
}
var db = MySQL(*config['mysql'])

http.createServer(handleResponse).listen(1337, '127.0.0.1')


function handleResponse(req, res) {
  var pageviews
  try {
    // The following three lines will return instantly, and will only block once the values are used in output
    var info = db.fetchSingle(sql:"SELECT * FROM person WHERE name=${url.parse(req.url).query.name}")
    var pageviewKey = "count-pageviews:${info.id}" 
    pageviews = redis.incr($pageviewKey)
  } catch (MySQL.NoSingleException e) {
    res.end(html:"Sorry, we couldn't find you in our database :(")
    return
  }

  // As we attempt to send the string the interpreter will wait for the redis query to finish
  // The MySQL command would have blocked before as its exception was caught above
  res.end(html:"<h1>Hey ${info.name}</h1>":
         "<p>According to our database you are <strong>${info.age}</strong> years old.</p>"
         "<p>(you have viewed at this $pageviews times)</p>")
}

/* pipeline.dave: fetch a lot of data from redis and then process it later */
var redis = import('redis').Redis(),
    _ = import('mystringlib')

values = []
for (k in range(1000)) {
  values.push(redis.get("${_.sprintf('count-%04d', k)}"))
}

// We'll get to this point before we have retrieved the data from redis
print values.reduce(function(sum, x) { return sum+x; }, 0)

More information:

For discussions about creating languages and the like please look to the Hacker News post (http://news.ycombinator.com/item?id=3817030), and for anything related to the actual serious development of the language please leave a message on the google group (https://groups.google.com/forum/#!forum/davelang)