The Magenta Annotated Partial Reference Manual

Brian Connors
4 October 1999


What is this?

What you have here is the original Magenta programming language guide, marked up with italic commentary from 1999 explaining what the hell I was thinking. The original is in plain text; corrections have been made to this version here and there, and section headings have been regularized, complete with numbers and a few minor rearrangements for organizational purposes. There are also a few additions here and there that aren't in the supplemental manual; they're in italics.

What this isn't is a complete reference manual for Magenta as it stands now. Apart from a few features that were added here because they were too simple to bother with an explanation in the supplement manual, this is substantially the same as the original document that I cranked out in 1995. If you want to do a full implementation, you need the supplement. However, I wouldn't mind seeing someone write a full manual based on these two documents.

Enjoy.

-Brian (bc99)


This document is (c) 1999 Brian Connors.

The following remain unfinished [and shall remain unfinished, I suppose -- bc99]:

1 comments and block structure

note: this language, for convenience, will be referred to as Magenta in these notes until we can come up with something better. Of course, "we" already had, but it was taken. --bc99

1.1 block structure delineation

The procedural subset of Magenta derives from a hybridization of the Algol and C models, with a few ideas to itself. Both an Algol begin/end and C {} block format are supported.

Not to mention Ada's named-block syntax. --bc99

Magenta is closer to Algol or GNU C than standard ANSI C in the implementation of blocks in that functions can be local or global.

Although begin/end and {} constructs are interchangeable, they may not be used together in the same block.

I don't even know if this is possible syntactically. The chief problem with it is that you probably can mix and match constructs, great for the IOMCC (International Obfuscated Magenta Code Contest) but rather useless and even dangerous in practice. -bc99

1.1.1 begin/end

Begin/end is the primary form. It is best used for procedure or function definitions:

--this example actually demonstrates both forms, but the prime focus
--is the begin/end clause

function feedthebear (enum[bear] whichone, enum[food] bearfood)

begin
	bool fed;					//if all goes well...
	whichone[call] ();
	try	{
		whichone[eat] (bearfood);
		throw (whichone[eat](armp));		//armp is a global indicating
	}						//zookeeper's arm
	
	return (fed=TRUE);
end;

I have no idea what this example means or where it came from. I have been ridiculed for it in the past and I don't suppose I will ever figure out why I wrote it.

I *think* that the idea is that the zookeeper is told to feed a specific bear; the exception call (which should have been play/punt instead of try/throw) is supposed to trigger a response in case the bear gets a little too much of the munchies. Your guess is as good as mine what the return statement is supposed to do, but I suspect fed should have been declared as a package-level variable. In addition, I have not a clue what those enums are doing in there; bear and food datatypes should be perfectly acceptable. The code *probably* should look like this:


--declare a static or persistent variable somewhere else in the package...

bool fed;

function feedthebear (bear whichone, food bearfood) returns bool is:
	whichone:call();
	try	{
		whichone:eat(bearfood);
		throw (whichone:eat(armp));		//armp is a global indicating
	}						//zookeeper's arm
	
	return (fed=TRUE);
end feedthebear;

In this case, fed is set within the return statement and the value returned is actually a boolean indicating that the assignment was successful. Of course, the function declaration syntax is a little vague... --bc99

Begin/end is probably most intuitive when used as shown above, that is to indicate the beginning and ending of a procedure definition. Note that a semicolon must appear after the end statement.

1.1.2 braces

The use of braces as in C is interchangeable with begin/end, but finds its best use in other circumstances, such as loop definitions and the like where begin/end would be unnecessarily clumsy. Like begin/end, the clause must end with a semicolon.

--this loop prints out the numbers from 1 to 10 to the console in increments
--of .5.  

for i(1 10 step .5) {
	print(i,"\n");
};

1.1.3 is:/end

