+ comment("Generate type resolution code for "
+ getContainer().getFullName()));
// Include the constantsBlock at the top so that sharedBlocks from
// actors can use true and false etc. StringMatches needs this.
CodeStream sharedStream = new CodeStream(
"$CLASSPATH/ptolemy/codegen/SystemC/kernel/SharedCode.c", this);
sharedStream.appendCodeBlock("constantsBlock");
code.append(sharedStream.toString());
HashSet functions = _getReferencedFunctions();
HashSet types = _getReferencedTypes(functions);
Object[] typesArray = types.toArray();
CodeStream[] typeStreams = new CodeStream[types.size()];
// Generate type map.
StringBuffer typeMembers = new StringBuffer();
code.append("#define TYPE_Token -1 " + _eol);
for (int i = 0; i < typesArray.length; i++) {
// Open the .c file for each type.
typeStreams[i] = new CodeStream(
"$CLASSPATH/ptolemy/codegen/SystemC/kernel/type/" + typesArray[i]
+ ".c", this);
code.append("#define TYPE_" + typesArray[i] + " " + i + _eol);
// Dynamically generate all the types within the union.
if (i > 0) {
typeMembers.append(_INDENT2);
}
typeMembers.append(typesArray[i] + "Token " + typesArray[i] + ";");
if (i < typesArray.length - 1) {
typeMembers.append(_eol);
}
}
Object[] functionsArray = functions.toArray();
// True if we have a delete function that needs to return a Token
boolean defineEmptyToken = false;
// Generate function map.
for (int i = 0; i < functionsArray.length; i++) {
code.append("#define FUNC_" + functionsArray[i] + " " + i + _eol);
if (functionsArray[i].equals("delete")) {
defineEmptyToken = true;
}
}
code.append("typedef struct token Token;" + _eol);
// Generate type and function definitions.
for (int i = 0; i < typesArray.length; i++) {
// The "declareBlock" contains all necessary declarations for the
// type; thus, it is always read into the code stream when
// accessing this particular type.
typeStreams[i].appendCodeBlock("declareBlock");
code.append(typeStreams[i].toString());
}
ArrayList args = new ArrayList();
// Token declareBlock.
if (typeMembers.length() != 0) {
sharedStream.clear();
args.add(typeMembers.toString());
sharedStream.appendCodeBlock("tokenDeclareBlock", args);
if (defineEmptyToken) {
sharedStream.append("Token emptyToken; "
+ comment("Used by *_delete() and others.") + _eol);
}
}
// Set to true if we need the unsupportedFunction() method.
boolean defineUnsupportedTypeFunctionMethod = false;
// Set to true if we need to scalarDelete() method.
boolean defineScalarDeleteMethod = false;
// Append type-polymorphic functions included in the function table.
for (int i = 0; i < types.size(); i++) {
// The "funcDeclareBlock" contains all function declarations for
// the type.
for (int j = 0; j < functionsArray.length; j++) {
String typeFunctionName = typesArray[i] + "_"
+ functionsArray[j];
if (_unsupportedTypeFunctions.contains(typeFunctionName)) {
defineUnsupportedTypeFunctionMethod = true;
}
if (_scalarDeleteTypes.contains(typesArray[i])
&& functionsArray[j].equals("delete")) {
defineScalarDeleteMethod = true;
}
if (functionsArray[j].equals("isCloseTo")
&& (typesArray[i].equals("Boolean") || typesArray[i]
.equals("String"))) {
boolean foundEquals = false;
for (int k = 0; k < functionsArray.length; k++) {
if (functionsArray[k].equals("equals")) {
foundEquals = true;
}
}
if (!foundEquals) {
// Boolean_isCloseTo and String_isCloseTo
// use Boolean_equals and String_equals.
args.clear();
args.add(typesArray[i] + "_equals");
sharedStream.appendCodeBlock("funcHeaderBlock", args);
}
}
if (!_scalarDeleteTypes.contains(typesArray[i])
|| !functionsArray[j].equals("delete")) {
// Skip Boolean_delete etc.
args.clear();
args.add(typeFunctionName);
sharedStream.appendCodeBlock("funcHeaderBlock", args);
}
}
}
if (defineUnsupportedTypeFunctionMethod) {
// Some type/function combos are not supported, so we
// save space by defining only one method.
sharedStream.appendCodeBlock("unsupportedTypeFunction");
}
if (defineScalarDeleteMethod) {
// Types that share the scalarDelete() method, which does nothing.
// We use one method so as to reduce code size.
sharedStream.appendCodeBlock("scalarDeleteFunction");
}
code.append(sharedStream.toString());
// Append functions that are specified used by this type (without
// going through the function table).
for (int i = 0; i < typesArray.length; i++) {
typeStreams[i].clear();
typeStreams[i].appendCodeBlock("funcDeclareBlock");
code.append(typeStreams[i].toString());
}
// FIXME: in the future we need to load the convertPrimitivesBlock
// dynamically, and maybe break it into multiple blocks to minimize
// code size.
sharedStream.clear();
sharedStream.appendCodeBlock("convertPrimitivesBlock");
code.append(sharedStream.toString());
// Generate function type and token table.
code.append(generateFunctionTable(typesArray, functionsArray));
for (int i = 0; i < typesArray.length; i++) {