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