<specifier> <object> is: ... end <object>; This construct is most useful for record or class definitions, although it also has other uses [and will henceforth be known as the named-block syntax. Several times throughout this text and its companions you'll find the words "syntactic saccharin", something that's cute but useless. This is the first example.

structure cube is:

	int x;
	int y;
	int z;

end;
This most likely should be struct instead of structure, but I was trying to be different. --bc99 This is pretty much syntactic sugar. The construct also extends to other forms, such as the cases in a switch block:

switch(i){
	case TRUE is:
		print("whaddya, stupid?");
	end;
	case FALSE is:
		print("whew, that was close.");
	end;
	default is:
		exit;
	end;
}
A reminder: this is not a C switch construct. The Magenta construct (see below) has some rather unique properties that make this example rather strange. Also, it indicates that as long as the compiler can tell the difference, the block's name doesn't have to show up in the end statement. --bc99

The general case starts with : and ends with end;. The keyword def is generally meaningless, but is suggested for readability.

Def? would that be default? I have no idea if this meant something.

One other thing to say about named blocks: regarding the previously mentioned named for loop, its syntax is left as an exercise to the reader.

1.2 comments

Magenta comments come in three styles, derived respectively from Ada, C++, and C. The third type is actually not a comment but a form of conditional compilation directive.

The funny thing about that last bit is that I actually use it in the supplementary manual. I'm not proud. --bc99

1.2.1 block comments

Block comments are Ada-style, beginning with a double hyphen at the left margin and terminating with a carriage return. It is highly recommended that they not be placed in the actual body of the program.

--This is a Magenta block comment.  The double hyphen only works to the
--end of the line.  It was chosen for readability and unclutteredness.
--And sheer copycatness. --bc99

1.2.2 line comments

Individual comments in a line of code are done with a double-slash a la C++. They end with a carriage return.

int foo(15,15);			//what does the foo map look like?

1.2.3 code comments

What, this old thing? I'm not quite sure whether any of this is a good idea. It's interesting, but fairly byzantine, and I'm not sure it's implementable in any practical manner. --bc99

In Magenta, the /* */ C-style comment is reserved to act as a conditional compilation directive. The code within the beginning and end symbols should be legal code if the conditional compilation directive placed in brackets after the beginning is used. Otherwise it is interchangeable with the other two varieties. /* */ comments may be nested, but only if they are used for conditional compilation and not as block comments.

/* This is a comment, people. */

/* [?_unix]		//the brackets indicate a condition to fill in order to 
				//compile the following code.

--this, on the other hand, should be legal code.

[else]

--this is the code that gets compiled on another machine.

 */
Definition symbols can be upper or lower case. The following are the definition-testing symbols:
?condition		if the following condition is true...
!condition		if the following condition is false...
else			assuming the last test was false, do this instead.

2 Reserved words in the Magenta programming language

begin		end 		is			case
switch		if			alloc		else
for			step		rerun		continue
break		while		end			do
until		except		wrapped		kibo
and			or			not			xor
with		exit		return		call
play 		punt		catch 		structure
union		int			char		class
wide		long		double		function
procedure 	member		public		private
protected	friend		virtual		container
gc			goto		to			lest
task		priority	It			signal
reciever	xp			yp			zp
rp			ythetap		zthetap		persist
volatile	const		external	evil
static		persist		bool		module
from		as			operator	kill
default		typedef		negative	daemon
Though several of these might have different forms on a Unicode machine, particularly the theta words. The amazing thing is that Magenta has well over eighty (well, maybe ninety now if you consider the supplementary material) reserved words. Of course, according to my copy of the draft C++ standard, there's about seventy there, so this is in good company. --bc99

3 Operators in the Magenta Language

Operators are predefined with regard to identity and precedence, but meaning can be overloaded. This table is obsolete; I've javafied or C-ified most of the operators.. See the supplementary manual.-bc99

operator	default meaning				direction		
------------------------------------------------------------------
()		force precedence
:		member					l->r
~		external label				l->r

-(unary)	negative				l->r
!(unary)	not					l->r
-> 		pointer to (address)			r->l
<-		contents of				r->l
sizeof		size of an object			r->l

++(unary)	increment				operand->operator
--(unary)	decrement				operand->operator

and		bitwise AND				l->r
or		bitwise OR				l->r
xor		bitwise XOR				l->r
~		binary select				l->r
$		binary mingle				l->r

[Intercal has a few interesting features. Frightening, but interesting. 
See the companion doc for info. --bc99]

^		exponentiation				l->r

*		multiplication				l->r
/		division				l->r
mod 		modulo					l->r

+		addition				l->r
-(binary)	subtraction				l->r

<< 		shift left				l->r
>>		shift right				l->r

< 		less than				l->r
<=		less than/equal to			l->r
>		greater than				l->r
>=		greater than/equal to			l->r

==		comparison				l->r
<> 		not equal to				l->r

&		logical and				l->r
:=		assignment				r->l

,		comma					l->r

Character sets that support them may substitute the appropriate
symbols for ->, <-, >=, <=, $ (==US cent sign)

4 Declarations

Simple types:  |<storage class>| |<qualifier>| <type> <identifier> |with <unit>|;
compound types: |<storage class>| |<qualifier>| <type> <identifier> { <declaration> }
|<alias>|;
The alias is designed to be used in conjunction with the typedef qualifier.

4.1 Scoping qualifiers

|...| refers to an implicit identification

|local|--may be declared at any level; will remain in existence until its declaration block goes out of scope

Syntactic saccharin, like auto in C.

global--the variable created has unlimited scope after its creation; implicit at top level

Actually, if I had written down my ideas for packages, this would probably not be in here. It's a rather silly idea anyway.--bc99

static--scope is limited to the block it's created in, but its value remains constant until creating block comes back into scope

persist--scope is limited to the block it's created in, but its value remains constant between invocations of the program

This one could make for some very interesting implementation issues in the runtime library. On the upside, it would drastically simplify anything involving file-handling, but I never added syntax to define a specific persistent file. See the supplementary manual if you want one possibility. --bc99

private--accessible only within a module or class

protected--accessible within a class or all derived classes (illegal and redundant for modules)

public--accessible to all parts of the class or module's scope

reciever | for <id> |--accessible to a specified signal block; otherwise local

More specifically, it's intended as a simple way to do interprocess messaging. If a variable is declared as a reciever, outside threads can see it and change it (as long as it's not declared private or something like that). --bc99

