PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

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