|
|
|
|
By Andrew J. Wozniewicz
Milwaukee, June 17, 2007
These are sanitized (spelling-corrected) excerpts from my original newsgroup post in response to Juanca. Note that many details of the language have changed since then. -AJW 2008/08/05
I already have devised most of the language called Modula-7.
Originally, I had all statements terminated with semicolons, but I now think
this is unnecessary, except in some very specific cases. Here are some
highlights of the language, again, by way of example:
project ProjName
attribute SomeAttr="XYZ" // That's the way to set them
attribute Name="NewName" // Redefines proj name
// Not that this is a good idea, but consistent
// Programmer has access to *all* attributes
import BuildLib;
//Other scripts incorporated this way
// This is exactly equivalent to saying "depends"
//Anywhere within a block, executable statements can go
// Setup event handlers
EventBuildSuccess += OnBuildSuccess
EventBuildFailure += OnBuildFailure
//Default procedure/target calls go here
Compile() // Calls may have to have empty parens
// Declarations are valid within
// the entire scope of the enclosing
// element (multiple passes required)
const
Whatever = 42
ProjectSource = "want.dpr"
var
Version = "1.2.0" //Implicitly typed as String
Counter = 0 //Implicitly typed as Int
type
TWeekdays = (Mon, Tue, Wed, Thu, Fri, Sat, Sun)
TRange100 = 1..100
target Target1
//Target is just a special procedure
// with no parameters.
depends Target2, Target3;
//Lists of identifiers are in
// general terminated with a semicolon???
task DCC
Source := ProjectSource
// Passing trees is a problem here
// Lists/Collections are no problem
define SUPPORTS_WIDESTRING
// Implicit add to the collection
define ANOTHER
end
end
procedure ShowMsg(...)
// Multiple, anonymous, parameters...?
task Echo with
//It will take whatever is passed.
...
end
Counter += 1 // Yeah, I like those :-)
Echo("Continuing...")
//Alternative way of invoking tasks/procs
end
procedure LetsSeeSomeLogic(Param1, Param2)
procedure Internal
// Yes, nested procedures, but not tasks
var X, Y, Z //Only visible in Internal
end
var X, Y, Z // Locals
if param1 then
WriteLn("Param1 is true")
else
WriteLn("Param1 is false")
end
switch Param2
case 1:
WriteLn("Param2=1")
case 2..10:
WriteLn("Param2=2..10")
else //or case else
WriteLn("None of the above")
end
"End of procedure"
// could this be a shorthand for WriteLn()?
procedure Internal2
// OK, maybe an overkill, but thus avoids BEGINs
end
"Can execute statements anywhere within a procedure block"
end
function Fib(N)
if N in [0..1] then
Result := 1
else
Result := Fib(N-1) + Fib(N-2)
end
end
function Sum(N)
var C = 1;
Result := 0
while C <= N loop //or do
Result += C
end
end
procedure OnBuildSuccess
"Build succeeded"
perform EMail with
AddrTo := "recipient@domain.com";
AddrFrom := "wantscript@domain.com";
Subject := "Notification from WANT";
Body := Message;
end;
end
whitelephant Bamboo
// statements go here
// if the exec env. does not know what whiteelephant is,
// it will either optionally ignore it, or complain
// or otherwise just treat it as a normal procedure
// if it is invoked via a call statement
end
end //module
So, targets are just special procedures that are invoked only once during a
run.
Tasks are just invocations of internally registered functions/procedures
(which are implemented as
task-like objects), with parameters bound either by name, or by position
(which allows for anonymous parameters, and a variable number of them).
Identifiers and keywords are case-INsensitive (like in Pascal).
The block-structure of the language allows for things to be nested
arbitrarily deep. Every nested block is a module in its own right, with
type, const, var, depends, etc., as well as executable statements.
There is nothing special about the keywords like target, procedure, or
event. They are just names of the nodes in the parse tree. A compiler option
could allow for strict validation, or just ignore unknown nodes.
-Andrew
P.S. The original post appeared at news://news.optimax.com/sdforum.want
|