blob: 077e7d6b4c6b03aa40f68842d837b2f3017c433f [file] [log] [blame]
/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package net.hydromatic.linq4j.expressions;
import java.lang.reflect.Type;
import java.util.*;
/**
* Converts an expression to Java code.
*/
class ExpressionWriter {
static Indent INDENT = new Indent(20);
private final StringBuilder buf = new StringBuilder();
private int level;
private String indent;
private boolean indentPending;
public ExpressionWriter() {
}
public void write(Expression expression) {
expression.accept(this, -1, -1);
}
@Override
public String toString() {
return buf.toString();
}
public boolean requireParentheses(
Expression expression, int lprec, int rprec)
{
if (lprec < expression.nodeType.lprec
&& expression.nodeType.rprec >= rprec)
{
return false;
}
buf.append("(");
expression.accept(this, -1, -1);
buf.append(")");
return true;
}
/**
* Increases the indentation level.
*/
public void begin() {
indent = INDENT.get(++level);
}
/**
* Decreases the indentation level.
*/
public void end() {
indent = INDENT.get(--level);
}
public ExpressionWriter newlineAndIndent() {
buf.append("\n");
indentPending = true;
return this;
}
public ExpressionWriter indent() {
buf.append(indent);
return this;
}
public ExpressionWriter begin(String s) {
append(s);
begin();
indentPending = s.endsWith("\n");
return this;
}
public ExpressionWriter end(String s) {
end();
append(s);
indentPending = s.endsWith("\n");
return this;
}
public ExpressionWriter append(char c) {
checkIndent();
buf.append(c);
return this;
}
public ExpressionWriter append(Type type) {
checkIndent();
buf.append(Types.className(type));
return this;
}
public ExpressionWriter append(Expression o) {
o.accept0(this);
return this;
}
public ExpressionWriter append(Object o) {
checkIndent();
buf.append(o);
return this;
}
public ExpressionWriter append(String s) {
checkIndent();
buf.append(s);
return this;
}
private void checkIndent() {
if (indentPending) {
buf.append(indent);
indentPending = false;
}
}
public StringBuilder getBuf() {
checkIndent();
return buf;
}
public ExpressionWriter list(
String begin, String sep, String end, Iterable<?> list)
{
begin(begin);
int k = 0;
for (Object o : list) {
if (k++ > 0) {
buf.append(sep);
if (sep.endsWith("\n")) {
indentPending = true;
}
}
if (o instanceof Expression) {
((Expression) o).accept(this, 0, 0);
} else if (o instanceof MemberDeclaration) {
((MemberDeclaration) o).accept(this);
} else {
append(o);
}
}
end(end);
return this;
}
private static class Indent extends ArrayList<String> {
public Indent(int initialCapacity) {
super(initialCapacity);
ensureSize(initialCapacity);
}
public synchronized String of(int index) {
ensureSize(index + 1);
return get(index);
}
private void ensureSize(int targetSize) {
if (targetSize < size()) {
return;
}
char[] chars = new char[2 * targetSize];
Arrays.fill(chars, ' ');
String bigString = new String(chars);
clear();
for (int i = 0; i < targetSize; i++) {
add(bigString.substring(0, i * 2));
}
}
}
}
// End ExpressionWriter.java