Introduction
For those of you that are new to Myrddin, welcome. Myrddin is a language that I put together for fun, but which has developed delusions of usefulness. Once a month, I'll be shamelessly promoting writing a status report on what's going on with Myrddin.
Overview For The Uninitiated
If you haven't heard of this language -- fear not, you're not alone. Here are a few links to an overview of the language, some code you can browse, and some documentation of the internals.
- WTF is a Myrddin?
- I'm a masochist that likes reading slightly outdated language specs
- I'm a masochist that likes reading about compiler internals
- The compiler and standard library source
- The regex library source
- The buffered io library source
Fixing generic containers
In the last month, there were a number of bugs to do with the specialization of generics that were causing infinite loops, missing symbols, and crashes when using 'std.htab'. This was fixed, and it seems like there is now a solid hash table implementation in the standard library. It can be used with any type, as long as you provide it with a hash function (some of which live in libstd for common types). For example:
var ht : std.htab(byte[:], int)#
ht = std.mkht(std.strhash, std.streq)
std.htput(ht, "foo", 123)
std.htdel(ht, "foo")
Of course, you don't need the standard library hash functions. If you wanted "FOO", "Foo", and "foo" all to hash to the same string, you might want to use a hash function of your own, which is trivial.
Supporting 'for _ in _'
loops
Like most other languages written in this decade, Myrddin now supports `for x in y' loops. You can even pattern match on the values while iterating. For example:
var array = [
`std.Some 123,
`std.None,
`std.Some 456,
`std.None,
`std.Some 555
]
for `std.Some val in array
std.put("%i\n", val)
;;
Will only pass through the std.Some values in the loop body, skipping over
the
`std.None` values.
Floating point support in the compiler
The compiler supports code generation for floating point values now. There is no library support yet for common floating point operations (not even parsing them from strings), although this is planned once I can wrap my head around the right papers.
If there are any people that want to help out, that would be welcome. Correct floating point algorithms are scary.
Libregex Improvements:
Myrddin now has a homegrown regex library that works. There are a few niggles I have to make sure I shake out of it regarding precedence of operations, but overall it seems to be working well.
It uses a Thompson NFA implementation, which implies that it supports only the regular language subeset of regular expressions. Hoever, it supports unicode fully, although the range abbreviations do not use the unicode tables because of efficiency reasons. Most of the time, I only want to match words within the ascii range, and having several hundred unciode ranges for, eg, uppercase characters to match against is painful
However, for completeness, there should be support added for all the Unicode character class abbreviations. This should be pretty easy, since I have the unicode table generated and checked in. It's just up to iterating over it and adding the ranges to the set.
Libbio improvements:
Added tests, so now we have some idea that it works.
Make it consistently return a maybe type from the various read functions.
Growing libstd:
A large number of new functions have popped up in libstd. A sample of some of the more useful ones are below:
String handling functions:
const strfind : (haystack : byte[:], needle : byte[:] -> option(size))
const strsplit : (s : byte[:], delim : byte[:] -> byte[:][:])
const strcat : (a : byte[:], b : byte[:] -> byte[:])
const strjoin : (strings : byte[:][:], delim : byte[:] -> byte[:])
Networking functions:
const dial : (dialstr : byte[:] -> error(fd, byte[:]))
const resolve : (host : byte[:] -> error(hostinfo[:], resolveerr))
const resolvemx : (host : byte[:] -> error(hostinfo[:], resolveerr))
const resolverec : (host : byte[:], t : rectype -> error(hostinfo[:], resolveerr))
System calls:
const execv : (cmd:byte[:], args:byte[:][:] -> int64)
const execve : (cmd:byte[:], args:byte[:][:], env : byte[:][:] -> int64)
const execvp : (cmd:byte[:], args:byte[:][:] -> int64)
const execvpe : (cmd:byte[:], args:byte[:][:], env : byte[:][:] -> int64)
const sleep : (time : uint64 -> int32)
const nanosleep : (req : timespec#, rem : timespec# -> int32)
Miscellania:
generic sort : (sl:@a[:], cmp:(a:@a, b:@a -> order) -> @a[:])
const hasprefix : (s : byte[:], pre : byte[:] -> bool)
And many more functions.
Next Month?
Implementing traits. It should be possible to add traits to any type, at any point in the code. Expected sytnax will be something like:
trait hashable @a = generic hash : (val : @a -> uint32) ;;
impl hashable int ...
const hash = {val : int -> uint32 ... }
Implementing environment capture: When defining a nested function, it should capture the enclosing environment. Semantics still have to be worked out.