Overview
The
IntermediateCodeGeneration step will take the fully correct and transformed tree from the
SemanticAnalysis step and generate source code for the
TargetCodeGeneration step to handle. More details in the
CompilerOverview.
Structure and Code Flow
The ICG is structured around the icgMainLoop() method that is invoked immediately upon funcall.
icgMainLoop() looks like this:
private void icgMainLoop(Object obj) {
if (Null.NIL.equals(obj)) {
emitter.emitNull();
}
else if (obj instanceof Symbol) {
genCodeSymbolValue((Symbol) obj);
}
else if (obj instanceof List) {
genCodeList((List) obj);
}
else if (obj instanceof java.lang.Number) {
genCodeNumber((java.lang.Number) obj);
}
.
.
.
else {
throw new ICGException("Found thing I can't generate code for: " + obj);
}
}
As you can see from the code above icgMainLoop merely checks to see what type of object it is generating code for and calls that genCode
method. The genCode methods are responsible for taking their arguments and then generating the proper code by calling the emitter. For example, genCodeNumber():
private void genCodeNumber(java.lang.Number num) {
if (num instanceof java.lang.Integer) {
emitter.emitNew("java/lang/Integer");
emitter.emitDup();
emitter.emitLdc(num.intValue());
emitter.emitInvokespecial("java/lang/Integer/<init>(I)V");
} else if (num instanceof java.lang.Float) {
emitter.emitNew("java/lang/Float");
emitter.emitDup();
emitter.emitLdc(num.floatValue());
emitter.emitInvokespecial("java/lang/Float/<init>(F)V");
} else if (num instanceof java.lang.Short) {
emitter.emitNew("java/lang/Short");
emitter.emitDup();
emitter.emitLdc(num.shortValue());
emitter.emitInvokespecial("java/lang/Float/<init>(S)V");
} else if (num instanceof java.lang.Long) {
emitter.emitNew("java/lang/Long");
emitter.emitDup();
emitter.emitLdc2_w(num.longValue());
emitter.emitInvokespecial("java/lang/Long/<init>(J)V");
} else if (num instanceof java.lang.Float) {
emitter.emitNew("java/lang/Double");
emitter.emitDup();
emitter.emitLdc2_w(num.doubleValue());
emitter.emitInvokespecial("java/lang/Double/<init>(D)V");
}
}
There are other genCode methods not referenced in icgMainLoop, however, they perfom exactly the same functions for their respective objects.
The other main portion of the ICG is genCodeList():
private void genCodeList(List list) {
if (list.getCar() instanceof Symbol) {
if (specialOps.containsKey(((Symbol) list.getCar()).getName())) {
genCodeSpecialForm(list);
} else {
genCodeSymbolFunction((Symbol)list.getCar());
genCodeFunctionCall(list);
}
} else if (list.getCar() instanceof List) {
List first = (List) ((List)list).getCar();
if (first.getCar() instanceof Symbol &&
((Symbol)first.getCar()).getName().equals("LAMBDA")) {
genCodeLambda(first);
genCodeFunctionCall(list);
}
}
}
As the code indicates, genCodeList() decides whether its 'car' is a special operator or merely a function. If it is indeed a special operator then the genCodeSpecialForm() method (incorrectly named for now) is called, which then decides which special operator is being invoked and calls the appropriate genCode method.
The ICG does not need to worry about compile-time compiler-macro invocation, that is to be done by the SemanticAnalyzer.
References
Implementation
Details of implementation
Discussions
Links to Blog issues
Status:
Release Level:
Open bug count:
Test Suites
Links to JUnit results
-- JerryBoetje - 12 Jul 2003