|
My brain is built of paths and slides and ladders and lasers and I have invited all of you to enter its pavilion. My brain, as you enter, will smell of tangerines and brand-new running shoes.
| Sunday, September 21, 2008 |
 The Epoch Manifesto |
Posted - 9/21/2008 9:22:29 PM | The Epoch Manifesto
Answering all the big questions about who, what, when, and why.
Please note that this is highly forward-looking; it speaks in present tense, but most of this stuff won't be true until some point in the future.
What is Epoch, exactly?
Epoch is designed to be a full-featured general purpose programming language, similar to C, Lisp, and so on. One of the main targets is high-productivity development, meaning that Epoch supports a host of modern language features that make it highly expressive and powerful.
First and foremost, Epoch is a pragmatic language. We're all about getting work done in the real world. This guides every facet of the language's design, and is our core and most sacred philosophy. Some things may be deemed interesting but not useful enough to be first-class language concepts; but, for the most part, if it helps get stuff done, it's going to be richly supported in the language.
What is Epoch's execution model? Where can I run Epoch code?
Epoch is currently hosted by a virtual machine known as Fugue. The Fugue VM includes a parser front end which reads raw Epoch code, and a serialization system that outputs raw bytecode for the VM itself. The goal is for Fugue to act as a reference implementation of the language, and a bootstrapping system for getting things off the ground.
Once the language gains some momentum, Epoch will be execution model agnostic. Running in a VM/interpreter like Fugue is a possibility, but we'd like to see native code compilation and other such features eventually. More on that later on, though.
In short, there's nothing saying Epoch can't be used as an embedded scripting language, or a full native compiled language, or anything in between. We aim to be as flexible as possible, in keeping with our pragmatic philosophy.
When can I use this mystical language?
Right now.
We are committed to keeping regular updates of the language available. This means that the latest version of the language, with all its capabilities, features, and of course flaws, is always floating around ready to be used. This journal is currently the best place to keep up with the project, so if you're interested in picking up the language, hang around here a lot.
More realistically, we aim to support real-world development as quickly as possible. As of this writing the language is largely just an experimental toy, but with the advent of Release 6 (two releases from now) we intend to support full Win32 development. Of course a large amount of work still needs to go into development of a language library, but real-world work will definitely be possible Very Soon.
I also plan to have a fairly rich version of the language (and a demo game or two) ready in time for GDC 2009. So be sure to attend GDC and get one of my demo CDs from me if you're interested in the project!
What platforms can I use Epoch on?
As many as we can get 
Realistically - Win32 is our primary focus, since Win32 is the biggest client for software at this point in time. However, we intend to write ports of Fugue to run on Linux, BSD, and possibly even Mac OS X at some point in The Distant Future. This is subject to time constraints on the part of the project's authors, of course.
However, in the long term we'd like to see Epoch become generic enough to run on pretty much any platform. Again, more on that in a bit.
Who exactly is this mysterious "we"?
Well, ok, fine, it's just me... for now. But I hope to sucker more people in entice more followers soon enough, and hopefully we'll see a community develop around the language quickly. This is one of the big reasons why pragmatism and real-world applicability are so important - if nobody can use it to get real work done, nobody will join the development community.
So why bother creating a new language anyways? Aren't there enough good languages already?
This is the big issue, and it's something that's been weighing heavily on my brain for quite some time now. I think there are plenty of good languages for current computing paradigms. However, I envision a very large paradigm shift in the near future, and I don't currently see any languages which are suitable for taking advantage of the hardware architectures that will come "next."
Specifically, I'm talking about asymmetric multiprocessing. Currently, we see machines with multiple identical CPU cores, all doing their thing. This is fine in principle, but doesn't scale past a few cores, because eventually there isn't enough stuff going on on the computer to keep all the cores busy.
In short, I envision a change towards many "miniature" CPUs, each of which specializes in certain types of processing. One CPU core might look like a modern CPU, with branch prediction, out of order execution, and so on. Another core might look like a GPU, or even like Cell with its SPU architecture. Generally speaking, we will start to see diversification in the way cores are designed.
Programming for such hardware will be similar to current multithreaded programming, but with key differences. For one thing, it will be particularly important to be able to give "hints" as to which processor code should run on. Some code is well-suited to a modern CPU architecture; other code runs best on a GPU-style massively parallel architecture. Some rare code even runs well on the Cell 
While we are seeing some general support for this kind of thing with language annotations like OpenMP and languages like CUDA, there still isn't a really robust, first-rate language out there with first-class support for asymmetric multiprocessing.
So the intention of Epoch is to provide a language that is both modern and rich, while forward-looking to the next generation of AMP-style hardware that is more or less inevitable.
Concluding Thoughts
That pretty much sums up the important details about Epoch. I need to refine the "elevator pitch" a bit so I can explain the concept of the language briefly to someone new to the concept, but the gist of it is pretty much nailed down. I've had a couple of years to perfect it, after all 
You may send your cash, your soul, and/or any other tribute to me via PM or comment here on my journal.
| |
 Back to Epoch for a bit |
