You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.5 KiB
117 lines
3.5 KiB
package chocopy.common.codegen;
|
|
|
|
import chocopy.common.astnodes.*;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* A store for caching and re-using program constants that are represented as immutable objects.
|
|
*
|
|
* <p>Constants are emitted in assembly in the DATA section, and therefore are represented by their
|
|
* labels.
|
|
*/
|
|
public class Constants {
|
|
|
|
/** A counter used to generate unique label names for constants. */
|
|
protected int nextLabelSuffix = 0;
|
|
|
|
/** The constant representing the boolean `False`. */
|
|
final Label falseConstant = generateConstantLabel();
|
|
|
|
/**
|
|
* The constant representing the boolean `True`. This immediately follows falseConstant in
|
|
* static memory.
|
|
*/
|
|
final Label trueConstant = generateConstantLabel();
|
|
|
|
/** A cache for integer-valued constants. */
|
|
final Map<Integer, Label> intConstants = new HashMap<>();
|
|
|
|
/** A cache for string-valued constants. */
|
|
final Map<String, Label> strConstants = new HashMap<>();
|
|
|
|
/**
|
|
* Returns the next unique label suffix for constants.
|
|
*
|
|
* @return the next unique label suffix for constants
|
|
*/
|
|
protected int getNextLabelSuffix() {
|
|
return nextLabelSuffix++;
|
|
}
|
|
|
|
/**
|
|
* Generates a fresh label for constants.
|
|
*
|
|
* <p>This label is guaranteed to be unique amongst labels generated by invoking this method.
|
|
* All such labels have a prefix of `const_`.
|
|
*
|
|
* @return a fresh label
|
|
*/
|
|
public Label generateConstantLabel() {
|
|
return new Label(String.format("const_%d", getNextLabelSuffix()));
|
|
}
|
|
|
|
/**
|
|
* Returns the label for a `bool` constant.
|
|
*
|
|
* @param value the boolean value
|
|
* @return the label for the boolean value
|
|
*/
|
|
public Label getBoolConstant(boolean value) {
|
|
return value ? trueConstant : falseConstant;
|
|
}
|
|
|
|
/**
|
|
* Returns the label for am `int` constant.
|
|
*
|
|
* @param value the integer value
|
|
* @return the label for the integer value
|
|
*/
|
|
public Label getIntConstant(int value) {
|
|
if (intConstants.containsKey(value)) {
|
|
return intConstants.get(value);
|
|
} else {
|
|
Label newLabel = generateConstantLabel();
|
|
intConstants.put(value, newLabel);
|
|
return newLabel;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the label for a `str` constant.
|
|
*
|
|
* @param value the string value
|
|
* @return the label for the string value
|
|
*/
|
|
public Label getStrConstant(String value) {
|
|
if (strConstants.containsKey(value)) {
|
|
return strConstants.get(value);
|
|
} else {
|
|
Label newLabel = generateConstantLabel();
|
|
strConstants.put(value, newLabel);
|
|
return newLabel;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts a constant literal in the AST to a constant for code generation.
|
|
*
|
|
* @param literal the literal expression in the AST
|
|
* @return a {@link Label} representing a constant int/str/bool, or `null` representing the None
|
|
* literal
|
|
*/
|
|
public Label fromLiteral(Literal literal) {
|
|
if (literal instanceof IntegerLiteral) {
|
|
return getIntConstant(((IntegerLiteral) literal).value);
|
|
} else if (literal instanceof StringLiteral) {
|
|
return getStrConstant(((StringLiteral) literal).value);
|
|
} else if (literal instanceof BooleanLiteral) {
|
|
return getBoolConstant(((BooleanLiteral) literal).value);
|
|
} else {
|
|
assert literal == null || literal instanceof NoneLiteral;
|
|
return null;
|
|
}
|
|
}
|
|
}
|