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:
- Free and open source (MIT licensed)
- Built-in string encoding (html, url, sql, ...)
- Scoping from javascript (single user thread)
- Function parameters from python (named, list, dict arguments)
- Context managers and 'with' from python
- Curly-brace language, but no-semicolons
- Automatic big number switching (python)
- Automatic lazy network/file access for easy pipelining
- Willingness to drop backwards compatibility (python 3)
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" // <3 print html:"<strong>$heart</strong>" // <strong><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><3</strong> built-in encodings -- <3. print html:"Double encoded: ${"$boldheart"}." // Double encoded: <strong>&lt;3</strong> print html:""" <html><head> <title>$title</title> </head><body> <h1>$title</h1> </body><html> """ /* <html><head> <title>Language proposal > dave</title> </head><body> <h1>Language proposal > 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)