Posted - 9/21/2008 8:46:31 PM | Took a break from Castle Crashers to play with Epoch. Didn't do much, but higher order functions now support reference parameters, meaning that this code is now possible:
entrypoint : () -> ()
{
integer(foo, 41)
operateref(foo, incrementref)
}
operateref : (integer ref(number), function op : (integer ref)->()) -> ()
{
op(number)
debugwritestring(cast(string, number))
}
incrementref : (integer ref(number)) -> ()
{
assign(number, add(1, number))
}
I've more or less given up on messing with Visual Studio integration. It's a neat concept and a lot of fun to play with VS's guts, but it's just too much work for a language that's still essentially just proof-of-concept. There's not nearly enough documentation or prior art available on the Intertron to find anything out when getting stuck, either.
For example, I currently have no idea how to define a project type that doesn't use MSBuild, and doesn't implicitly expect a lot of .Net bindings that Epoch doesn't need to have. It doesn't seem like it's easy to do, although obviously it's possible as VC++ does it.
Maybe I'll come back to it later, but at least for the moment it's more productive to work on the core language and get it to a point that makes sense.
Speaking of which, I need to go write an explanation of what Epoch is supposed to be in the first place. I think I'll do that now.
| |
| Sunday, September 14, 2008 |
 Wootness |
Posted - 9/14/2008 10:16:55 AM | Castle Crashers.
Buy it and play it.
That is all.
| |
| Wednesday, September 10, 2008 |
 Visual Studio integration |
Posted - 9/10/2008 5:37:20 AM | I got bit by the insomnia bug again, so I downloaded the Visual Studio SDK and started playing around with it. So far it's fairly huge and daunting, and, like most of the Visual Studio Extensibility stuff, pretty poorly documented.
After spending much of the night screwing around, I finally managed to get a new project type added to VS. Shortly after this will come the actual syntax highlighting and Intellisense support; however, those require that I rewrite the grammar for Flex/Bison (instead of boost::spirit which I use currently). Since redoing the grammar is a pretty major job, I'm going to leave it alone for now.
I might look into seeing how much of a pain it is to use my own parser, in which case I'll just copy the spirit grammar directly, and see how well it performs.
Anyways, shiny screenshots, which are a rarity in the Epoch project right now:

I also took some random time to make some minor improvements to Fugue, so now some things are possible that weren't before, like passing structures and tuples into functions. Higher-order function support is a bit more robust, too.
All in all, a productive day or so... now I just have to figure out this sleeping business 
| |
| Monday, September 8, 2008 |
 Some Epoch shtuffs |
Posted - 9/8/2008 10:09:04 PM | There's still a handful of TODOs left sprinkled around the code, but higher-order functions are now in place. This makes it possible to pass a function to another function, and... ahh, screw it, here's an example:
entrypoint : () -> ()
{
operate(41, increment)
operate(43, decrement)
}
increment : (integer(number)) -> (integer(result, 0))
{
assign(result, add(number, 1))
}
decrement : (integer(number)) -> (integer(result, 0))
{
assign(result, subtract(number, 1))
}
operate : (integer(number), function op : (integer)->(integer)) -> ()
{
debugwritestring(cast(string, op(number)))
}
The increment function is applied to the value 41, which is then written out to the debugger by the operate function. Something similar then happens with decrement and the value 43.
The result, of course, is a shiny little "42/42" output in the debugger window.
Besides being just a plain damn handy feature by itself, higher-order function support will make it trivial to pass functions to external APIs. This means that, shortly, it will be possible to have a callback from an external API into Epoch code, via the marshaling interface of course.
I still have a lot of technical decisions to make about how exactly callbacks will work, but that's a ways down the road; I have to get higher-order functions totally polished off first.
Notably missing is the ability to statically validate a function to make sure it is acceptable. For example, in the above demo, the operate function expects as its second parameter a function that maps an integer onto another integer. Right now, I could pass a function that, say, maps an integer onto null; this would trash the VM's stack and cause chaos.
It's straightforward (but not exactly simple) to validate the function call statically, so that I can't do evil shenanigans like that. Well, to be honest, it is pretty simple - I'm 80% of the way there already - but it requires some refactoring of the way I handle function call validation in general, and I'm too lazy to mess with that right away.
So for now I'll be content with my "42/42" demo program, and we'll tackle static validation another day. I have a feeling there's generally a lot of miscellaneous type work I can do to the VM, so I'll probably sit down and have a hardcore cleanup session sometime in the near future.
| |
| Sunday, September 7, 2008 |
 Higher order functions |