external--defined elsewhere

kibo--value is local, name is global; thus can have different values depending on scope of the variable. The value of a kibo variable can be defined globally, but if reassigned locally it takes on a different value local to that scope, while retaining its global value elsewhere.

As a matter of fact this is completely useless. Does anyone still remember the name of James "Kibo" Parry? --bc99

4.2 Type Qualifiers

const--may not be assigned to or otherwise changed

volatile--may change

evil--will seriously f--- up your system if you mess with it

Used in system includes to mark things you shouldn't screw with, I suppose. --bc99

short
long
wide
double--type- and compiler-specific

unsigned--positive only

negative--negative only

wrapped |[<range>]|--rolls over when the value in the <range> parameter is reached; defaults to MAXINT or the maximum value of the enumeration fof integral and enumerated types respectively.

Does Perl do this already? Perl does so much it's hard to tell. -bc99

4.3 Data types

Note that any data type not explicitly listed is undefined and can thus do whatever the compiler writer's twisted little mind desires.

4.3.1 Primitive Types

Note: Integral types may be assigned a unit (kg, cm, smoot, etc.). And this was many years before I learned VB. Realistically, this should be handled with a format command. -- bc99

4.3.2 Enumerations

Enumerations are declared using the following syntax:

|<qualifier>| enum { <label list> } <identifier>;
An enumeration may not have more entries than MAXINT. An enumeration may be used in any manner identical to an integral type, although it may not accept a unit.

An enumeration declared 'kibo' may have different values in different parts of the program, according to the specification of the 'kibo' qualifier.

4.3.3 Composite Types

See the section on the Magenta Object Model for full details.

