You will extend your compiler to allow procedures to be more
flexibly defined and called. Rather than your program containing
only a single zero-argument procedure
(ordinarily main
), it will be able to contain any
number of procedures, each expecting any number of arguments.
Rather than only being able to call one-argument procedures (such as
println
), you will be able to call procedures with any
number of arguments. Thus, you will be able to write interesting
multi-procedure programs. As a side effect, the library won't be
needed any more.
Remember to test your work frequently. You don't need to complete this whole section in order to conduct useful tests; each paragraph can be tested.
Change the syntax of a program so that there can be any number of procedure definitions.
Because each procedure call still passes in one argument, it would be
nice if each procedure were expecting an argument. The syntax of
a procedure definition should no longer have an empty pair of
parentheses. Instead, include the keyword int
and
a variable name. Your LLVM code should allocate stack space, just
like for any other local variable, and store the argument into that
variable. Here is an example of how the LLVM code for a typical
procedure definition might start:
define i32 @factorial(i32 %t0) { %t1 = alloca i32 ; parameter n store i32 %t0, i32* %t1
If you didn't take Lab 2's invitation to add return
statements, now would be a good time to do so. With your own
procedures, having them always return 0 would be rather boring.
At this point, you can eliminate the library, because the
definitions of print
and println
are now
within the language your compiler can process. (For that to be
literally true, you need to have taken Lab 2's suggestion of
allowing character constants. If you skipped that, you can give
your compiler modified definitions of print
and println
in which each character constant is
replaced with the corresponding decimal code number.) If
you need help with the build.xml
aspects of eliminating
the library, I'd be glad to assist. For the moment you'll still
need the LibraryDeclarations
class to provide a
declaration of the standard putchar
procedure.
Languages like C conventionally provide procedure declarations, such as
int putchar(int c);
as well as procure definitions, such as
int square(int n){return n*n;}
By making your compiler accept any list of zero or more items, each
of which is either a procedure declaration or a procedure
definition, you'll be able to totally
eliminate LibraryDeclarations
. If someone wants to
use putchar
, they can jolly well declare it
themself.
In the LLVM output, you'll need to follow LLVM's rules, which are somewhat different: only output an LLVM declaration for a procedure if there is no definition.
Change procedure calls, procedure definitions, and procedure
declarations to allow any number of
arguments. In addition to allowing you to write more interesting
procedures yourself, this opens up more of the standard C library
for your use. If you find yourself wanting to use a test program
that reads input, you'll need to modify build.xml
. If
you don't find ant
's documentation readable, I can
give you a hand with this.
It would be nice if your compiler enforced the following rules, which help prevent programming errors:
Each procedure call must use a procedure name that was previously either declared or defined, and the number of arguments must match the declaration or definition.
No procedure name may be defined more than once. (Remember, this applies only to definitions, not declarations.)
If the total number of declarations and definitions for a particular procedure name is greater than one, then all those declarations and definitions must be in agreement regarding the number of arguments.
Upload to moodle a zip file of your project.