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