All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gxp.compiler.cpp..svn.text-base.BaseCppCodeGenerator.svn-base Maven / Gradle / Ivy

Go to download

Google XML Pages (GXP) is a templating system used to generate XML/SGML markup (most often HTML).

The newest version!
/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.gxp.compiler.cpp;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.gxp.compiler.alerts.AlertSink;
import com.google.gxp.compiler.alerts.common.NothingToCompileError;
import com.google.gxp.compiler.base.BooleanType;
import com.google.gxp.compiler.base.BundleType;
import com.google.gxp.compiler.base.ContentType;
import com.google.gxp.compiler.base.CppFileImport;
import com.google.gxp.compiler.base.CppLibraryImport;
import com.google.gxp.compiler.base.DefaultingImportVisitor;
import com.google.gxp.compiler.base.FormalTypeParameter;
import com.google.gxp.compiler.base.Parameter;
import com.google.gxp.compiler.base.Import;
import com.google.gxp.compiler.base.ImportVisitor;
import com.google.gxp.compiler.base.InstanceType;
import com.google.gxp.compiler.base.Interface;
import com.google.gxp.compiler.base.NativeType;
import com.google.gxp.compiler.base.NullRoot;
import com.google.gxp.compiler.base.Root;
import com.google.gxp.compiler.base.RootVisitor;
import com.google.gxp.compiler.base.Template;
import com.google.gxp.compiler.base.TemplateName;
import com.google.gxp.compiler.base.TemplateType;
import com.google.gxp.compiler.base.Tree;
import com.google.gxp.compiler.base.Type;
import com.google.gxp.compiler.base.TypeVisitor;
import com.google.gxp.compiler.codegen.BracesCodeGenerator;

import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * Base class for C++ {@code CodeGenerator}s.
 */
public abstract class BaseCppCodeGenerator> extends BracesCodeGenerator {
  protected BaseCppCodeGenerator(T tree) {
    super(tree);
  }

  public void generateCode(final Appendable appendable, final AlertSink alertSink)
      throws IOException {
    alertSink.addAll(tree.getAlerts());

    root.acceptVisitor(new RootVisitor() {
      public Void visitInterface(Interface iface) {
        createInterfaceWorker(appendable, alertSink, iface).run();
        return null;
      }

      public Void visitNullRoot(NullRoot nullRoot) {
        alertSink.add(new NothingToCompileError(nullRoot.getSourcePosition()));
        return null;
      }

      public Void visitTemplate(Template template) {
        createTemplateWorker(appendable, alertSink, template).run();
        return null;
      }
    });
  }

  protected abstract static class Worker extends BracesCodeGenerator.Worker {
    protected Worker(Appendable out, AlertSink alertSink) {
      super(out, alertSink, "public:", "private:");
    }

    protected String getClassName(TemplateName name) {
      return name.getBaseName();
    }

    protected String getQualifiedClassName(TemplateName name) {
      return Joiner.on("::").join(name.toString().split("\\."));
    }

    private String getIfdefGuard(TemplateName templateName) {
      return templateName.toString().replace('.', '_').toUpperCase() + "_H__";
    }

    protected void appendIfdefGuardStart(Root root) {
      String ifdefGuard = getIfdefGuard(root.getName());
      formatLine("#ifndef %s", ifdefGuard);
      formatLine("#define %s", ifdefGuard);
    }

    protected void appendIfdefGuardEnd(Root root) {
      formatLine("#endif  // %s", getIfdefGuard(root.getName()));
    }

    private final ImportVisitor IMPORT_VISITOR =
        new DefaultingImportVisitor(){
          public Void defaultVisitImport(Import imp) {
            // do nothing
            return null;
          }

          public Void visitCppFileImport(CppFileImport imp) {
            formatLine(imp.getSourcePosition(), "#include %s", imp.getTarget());
            return null;
          }

          public Void visitCppLibraryImport(CppLibraryImport imp) {
            formatLine(imp.getSourcePosition(), "#include %s", imp.getTarget());
            return null;
          }
        };

