Tuesday 19 April 2011

C as a Systems Language

The "Systems Language" definition is a bit fuzzy. I'd say it has to have address manipulation, type coercion (not conversion but all that evil stuff with unions and the like). It should also support plenty of bit meddling operations and structures.

To this end C has served well.

What has not served well has been the standard libraries and it's evolution.

Huge amounts of the specification can no longer change due to backwards compatibility. For example, we really don't need both typedefs and structs. We really could use polymorphism and even templates (without classes). We could build an object system (ala QObject or Objective C) if we had a slightly better macro system. The typedef synonym system really doesn't work well with automatic type conversion (which should be banned!). The string format is a bit... hmmm... It WOULD be FAR more efficient to store length (I really can't over-emphasize that!)

We could... but it works.

Maybe there's a need for a "new" C... but maybe what we've got is just damn good enough.

I say this as I just been rolling a new first fit and buddy memory allocator - it would be nice to have ref counted objects but, you know what, we can still work without them.

Monday 18 April 2011

Flow... Explicit vs Implicit

Our computer programs are generally written with the idea that data processing runs from the top of the app the the bottom and may loop round again. Whole programs are written by putting lots and lots of these pieces together.

EDGE programs may be written the same way and re-interpreted to make a graph like system or vice versa - in fact we can translate between representations (compilation and optimisation patterns often use SSA - Single Strategic Assignment - which is a lot like a simple graph).

My code will look a lot more like EDGE than, say, C. This seems a good way to represent a program pre-compilation and for use in a graphical environment.

Friday 15 April 2011

No Update Today?

Yup, just a little one.

I'm gonna use Qt for GUI work - yup, I also understand that most of this stuff isn't GUI at all but I'll probably steal their colour coded editor or just plane old QTextEdit, wrap some open/close stuff around it and call it a UI.

There are advantages to working this way - think multiple tabs and/or multiple windows - one shows you your central scripting whilst the others change as fast as possible to show how your models are turned into code, interpreted, graph outputs etc. Very nice.

One disadvantage is that an installer gets "big" once you've added all of Qt's libraries. Linux with it's dependency system doesn't worry too much. Windows - well you have to ship 'em and same with Mac.

I work almost exclusively with Linux (Ubuntu & Android to be precise - although Angstrom is on my list soon too). I do have a Mac (used to be for iPod/iPhone dev - but I simply don't have time to do that anymore). Windows - I don't even have a machine.

Qt also added QAudioInput and QAudioOutput recently - I'm not sure what the backing code is but I don't really mind. I used to use PortAudio but doubt I will anymore.

Right, next time a lot more on machines then samples and graphing.

Thursday 14 April 2011

Going Native

Machines

We defined a machine as a functional unit - give some input data it will produce some outputs.

To map to native code inputs will be mapped as a pointer (that points to a machines output - note, it _could_ be itself).

To map to native code outputs will be represented as physical storage.

Every input and output can be named (and maybe typed one day).

Somewhat stolen from Forth is the idea that a machine can be compiled - once compiled a lot of dead code can be eliminated BUT (and it's a big but) what's within the machine can no longer change - the data flowing through it can change (necessarily) but we can't add or remove components nor can it's output to input connections be changed.

You don't have to do this though. If you continue to interpret your machine all edits are still possible - it will just run a bit slower (probably about 10 times slower!)

Wednesday 13 April 2011

Me again... graphs this time...

Not the sort with an x and y axis that show you data but interconnected nodes.

These graphs are a collection of "nodes". Each node in my system represents a function, some work and has a number of inputs and outputs.

Inputs are connected to outputs of other nodes (or in fact the same node - they can represent feedback and this is both annoying from a functional perspective but also incredibly useful, nay essential, for programming - my view is that although it creates a slight problem in that is is impossible for a node to ever be coherent it creates an opportunity by allowing feedback to be used as memory).

An input can only be connected to a single output (the reasoning here is that all work must be done by a node - if we simply connect 2 inputs to 1 output what work would need to be done to merge those inputs... and, or, addition, multiplication??? It's ambiguous and thus avoided).

MACHINE

A collection of connected nodes is called a "machine".

Each node has a "type" (this saves us duplicating every single machine of every single type!)

Each node has a name - this must be unique to the environment that it is contained in (but does not preclude a machine within this one from having a machine with this name)

CYCLE

Once per output sample the entire machine (the outer one) is cycled. At least 1 of its inputs needs to be connected to something "outside" the machine - in this case the audio circuitry. Top level inputs could be connected to other devices but don't actually need to be (we can build a whole machine to represent a song).

THE SPECIALS A.K.A. The Coventry Automatics

"Special" machines are built in and deal with lovely stuff like loading and playing samples, simple oscillators, time conversion (time is a MASSIVE subject for discrete mode synthesis), basic math operations.

My original intention was to build the entire thing to run as 32 bit ints (which is possible for basic synthesis) but I think the standard atom/quanta of information will be the 64 bit int or double. Much more powerful even if much slower.

Lunch nearly over... more soon!

Tuesday 12 April 2011

How to allocate executable memory on Linux...

#include <stdio.h>
#include <sys/mman.h>

typedef unsigned (*asmFunc)(void);

int main(int argc, char *argv[])
{
// probably needs to be page aligned...

unsigned int codeBytes = 4096;
void * virtualCodeAddress = 0;

virtualCodeAddress = mmap(
NULL,
codeBytes,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE,
0,
0);

printf("virtualCodeAddress = %p\n", virtualCodeAddress);

// write some code in
unsigned char * tempCode = (unsigned char *) (virtualCodeAddress);
tempCode[0] = 0xb8;
tempCode[1] = 0x00;
tempCode[2] = 0x11;
tempCode[3] = 0xdd;
tempCode[4] = 0xee;
// ret code! Very important!
tempCode[5] = 0xc3;

asmFunc myFunc = (asmFunc) (virtualCodeAddress);

unsigned out = myFunc();

printf("out is %x\n", out);

return 0;
}

Of hyper-graphs, sound and "issues"

As I wander my merry way through life, digging the garden, playing with Charlie, sorting out the car... I wonder things like "how do I allocate memory that is executable and can be used by a dynamic compiler?"

Then I think, g'z - it's going to be different on different machines!

So that's were I'll start first, then we'll get the parser (very simples), some GUI output, a compiler (of sorts), an interpreter (of sorts) and hopefully some sound (yay!)