--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.utils;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+import java.util.ArrayDeque;\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
+\r
+public class PrintingContext {\r
+\r
+ THashMap<Object, String> names = new THashMap<Object, String>(); \r
+ int nameId = 0;\r
+ int indentation = 0;\r
+ StringBuilder stringBuilder = new StringBuilder();\r
+ TypeUnparsingContext typeUnparsingContext = \r
+ new TypeUnparsingContext();\r
+ Object errorMarker;\r
+ THashMap<BoundVar, LetApply> inlineExpressions = new THashMap<BoundVar, LetApply>(); \r
+ \r
+ private static class BlockEntry { \r
+ ArrayDeque<SSABlock> blockQueue = new ArrayDeque<SSABlock>(); \r
+ THashSet<SSABlock> blockSet = new THashSet<SSABlock>();\r
+ } \r
+ private ArrayList<BlockEntry> blockQueueStack = new ArrayList<BlockEntry>(2); \r
+ \r
+ public void pushBlockQueue() {\r
+ blockQueueStack.add(new BlockEntry());\r
+ }\r
+ \r
+ public void popBlockQueue() {\r
+ blockQueueStack.remove(blockQueueStack.size()-1);\r
+ }\r
+ \r
+ public SSABlock pollBlock() {\r
+ BlockEntry entry = blockQueueStack.get(blockQueueStack.size()-1);\r
+ return entry.blockQueue.poll();\r
+ }\r
+ \r
+ public void addBlock(SSABlock block) {\r
+ BlockEntry entry = blockQueueStack.get(blockQueueStack.size()-1);\r
+ if(entry.blockSet.add(block))\r
+ entry.blockQueue.add(block);\r
+ }\r
+ \r
+ public void append(Constant val) {\r
+ append(val.toString());\r
+ }\r
+ \r
+ public void append(ReturnCont val) {\r
+ append("return");\r
+ }\r
+ \r
+ public void append(Type type) {\r
+ append(type.toString(typeUnparsingContext));\r
+ }\r
+ \r
+ public void append(Type[] types) {\r
+ append('[');\r
+ boolean first = true;\r
+ for(Type type : types) {\r
+ if(first)\r
+ first = false;\r
+ else\r
+ append(", ");\r
+ append(type);\r
+ }\r
+ append(']');\r
+ }\r
+ \r
+ public void append(ValRef ref) {\r
+ append(ref.getBinding());\r
+ if(ref.getTypeParameters().length > 0) {\r
+ append("<");\r
+ for(int i=0;i<ref.getTypeParameters().length;++i) {\r
+ if(i > 0)\r
+ append(",");\r
+ append(ref.getTypeParameters()[i]);\r
+ }\r
+ append(">");\r
+ }\r
+ }\r
+ \r
+ public void append(Val val) {\r
+ if(val instanceof Constant) {\r
+ append((Constant)val);\r
+ }\r
+ else if(val instanceof BoundVar) {\r
+ BoundVar var = (BoundVar)val;\r
+ \r
+ LetApply inlineExpression = inlineExpressions.remove(var);\r
+ if(inlineExpression != null) {\r
+ append('(');\r
+ inlineExpression.bodyToString(this);\r
+ append(')');\r
+ }\r
+ else {\r
+ String label = var.getLabel();\r
+ if(label == null)\r
+ label = getName(val);\r
+ append(label);\r
+ }\r
+ }\r
+ else {\r
+ append(getName(val));\r
+ }\r
+ /*append('{');\r
+ append(val.getType());\r
+ append('}');*/\r
+ }\r
+\r
+ public void append(ContRef ref) {\r
+ append(ref.getBinding());\r
+ }\r
+ \r
+ public void append(Cont cont) {\r
+ if(cont instanceof ReturnCont)\r
+ append((ReturnCont)cont);\r
+ else\r
+ append("[" + getName(cont) + "]");\r
+ }\r
+\r
+ private String getName(Object var) {\r
+ if(var == null)\r
+ return "NULL";\r
+ String name = names.get(var);\r
+ if(name == null) {\r
+ name = idToName(nameId++);\r
+ names.put(var, name);\r
+ }\r
+ return name;\r
+ }\r
+\r
+ private static final int alphabetCount = 'z'-'a'+1;\r
+ \r
+ private static String idToName(int id) {\r
+ String name = Character.toString((char)('a' + id % alphabetCount));\r
+ id /= alphabetCount;\r
+ if(id > 0)\r
+ name = idToName(id-1) + name;\r
+ return name;\r
+ }\r
+ \r
+ public PrintingContext append(String str) {\r
+ stringBuilder.append(str);\r
+ return this;\r
+ }\r
+ \r
+ public PrintingContext append(char c) {\r
+ stringBuilder.append(c);\r
+ return this;\r
+ }\r
+ \r
+ public void indentation() {\r
+ for(int i=0;i<indentation;++i)\r
+ stringBuilder.append(" ");\r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ return stringBuilder.toString();\r
+ }\r
+\r
+ public void indent() {\r
+ ++indentation;\r
+ }\r
+\r
+ public void dedent() {\r
+ --indentation;\r
+ }\r
+\r
+ public void setErrorMarker(Object errorMarker) {\r
+ this.errorMarker = errorMarker; \r
+ }\r
+ \r
+ public Object getErrorMarker() {\r
+ return errorMarker;\r
+ }\r
+\r
+ public void addInlineExpression(BoundVar target, LetApply letApply) {\r
+ inlineExpressions.put(target, letApply);\r
+ }\r
+\r
+}\r