I dropped the ball on this one, got my concepts of object model inside out. This actually should be a package, but my education was not what it is now, and this entry consequently fails to make any sense at all. --bc99

4.3.3.1 Use of It

It is an internal data type that is replaced with the local variable last used in a previous expression within the same block. It, due to the scoping rules of the language, works only within one level of one block at a time. It may be used in multiple processes, but the meaning is strictly local to each one. It is an error to declare It static. It is also an error to assign to It, since It is implicitly assigned.

task feed_fish(food Fishfood, fish Goldfish) [yp=lastproc+1, \ zp=MINPRIORITY] begin
	bowl Fishbowl;
	commode toilet;
	
	get(Fishfood);
	feed(It, Goldfish);		//It=Fishfood here
	
	toilet=Fishbowl:empty();
	toilet:flush();
	clean(It);				//It=toilet here
	
end;

4.4 The Magenta Object Model

4.4.1 Overview

The Magenta language has a static object model based largely on that of C++. The various supported features include:

Did I miss anything? Yes, I did, actually. Packages. -bc99

There are three types of object recognized by Magenta; the distinction is made by the nature of the declaration.

The module/class distinction is as follows:

Okay, so I hadn't taken OO Design yet. This was based on a misunderstanding of part of Marshall Cline's C++ FAQ book. This is probably... I don't know what this is in real life. It's a COM object (a la ActiveX, with no inheritance, etc.), I think. --bc99 Both are subject to garbage collection. Automatic garbage collection is not built in to the language, but is included as a daemon task in one of the standard libraries.

If I had it all to do again, I'd go the Smalltalk/ObjC/Java route and make it an OODL instead of following the C++/Simula static OO design as many on afc suggested. But I hadn't taken Programming Languages at that point either. --bc99

4.4.2 Definitions

class--see above

composition--the insertion of a class or module as a member of a class or module

container class--a class defined in terms of an incomplete definition with the incomplete part being an indeterminate type to be defined as a parameter to the class.

friend--affects internals of the class or module, but is defined elsewhere

inheritance--the creation of a derived class by adding on to a base class

module--see above

4.4.3 Object Model statements and syntax

The <identifier> is:/end <identifier> syntax will be used for these definitions.

4.4.3.1 Declarations

4.4.3.1.1 Classes

--This is a skeleton for a declaration for a standard class.

class <identifier> is:	
	public { public declarations};
	|private { private declarations };|
	|protected { protected declarations };|
	|friend { friend declarations }|;
end <identifier>;
Inheritance is indicated using the following syntax:
	public from <identifier>;
where <identifier> indicates the class inherited from. Multiple inheritance is indicated by multiple 'from' clauses; composition is indicated simply by including the class(es) to be added in with the standard declarations.

A better way would be

	class <identifier> extending <identifier> is:
		<yada yada yada>
	end <identifier>;
But that would make too much sense, and would therefore be inappropriate to this situation :-) --bc99

4.4.3.1.2 Container Classes

--this is a declaration for a container class

container class <identifier> (<type parameters>) is:
	with <typeidentifier> as { list of types };		
		//an insidious plot to force type correctness
	public { public declaration };
	|private { private declaration };|
	|protected { protected declaration };|
	|friend { friend declaration };|
end <identifier>;
The with clause is required for a container class. The with clause keeps track of what a virtual function can take; if type correctness is to be overridden, there is a special 'anything' declaration that tells the compiler to figure it out for itself.

I'd like to see someone figure that one out --bc99

4.4.3.1.3 Modules

--this is a declaration for a module

module <identifier> is:
	public { public declarations };
	|private { private definitions };|
	|friend { friend declarations };|
end <identifier>;
It is illegal to add a 'from' clause to a module declaration.

4.4.3.2 Member access

Class, structure, union, or module members are accessed using the following syntax:

<classname>:<itemname>
Functions, procedures, or tasks can be called using

<classname>:<functionname>( parameter list );
Friend items are accessed by their names apart from the class, since they are defined outside the scope of the class.

