/** * Helper method to generate the signatures for binding the factory. Must account for the * inheritance relationships for any arguments that are classes. Ths, each argument can * potentially result in a range of values for type, and we have to handle the cross product of * all of these. */ private static Vector makeFactoryNames(IXMLElement constructor) { String factoryName = XMLUtil.nameOf(constructor.getParent()); Vector allPermutations = new Vector(); for (Enumeration e = constructor.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement element = (IXMLElement) e.nextElement(); if (!element.getName().equals("arg")) { break; } String argType = XMLUtil.typeOf(element); Vector argTypeAlternates = new Vector(); argTypeAlternates.add(argType); if (ModelAccessor.isClass(argType)) { List ancestors = ModelAccessor.getAncestors(argType); if (ancestors != null) argTypeAlternates.addAll(ancestors); } allPermutations.add(argTypeAlternates); } // Generate all the signatures Vector factoryNames = new Vector(); makeFactoryNames(factoryName, allPermutations, 0, factoryNames); return factoryNames; }
/** * Builds the argument invocation string for calling a constructor * * @param classVariables The collection of member variables as XMLElements * @param constructorArguments The set of names for constructor arguments * @param allocatedMemberVariables The set of member variables already allocated * @param element The specific 'new' xml element */ private static String buildArguments( Vector classVariables, Set constructorArguments, Set allocatedMemberVariables, IXMLElement element) throws IOException { XMLUtil.checkExpectedNode("new", element); boolean comma = false; String arguments = ""; for (Enumeration e = element.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement argument = (IXMLElement) e.nextElement(); String argType = ModelAccessor.getValueType(argument); String value = ModelAccessor.getValue(argument); /* Exclude cases where we do nothing to the value */ if (!primitives.contains(argType) && !value.equals("true") && !value.equals("false")) { // CASE 0: Translate 'this' if (value.equalsIgnoreCase("this")) { value = "m_id"; } // CASE 1: It is a singleton member variable which must be mapped to the singleton else if (allocatedMemberVariables.contains(value)) { String singletonType = getVariableType(classVariables, value); if (primitives.contains(singletonType)) { value = "(" + singletonType + ") singleton(" + value + ")"; } else value = "singleton(" + value + ")"; } // CASE 2: It is a constructor argument else if (constructorArguments.contains(value)) { // Do nothing, just use the string as is. } // CASE 3: Test for error - using a member before initializing it else if (!allocatedMemberVariables.contains(value) && isMember(classVariables, value)) { value = "!ERROR: Cannot use " + value + " without prior initialization."; } // Otherwise it is a string or enumerataion else if (argType.equals("string") || // It is an enumeartion of some kind ModelAccessor.isEnumeration(argType) || argType.equals("symbol")) { value = "LabelStr(\"" + XMLUtil.escapeQuotes(value) + "\")"; } // If we fall through to here, there is an error. else value = "!ERROR:BAD ASSIGNMENT"; } // CASE 3: It is a true or false value if (comma) arguments = arguments + ", "; arguments = arguments + value; comma = true; } return arguments; }
public static void writeTypedefs(IndentWriter writer, IXMLElement klass) throws IOException { String name = ModelAccessor.getClassName(klass); if (!ModelAccessor.isPredefinedClass(name)) { SharedWriter.writeTypedefs(writer, name); writer.write("typedef ObjectDomain " + name + "Domain;\n\n"); } }
/** @brief Generates the signature for the class constructors */ private static void generateSignature(IndentWriter writer, IXMLElement constructor) throws IOException { assert (DebugMsg.debugMsg("ClassWriter", "Begin ClassWriter::generateSignature")); writer.write("constructor("); boolean comma = false; for (Enumeration e = constructor.enumerateChildren(); e.hasMoreElements(); ) { IXMLElement element = (IXMLElement) e.nextElement(); if (!element.getName().equals("arg")) { break; } String argType = XMLUtil.typeOf(element); String argName = XMLUtil.getAttribute(element, "name"); if (comma) { writer.write(", "); } // Argument are structured as: <arg name="argName" type="argType"/> if (argType.equals(NddlXmlStrings.x_int)) writer.write("int " + argName); else if (argType.equals(NddlXmlStrings.x_float)) writer.write("double " + argName); else if (argType.equals(NddlXmlStrings.x_boolean)) writer.write("bool " + argName); else if (argType.equals(NddlXmlStrings.x_string) || argType.equals(NddlXmlStrings.x_symbol) || ModelAccessor.isEnumeration(argType)) writer.write("const LabelStr& " + argName); else writer.write("const " + argType + "Id& " + argName); comma = true; } writer.write(")"); assert (DebugMsg.debugMsg("ClassWriter", "End ClassWriter::generateSignature")); }
private static String getVariableType(Vector classVariables, String name) { String type = "!ERROR"; for (int i = 0; i < classVariables.size(); i++) { IXMLElement variable = (IXMLElement) classVariables.elementAt(i); if (XMLUtil.nameOf(variable).equals(name)) { type = XMLUtil.getAttribute(variable, "type"); String _class = XMLUtil.getAttribute(variable.getParent(), "name"); if (ModelAccessor.isEnumeration(_class + "::" + type)) type = _class + "::" + type; break; } } return type; }
public static void generateImplementation(IndentWriter writer, IXMLElement klass) throws IOException { String superClass = ModelAccessor.getSuperClass(klass); String name = XMLUtil.getAttribute(klass, "name"); if (ModelAccessor.isPredefinedClass(name)) { writer.write("// SKIPPING IMPLEMENTATION FOR BUILT-IN CLASS " + name + "\n\n"); return; } ModelAccessor.setCurrentObjectType(name); String longname = XMLUtil.qualifiedName(klass); boolean extendsBuiltIn = ModelAccessor.isPredefinedClass(superClass); String superCppClass = ModelAccessor.getCppClass(superClass); writer.write("\n"); SharedWriter.generateFileLocation(writer, klass); writer.write( longname + "::" + name + "(const PlanDatabaseId& planDatabase, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(planDatabase, \"" + name + "\", name, true)"); else writer.write(" : " + superCppClass + "(planDatabase, \"" + name + "\", name)"); writer.write(" {\n"); writer.write("}\n"); writer.write( longname + "::" + name + "(const PlanDatabaseId& planDatabase, const LabelStr& type, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(planDatabase, type, name, true)"); else writer.write(" : " + superCppClass + "(planDatabase, type, name)"); writer.write(" {\n"); writer.write("}\n"); writer.write(longname + "::" + name + "(const ObjectId& parent, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(parent, \"" + name + "\", name, true)"); else writer.write(" : " + superCppClass + "(parent, \"" + name + "\", name)"); writer.write(" {}\n"); writer.write( longname + "::" + name + "(const ObjectId& parent, const LabelStr& type, const LabelStr& name)\n"); if (extendsBuiltIn) writer.write(" : " + superCppClass + "(parent, type, name, true)"); else writer.write(" : " + superCppClass + "(parent, type, name)"); writer.write(" {}\n"); Vector classVariables = klass.getChildrenNamed("var"); SharedWriter.defineHandleDefaults(writer, klass, classVariables); generateChildren(writer, klass); ModelAccessor.resetCurrentObjectType(); }
private static String makeArgumentType(String argType) { if (primitives.contains(argType)) return argType; else if (argType.equals("string") || ModelAccessor.isEnumeration(argType)) return "LabelStr"; else return argType + "Id"; }
public static void declareDefaultConstructor(IndentWriter writer, String superClass) throws IOException { // If it is a built in class then define the default 'constructor' call if (ModelAccessor.isPredefinedClass(superClass)) writer.write("virtual void constructor(); // default constructoror\n"); }
public static void defineConstructor(IndentWriter writer, IXMLElement constructor) throws IOException { assert (DebugMsg.debugMsg("ClassWriter", "Begin ClassWriter::defineConstructor")); IXMLElement klass = constructor.getParent(); SharedWriter.generateFileLocation(writer, klass); if (klass == null) { throw new RuntimeException("missing class for constructor"); } String longname = XMLUtil.nameOf(klass); writer.write("void " + longname + "::"); generateSignature(writer, constructor); writer.write(" {\n"); writer.indent(); // If the constructor has a call to the super class, invoke it. assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - getting children named 'super'")); Vector superCalls = constructor.getChildrenNamed("super"); assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - " + superCalls.size() + " children named retrieved")); if (!superCalls.isEmpty()) { assert (DebugMsg.debugMsg("ClassWriter", "ClassWriter::defineConstructor - calling super")); if (superCalls.size() > 1) writer.write("!ERROR: AT MOST ONE CALL TO SUPER ALLOWED\n"); IXMLElement superCall = (IXMLElement) superCalls.elementAt(0); String superClass = ModelAccessor.getParentClassName(klass); String superCppClass = ModelAccessor.getCppClass(superClass); writer.write(superCppClass + "::constructor("); String comma = ""; Enumeration arguments = superCall.enumerateChildren(); while (arguments.hasMoreElements()) { IXMLElement argument = (IXMLElement) arguments.nextElement(); String value = ModelAccessor.getValue(argument); if (argument.getName().equals("value") && XMLUtil.getAttribute(argument, "type").equals("string")) writer.write(comma + "\"" + value + "\""); else writer.write(comma + value); comma = ", "; } writer.write(");\n"); } Set allocatedMemberVariables = new HashSet(); // Store names as we go for reference /* Now capture names of constructor arguments */ Set constructorArguments = new HashSet(); // Store for names of constructor arguments { Vector args = constructor.getChildrenNamed("arg"); assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - getting " + args.size() + " arguments")); for (int i = 0; i < args.size(); i++) { IXMLElement arg = (IXMLElement) args.elementAt(i); String argName = XMLUtil.getAttribute(arg, "name"); constructorArguments.add(argName); } } Vector constructorAssignments = constructor.getChildrenNamed("assign"); Vector classVariables = klass.getChildrenNamed("var"); // Use the set below to track when an assignment is being made more than once for same variable Set assignmentsMade = new HashSet(); for (int i = 0; i < constructorAssignments.size(); i++) { IXMLElement element = (IXMLElement) constructorAssignments.elementAt(i); String target = XMLUtil.getAttribute(element, "name"); if (assignmentsMade.contains(target)) { writer.write("!ERROR: Duplicate assignment for " + target + "\n"); } else { assignmentsMade.add(target); // String type = getVariableType(classVariables, target); // trust in the parser, for it will assign the correct types String type = XMLUtil.getAttribute(element, "type"); IXMLElement sourceElement = element.getChildAtIndex(0); if (sourceElement.getName().equals("new")) { // Handle object allocation assert (DebugMsg.debugMsg( "ClassWriter", "ClassWriter::defineConstructor - allocating object for " + target)); String sourceType = XMLUtil.typeOf(sourceElement); writer.write(target + " = addVariable("); writer.write( sourceType + "Domain((new " + sourceType + "(m_id, \"" + target + "\"))->getId(), \"" + sourceType + "\")"); writer.write(", " + makeObjectVariableNameString(target) + ");\n"); writer.write( "Id<" + type + ">(singleton(" + target + "))->constructor(" + buildArguments( classVariables, constructorArguments, allocatedMemberVariables, sourceElement) + ");\n"); // Invoke initialization writer.write( "Id<" + type + ">(singleton(" + target + "))->handleDefaults();\n"); // Default variable setup } else { // Handle variable allocation String value = ModelAccessor.getValue(sourceElement); if (sourceElement.getName().equals("id") && type.equals(NddlXmlStrings.x_string)) value = XMLUtil.escapeQuotes(value); else if (sourceElement.getName().equals(NddlXmlStrings.x_symbol) || XMLUtil.getAttribute(sourceElement, "type").equals(NddlXmlStrings.x_string)) value = "LabelStr(\"" + XMLUtil.escapeQuotes(value) + "\")"; else if (ModelAccessor.isNumericPrimitive(type) && !type.equals(NddlXmlStrings.x_boolean)) { // Set both bounds to singleton value value = value + ", " + value; } writer.write(target + " = addVariable("); if (allocatedMemberVariables.contains( value)) // If we are assigning one member to another, we obtain the base domain for it writer.write(value + "->baseDomain()"); else writer.write(ModelAccessor.getDomain(type) + "(" + value + ", \"" + type + "\")"); writer.write(", " + makeObjectVariableNameString(target) + ");\n"); } // Add member to the set allocatedMemberVariables.add(target); } } writer.unindent(); writer.write("}\n"); assert (DebugMsg.debugMsg("ClassWriter", "End ClassWriter::defineConstructor")); }
/** * The pattern we have is to generate the schema through an implementation of thie schema() * function which will be invoked by the client. */ public static void generate(IndentWriter writer) throws IOException { writer.write("namespace NDDL {\n"); writer.indent(); // Implement expected initialization hooks writer.write("// Boot-strap code to initialize schema\n"); writer.write( "extern \"C\" SchemaId loadSchema(const SchemaId& schema,const RuleSchemaId& ruleSchema)\n{\n"); writer.indent(); String modelName = ModelAccessor.getModelName(); if (modelName == null) throw new RuntimeException("Failed to set model name. Bug in NddlCompiler"); writer.write("SchemaId id = schema;\n"); // Register Constraints writer.write("// Register Constraints\n"); for (Iterator it = s_constraintRegistrations.iterator(); it.hasNext(); ) { String constraint = (String) it.next(); writer.write(constraint + ";\n"); } writer.write("// Invoke commands to populate schema with type definitions\n"); // Iterate over all type definition commands for (int i = 0; i < s_objectTypeCommands.size(); i++) { writer.write("id->" + s_objectTypeCommands.elementAt(i) + ";\n"); } // Iterate over all type definition commands for (int i = 0; i < s_commands.size(); i++) { writer.write("id->" + s_commands.elementAt(i) + ";\n"); } // Force allocation of type factories. This should do a mapping for external names // to internal writer.write("// Force allocation of model specific type factories\n"); // Allocate Factories writer.write("// Allocate factories\n"); for (Iterator it = s_factoryAllocations.iterator(); it.hasNext(); ) { String command = (String) it.next(); writer.write(command); } // Iterate over all rules and allocate singletons - this registers rules writer.write("// Allocate rules\n"); Set ruleNames = RuleWriter.getRules(); for (Iterator it = ruleNames.iterator(); it.hasNext(); ) { String ruleName = (String) it.next(); writer.write("ruleSchema->registerRule((new " + ruleName + "())->getId());\n"); } writer.write("return id;\n"); writer.unindent(); writer.write("}\n\n"); writer.unindent(); writer.write("}\n"); }