The Filter example shows how a simple Gilda program can be created. The Filter program computes values for an RC circuit. The user gives two values for either resistance, capacitance, or frequency. The program finds the omitted value.
Source code and a Windows program for rc.filter: rc.filter.zip
From the command shell, first create a directory for the project and go into it. Then use a plain text editor to compose the signature. Note that the commands are abbreviated and the unabridged form is written as a comment.
> mkdir filter :Create a new directory. > cd filter :Go into it. filter> edit rc.filter.g :Use any plain text editor.
After the editor comes up with a blank page add text for the signature. Aside from comments you can use lower case and let the pretty printer, pretty.gilda.exe, adjust the case for you.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : method RC.FILTER: Given any two values determine the third. entry R = 0 double, &Resistance in ohms C = 0 double, &Capacitance in uF F = 0 double :Frequency in Hz : :............................................................................... return
The utility, new.gilda.exe, generates boilerplate files for your project. It reads the program signature file to create files with code to parse a command line (root.rc.filter.g) and print a help message (help.rc.filter.g). The primary class file (rc.filter.clg) is also created.
filter> new.gilda rc.filter.g :Generate initial files. filter> dir :directory listing help.rc.filter.g rc.filter.clg rc.filter.g root.rc.filter.g
Now you can do an initial project build. Note that if you omit the Silent switch all the files used to build the program are listed. After compiling, if you run the program with no arguments the help message will be printed. At this point the program can't do anything else.
filter> gilda -s -p rc.filter :gilda -silent -project rc.filter filter> dir asm\ rc.filter.clg rc.filter.log obj\ rc.filter.exe rc.filter.pdb help.rc.filter.g rc.filter.g root.rc.filter.g filter> rc.filter rc.filter: Given any two values determine the third. -RResistance in ohms -C Capacitance in uF -F Frequency in Hz
The help message displays keywords with a leading dash and the first letter is capitalized. Regardless of the shell, the program parses keywords as case insensitive names.
When you run the compiler several files are created along with the asm\ and obj\ directories. The rc.filter.log file has a log of the build. The rc.filter.pdb file has symbols used by the Visual Studio debugger. Files in the two directories are used by the Gilda compiler. They are temporary and can safely be deleted.
If you code a Trace command the program will list the parameters. The Trace command is useful when debugging to print out variable values. It also prints the name of the procedure containing the trace and its line number. Edit rc.filter.g and add the Trace like so:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : method RC.FILTER: Given any two values determine the third. entry R = 0 double, &Resistance in ohms C = 0 double, &Capacitance in uF F = 0 double :Frequency in Hz : :............................................................................... trace r, c, f return
filter> rc.filter 1 2 3 rc.filter@12: R=1.0 C=2.0 F=3.0
If you run the program with a "-?" argument it will print help information.
filter> rc.filter -? rc.filter: Given any two parameters determinte the third. -RResistance in ohms -C Capacitance in uF -F Frequency in Hz
Next we'll add some Assertions to validate the parameters and add some skeletal code.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : method RC.FILTER: Given any two values determine the third. entry R = 0 double, &Resistance in ohms C = 0 double, &Capacitance in uF F = 0 double :Frequency in Hz : :............................................................................... trace r, c, f IF R: IF the resistance is known, IF C: IF resistance and capacitance are known, assert F = 0; All three parameters were given. ELSE: ELSE resistance and frequency are known, assert F; Only the resistance was given. . ELSE IF C: ELSE IF capacitance and frequency are known, assert F; Only the capacitance was given. ELSE: ELSE no resistance and no capacitance, assert F; No parameters were set. assert; Only the frequency was given. . return
You can give it some bad input to see how error reporting works.
filter> gilda -s rc.filter :Recompile the program. filter> rc.filter 1 rc.filter@12: R=1.0 C=0.0 F=0.0 ERROR: Only the resistance was given. filter> rc.filter 1 2 3 rc.filter@12: R=1.0 C=2.0 F=3.0 ERROR: All three parameters were given.
Now lets do the math. We'll be using Pi which is defined in the Basis library class, Math.Real. It needs to be imported by the rc.filter.clg class file.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : Generated initial class for 'Rc.Filter'; edit as needed. : class Rc.Filter: Given any two values determine the third. import Gilda.Basis, &Standard libraries Program.Argument :Agrument processing import Math.Real :Real number constants : :............................................................................... gilda Root.Rc.Filter ROOT :Scan the arguments. gilda Help.Rc.Filter :Display arguments. gilda Rc.Filter :Program entry point. end
Since R, C, and F are Entry parameters they cannot be modified. The shadow variables, R$, C$, and F$ are used as a convenience. Each variable ending with a dollar sign is implicitly declared as a Local variable and is initialized to the value of the corresponding parameter.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : method RC.FILTER: Given any two values determine the third. entry R = 0 double, &Resistance in ohms C = 0 double, &Capacitance in uF F = 0 double :Frequency in Hz use Math.Real/Pi :Archimedes says 3.14159_26535_89793_23846_26433 : :............................................................................... IF R: IF the resistance is known, IF C: IF resistance and capatitance are known, assert F = 0; All three parameters were given. F$ = 1 / (2 * Pi * R * C * 1e-6); Compute the frequency. ELSE: ELSE resistance and frequency are known, assert F; Only the resistance was given. C$ = 1 / (2 * Pi * R * F * 1e-6); Compute the capatitance. . ELSE IF C: ELSE IF capatitance and frequency are known, assert F; Only the capatitance was given. R$ = 1 / (2 * Pi * C * 1e-6 * F); Compute the resistance. ELSE: ELSE no resistance and no capatitance, assert F; No parameters were set. assert; Only the frequency was given. . PRINT "R =", R$|n9d.dn4, &Print values with 1 to 10 mantissa digits " C =", C$|n9d.dn4, &and 1 to 5 fractional digits. " F =", F$|n9d.dn4 return
After rebuilding we can run the program to get some results:
filter> rc.filter C=.01 F=320 R = 49735.91972 C = 0.01 F = 320.0 filter> rc.filter R=49735.91972 F=320 R = 49735.91972 C = 0.01 F = 320.0 filter> rc.filter R=49735.91972 C=.01 R = 49735.91972 C = 0.01 F = 320.0
An exception handler can be added to enhance error reporting. The Assertion variable in the Assertion class is used. This class is implicitly imported with the Basis library. The Assertion variable contains context information about an exception.
class Assertion public Gilda &Capture an assertion message and context. is Message string, &A message passed from an Assert statement Context string, &Context associated with the message Note string, &An additional message Method string, &Name of the method that failed Line word, &Assertion line or negative instruction offset Fault Program.Fault :Enumerated fault codes
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : method RC.FILTER: Given any two values determine the third. entry R = 0 double, &Resistance in ohms C = 0 double, &Capacitance in uF F = 0 double :Frequency in Hz use Math.Real/Pi, :Archimedes says 3.14159_26535_89793_23846_26433 Assertion :Context information for an exception : :............................................................................... IF R: IF the resistance is known, IF C: IF resistance and capatitance are known, assert F = 0; All three parameters were given. F$ = 1 / (2 * Pi * R * C * 1e-6); Compute the frequency. ELSE: ELSE resistance and frequency are known, assert F; Only the resistance was given. C$ = 1 / (2 * Pi * R * F * 1e-6); Compute the capatitance. . ELSE IF C: ELSE IF capatitance and frequency are known, assert F; Only the capatitance was given. R$ = 1 / (2 * Pi * C * 1e-6 * F); Compute the resistance. ELSE: ELSE no resistance and no capatitance, assert F; No parameters were set. assert; Only the frequency was given. . PRINT "R =", R$|n6d.zd4, &Print values with 1 to 7 mantissa digits "C =", C$|n6d.zd4, &and 1 to 5 fractional digits. "F =", F$|n6d.zd4 return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: : catch: Catch all exceptions from this method or any that it has called. : :............................................................................... PRINT Assertion`Message; Error message from the Assert command comment. PRINT HELP.RC.FILTER; Print a help message for: Rc.Filter return
Now when an error comes up you will see the help message as well.
play/filter> rc.filter 0 .01 ERROR: Only the capacitance was given. rc.filter: Given any two parameters determinte the third. -RResistance in ohms -C Capacitance in uF -F Frequency in Hz