4.4.3.3 Operator overloading

In order to do something predictable to a class or module when you use an operator on it, there is a built-in operator overloading feature.

To change the meaning of an operator, one must define the operator as a friend function related to the class or module in question. The definition may be local.

Syntax:

	friend operator <operator> (<param1>, <param2>) is: { <body> };

5 Program Structure

Or, everything other than declarations. I got very sloppy writing this manual, and the section headings have gotten quite confusing doing this markup. --bc99

5.1 Control Flow

Control flow is of course vital to a computer program. The Magenta language has a generous set of control constructs, each fairly useful in their own twisted way...

If some had had their way, Magenta would have been a functional language, and maybe only if and switch would have made it in here. But that's not how it worked out. With the exception of the non-block-oriented stuff, this has been superseded by what's in the supplementary manual anyway. --bc99

5.1.1 Looping

The {} syntax will be used in the following examples.

5.1.1.1 while

while ( <condition > ) { body of loop };
The while loop is evaluated zero or more times, with the exit condition evaluated at the top of the loop.

5.1.1.2 do/while

do { body of loop } while ( <condition> );
The do loop is evaluated one or more times, with the exit condition evaluated at the bottom of the loop.

5.1.1.3 for

for (<initial condition>; <exit condition>; step <quantity> |except
	<condition>|) { body of loop };
The for loop is evaluated according to the 'step/except' clause. The step keyword defines the amount and direction to increment the loop, while the except skips the points where the expression indicates. The index variable may be either an integral type or an enumeration and may be wraparound types. I have much to say about this construct in the supplementary manual. Basically, cute but stupid.