    protected void appendImports(Root root) {
      for (String imp : root.getSchema().getCppImports()) {
        formatLine(root.getSourcePosition(), "#include \"%s\"", imp);
      }

      for (Import imp : root.getImports()) {
        imp.acceptVisitor(IMPORT_VISITOR);
      }
    }

    protected void appendImports(Root root, Set extraIncludes) {
      appendImports(root);
      for (TemplateName extraInclude : extraIncludes) {
        formatLine("#include \"%s.h\"", extraInclude.toString().replace('.', '/'));
      }
    }

    protected void appendNamespacesOpen(TemplateName templateName) {
      for (String part : templateName.getPackageName().split("\\.")) {
        formatLine("namespace %s {", part);
      }
    }

    protected void appendNamespacesClose(TemplateName templateName) {
      for (String part : templateName.getPackageName().split("\\.")) {
        appendLine("}");
      }
    }

    protected static final String GXP_OUT_VAR = "gxp_out";
    protected static final String GXP_CONTEXT_VAR = "gxp_context";

    protected static final String GXP_SIG =
        COMMA_JOINER.join("%s " + GXP_OUT_VAR, "const GxpContext& " + GXP_CONTEXT_VAR);

    protected static final String DEFAULT_GXP_OUT_TYPE = "Appendable*";

    /**
     * Defines a type that can be the first parameter to a gxp Write method along
     * with the wrapper class that turns this type into an Appendable.
     */
    protected class ExtraOutType {
      private final String outType;
      private final String outWrapper;

      public ExtraOutType(String outType, String outWrapper) {
        this.outType = Preconditions.checkNotNull(outType);
        this.outWrapper = Preconditions.checkNotNull(outWrapper);
      }

      public String getOutType() {
        return outType;
      }

      public String getOutWrapper() {
        return outWrapper;
      }

      public String getGxpSig() {
        return String.format(GXP_SIG, outType);
      }
    }

    protected List extraOutTypes = ImmutableList.of(
        new ExtraOutType("string*", "StringAppendable"));

    protected String toCppType(Type type) {
      return type.acceptTypeVisitor(new TypeVisitor() {
        public String visitBooleanType(BooleanType type) {
          return "bool";
        }

        public String visitBundleType(BundleType type) {
          // TODO(harryh): make this real, only an int now so it's
          //               a valid C++ type
          return "int";
        }

        public String visitContentType(ContentType type) {
          return type.getSchema().getCppType() + "*";
        }

        public String visitInstanceType(InstanceType type) {
          return getClassName(type.getTemplateName()) + "::Interface";
        }

        public String visitNativeType(NativeType type) {
          return CppUtil.validateType(alertSink, type);
        }

        public String visitTemplateType(TemplateType type) {
          return getClassName(type.getTemplateName());
        }
      });
    }

    protected Function parameterToCallName =
      new Function() {
        public String apply(Parameter param) {
          StringBuilder sb = new StringBuilder();
          sb.append(toCppType(param.getType()));
          sb.append(" ");
          sb.append(param.getPrimaryName());
          return sb.toString();
        }
      };

    protected List toBoundedTypeDecls(boolean isDeclaration,
                                              Iterable formalTypeParameters) {
      List result = Lists.newArrayList();
      for (FormalTypeParameter formalTypeParameter : formalTypeParameters) {
        if (isDeclaration) {
          result.add("typename " + formalTypeParameter.getName());
        } else {
          result.add(formalTypeParameter.getName());
        }
      }
      return result;
    }

    protected void appendCppFormalTypeParameters(StringBuilder sb, boolean isDeclaration,
                                                 List formalTypeParameters) {
      if (!formalTypeParameters.isEmpty()) {
        if (isDeclaration) {
          sb.append("template");
        }
        sb.append("<");
        COMMA_JOINER.appendTo(sb, toBoundedTypeDecls(isDeclaration, formalTypeParameters));
        sb.append(">");
      }
    }

