Contributed by Scott Anderson
THIS one is a monstrosity: OO-awk.
Note that the framework can be used by any OO awk program, since the objects are defined in a separate file.
Put all the files in a single directory, and run it with the command "awk -f test.awk".
Don't blame me if your machine melts down; it's quite slow. :-)
# draw a circle
BEGIN {
# get the members from the runtime data
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=x "runtimedata | getline x;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=y "runtimedata | getline y;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=radius "runtimedata | getline radius;
printf("Drawing circle at: (%s,%s), radius: %s\n", x, y, radius);
}
# create an object
# for whatever reason, 'foo in bar' does not seem to work as it should.
# I need to save the index regardless
function findit(val, arr)
{
for (g in arr) {
if (arr[g] == val) return g;
}
return 0;
}
BEGIN {
FS = ":";
# split up the arguments: arg1:val1,arg2:val2,etc.
split(oargs, apairs, ",");
i = 0;
for (p in apairs)
{
split(apairs[p], apair, ":");
aargs[i] = apair[1];
avals[i] = apair[2];
i = i + 1;
}
# place the type of the new object in the runtime data
"awk -f setdict.awk -v variable="name" -v member=class
-v field=type -v data="type" "runtimedata | getline x;
}
# for each slot in the type
(($1 == type) && ($2 == "slot")) {
i = findit($3, aargs);
# if we have been given an argument of the same name of the slot
if (i)
{
# insert the value in the slot for the new object
"awk -f setdict.awk -v variable="name" -v
member=slot -v field="$3" -v data="avals[i]"
"runtimedata | getline x;
}
else
{
# insert the default value in the slot for the new object
"awk -f setdict.awk -v variable="name" -v
member=slot -v field="$3" -v data="$4"
"runtimedata | getline x;
}
}
END {
}
# run through the class data, and copy all slots and methods for the
inherited class
BEGIN {
FS = ":";
}
($1 == super) {
"awk -f setdict.awk -v variable="class" -v
member="$2" -v field="$3" -v data="$4"
"FILENAME | getline x;
}
END {
}
# pull a particular value from the runtime data hash file
BEGIN {
FS=":";
}
(($1 == variable) && ($2 == member) && ($3 == field)) {
print $4;
fflush();
}
END {
}
# read in the object definitions and place them in the object data file
BEGIN {
FS = ":";
system("rm "dictfile" > /dev/null");
system("touch "dictfile" > /dev/null");
}
substr($0, 1, 1) == "#" {}
# inherit line: go copy all the slots and method for the superclass
($2 == "inherit") {
print "inherit: "$0;
"awk -f doinherit.awk -v super="$3" -v
class="$1" "dictfile | getline x;
}
# insert a method into the vtable
($2 == "method") {
print "method: "$0;
"awk -f setdict.awk -v variable="$1" -v member=method
-v field="$3" -v data="$4" "dictfile | getline
x;
}
# insert a slot into the vtable
($2 == "slot") {
print "slot: "$0;
"awk -f setdict.awk -v variable="$1" -v member=slot -v
field="$3" -v data="$4" "dictfile | getline x;
}
END {
}
# draw a rectangle
BEGIN {
# get the members from the runtime data
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=x "runtimedata | getline x;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=y "runtimedata | getline y;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=width "runtimedata | getline width;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=height "runtimedata | getline height;
printf("Drawing rectangle at: (%s,%s), width: %s, height:
%s\n", x, y, width, height);
}
# set the height for a rectangle
BEGIN {
"awk -f setdict.awk -v variable="name" -v member=slot
-v field=height -v data="aargs[1]" "runtimedata | getline
x;
}
# set the width for a rectangle
BEGIN {
"awk -f setdict.awk -v variable="name" -v member=slot
-v field=width -v data="args" "runtimedata | getline x;
}
# set a value in a dictionary file
BEGIN {
FS=":";
}
# look for the proper dictionary entry and copy it with the new value
{
if (($1 == variable) && ($2 == member) && ($3 == field)) {
printf("%s:%s:%s:%s\n", variable, member, field, data) >>
FILENAME".tmp";
foundit = "YES";
}
else {
# not a match; simply copy the existing values
print >> FILENAME".tmp";
}
}
END {
# if we didn't find it, add a new entry to the dictionary
if (foundit != "YES") {
printf("%s:%s:%s:%s\n", variable, member, field, data) >>
FILENAME".tmp";
}
# move the new information into the old dictionary file
close(FILENAME".tmp");
system("mv "FILENAME".tmp "FILENAME);
}
# move a shape relative to its origin
BEGIN {
split(args, aargs, ",");
# get the old origin
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=x "runtimedata | getline x;
"awk -f getdict.awk -v variable="name" -v member=slot
-v field=y "runtimedata | getline y;
# add the deltas
newx = aargs[1] + x;
newy = aargs[2] + y;
# write the new values
"awk -f setdict.awk -v variable="name" -v member=slot
-v field=x -v data="newx" "runtimedata | getline a;
"awk -f setdict.awk -v variable="name" -v member=slot
-v field=y -v data="newy" "runtimedata | getline b;
}
# object definition file for Scott's god-awful OO-awk engine # define the base class class:shape # give it two slots for the origin shape:slot:x:0 shape:slot:y:0 # give it two move methods shape:method:move-to:shape-move-to shape:method:rel-move-to:shape-rel-move-to # define the rectangle class class:rectangle # inherit the slots and methods from shape rectangle:inherit:shape # give it width and height slots rectangle:slot:width:0 rectangle:slot:height:0 # give it draw and set methods rectangle:method:draw:rectangle-draw rectangle:method:set-width:rectangle-set-width rectangle:method:set-height:rectangle-set-height # define the circle class class:circle # inherit the slots and methods from shape circle:inherit:shape # give it a radius slot circle:slot:radius:0 # give it a draw method circle:method:draw:circle-draw
# polymorphic example in awk
# November 8, 1999 - Scott Anderson
# Good god, why did I do this...
# create a new object
function new_object(type, name, args)
{
"awk -f createobject.awk -v type="type" -v
name="name" -v oargs="args" -v
runtimedata="runtimedata" "shapedict | getline x;
return name;
}
# clear and create a file
function prepare_file(file)
{
system("rm "file" > /dev/null");
system("touch "file" > /dev/null");
}
BEGIN {
shapedict = "shape.dict";
shapedata = "shapes.aoo";
runtimedata = "shape.run";
prepare_file(shapedict);
prepare_file(runtimedata);
# read the object definitions into a dictionary
"awk -f readaoo.awk -v dictfile="shapedict"
"shapedata | getline x;
# create some shapes
scribble[0] = new_object("rectangle", "rec1",
"x:10,y:20,width:5,height:6");
scribble[1] = new_object("circle", "circ1",
"x:15,y:25,radius:8");
# loop through and polymorphically draw and move the shapes
for (s in scribble)
{
system("awk -f callmethod.awk -v obj="scribble[s]"
-v method=draw -v args="" -v
runtimedata="runtimedata" -v shapedict="shapedict);
system("awk -f callmethod.awk -v obj="scribble[s]"
-v method=rel-move-to -v args=100,100 -v
runtimedata="runtimedata" -v shapedict="shapedict);
system("awk -f callmethod.awk -v obj="scribble[s]"
-v method=draw -v args="" -v
runtimedata="runtimedata" -v shapedict="shapedict);
}
# create a rectangle
# note the use of the default values
rec = new_object("rectangle", "rec2",
"width:15,height:15");
# call a rectangle-specific method
system("awk -f callmethod.awk -v obj="rec" -v
method=set-width -v args=30 -v runtimedata="runtimedata" -v
shapedict="shapedict);
# draw the rectangle
system("awk -f callmethod.awk -v obj="rec" -v
method=draw -v args="" -v runtimedata="runtimedata"
-v shapedict="shapedict);
exit;
}
Drawing rectangle at: (10,20), width: 5, height: 6 Drawing rectangle at: (110,120), width: 5, height: 6 Drawing circle at: (15,25), radius: 8 Drawing circle at: (115,125), radius: 8 Drawing rectangle at: (0,0), width: 30, height: 15