[We forgot 5.1.1.4 until

until <condition> { <loop body };
5.1.1.5 do/until
do { <loop body> > until ( <condition> );
Don't know why. --bc99]

5.1.2 Block control

5.1.2.1 Goto

goto <label>;
goto is just an unconditional branch. It does not work between functions.

not pointed out: labels are literal addresses. That would make alter and entry constructs possible. See the supplement for details. Also, the supplement details a comefrom structure just for the halibut. --bc99

5.1.2.2 set/jump

set <label>;
jump <label>;
set sets up a position in the program for jump to jump to. It works between functions but is disparaged.

Disparaged? Why? It's in here for the same reason as setjmp/longjmp in C: to unwind the stack if things get messy. It may be disparaged, but it shouldn't be.

5.1.2.3 break

break;
Jumps out of the current block to the next level out.

5.1.2.4 continue

continue;
Jumps out of the current iteration of a loop and begins the loop again.

5.1.3 Conditionals

5.1.3.1 if/else
if (<condition>) { <statements_if_true> } |else {<statements_if_false>}|;
Basic if statement with optional else clause.

5.1.3.2 Switch

switch <condition_variable> begin
	case (<condition>) { <statements> };
		...
	default { <statements> };
end;
Basic switch statement.

No it isn't. The individual cases are blocks, not simply labels, so there is no fallthrough. See the supplementary manual. --bc99

5.1.3.3 unless

unless <condition> { <statements> };
Meaning don't even bother if it ain't true.

5.1.4 IPC Structures

If Magenta has a strong point, it's the IPC handling. It's very amateurishly designed, but what's there is quite useful. By treating when and during as control structures, the process of writing multithreaded controls is much simpler. Of course, it would be a pain to implement, but Magenta, at its heart, is not a simple tool, but a fuzzy-minded collection of things that seemed like a good idea at the time. --bc99

5.1.4.1 when

when <task condition> { <statements> };
Stops current thread to watch for a condition in another thread, then executes its body.

5.1.4.2 during

during <task condition> { <loop body> };
Watches another task within the same program and keeps executing the loop while that task is true. The loop will always finish its current iteration when the exit condition is fulfilled.

5.2 Exception handling

Magenta, being as it is such a useful language, has a built-in exception handling model. The general model is based on the philosophy of passing the buck--if you can't deal with it, punt.

Well, don't literally punt... Well, okay.

Punt makes as much sense as throw, if you think about it, and more than raise. The syntax was nevertheless quite awkward, and a bit silly. -bc99

5.2.1 The exception model

The catch block is ideally implemented as a separate task under the main program begun at the point of the punt; failing that a function block is a legitimate replacement.

The exception frame is set up with a play block terminated with a punt condition. If the play block fails, then the punt condition automatically transfers control to the specified catch block. The current task is terminated.

Catch blocks return to the original calling function by default; they can be reassigned anywhere.

The lest clause calls an abort function unless a specific catch block is specified; it is invoked primarily as an escape when the normal flow of a loop block is disrupted and its primary use is for dealing with timing failures involving reciever variables.

I promised an explanation of what I was smoking; unfortunately, I think like this as a general rule, and smoking something would probably make me sane. lest is possibly one of the weirdest constructs in the language, and it is very much Intercal-inspired. The semantics are something like on error goto in Basic, though good taste might limit it strictly to sanity checks and that sort of thing. Interestingly, I believe it predates the finally clause in Java, and seems to do exactly the opposite. Needless to say, if I was creating Magenta now I'd have both of them in there. --bc99

5.2.2 Syntax

{} block syntax will be used for the following descriptions.

5.2.2.1 play/punt

play { questionable_routine } punt |to| <catchname>;
This is the syntax for a play/punt block. The 'to' is optional. [Why? Syntactic saccharine. It's becoming my favorite phrase.--bc99] Under Canadian rules there is no touchback for a dropped punt; therefore if it is assigned to a null or illegal handler, the compiler should return an error.

Canadian rules, eh? Something to do with the fact that as a BC student (now grad), Doug Flutie had to be a hero of mine. To those of you living under a rock, before ripping it up in Buffalo Flutie was the single best damn quarterback the Canadian Football League had ever seen. I think it was a tribute. --bc99

5.2.2.2 catch

catch <catchname> { cleanup_routine } |<return_to_label>|;
This is the syntax for a catch block. The return_to_label is wherever the return from the catch block is to be sent; as stated above the default is the routine that called the punting routine.

5.2.2.3 lest

<loop_type/setup> { body of loop } lest ( condition ) |<catchname>|;

lest (condition)  { routine to run } |<catchname>|;
The second is useful for failsafing non-loop constructs.

This meant something at the time. I swear. As I said before, lest is in here because it sounded good. I believe the idea was that a lest clause would be executed if the block it was attached to failed for some reason. Another way of doing an on error goto, I suppose. --bc99

5.3 Concurrency

Because any language that comes down from on high has to have proper thread support. None of that silly library business. --bc99

5.3.1 Concurrency model in the Magenta programming language

The concurrency model of the Magenta programming language is based on a three-dimensional grid. Each axis represents an aspect of the current process:

z<-process priority (decreases away from origin)
|
|
|
|
|
+----------x<-intraprocess control flow
 \
  \
   \
    \
     \
      y<-process number
The y-axis can be replaced with a ytheta value for queued processes with limited lifespans.

The z-axis can be replaced with a ztheta value of user-defined size for processes with rotating priorities.

Tasks created without explicit positioning are given the values zp=1 (highest priority for a non-main process) and yp=#lastproc+1 .

Given a process proc, the y and z axes are defined as

	yp=#(task)proc		//the process's task number
	zp=#(priority)proc	//the current priority
If the radial system is used, the values rp, ythetap, and zthetap (canonically represented using the Greek letter theta as opposed to the word theta) replace xp, yp, and zp as needed. The theta values are given a range and the tasks assigned to them are queued in such a way that as a task passes out of the queue, its number is reassigned to the next task into the queue.

A zero priority coordinate results in the termination of the calling thread; the default is a priority of 1.

A zero task number on a linear task axis, if assigned to anything other than the main thread, produces undefined results. On a radial axis, the result is a program with no real main thread.

A task is invoked in the same manner as a procedure or function; the current process continues unless an explicit zero-priority directive is issued.

	<taskname> [<number/priority coordinates>] ( <parameterlist> );
A task may be defined in terms of priority.

A task may be declared a daemon task; these become active when declared and are terminated when they go out of scope.

At the time I had never heard of Befunge; this mess was loosely inspired by the original Orthagonal. The basic point here was that I couldn't see any real use for multidimensional process control *unless* it had something to do with concurrency. I know better now; it has no use at all :-) --bc99

5.3.2 The signal/reciever keywords and intertask communications

5.3.2.1 Signal

signal <task[:label]> [when <condition>] {items to send} to <reciever>
signal passes information between tasks to a specific point within the recieving task. That point is specified by a label or a specified condition within the recieving task.

A signal with no specified condition assumes the signal goes into effect at the first invocation of a reciever variable.

The presence of a label in the signal statement indicates that the signalled information will go into effect at the corresponding label in the recieving task.

The presence of a when condition in the signal statement indicates that the signalled information will go into effect at the first invocation of the corresponding reciever variable after the when condition is fulfilled.

comments:

5.3.2.2 reciever

reciever <type> <variable name>
reciever is a type qualifier that indicates that the variable specified may be used as a container for a signal from a different task. Any local variable which can be changed from outside the task must be declared a reciever variable.

Wow. What little I knew. What's missing here? You take your pick. Sockets. Semaphores. Shared Memory. Synchronization. Lots of other IPC-related junk that probably begins with S. Doing it over again I'd squish it all into the runtime library and build an object-POSIX type interface using streams and SysV IPC together. But I never did get to the runtime library. --bc99

5.4 Memory Management

Not too well thought through, this part. It would work, but I'd probably do it somewhat differently if I was redesigning it. --bc99

5.4.1 alloc

alloc (<type>);
Built-in function that returns a pointer of the specified type to the caller.

5.4.2 kill

kill (<type> |, <offset>|);
Built-in function that destroys the allocated object (if offset is specified, the result is that the object occupying the specified area after the object having the kill called on it is killed instead).

5.4.3 gc

gc;
Sweeps up all unused non-persistent objects and variables and resets all inactive kibo-declared variables to the value of the widest-scoped declaration.

--End of the original Magenta reference manual--


Parting Comments, 1999 update

Magenta could have gone in half a dozen different directions. I was looking for something of a systems-programming language with pretensions of dynamic object-orientation, like ANSI C++. A lot of the alt.folklore.computers crowd (henceforth known as "AFCers") were pushing for features more in common with Lisp or ML, such as a functional paradigm; one suggestion even took it to an extreme by suggesting that the source code be kept in its own object so that a program could be quit simply by a call to the effect of Source:kill().

I have a few gripes with the language as it stands anyway. My liberal use of brackets almost completely fails to make sense four years later, and (as you read in my note on the bearfood program) I have no idea how a function call was supposed to work. The object syntax came out slightly Smalltalkish, interesting given the language's rather static nature. The libraries were undefined, although I had some inkling that a basic graphical interface was part of the package. Filesystem? No idea. Networking? Uh, no. Console? Well, more or less C-like, though extended a bit.

And then there's the manual itself. It would be an understatement to say it was sloppy; I gave up early on the sections, resulting in a poorly-organized mess. The HTML markup for the annotated version has been an absolute bitch, but it resulted in a much more usable document, I think. As a result, it now has proper section references, plus a few things that are here now that were left out before. This may be enough to help make sense of the whole mess, in case someone was crazy enough to try to implement this. There are many changes to the old document, but the reorg is probably the most important as far as readability is concerned.

There's a separate HTML doc on this site that describes what could have been part of Magenta, including the package system (a deranged parody of Java's), variagents (sort of object-method-as-procedural-thread; the name came out of a travesty generator), and a few things I'd throw in now, including fragments that were considered for the Dominatrices. Check that out for even more weirdness, and feel free to add things.

/Brian
24 September 1999


Click here to return to the Magenta page.
Click here to return to the Turing Tarpit. 1