package sizzle.compiler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Vector;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import sizzle.parser.syntaxtree.ArrayType;
import sizzle.parser.syntaxtree.Assignment;
import sizzle.parser.syntaxtree.Block;
import sizzle.parser.syntaxtree.BreakStatement;
import sizzle.parser.syntaxtree.BytesLiteral;
import sizzle.parser.syntaxtree.Call;
import sizzle.parser.syntaxtree.CharLiteral;
import sizzle.parser.syntaxtree.Comparison;
import sizzle.parser.syntaxtree.Component;
import sizzle.parser.syntaxtree.Composite;
import sizzle.parser.syntaxtree.Conjunction;
import sizzle.parser.syntaxtree.ContinueStatement;
import sizzle.parser.syntaxtree.Declaration;
import sizzle.parser.syntaxtree.DoStatement;
import sizzle.parser.syntaxtree.EmitStatement;
import sizzle.parser.syntaxtree.ExprList;
import sizzle.parser.syntaxtree.ExprStatement;
import sizzle.parser.syntaxtree.Expression;
import sizzle.parser.syntaxtree.Factor;
import sizzle.parser.syntaxtree.FingerprintLiteral;
import sizzle.parser.syntaxtree.FloatingPointLiteral;
import sizzle.parser.syntaxtree.ForExprStatement;
import sizzle.parser.syntaxtree.ForStatement;
import sizzle.parser.syntaxtree.ForVarDecl;
import sizzle.parser.syntaxtree.Function;
import sizzle.parser.syntaxtree.FunctionType;
import sizzle.parser.syntaxtree.Identifier;
import sizzle.parser.syntaxtree.IdentifierList;
import sizzle.parser.syntaxtree.IfStatement;
import sizzle.parser.syntaxtree.Index;
import sizzle.parser.syntaxtree.IntegerLiteral;
import sizzle.parser.syntaxtree.MapType;
import sizzle.parser.syntaxtree.Node;
import sizzle.parser.syntaxtree.NodeChoice;
import sizzle.parser.syntaxtree.NodeSequence;
import sizzle.parser.syntaxtree.NodeToken;
import sizzle.parser.syntaxtree.Operand;
import sizzle.parser.syntaxtree.OutputType;
import sizzle.parser.syntaxtree.Pair;
import sizzle.parser.syntaxtree.PairList;
import sizzle.parser.syntaxtree.Program;
import sizzle.parser.syntaxtree.ProtoFieldDecl;
import sizzle.parser.syntaxtree.ProtoMember;
import sizzle.parser.syntaxtree.ProtoMemberList;
import sizzle.parser.syntaxtree.ProtoTupleType;
import sizzle.parser.syntaxtree.Regexp;
import sizzle.parser.syntaxtree.RegexpList;
import sizzle.parser.syntaxtree.ResultStatement;
import sizzle.parser.syntaxtree.ReturnStatement;
import sizzle.parser.syntaxtree.Selector;
import sizzle.parser.syntaxtree.SimpleExpr;
import sizzle.parser.syntaxtree.SimpleMember;
import sizzle.parser.syntaxtree.SimpleMemberList;
import sizzle.parser.syntaxtree.SimpleTupleType;
import sizzle.parser.syntaxtree.Start;
import sizzle.parser.syntaxtree.Statement;
import sizzle.parser.syntaxtree.StatementExpr;
import sizzle.parser.syntaxtree.StaticVarDecl;
import sizzle.parser.syntaxtree.StringLiteral;
import sizzle.parser.syntaxtree.SwitchStatement;
import sizzle.parser.syntaxtree.Term;
import sizzle.parser.syntaxtree.TimeLiteral;
import sizzle.parser.syntaxtree.TupleType;
import sizzle.parser.syntaxtree.Type;
import sizzle.parser.syntaxtree.TypeDecl;
import sizzle.parser.syntaxtree.VarDecl;
import sizzle.parser.syntaxtree.WhenStatement;
import sizzle.parser.syntaxtree.WhileStatement;
import sizzle.parser.visitor.GJDepthFirst;
import sizzle.types.SizzleArray;
import sizzle.types.SizzleBytes;
import sizzle.types.SizzleFunction;
import sizzle.types.SizzleMap;
import sizzle.types.SizzleString;
import sizzle.types.SizzleTable;
import sizzle.types.SizzleType;
class TableDescription {
private String aggregator;
private SizzleType type;
private List<String> parameters;
public TableDescription(final String aggregator, final SizzleType type) {
this(aggregator, type, null);
}
public TableDescription(final String aggregator, final SizzleType type, final List<String> parameters) {
this.aggregator = aggregator;
this.type = type;
this.parameters = parameters;
}
/**
* @return the name
*/
public String getAggregator() {
return this.aggregator;
}
/**
* @return the parameters
*/
public List<String> getParameters() {
return this.parameters;
}
/**
* @param name
* the name to set
*/
public void setAggregator(final String aggregator) {
this.aggregator = aggregator;
}
/**
* @param parameters
* the parameters to set
*/
public void setParameters(final List<String> parameters) {
this.parameters = parameters;
}
/**
* @return the types
*/
public SizzleType getType() {
return this.type;
}
/**
* @param types
* the types to set
*/
public void setTypes(final SizzleType type) {
this.type = type;
}
}
public class CodeGeneratingVisitor extends GJDepthFirst<String, SymbolTable> {
private final TypeCheckingVisitor typechecker;
private final NameFindingVisitor namefinder;
private final StaticDeclarationCodeGeneratingVisitor staticdeclarator;
private final StaticInitializationCodeGeneratingVisitor staticinitializer;
private final HashMap<String, TableDescription> tables;
private final String name;
private final StringTemplateGroup stg;
public CodeGeneratingVisitor(final String name, final StringTemplateGroup stg) throws IOException {
this.typechecker = new TypeCheckingVisitor();
this.namefinder = new NameFindingVisitor();
this.staticdeclarator = new StaticDeclarationCodeGeneratingVisitor(this);
this.staticinitializer = new StaticInitializationCodeGeneratingVisitor(this);
this.tables = new HashMap<String, TableDescription>();
this.tables.put("stdout", new TableDescription("stdout", new SizzleString()));
this.tables.put("stderr", new TableDescription("stderr", new SizzleString()));
this.tables.put("output", new TableDescription("output", new SizzleBytes()));
this.name = name;
this.stg = stg;
}
@Override
public String visit(final Start n, final SymbolTable argu) {
return n.f0.accept(this, argu);
}
@Override
public String visit(final Program n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Program");
st.setAttribute("name", this.name);
if (argu.get("input").equals(new SizzleString())) {
st.setAttribute("inputFormatClass", "org.apache.hadoop.mapreduce.lib.input.TextInputFormat");
st.setAttribute("keyClass", "org.apache.hadoop.io.LongWritable");
st.setAttribute("valueClass", "org.apache.hadoop.io.Text");
} else if (argu.get("input").equals(new SizzleBytes())) {
throw new RuntimeException("unimplemented");
}
st.setAttribute("staticDeclarations", this.staticdeclarator.visit(n, argu));
st.setAttribute("staticStatements", this.staticinitializer.visit(n, argu));
final List<String> statements = new ArrayList<String>();
for (final Node node : n.f0.nodes) {
final String statement = node.accept(this, argu);
if (statement != null)
statements.add(statement);
}
st.setAttribute("statements", statements);
final List<String> tables = new ArrayList<String>();
for (final Entry<String, TableDescription> entry : this.tables.entrySet()) {
final String id = entry.getKey();
final TableDescription description = entry.getValue();
final String parameters = description.getParameters() == null ? "" : description.getParameters().get(0);
final SizzleType type = description.getType();
final StringBuilder src = new StringBuilder();
for (final Class<?> c : argu.getAggregators(description.getAggregator(), type))
src.append(", new " + c.getCanonicalName() + "(" + parameters + ")");
tables.add("this.tables.put(\"" + id + "\", new sizzle.aggregators.Table(" + src.toString().substring(2) + "));");
}
st.setAttribute("tables", tables);
return st.toString();
}
@Override
public String visit(final Declaration n, final SymbolTable argu) {
return n.f0.choice.accept(this, argu);
}
@Override
public String visit(final TypeDecl n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final StaticVarDecl n, final SymbolTable argu) {
// this is handled by the static code generator
return null;
}
@Override
public String visit(final VarDecl n, final SymbolTable argu) {
final SizzleType type = argu.get(n.f0.f0.tokenImage);
if (n.f2.present()) {
argu.setId(n.f0.f0.tokenImage);
n.f2.node.accept(this, argu);
argu.setId(null);
}
if (type instanceof SizzleTable)
return null;
final StringTemplate st = this.stg.getInstanceOf("VarDecl");
st.setAttribute("id", n.f0.f0.tokenImage);
// TODO: make templates for types
st.setAttribute("type", type.toJavaType());
if (n.f3.present()) {
final NodeChoice nodeChoice = (NodeChoice) n.f3.node;
switch (nodeChoice.which) {
case 0: // initializer
SizzleType t;
try {
t = this.typechecker.visit((Expression) ((NodeSequence) nodeChoice.choice).elementAt(1), argu.cloneNonLocals());
} catch (final IOException e) {
throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
}
String src = ((NodeSequence) nodeChoice.choice).elementAt(1).accept(this, argu);
if (!type.assigns(t)) {
final SizzleFunction f = argu.getCast(t, type);
if (f.hasName()) {
src = f.getName() + "(" + src + ")";
} else if (f.hasMacro()) {
src = CodeGeneratingVisitor.expand("X" + f.getMacro(), src.split(","));
}
}
st.setAttribute("initializer", src);
break;
default:
throw new RuntimeException("unexpected choice " + nodeChoice.which + " is a " + nodeChoice.choice.getClass().getSimpleName().toString());
}
}
return st.toString();
}
@Override
public String visit(final Type n, final SymbolTable argu) {
return n.f0.choice.accept(this, argu);
}
@Override
public String visit(final Component n, final SymbolTable argu) {
// intentionally ignoring the identifier
return n.f1.accept(this, argu);
}
@Override
public String visit(final ArrayType n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("ArrayType");
st.setAttribute("type", n.f2.accept(this, argu));
return st.toString();
}
@Override
public String visit(final TupleType n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final SimpleTupleType n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final SimpleMemberList n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final SimpleMember n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ProtoTupleType n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ProtoMemberList n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ProtoMember n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ProtoFieldDecl n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final MapType n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("MapType");
st.setAttribute("key", n.f2.accept(this, argu));
st.setAttribute("value", n.f2.accept(this, argu));
return st.toString();
}
@Override
public String visit(final OutputType n, final SymbolTable argu) {
final String id = argu.getId();
final String aggregator = n.f1.f0.tokenImage;
final SizzleTable t = (SizzleTable) argu.get(id);
if (n.f2.present()) {
final String parameter = ((NodeSequence) n.f2.node).nodes.get(1).accept(this, argu);
this.tables.put(id, new TableDescription(aggregator, t.getType(), Arrays.asList(parameter)));
} else {
this.tables.put(id, new TableDescription(aggregator, t.getType()));
}
return null;
}
@Override
public String visit(final ExprList n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("ExprList");
final List<String> expressions = new ArrayList<String>();
expressions.add(n.f0.accept(this, argu));
if (n.f1.present())
for (final Node node : n.f1.nodes)
expressions.add(((NodeSequence) node).elementAt(1).accept(this, argu));
st.setAttribute("expressions", expressions);
return st.toString();
}
@Override
public String visit(final FunctionType n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Statement n, final SymbolTable argu) {
return n.f0.choice.accept(this, argu);
}
@Override
public String visit(final Assignment n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Block n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Block");
final List<String> statements = new ArrayList<String>();
if (n.f1.present())
for (final Node node : n.f1.nodes)
statements.add(node.accept(this, argu));
st.setAttribute("statements", statements);
return st.toString();
}
@Override
public String visit(final BreakStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ContinueStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final DoStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final EmitStatement n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("EmitStatement");
if (n.f2.present()) {
final List<String> indices = new ArrayList<String>();
for (final Node node : n.f2.nodes)
indices.add(((NodeSequence) node).elementAt(1).accept(this, argu));
st.setAttribute("indices", indices);
}
st.setAttribute("id", Character.toString('"') + n.f1.f0.tokenImage + '"');
st.setAttribute("expression", n.f4.f0.accept(this, argu));
if (n.f5.present())
st.setAttribute("weight", ((NodeSequence) n.f5.node).elementAt(1).accept(this, argu));
return st.toString();
}
@Override
public String visit(final ExprStatement n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("ExprStatement");
st.setAttribute("expression", n.f0.accept(this, argu));
if (n.f1.present()) {
final NodeChoice nodeChoice = (NodeChoice) n.f1.node;
switch (nodeChoice.which) {
case 0:
st.setAttribute("operator", "++");
break;
case 1:
st.setAttribute("operator", "--");
break;
default:
throw new RuntimeException("unexpected choice " + nodeChoice.which + " is a " + nodeChoice.choice.getClass().getSimpleName().toString());
}
}
return st.toString();
}
@Override
public String visit(final ForStatement n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("ForStatement");
SymbolTable symtab;
try {
symtab = argu.cloneNonLocals();
} catch (final IOException e) {
throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
}
this.typechecker.visit(n.f2, symtab);
st.setAttribute("declaration", n.f2.accept(this, symtab));
st.setAttribute("expression", n.f4.accept(this, symtab));
st.setAttribute("exprstmt", n.f6.accept(this, symtab));
st.setAttribute("statement", n.f8.accept(this, symtab));
return st.toString();
}
@Override
public String visit(final ForVarDecl n, final SymbolTable argu) {
final VarDecl varDecl = new VarDecl(n.f0, n.f1, n.f2, n.f3, new NodeToken(";"));
return varDecl.accept(this, argu);
}
@Override
public String visit(final ForExprStatement n, final SymbolTable argu) {
final ExprStatement exprStatement = new ExprStatement(n.f0, n.f1, new NodeToken(";"));
return exprStatement.accept(this, argu);
}
@Override
public String visit(final IfStatement n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("IfStatement");
st.setAttribute("expression", n.f2.f0.accept(this, argu));
st.setAttribute("statement", n.f4.f0.accept(this, argu));
if (n.f5.present())
st.setAttribute("elseStatement", ((NodeSequence) n.f5.node).nodes.elementAt(1).accept(this, argu));
return st.toString();
}
@Override
public String visit(final ResultStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final ReturnStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final SwitchStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final WhenStatement n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("WhenStatement");
st.setAttribute("expression", n.f3.accept(this, argu));
st.setAttribute("statement", n.f5.accept(this, argu));
return st.toString();
}
@Override
public String visit(final IdentifierList n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final WhileStatement n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Expression n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Expression");
st.setAttribute("lhs", n.f0.accept(this, argu));
if (n.f1.present()) {
final List<String> operators = new ArrayList<String>();
final List<String> operands = new ArrayList<String>();
for (final Node node : n.f1.nodes) {
operators.add("||");
operands.add(((NodeSequence) node).elementAt(1).accept(this, argu));
}
st.setAttribute("operators", operators);
st.setAttribute("operands", operands);
}
return st.toString();
}
@Override
public String visit(final Conjunction n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Expression");
st.setAttribute("lhs", n.f0.accept(this, argu));
if (n.f1.present()) {
final List<String> operators = new ArrayList<String>();
final List<String> operands = new ArrayList<String>();
for (final Node node : n.f1.nodes) {
operators.add("&&");
operands.add(((NodeSequence) node).elementAt(1).accept(this, argu));
}
st.setAttribute("operators", operators);
st.setAttribute("operands", operands);
}
return st.toString();
}
@Override
public String visit(final Comparison n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Expression");
st.setAttribute("lhs", n.f0.accept(this, argu));
if (n.f1.present()) {
final List<String> operators = new ArrayList<String>();
final List<String> operands = new ArrayList<String>();
final Vector<Node> nodes = ((NodeSequence) n.f1.node).nodes;
final NodeChoice nodeChoice = (NodeChoice) nodes.elementAt(0);
switch (nodeChoice.which) {
case 0:
operators.add(" == ");
break;
case 1:
operators.add(" != ");
break;
case 2:
operators.add(" < ");
break;
case 3:
operators.add(" <= ");
break;
case 4:
operators.add(" > ");
break;
case 5:
operators.add(" >= ");
break;
default:
throw new RuntimeException("unexpected choice " + nodeChoice.which + " is " + nodeChoice.choice.getClass());
}
operands.add(nodes.elementAt(1).accept(this, argu));
st.setAttribute("operators", operators);
st.setAttribute("operands", operands);
}
return st.toString();
}
@Override
public String visit(final SimpleExpr n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Expression");
st.setAttribute("lhs", n.f0.accept(this, argu));
if (n.f1.present()) {
final List<String> operators = new ArrayList<String>();
final List<String> operands = new ArrayList<String>();
for (final Node node : n.f1.nodes) {
final NodeSequence nodeSequence = (NodeSequence) node;
operators.add(((NodeToken) ((NodeChoice) nodeSequence.elementAt(0)).choice).tokenImage);
operands.add(nodeSequence.elementAt(1).accept(this, argu));
}
st.setAttribute("operators", operators);
st.setAttribute("operands", operands);
}
return st.toString();
}
@Override
public String visit(final Term n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Expression");
st.setAttribute("lhs", n.f0.accept(this, argu));
if (n.f1.present()) {
final List<String> operators = new ArrayList<String>();
final List<String> operands = new ArrayList<String>();
for (final Node node : n.f1.nodes) {
final NodeSequence nodeSequence = (NodeSequence) node;
operators.add(((NodeToken) ((NodeChoice) nodeSequence.elementAt(0)).choice).tokenImage);
operands.add(nodeSequence.elementAt(1).accept(this, argu));
}
st.setAttribute("operators", operators);
st.setAttribute("operands", operands);
}
return st.toString();
}
@Override
public String visit(final Factor n, final SymbolTable argu) {
if (n.f1.present()) {
final NodeChoice nodeChoice = (NodeChoice) n.f1.nodes.get(0);
switch (nodeChoice.which) {
case 1: // index
case 2: // call
argu.setOperand(n.f0);
final String accept = n.f1.nodes.elementAt(0).accept(this, argu);
argu.setOperand(null);
return accept;
default:
throw new RuntimeException("unexpected choice " + nodeChoice.which + " is " + nodeChoice.choice.getClass());
}
} else {
return n.f0.accept(this, argu);
}
}
@Override
public String visit(final Selector n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Index n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Index");
try {
final SizzleType t = this.typechecker.visit(argu.getOperand(), argu.cloneNonLocals());
if (t instanceof SizzleMap)
st.setAttribute("map", true);
else if (t instanceof SizzleArray)
st.setAttribute("map", false);
} catch (final IOException e) {
throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
}
st.setAttribute("operand", argu.getOperand().accept(this, argu));
st.setAttribute("index", n.f1.accept(this, argu));
if (n.f2.present())
st.setAttribute("slice", ((NodeSequence) n.f2.node).elementAt(1).accept(this, argu));
return st.toString();
}
@Override
public String visit(final Call n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Call");
final SizzleFunction f = argu.getFunction(this.namefinder.visit(argu.getOperand()).toArray()[0].toString(), this.typechecker.check(n, argu));
if (f.hasMacro()) {
st.setAttribute("call", CodeGeneratingVisitor.expand(f.getMacro(), ((ExprList) n.f1.node).accept(this, argu).split(",")));
} else if (f.hasName()) {
st.setAttribute("operand", f.getName());
if (n.f1.present())
st.setAttribute("parameters", n.f1.node.accept(this, argu));
}
return st.toString();
}
@Override
public String visit(final RegexpList n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Regexp n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Operand n, final SymbolTable argu) {
return n.f0.choice.accept(this, argu);
}
@Override
public String visit(final Composite n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Composite");
if (n.f1.present()) {
final NodeChoice nodeChoice = (NodeChoice) n.f1.node;
switch (nodeChoice.which) {
case 0: // pair list
st.setAttribute("pairlist", nodeChoice.choice.accept(this, argu));
break;
case 1: // expression list
final SizzleType t;
try {
t = this.typechecker.visit((ExprList) nodeChoice.choice, argu.cloneNonLocals());
} catch (final IOException e) {
throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
}
st.setAttribute("type", t.toJavaType());
st.setAttribute("exprlist", nodeChoice.choice.accept(this, argu));
break;
default:
throw new RuntimeException("unexpected choice " + nodeChoice.which + " is " + nodeChoice.choice.getClass());
}
}
return st.toString();
}
@Override
public String visit(final PairList n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("PairList");
final List<String> pairs = new ArrayList<String>();
pairs.add(n.f0.accept(this, argu));
if (n.f1.present())
for (final Node node : n.f1.nodes)
pairs.add(((NodeSequence) node).elementAt(1).accept(this, argu));
st.setAttribute("pairs", pairs);
return st.toString();
}
@Override
public String visit(final Pair n, final SymbolTable argu) {
final StringTemplate st = this.stg.getInstanceOf("Pair");
st.setAttribute("map", argu.getId());
st.setAttribute("key", n.f0.accept(this, argu));
st.setAttribute("value", n.f2.accept(this, argu));
return st.toString();
}
@Override
public String visit(final Function n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final StatementExpr n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final Identifier n, final SymbolTable argu) {
// TODO: support protobufs/sequence files/avro here
final String id = n.f0.tokenImage;
if (argu.hasType(id))
return argu.getType(id).toString();
// otherwise return the identifier template
final StringTemplate st = this.stg.getInstanceOf("Identifier");
st.setAttribute("id", id);
return st.toString();
}
@Override
public String visit(final IntegerLiteral n, final SymbolTable argu) {
return n.f0.tokenImage + 'l';
}
@Override
public String visit(final FingerprintLiteral n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final FloatingPointLiteral n, final SymbolTable argu) {
return n.f0.tokenImage + "d";
}
@Override
public String visit(final CharLiteral n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final StringLiteral n, final SymbolTable argu) {
return n.f0.tokenImage;
}
@Override
public String visit(final BytesLiteral n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
@Override
public String visit(final TimeLiteral n, final SymbolTable argu) {
throw new RuntimeException("unimplemented");
}
private static String expand(final String template, final String... parameters) {
String replaced = template;
for (int i = 0; i < parameters.length; i++)
replaced = replaced.replace("${" + i + "}", parameters[i]);
return replaced;
}
// private static String expand(final String template, final String[]
// parameters) {
// String replaced = template;
//
// for (int i = 0; i < parameters.length; i++)
// replaced = replaced.replace("${" + i + "}", parameters[i]);
//
// return replaced;
// }
// private String name;
//
// private final NameFindingVisitor namefinder;
// private final TypeCheckingVisitor typefinder;
// private final IndexeeFindingVisitor indexeefinder;
// private StaticDeclarationCodeGeneratingVisitor staticfinder;
// private String staticDeclarations;
//
// private final Map<String, AggregatorDescription> aggregators;
// private final Map<String, String> codeMap;
//
//
// public CodeGeneratingVisitor(final String name) {
// this();
//
// this.staticfinder = new
// StaticDeclarationCodeGeneratingVisitor(this.namefinder);
//
// this.name = name;
// }
//
// // TODO: really support implicit cast on assignment?
// /** {@inheritDoc} */
// @Override
// public String visit(final Assignment n, final SymbolTable argu) {
// final String id = n.f0.f0.tokenImage;
//
// argu.setInitializerType(argu.get(id));
// final String source = n.f0.accept(this, argu) + " = " + n.f2.accept(this,
// argu);
// argu.setInitializerType(null);
//
// return source;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final AssignmentList n, final SymbolTable argu) {
// final StringBuilder source = new StringBuilder(n.f0.accept(this, argu));
//
// if (n.f1.present())
// for (final Node node : n.f1.nodes)
// source.append(((AssignmentRest) node).accept(this, argu));
//
// return source.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final AssignmentRest n, final SymbolTable argu) {
// return n.f1.accept(this, argu);
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final AssignmentStatement n, final SymbolTable argu)
// {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Atom n, final SymbolTable argu) {
// switch (n.f0.which) {
// case 0: // identifier
// return ((Identifier) n.f0.choice).accept(this, argu);
// case 1: // string
// return ((StringLiteral) n.f0.choice).accept(this, argu);
// case 2: // integer
// return ((IntegerLiteral) n.f0.choice).accept(this, argu);
// case 3: // float
// return ((FloatingPointLiteral) n.f0.choice).accept(this, argu);
// default:
// throw new RuntimeException("unexpected choice " + n.f0.which + " is " +
// n.f0.choice.getClass());
// }
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Block n, final SymbolTable argu) {
// final StringBuilder source = new StringBuilder("{\n");
//
// if (n.f1.present()) {
// final List<Node> arrayList = n.f1.nodes;
// for (final Node i : arrayList)
// source.append(((Statement) i).accept(this, argu) + "\n");
// }
//
// source.append("}");
//
// return source.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final CallExpression n, final SymbolTable argu) {
// final String id = n.f0.f0.tokenImage;
//
// if (n.f2.present()) {
// final SizzleFunction function = argu.getFunction(id,
// this.typefinder.check((ExpressionList) n.f2.node, argu));
//
// final String parameters = ((ExpressionList) n.f2.node).accept(this,
// argu);
//
// if (function.hasMacro())
// return CodeGeneratingVisitor.expand(function.getMacro(),
// parameters.split(","));
// else
// return function.getCanonicalName() + "(" + parameters + ")";
// } else {
// final SizzleFunction function = argu.getFunction(id);
// return function.getCanonicalName() + "()";
// }
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ComparisonExpression n, final SymbolTable argu)
// {
// final String lhs = n.f0.accept(this, argu);
//
// if (!n.f1.present())
// return lhs;
//
// SizzleType type;
// try {
// type = this.typefinder.visit(n.f0, argu.cloneNonLocals());
// } catch (final IOException e) {
// throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
// }
// final List<Node> nodes = ((NodeSequence) n.f1.node).nodes;
//
// final String operator = ((NodeToken) ((NodeChoice)
// nodes.get(0)).choice).tokenImage;
//
// final String rhs = ((PlusExpression) nodes.get(1)).accept(this, argu);
// if (operator.equals("==") || operator.equals("!="))
// if (type.getClass().equals(SizzleArray.class))
// return "java.util.Arrays.equals(" + lhs + ", " + rhs + ")";
// else if (type.getClass().equals(SizzleString.class))
// return (operator.equals("!=") ? "!" : "") + rhs + ".equals(" + lhs + ")";
// else if (Character.isUpperCase(type.toJavaType().toCharArray()[0]))
// return (operator.equals("!=") ? "!" : "") + rhs + ".equals(" + lhs + ")";
// else
// return lhs + " " + operator + " " + " " + rhs;
// else
// return lhs + " " + operator + " " + rhs;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Expression n, final SymbolTable argu) {
// final StringBuilder expression = new StringBuilder(n.f0.accept(this,
// argu));
//
// if (n.f1.present())
// for (final Node node : n.f1.nodes)
// expression.append(" " + ((NodeToken) ((NodeChoice) ((NodeSequence)
// node).nodes.get(0)).choice).tokenImage + " "
// + ((ComparisonExpression) ((NodeSequence)
// node).nodes.get(1)).accept(this, argu));
//
// return expression.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ExpressionList n, final SymbolTable argu) {
// final StringBuilder rest = new StringBuilder();
// if (n.f1.present())
// for (final Node i : n.f1.nodes)
// rest.append(", " + ((ExpressionRest) i).accept(this, argu));
//
// return n.f0.accept(this, argu) + rest.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ExpressionRest n, final SymbolTable argu) {
// return n.f1.accept(this, argu);
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final FloatingPointLiteral n, final SymbolTable argu)
// {
// return n.f0.tokenImage;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ForStatement n, final SymbolTable argu) {
// // when they say "for loops [...] take on their familiar form", I assume
// // they mean K&R form, e.g. declarations not allowed in initializer.
// String src = "for (";
//
// if (n.f2.present())
// src += ((AssignmentList) n.f2.node).accept(this, argu);
//
// src += "; ";
//
// if (n.f4.present())
// src += ((ExpressionList) n.f4.node).accept(this, argu);
//
// src += "; ";
//
// if (n.f6.present())
// src += ((ExpressionList) n.f6.node).accept(this, argu);
//
// return src + ")\n" + n.f8.accept(this, argu);
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final IdentifierList n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final IdentifierRest n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final IfStatement n, final SymbolTable argu) {
// String src = "if (" + n.f2.accept(this, argu) + ")\n" + n.f4.accept(this,
// argu) + "\n";
//
// if (n.f5.present())
// src += "else\n" + ((Statement) ((NodeSequence)
// n.f5.node).elementAt(1)).accept(this, argu);
//
// return src;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final IndexExpression n, final SymbolTable argu) {
// final String id = n.f0.accept(this, argu);
// final SizzleType type = argu.get(n.f0.f0.tokenImage);
//
// if (n.f1.present()) {
// final String index = ((NodeSequence) n.f1.node).nodes.get(1).accept(this,
// argu);
// if (type.getClass().equals(SizzleArray.class))
// return "(" + id + ".length > " + index + " ? " + id + "[(int)" + index +
// "]" + " : null)";
// else if (type.getClass().equals(SizzleMap.class))
// return id + ".get(" + index + ")";
// else
// throw new RuntimeException("wtf");
// } else
// return id;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Initializer n, final SymbolTable argu) {
// switch (n.f0.which) {
// case 0: // expression
// final SizzleType t = argu.getInitializerType();
// final SizzleType u = this.typefinder.visit(((Expression) n.f0.choice),
// argu);
//
// if (!t.assigns(u) && argu.hasCast(u, t))
// return argu.getCast(u, t).getCanonicalName() + "(" + ((Expression)
// n.f0.choice).accept(this, argu) + ")";
// return ((Expression) n.f0.choice).accept(this, argu);
// case 1: // map or array
// final NodeOptional nodeOptional = (NodeOptional) ((NodeSequence)
// n.f0.choice).nodes.get(1);
// if (nodeOptional.present()) {
// final NodeChoice node = (NodeChoice) nodeOptional.node;
// switch (node.which) {
// case 0: // pair list
// argu.setStaticInitializer(((PairList) node.choice).accept(this, argu));
// return "new " + argu.getInitializerType().toJavaType() + "()";
// case 1: // expression list
// return "new " + argu.getInitializerType().toJavaType() + " { " +
// ((ExpressionList) node.choice).accept(this, argu) + " }";
// default:
// throw new RuntimeException("unexpected choice " + n.f0.which + " is " +
// n.f0.choice.getClass());
// }
// } else
// return "";
// default:
// throw new RuntimeException("unexpected choice " + n.f0.which + " is " +
// n.f0.choice.getClass());
// }
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final IntegerLiteral n, final SymbolTable argu) {
// return n.f0.tokenImage;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final MemberExpression n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ParentheticalExpression n, final SymbolTable
// argu) {
// return "(" + n.f1.accept(this, argu) + ")";
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final PlusExpression n, final SymbolTable argu) {
// final StringBuilder src = new StringBuilder();
//
// src.append(n.f0.accept(this, argu));
//
// if (n.f1.present())
// for (final Node i : n.f1.nodes) {
// final NodeSequence nodeSequence = (NodeSequence) i;
// src.append(" " + ((NodeToken) ((NodeChoice)
// nodeSequence.nodes.get(0)).choice).tokenImage + " " +
// nodeSequence.nodes.get(1).accept(this, argu));
// }
//
// return src.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final ProtoStatement n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final SliceExpression n, final SymbolTable argu) {
// if (n.f1.present()) {
// final String lower = ((NodeSequence)
// n.f1.nodes.get(0)).elementAt(1).accept(this, argu);
// final String upper = ((NodeSequence)
// n.f1.nodes.get(0)).elementAt(3).accept(this, argu);
// final String id = n.f0.accept(this, argu);
// return "(" + lower + " > " + upper + " ? java.util.Arrays.copyOfRange(" +
// id + ", " + upper + ", " + upper + ") : java.util.Arrays.copyOfRange("
// + id + ", " + lower + ", " + upper + "))";
// } else
// return "";
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Start n, final SymbolTable argu) {
// this.staticDeclarations = this.staticfinder.visit(n, argu);
// return n.f0.accept(this, argu);
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Statement n, final SymbolTable argu) {
// switch (n.f0.which) {
// case 3: // non-static variable declaration
// return ((VariableDeclaration) n.f0.choice).accept(this, argu);
// case 4: // block
// return ((Block) n.f0.choice).accept(this, argu);
// case 6: // emit statement
// return ((EmitStatement) n.f0.choice).accept(this, argu);
// case 7: // if statement
// return ((IfStatement) n.f0.choice).accept(this, argu);
// case 9: // for statement
// return ((ForStatement) n.f0.choice).accept(this, argu);
// case 10: // when statement
// return ((WhenStatement) n.f0.choice).accept(this, argu);
// case 11: // proto statement
// return ((ProtoStatement) n.f0.choice).accept(this, argu);
// default:
// throw new RuntimeException("unexpected choice " + n.f0.which + " is " +
// n.f0.choice.getClass());
// }
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final StringLiteral n, final SymbolTable argu) {
// return n.f0.tokenImage;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Term n, final SymbolTable argu) {
// switch (n.f0.which) {
// case 0: // call
// return ((CallExpression) n.f0.choice).accept(this, argu);
// case 2: // wide index into array
// return ((SliceExpression) n.f0.choice).accept(this, argu);
// case 3: // index into array
// return ((IndexExpression) n.f0.choice).accept(this, argu);
// case 4: // expressions in parantheses
// return ((ParentheticalExpression) n.f0.choice).accept(this, argu);
// case 5: // atom
// return ((Atom) n.f0.choice).accept(this, argu);
// default:
// throw new RuntimeException("unexpected choice " + n.f0.which + " is " +
// n.f0.choice.getClass());
// }
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final TimesExpression n, final SymbolTable argu) {
// final StringBuilder src = new StringBuilder();
//
// src.append(n.f0.accept(this, argu));
//
// if (n.f1.present())
// for (final Node i : n.f1.nodes) {
// final NodeSequence nodeSequence = (NodeSequence) i;
// src.append(" " + ((NodeToken) ((NodeChoice)
// nodeSequence.nodes.get(0)).choice).tokenImage + " " +
// nodeSequence.nodes.get(1).accept(this, argu));
// }
//
// return src.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final Typle n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final TypleList n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final TypleRest n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final UnaryExpression n, final SymbolTable argu) {
// String expression = n.f0.accept(this, argu);
//
// if (n.f1.present())
// expression += ((NodeToken) ((NodeChoice) n.f1.node).choice).tokenImage;
//
// return expression;
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final StaticVariableDeclaration n, final SymbolTable
// argu) {
// return "";
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final WhenStatement n, final SymbolTable argu) {
// SymbolTable st;
// try {
// st = argu.cloneNonLocals();
// } catch (final IOException e) {
// throw new RuntimeException(e.getClass().getSimpleName() + " caught", e);
// }
//
// final StringBuilder src = new StringBuilder();
// for (final Node node : n.f2.nodes) {
// // String quant;
// // switch (((NodeChoice)((NodeSequence)node).nodes.get(2)).which) {
// // case 0:
// // quant = "some";
// // break;
// // case 1:
// // quant = "each";
// // break;
// // case 2:
// // quant = "all";
// // break;
// // default:
// // throw new RuntimeException("unexpected choice " +
// // ((NodeChoice)((NodeSequence)node).nodes.get(2)).which + " is " +
// // ((NodeChoice)((NodeSequence)node).nodes.get(2)).choice.getClass());
// // }
//
// final SizzleType type = st.getType(((Identifier) ((NodeSequence)
// node).nodes.get(3)).f0.tokenImage);
//
// final Set<String> ids = this.namefinder.visit((IdentifierList)
// ((NodeSequence) node).nodes.get(0));
//
// for (final String id : ids)
// st.set(id, type);
//
// for (final String id : ids) {
// st.set(id, type);
// final Set<String> indexees = this.indexeefinder.visit(n.f3, id);
//
// if (indexees.size() > 0) {
// indexees.addAll(this.indexeefinder.visit(n.f5, id));
// src.append("for (int ___" + id + " = 0; ");
// final List<String> array = new ArrayList<String>(indexees);
// src.append("___" + id + " < ___" + array.get(0) + ".length");
// for (int i = 1; i < array.size(); i++)
// src.append(" && " + id + " < " + array.get(i) + ".length");
// src.append("; ___" + id + "++)\n");
// }
// }
// }
//
// src.append("if (" + n.f3.accept(this, st) + ")\n");
//
// src.append(n.f5.accept(this, st));
//
// return src.toString();
// }
//
// /** {@inheritDoc} */
// @Override
// public String visit(final WhileStatement n, final SymbolTable argu) {
// throw new RuntimeException("unimplemented");
// }
}