/src/org/ooc/backend/cdirty/FunctionDeclWriter.java

http://github.com/nddrylliog/ooc · Java · 229 lines · 179 code · 46 blank · 4 comment · 73 complexity · 9aa9e734b3d593b526ba1f20c225c318 MD5 · raw file

  1. package org.ooc.backend.cdirty;
  2. import java.io.IOException;
  3. import java.util.Iterator;
  4. import org.ooc.frontend.model.Argument;
  5. import org.ooc.frontend.model.FuncType;
  6. import org.ooc.frontend.model.FunctionDecl;
  7. import org.ooc.frontend.model.Line;
  8. import org.ooc.frontend.model.Type;
  9. import org.ooc.frontend.model.TypeDecl;
  10. import org.ooc.frontend.model.TypeParam;
  11. import org.ooc.frontend.model.VarArg;
  12. public class FunctionDeclWriter {
  13. public static void write(FunctionDecl functionDecl, CGenerator cgen) throws IOException {
  14. if(functionDecl.isProto()) {
  15. // FW
  16. cgen.current = cgen.fw;
  17. if(functionDecl.getVersion() != null) {
  18. VersionBlockWriter.writeVersionBlockStart(functionDecl.getVersion(), cgen);
  19. }
  20. cgen.current.nl().app("extern ");
  21. functionDecl.getReturnType().accept(cgen);
  22. cgen.current.app(' ').app(functionDecl.getExternName());
  23. writeFuncArgs(functionDecl, cgen);
  24. cgen.current.app(';');
  25. if(functionDecl.getVersion() != null) {
  26. VersionBlockWriter.writeVersionBlockEnd(cgen);
  27. }
  28. }
  29. if(functionDecl.isExtern()) {
  30. // FW
  31. cgen.current = cgen.fw;
  32. if(functionDecl.getVersion() != null) VersionBlockWriter.writeVersionBlockStart(functionDecl.getVersion(), cgen);
  33. cgen.current.nl().app("#define ");
  34. functionDecl.writeFullName(cgen.current);
  35. cgen.current.app(' ').app(functionDecl.getExternName());
  36. if(functionDecl.getVersion() != null) VersionBlockWriter.writeVersionBlockEnd(cgen);
  37. } else if(!functionDecl.isAbstract()) {
  38. // FW
  39. cgen.current = cgen.fw;
  40. if(functionDecl.isInline()) {
  41. writeFullBody(functionDecl, cgen);
  42. } else {
  43. writeFullPrototype(functionDecl, cgen);
  44. }
  45. // CW
  46. cgen.current = cgen.cw;
  47. if(!functionDecl.isInline()) {
  48. writeFullBody(functionDecl, cgen);
  49. }
  50. }
  51. }
  52. private static void writeFullPrototype(FunctionDecl functionDecl,
  53. CGenerator cgen) throws IOException {
  54. if(functionDecl.getVersion() != null) {
  55. VersionBlockWriter.writeVersionBlockStart(functionDecl.getVersion(), cgen);
  56. }
  57. cgen.current.nl();
  58. writeFuncPrototype(functionDecl, cgen);
  59. cgen.current.app(';');
  60. if(functionDecl.getVersion() != null) {
  61. VersionBlockWriter.writeVersionBlockEnd(cgen);
  62. }
  63. }
  64. private static void writeFullBody(FunctionDecl functionDecl, CGenerator cgen)
  65. throws IOException {
  66. if(functionDecl.getVersion() != null) {
  67. VersionBlockWriter.writeVersionBlockStart(functionDecl.getVersion(), cgen);
  68. }
  69. cgen.current.nl();
  70. writeFuncPrototype(functionDecl, cgen);
  71. cgen.current.app(' ').openBlock();
  72. if(functionDecl.isEntryPoint(cgen.params)) {
  73. if(cgen.params.enableGC) {
  74. cgen.current.nl().app("GC_INIT();");
  75. }
  76. cgen.current.nl().app(cgen.module.getLoadFunc().getName()).app("();");
  77. }
  78. for(Line line: functionDecl.getBody()) {
  79. line.accept(cgen);
  80. }
  81. cgen.current.closeSpacedBlock();
  82. if(functionDecl.getVersion() != null) {
  83. VersionBlockWriter.writeVersionBlockEnd(cgen);
  84. }
  85. }
  86. public static void writeFuncPrototype(FunctionDecl functionDecl, CGenerator cgen) throws IOException {
  87. writeFuncPrototype(functionDecl, cgen, null);
  88. }
  89. public static void writeFuncPrototype(FunctionDecl functionDecl, CGenerator cgen, String additionalSuffix) throws IOException {
  90. if(functionDecl.isInline()) {
  91. if(cgen.current == cgen.hw) {
  92. cgen.current.append("inline ");
  93. }
  94. cgen.current.append("static ");
  95. }
  96. Type returnType = functionDecl.getReturnType();
  97. if (returnType.isGeneric()) {
  98. cgen.current.append("void ");
  99. } else if(returnType instanceof FuncType) {
  100. TypeWriter.writeFuncPointerStart((FunctionDecl) returnType.getRef(), cgen);
  101. } else {
  102. TypeWriter.writeSpaced(returnType, cgen);
  103. }
  104. functionDecl.writeFullName(cgen.current);
  105. if(additionalSuffix != null) cgen.current.append(additionalSuffix);
  106. writeFuncArgs(functionDecl, cgen);
  107. if(returnType instanceof FuncType) {
  108. TypeWriter.writeFuncPointerEnd((FunctionDecl) returnType.getRef(), cgen);
  109. }
  110. }
  111. public static void writeFuncArgs(FunctionDecl functionDecl, CGenerator cgen) throws IOException {
  112. writeFuncArgs(functionDecl, ArgsWriteMode.FULL, null, cgen);
  113. }
  114. public static enum ArgsWriteMode {
  115. FULL,
  116. NAMES_ONLY,
  117. TYPES_ONLY
  118. }
  119. public static void writeFuncArgs(FunctionDecl functionDecl, ArgsWriteMode mode,
  120. TypeDecl baseType, CGenerator cgen) throws IOException {
  121. cgen.current.app('(');
  122. boolean isFirst = true;
  123. Iterator<Argument> iter = functionDecl.getArguments().iterator();
  124. if(functionDecl.hasThis() && iter.hasNext()) {
  125. if(!isFirst) cgen.current.app(", ");
  126. isFirst = false;
  127. Argument arg = iter.next();
  128. if(mode == ArgsWriteMode.NAMES_ONLY) {
  129. if(baseType != null) {
  130. cgen.current.app("(");
  131. baseType.getType().accept(cgen);
  132. cgen.current.app(") ");
  133. }
  134. cgen.current.app(arg.getName());
  135. } else if(mode == ArgsWriteMode.TYPES_ONLY) {
  136. arg.getType().accept(cgen);
  137. } else {
  138. arg.accept(cgen);
  139. }
  140. }
  141. Type returnType = functionDecl.getReturnType();
  142. if(returnType.isGeneric()) {
  143. if(!isFirst) cgen.current.app(", ");
  144. isFirst = false;
  145. if(mode == ArgsWriteMode.NAMES_ONLY) {
  146. cgen.current.app(functionDecl.getReturnArg().getName());
  147. } else if(mode == ArgsWriteMode.TYPES_ONLY) {
  148. functionDecl.getReturnArg().getType().accept(cgen);
  149. } else {
  150. functionDecl.getReturnArg().accept(cgen);
  151. }
  152. }
  153. for(TypeParam param: functionDecl.getTypeParams().values()) {
  154. if(param.isGhost()) continue;
  155. if(!isFirst) cgen.current.app(", ");
  156. isFirst = false;
  157. if(mode == ArgsWriteMode.NAMES_ONLY) {
  158. cgen.current.app(param.getArgument().getName());
  159. } else if(mode == ArgsWriteMode.TYPES_ONLY) {
  160. param.getArgument().getType().accept(cgen);
  161. } else {
  162. param.getArgument().accept(cgen);
  163. }
  164. }
  165. while(iter.hasNext()) {
  166. Argument arg = iter.next();
  167. if(!isFirst) cgen.current.app(", ");
  168. isFirst = false;
  169. if(mode == ArgsWriteMode.NAMES_ONLY) {
  170. cgen.current.app(arg.getName());
  171. } else if(mode == ArgsWriteMode.TYPES_ONLY) {
  172. if(arg instanceof VarArg) {
  173. cgen.current.app("...");
  174. } else {
  175. arg.getType().accept(cgen);
  176. }
  177. } else {
  178. arg.accept(cgen);
  179. }
  180. }
  181. cgen.current.app(')');
  182. }
  183. }