Posted - 9/7/2008 8:41:23 PM | As I mentioned a while back, my big goal for R5 of Epoch is first-class function support - specifically, the ability to work with higher-order functions.
So this afternoon I started hacking away on that. The parser recognizes the syntax and sends off alerts to the parse analyzer, which currently ignores them; so there's obviously still some progress to be made there 
On the back end, I'm about halfway done writing the support infrastructure for handling function signatures, which will be a major component to passing functions around. Once that is finished, I just need to write a function pointer system that actually passes the function references between calls on the stack. That should be trivial, as I already have a mechanism that does something similar for reference parameters.
The final piece then will be linking the parser front-end to the back-end on the VM, which is done via the parse analyzer. In brief, the idea is for the analyzer to set up the VM with the requisite metadata so that the running program can (A) pass functions as parameters cleanly and (B) do type validation on those parameters using function signatures.
Once all this is done, we'll see the following program running successfully in Epoch:
entrypoint : () -> ()
{
operate(41, increment)
operate(43, decrement)
}
increment : (integer(number)) -> (integer(result, 0))
{
assign(result(add(number, 1)))
}
decrement : (integer(number)) -> (integer(result, 0))
{
assign(result(subtract(number, 1)))
}
operate : (integer(number), function op : (integer)->(integer)) -> ()
{
debugwritestring(cast(string, op(number)))
}
Work may or may not get in the way this week, so I have no idea how long it'll be before this is actually finished. Overall though adding higher-order function support has gone a lot more smoothly than I originally guessed.
Combined with some parser refactorings and a couple of minor tweaks to the analyzer, R5 should have a pretty healthy set of improvements.
| |
| Saturday, September 6, 2008 |
 Epoch reference parameters |
Posted - 9/6/2008 7:49:01 PM | With nothing better to do over the weekend, I hacked out reference parameters for Epoch. This means that it is now possible to pass structures to external APIs and get results back. For example, the following Epoch program retrieves the number of processor cores in the host system:
structure msgboxtype :
(
integer(size),
integer(ownerwnd),
integer(instance),
string(text),
string(caption),
integer(style),
string(icon),
integer(helpid),
integer(callback),
integer(language)
)
structure systeminfotype :
(
integer16(architecture),
integer16(reserved),
integer(pagesize),
integer(minappaddress),
integer(maxappaddress),
integer(activeprocmask),
integer(numprocessors),
integer(proctype),
integer(allocgranularity),
integer16(proclevel),
integer16(procrevision)
)
external "user32.dll" MessageBoxIndirectW : (msgboxtype(params)) -> (integer)
external "kernel32.dll" GetSystemInfo : (systeminfotype ref(info)) -> ()
entrypoint : () -> ()
{
systeminfotype(info, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
GetSystemInfo(info)
string(proccountstr, "")
assign(proccountstr, concat("System processor count: ", cast(string, readstructure(info, numprocessors))))
integer(styleflags, 64)
msgboxtype(params, sizeof(msgboxtype), 0, 0, proccountstr, "Epoch test", styleflags, "", 0, 0, 0)
MessageBoxIndirectW(params)
}
Woot.
Of course, simpler programs that use reference parameters also work:
entrypoint : () -> ()
{
integer(foo, 0)
increment(foo)
debugwritestring(cast(string, foo))
}
increment : (integer ref(value)) -> ()
{
assign(value, add(value, 1))
}
All in all, a happy improvement to the system.
| |
| Friday, September 5, 2008 |
 Epoch (what else?) |
Posted - 9/5/2008 5:16:06 PM | So I finally got around to implementing the code to marshal structures back from the Win32 API into Epoch format.
This would be cause for major celebration, except for one minor problem: all variables in Epoch are currently pass-by-value. This means that a temporary copy of a structure is passed to the Win32 API, not the structure itself; which in turn means there's no way to read the marshalled data back from the structure.
Oops.
So now I have to go figure that out, except my head hurts and I'm lazy. So don't expect any progress until... later 
| |
| Monday, September 1, 2008 |
 Epoch Release 4 |
Posted - 9/1/2008 4:20:32 PM | Release 4 of the Epoch language prototype is now available.
Lots of new goodies in this release, which you should be familiar with if you've been following my journal lately. I'm too lazy to be keeping a work log at this early stage of the project, so a comprehensive list of changes isn't available, sorry.
The main goodies are tuples and structures (records). Please note that support isn't fully first-class yet - passing tuples/structures to functions isn't totally implemented, for example. I expect to shore up that kind of stuff shortly.
Enjoy R4, and as usual, your comments and feedback are requested; if you encounter any shortcomings that you'd like to see fixed sooner rather than later, please feel free to let me know.
[edit] Link fixed.
| |
In locus hic, omnes res dementes sunt.
|
| S | M | T | W | T | F | S | | | 2 | 3 | 4 | | | | | 9 | | 11 | 12 | 13 | | 15 | 16 | 17 | 18 | 19 | 20 | | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | | | |
OPTIONS
Track this Journal
ARCHIVES
July, 2009
June, 2009
May, 2009
April, 2009
March, 2009
February, 2009
January, 2009
October, 2008
September, 2008
August, 2008
July, 2008
June, 2008
May, 2008
April, 2008
March, 2008
February, 2008
January, 2008
December, 2007
November, 2007
October, 2007
September, 2007
August, 2007
July, 2007
June, 2007
May, 2007
April, 2007
March, 2007
February, 2007
January, 2007
December, 2006
November, 2006
October, 2006
September, 2006
August, 2006
July, 2006
June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
|