]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/PrintingContext.java
(refs #7250) Merging master, minor CHR bugfixes
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / utils / PrintingContext.java
1 package org.simantics.scl.compiler.internal.codegen.utils;
2
3 import java.util.ArrayDeque;
4 import java.util.ArrayList;
5
6 import org.simantics.scl.compiler.constants.Constant;
7 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
8 import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
9 import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
10 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
11 import org.simantics.scl.compiler.internal.codegen.references.Val;
12 import org.simantics.scl.compiler.internal.codegen.references.ValRef;
13 import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
14 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
17
18 import gnu.trove.map.hash.THashMap;
19 import gnu.trove.set.hash.THashSet;
20
21 public class PrintingContext {
22
23     THashMap<Object, String> names = new THashMap<Object, String>(); 
24     int nameId = 0;
25     int indentation = 0;
26     StringBuilder stringBuilder = new StringBuilder();
27     TypeUnparsingContext typeUnparsingContext = 
28             new TypeUnparsingContext();
29     Object errorMarker;
30     THashMap<BoundVar, LetApply> inlineExpressions = new THashMap<BoundVar, LetApply>(); 
31     
32     private static class BlockEntry {        
33         ArrayDeque<SSABlock> blockQueue = new ArrayDeque<SSABlock>(); 
34         THashSet<SSABlock> blockSet = new THashSet<SSABlock>();
35     }  
36     private ArrayList<BlockEntry> blockQueueStack = new ArrayList<BlockEntry>(2); 
37     
38     public void pushBlockQueue() {
39         blockQueueStack.add(new BlockEntry());
40     }
41     
42     public void popBlockQueue() {
43         blockQueueStack.remove(blockQueueStack.size()-1);
44     }
45     
46     public SSABlock pollBlock() {
47         BlockEntry entry = blockQueueStack.get(blockQueueStack.size()-1);
48         return entry.blockQueue.poll();
49     }
50     
51     public void addBlock(SSABlock block) {
52         BlockEntry entry = blockQueueStack.get(blockQueueStack.size()-1);
53         if(entry.blockSet.add(block))
54             entry.blockQueue.add(block);
55     }
56     
57     public void append(Constant val) {
58         append(val.toString());
59     }
60     
61     public void append(ReturnCont val) {
62         append("return");
63     }
64     
65     public void append(Type type) {
66         append(type.toString(typeUnparsingContext));
67     }
68     
69     public void append(Type[] types) {
70         append('[');
71         boolean first = true;
72         for(Type type : types) {
73             if(first)
74                 first = false;
75             else
76                 append(", ");
77             append(type);
78         }
79         append(']');
80     }
81     
82     public void append(ValRef ref) {
83         append(ref.getBinding());
84         if(ref.getTypeParameters().length > 0) {
85             append("<");
86             for(int i=0;i<ref.getTypeParameters().length;++i) {
87                 if(i > 0)
88                     append(",");
89                 append(ref.getTypeParameters()[i]);
90             }
91             append(">");
92         }
93     }
94     
95     public void append(Val val) {
96         if(val instanceof Constant) {
97             append((Constant)val);
98         }
99         else if(val instanceof BoundVar) {
100             BoundVar var = (BoundVar)val;
101             
102             LetApply inlineExpression = inlineExpressions.remove(var);
103             if(inlineExpression != null) {
104                 append('(');
105                 inlineExpression.bodyToString(this);
106                 append(')');
107             }
108             else {
109                 String label = var.getLabel();
110                 if(label == null)
111                     label = getName(val);
112                 append(label);
113             }
114         }
115         else {
116             append(getName(val));
117         }
118         /*append('{');
119         append(val.getType());
120         append('}');*/
121     }
122
123     public void append(ContRef ref) {
124         append(ref.getBinding());
125     }
126     
127     public void append(Cont cont) {
128         if(cont instanceof ReturnCont)
129             append((ReturnCont)cont);
130         else
131             append("[" + getName(cont) + "]");
132     }
133
134     private String getName(Object var) {
135         if(var == null)
136             return "NULL";
137         String name = names.get(var);
138         if(name == null) {
139             name = idToName(nameId++);
140             names.put(var, name);
141         }
142         return name;
143     }
144
145     private static final int alphabetCount = 'z'-'a'+1;
146     
147     private static String idToName(int id) {
148         String name = Character.toString((char)('a' + id % alphabetCount));
149         id /= alphabetCount;
150         if(id > 0)
151             name = idToName(id-1) + name;
152         return name;
153     }
154     
155     public PrintingContext append(String str) {
156         stringBuilder.append(str);
157         return this;
158     }
159     
160     public PrintingContext append(char c) {
161         stringBuilder.append(c);
162         return this;
163     }
164     
165     public void indentation() {
166         for(int i=0;i<indentation;++i)
167             stringBuilder.append("    ");
168     }
169     
170     @Override
171     public String toString() {
172         return stringBuilder.toString();
173     }
174
175     public void indent() {
176         ++indentation;
177     }
178
179     public void dedent() {
180         --indentation;
181     }
182
183     public void setErrorMarker(Object errorMarker) {
184         this.errorMarker = errorMarker;                
185     }
186     
187     public Object getErrorMarker() {
188         return errorMarker;
189     }
190
191     public void addInlineExpression(BoundVar target, LetApply letApply) {
192         inlineExpressions.put(target, letApply);
193     }
194
195 }