    protected void appendCppFormalTypeParameters(boolean isDeclaration,
                                                 List formalTypeParameters) {
      StringBuilder sb = new StringBuilder();
      appendCppFormalTypeParameters(sb, isDeclaration, formalTypeParameters);
      appendLine(sb.toString());
    }

    protected Function parameterToInitializer =
      new Function() {
        public String apply(Parameter param) {
          return param.getPrimaryName() + "(" + param.getPrimaryName() + ")";
        }
      };
  }

  protected abstract InterfaceWorker createInterfaceWorker(Appendable out,
                                                           AlertSink alertSink,
                                                           Interface iface);

  protected abstract static class InterfaceWorker extends Worker {
    protected final Interface iface;

    protected InterfaceWorker(Appendable out, AlertSink alertSink, Interface iface) {
      super(out, alertSink);
      this.iface = Preconditions.checkNotNull(iface);
    }

    protected abstract void appendClass();

    public void run() {
      appendHeader(iface);
      appendLine();
      appendClass();
      appendLine();
      appendFooter();
    }
  }

  protected abstract TemplateWorker createTemplateWorker(Appendable out,
                                                         AlertSink alertSink,
                                                         Template template);

  protected abstract static class TemplateWorker extends Worker {
    protected final Template template;

    protected TemplateWorker(Appendable out, AlertSink alertSink, Template template) {
      super(out, alertSink);
      this.template = Preconditions.checkNotNull(template);
    }

    protected abstract void appendClass();

    public void run() {
      appendHeader(template);
      appendLine();
      appendClass();
      appendLine();
      appendFooter();
    }

    protected String getWriteMethodSignature(boolean outsideClass, boolean isStatic) {
      return getWriteMethodSignature(DEFAULT_GXP_OUT_TYPE, outsideClass, isStatic);
    }

    protected String getWriteMethodSignature(String outType, boolean outsideClass,
                                             boolean isStatic) {
      Iterable params = isStatic
          ? template.getAllParameters()
          : template.getParameters();

      StringBuilder sb = new StringBuilder();
      if (isStatic) {
        if (!template.getFormalTypeParameters().isEmpty()) {
          appendCppFormalTypeParameters(sb, true, template.getFormalTypeParameters());
          sb.append("\n");
        }
        if (!outsideClass) {
          sb.append("static ");
        }
      }
      sb.append("void ");
      if (outsideClass) {
        sb.append(getQualifiedClassName(template.getName()));
        sb.append("::");
      }
      sb.append("Write(");
      COMMA_JOINER.appendTo(sb, Iterables.concat(
                                ImmutableList.of(String.format(GXP_SIG, outType)),
                                Iterables.transform(params, parameterToCallName)));
      sb.append(")");
      return sb.toString();
    }

    // TODO(harryh): combine this with getWriteMethodSignature() in some way?
    protected String getGetGxpClosureMethodSignature(boolean outsideClass, boolean isStatic) {
      Iterable params = isStatic
          ? template.getAllParameters()
          : template.getParameters();

      StringBuilder sb = new StringBuilder();
      if (isStatic) {
        if (!template.getFormalTypeParameters().isEmpty()) {
          appendCppFormalTypeParameters(sb, true, template.getFormalTypeParameters());
          sb.append("\n");
        }
        if (!outsideClass) {
          sb.append("static ");
        }
      }
      sb.append(toCppType(new ContentType(template.getSchema())));
      sb.append(" ");
      if (outsideClass) {
        sb.append(getQualifiedClassName(template.getName()));
        sb.append("::");
      }
      sb.append("GetGxpClosure(");
      COMMA_JOINER.appendTo(sb, Iterables.transform(params, parameterToCallName));
      sb.append(")");
      return sb.toString();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy