package chocopy.common.codegen; import chocopy.common.analysis.SymbolTable; import chocopy.common.analysis.types.ValueType; import chocopy.common.astnodes.Stmt; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; /** * A descriptor for function and method definitions. * *
This class stores information required for code generation such as the information about a * function's parameters, local variables, the local symbol table, the function body, and the label * where the code for the body is generated. */ public class FuncInfo extends SymbolInfo { /** * The fully-qualified name of the function. * *
All functions in a ChocoPy program have a unique fully-qualified name. Global functions * defined with name `f` have fully-qualified name `f`. Methods `m` in a class `C` have * fully-qualified name `C.m`. Functions `f` nested inside another function with fully-qualified * name `F` have a fully-qualified name of `F.f`. */ protected final String funcName; /** * The static depth of a function. * *
Global functions and class methods have a static depth of 0. Nested functions that are
* defined in the body of a function with static depth `D` have a static depth of `D+1`.
*/
protected final int depth;
/** This function's return type. */
protected final ValueType returnType;
/** A list of parameter names. */
protected final List The method should accept one parameter of type `FuncInfo`.
*/
protected final Consumer The convention is that for a function with N params and K local vars, the i`th param is at
* index `i` and the j`th local var is at index `N+j+2`. In all, a function stores N+K+2
* variables contiguously in its activation record, where the N+1st is the frame pointer and the
* N+2nd is the return address.
*
* Caution: this is an index (starting at 0), and not an offset in number of bytes.
*/
public int getVarIndex(String name) {
int idx = params.indexOf(name);
if (idx >= 0) {
return idx;
}
for (int i = 0; i < locals.size(); i++) {
if (locals.get(i).getVarName().equals(name)) {
return i + params.size() + 2;
}
}
String msg = String.format("%s is not a var defined in function %s", name, funcName);
throw new IllegalArgumentException(msg);
}
/** Returns the label corresponding to the function's body in assembly. */
public Label getCodeLabel() {
return codeLabel;
}
/**
* Returns the function's defined name in the program. This is the last component of the
* dot-separated fully-qualified name.
*/
public String getBaseName() {
int rightmostDotIndex = funcName.lastIndexOf('.');
if (rightmostDotIndex == -1) {
return funcName;
} else {
return funcName.substring(rightmostDotIndex + 1);
}
}
/** Returns the function's fully-qualified name. */
public String getFuncName() {
return funcName;
}
/** Returns the function's static nesting depth. */
public int getDepth() {
return depth;
}
/** Returns the function's parameters in order of definition. */
public List This list is mainly used in generating code for initializing local variables that are not
* parameters.
*/
public List