Translator.java
package org.sterling.source.translator;
import static org.sterling.runtime.expression.ExpressionFactory.*;
import static org.sterling.runtime.expression.JavaExpression.JAVA;
import java.util.Set;
import org.sterling.SterlingException;
import org.sterling.runtime.GlobalModule;
import org.sterling.runtime.expression.DeclaredExpression;
import org.sterling.runtime.expression.Expression;
import org.sterling.runtime.expression.Variable;
import org.sterling.source.syntax.*;
public class Translator implements SourceVisitor<Expression, TranslatorState> {
public Set<DeclaredExpression> translate(SourceNode tree, GlobalModule globalModule) throws SterlingException {
TranslatorState state = new TranslatorState(globalModule);
visit(tree, state);
return state.getDeclarations();
}
@Override
public Expression visit(SourceNode node, TranslatorState state) throws SterlingException {
return node.accept(this, state);
}
@Override
public Expression visitAccessorExpression(AccessorExpression accessor, TranslatorState state) throws SterlingException {
return access(state.popExpression(), symbol(accessor.getIdentifier().getValue()));
}
@Override
public Expression visitApplyExpression(ApplyExpression expression, TranslatorState state) throws SterlingException {
return visit(expression.getOperand(), state);
}
@Override
public Expression visitArgument(ArgumentExpression argument, TranslatorState state) throws SterlingException {
return apply(state.popExpression(), visit(argument.getExpression(), state));
}
@Override
public Expression visitArgumentsExpression(ArgumentsExpression arguments, TranslatorState state) throws SterlingException {
return join(arguments.getArgument(), arguments.getTail(), state);
}
@Override
public Expression visitArgumentsExpressionTail(ArgumentsExpressionTail tail, TranslatorState state) throws SterlingException {
return join(tail.getArgument(), tail.getTail(), state);
}
@Override
public Expression visitBinaryExpression(BinaryExpression binary, TranslatorState state) throws SterlingException {
return join(binary.getOperand(), binary.getTail(), state);
}
@Override
public Expression visitBinaryExpressionTail(BinaryExpressionTail tail, TranslatorState state) throws SterlingException {
Expression expression = access(state.popExpression(), symbol(tail.getOperator().getValue()));
Expression application = apply(expression, visit(tail.getOperand(), state));
return join(application, tail.getTail(), state);
}
@Override
public Expression visitBooleanLiteral(BooleanLiteral literal, TranslatorState state) throws SterlingException {
return constant(literal.getLiteral().isTrue());
}
@Override
public Expression visitCharacterLiteral(CharacterLiteral literal, TranslatorState state) throws SterlingException {
return constant(literal.getLiteral().getCharValue());
}
@Override
public Expression visitConstantExpression(ConstantExpression lambda, TranslatorState state) throws SterlingException {
return visit(lambda.getBody(), state);
}
@Override
public Expression visitDeclaration(Declaration lambda, TranslatorState state) throws SterlingException {
state.declare(lambda.getIdentifier(), visit(lambda.getTail(), state));
return null;
}
@Override
public Expression visitDeclarationLiteral(DeclarationLiteral tail, TranslatorState state) throws SterlingException {
return visit(tail.getLambda(), state);
}
@Override
public Expression visitDeclarationSequence(DeclarationSequence sequence, TranslatorState state) throws SterlingException {
visit(sequence.getDeclaration(), state);
visit(sequence.getTail(), state);
return null;
}
@Override
public Expression visitDeclarationSequenceTail(DeclarationSequenceTail tail, TranslatorState state) throws SterlingException {
visit(tail.getSequence(), state);
return null;
}
@Override
public Expression visitDoubleLiteral(DoubleLiteral literal, TranslatorState state) throws SterlingException {
return constant(literal.getLiteral().getDoubleValue());
}
@Override
public Expression visitExpression(SourceExpression expression, TranslatorState state) throws SterlingException {
return visit(expression.getOperand(), state);
}
@Override
public Expression visitFromIdentifier(FromIdentifier identifier, TranslatorState state) throws SterlingException {
state.appendFrom(identifier.getValue());
visit(identifier.getTail(), state);
return null;
}
@Override
public Expression visitFromIdentifierAlias(ImportIdentifierAlias alias, TranslatorState state) throws SterlingException {
state.setAlias(alias.getValue());
return null;
}
@Override
public Expression visitFromIdentifierList(FromIdentifierList list, TranslatorState state) throws SterlingException {
state.addImport(list.getValue());
visit(list.getAlias(), state);
visit(list.getTail(), state);
return null;
}
@Override
public Expression visitFromIdentifierListTail(FromIdentifierListTail tail, TranslatorState state) throws SterlingException {
visit(tail.getList(), state);
return null;
}
@Override
public Expression visitFromIdentifierTail(FromIdentifierTail tail, TranslatorState state) throws SterlingException {
state.appendFrom(tail.getValue());
visit(tail.getTail(), state);
return null;
}
@Override
public Expression visitFromIdentifiers(FromIdentifiers identifiers, TranslatorState state) throws SterlingException {
visit(identifiers.getList(), state);
return null;
}
@Override
public Expression visitFromStatement(FromStatement from, TranslatorState state) throws SterlingException {
visit(from.getModule(), state);
visit(from.getAliases(), state);
state.acceptImports();
return null;
}
@Override
public Expression visitFunctionArguments(FunctionArguments arguments, TranslatorState state) throws SterlingException {
return lambda(
state.define((Variable) visit(arguments.getArgument(), state)),
visitLambdaArguments(arguments.getTail(), state)
);
}
@Override
public Expression visitFunctionArgumentsTail(FunctionArgumentsTail list, TranslatorState state) throws SterlingException {
return lambda(
state.define((Variable) visit(list.getArgument(), state)),
visitLambdaArguments(list.getTail(), state)
);
}
@Override
public Expression visitFunctionLiteral(FunctionLiteral lambda, TranslatorState state) throws SterlingException {
state.pushSource(lambda.getExpression());
state.enterScope();
Expression expression = visit(lambda.getArguments(), state);
state.leaveScope();
return expression;
}
@Override
public Expression visitImportHeader(ImportHeader header, TranslatorState state) throws SterlingException {
visit(header.getStatement(), state);
visit(header.getSuffix(), state);
return null;
}
@Override
public Expression visitImportHeaderSuffix(ImportHeaderSuffix suffix, TranslatorState state) throws SterlingException {
visit(suffix.getTail(), state);
return null;
}
@Override
public Expression visitImportHeaderTail(ImportHeaderTail tail, TranslatorState state) throws SterlingException {
visit(tail.getHeader(), state);
visit(tail.getSuffix(), state);
return null;
}
@Override
public Expression visitImportHeaders(ImportHeaders headers, TranslatorState state) throws SterlingException {
if (headers.isDeclared()) {
visit(headers.getHeader(), state);
}
return null;
}
@Override
public Expression visitImportIdentifier(ImportIdentifier identifier, TranslatorState state) throws SterlingException {
state.appendFrom(identifier.getValue());
visit(identifier.getTail(), state);
visit(identifier.getAlias(), state);
state.acceptImports();
return null;
}
@Override
public Expression visitImportIdentifierTail(ImportIdentifierTail tail, TranslatorState state) throws SterlingException {
if (tail.hasTail()) {
state.appendFrom(tail.getValue());
visit(tail.getTail(), state);
} else {
state.addImport(tail.getValue());
}
return null;
}
@Override
public Expression visitImportStatement(ImportStatement statement, TranslatorState state) throws SterlingException {
visit(statement.getAlias(), state);
return null;
}
@Override
public Expression visitIndexerArgument(IndexerArgument argument, TranslatorState state) throws SterlingException {
return apply(state.popExpression(), visit(argument.getExpression(), state));
}
@Override
public Expression visitIndexerArguments(IndexerArguments arguments, TranslatorState state) throws SterlingException {
return join(arguments.getArgument(), arguments.getSuffix(), state);
}
@Override
public Expression visitIndexerArgumentsSuffix(IndexerArgumentsSuffix suffix, TranslatorState state) throws SterlingException {
return visitTail(suffix.getTail(), state);
}
@Override
public Expression visitIndexerArgumentsTail(IndexerArgumentsTail tail, TranslatorState state) throws SterlingException {
return join(tail.getArgument(), tail.getSuffix(), state);
}
@Override
public Expression visitIndexerExpression(IndexerExpression indexer, TranslatorState state) throws SterlingException {
state.pushExpression(access(state.popExpression(), symbol("[]")));
return visit(indexer.getArguments(), state);
}
@Override
public Expression visitIntegerLiteral(IntegerLiteral integer, TranslatorState state) throws SterlingException {
return constant(integer.getLiteral().getIntValue());
}
@Override
public Expression visitJavaExpression(JavaExpression expression, TranslatorState state) throws SterlingException {
return JAVA;
}
@Override
public Expression visitLambdaArgument(LambdaArgument argument, TranslatorState state) throws SterlingException {
return variable(argument.getValue());
}
@Override
public Expression visitLambdaLiteral(LambdaLiteral lambda, TranslatorState state) throws SterlingException {
return lambda(
state.define((Variable) visit(lambda.getArgument(), state)),
visitLambdaArguments(lambda.getExpression(), state)
);
}
@Override
public Expression visitLiteralExpression(LiteralExpression literal, TranslatorState state) throws SterlingException {
return visit(literal.getOperand(), state);
}
@Override
public Expression visitModuleDeclaration(ModuleDeclaration module, TranslatorState state) throws SterlingException {
visit(module.getModuleHeader(), state);
visit(module.getUseHeaders(), state);
visit(module.getDeclarations(), state);
return null;
}
@Override
public Expression visitModuleHeader(ModuleHeader header, TranslatorState state) throws SterlingException {
if (header.isDeclared()) {
visit(header.getIdentifier(), state);
state.acceptModule();
}
return null;
}
@Override
public Expression visitModuleIdentifier(ModuleIdentifier identifier, TranslatorState state) throws SterlingException {
state.appendModule(identifier.getValue());
visit(identifier.getTail(), state);
return null;
}
@Override
public Expression visitModuleIdentifierTail(ModuleIdentifierTail tail, TranslatorState state) throws SterlingException {
state.appendModule(tail.getValue());
visit(tail.getTail(), state);
return null;
}
@Override
public Expression visitNullLiteral(NullLiteral literal, TranslatorState state) throws SterlingException {
return nothing();
}
@Override
public Expression visitObjectArgument(ObjectArgument argument, TranslatorState state) throws SterlingException {
return variable(argument.getValue());
}
@Override
public Expression visitObjectArguments(ObjectArguments arguments, TranslatorState state) throws SterlingException {
if (arguments.hasList()) {
return visit(arguments.getList(), state);
} else {
return visit(state.popSource(), state);
}
}
@Override
public Expression visitObjectArgumentsList(ObjectArgumentsList arguments, TranslatorState state) throws SterlingException {
return lambda(
state.define((Variable) visit(arguments.getArgument(), state)),
visitLambdaArguments(arguments.getList(), state)
);
}
@Override
public Expression visitObjectBody(ObjectBody body, TranslatorState state) throws SterlingException {
return visit(body.getMembers(), state);
}
@Override
public Expression visitObjectHeader(ObjectHeader header, TranslatorState state) throws SterlingException {
if (header.isDeclared()) {
return visit(header.getArguments(), state);
} else {
return visit(state.popSource(), state);
}
}
@Override
public Expression visitObjectLiteral(ObjectLiteral literal, TranslatorState state) throws SterlingException {
state.pushSource(literal.getBody());
state.enterScope();
state.define(SELF);
Expression expression = visit(literal.getHeader(), state);
state.leaveScope();
return expression;
}
@Override
public Expression visitObjectMember(ObjectMember member, TranslatorState state) throws SterlingException {
state.declareMember(member.getName(), visit(member.getLambda(), state));
return null;
}
@Override
public Expression visitObjectMemberName(ObjectMemberName name, TranslatorState state) throws SterlingException {
throw new UnsupportedOperationException();
}
@Override
public Expression visitObjectMembers(ObjectMembers members, TranslatorState state) throws SterlingException {
state.beginObject();
visit(members.getMember(), state);
visit(members.getSuffix(), state);
return state.acceptObject();
}
@Override
public Expression visitObjectMembersSuffix(ObjectMembersSuffix suffix, TranslatorState state) throws SterlingException {
return visit(suffix.getTail(), state);
}
@Override
public Expression visitObjectMembersTail(ObjectMembersTail tail, TranslatorState state) throws SterlingException {
visit(tail.getMember(), state);
visit(tail.getSuffix(), state);
return null;
}
@Override
public Expression visitParentheticalExpression(ParentheticalExpression parenthetical, TranslatorState state) throws SterlingException {
return visit(parenthetical.getOperand(), state);
}
@Override
public Expression visitPrimaryExpression(PrimaryExpression primary, TranslatorState state) throws SterlingException {
return visit(primary.getOperand(), state);
}
@Override
public Expression visitQualifiedIdentifier(QualifiedIdentifier qualified, TranslatorState state) throws SterlingException {
return join(state.reference(qualified.getIdentifier().getValue()), qualified.getTail(), state);
}
@Override
public Expression visitQualifiedIdentifierTail(QualifiedIdentifierTail tail, TranslatorState state) throws SterlingException {
state.pushExpression(access(state.popExpression(), symbol(tail.getIdentifier().getValue())));
if (tail.hasTail()) {
return visit(tail.getTail(), state);
} else {
return state.popExpression();
}
}
@Override
public Expression visitSelectorExpression(SelectorExpression selector, TranslatorState state) throws SterlingException {
return join(selector.getOperand(), selector.getTail(), state);
}
@Override
public Expression visitSelectorExpressionTail(SelectorExpressionTail tail, TranslatorState state) throws SterlingException {
return join(tail.getOperand(), tail.getTail(), state);
}
@Override
public Expression visitSingleObjectArgument(SingleObjectArgument argument, TranslatorState state) throws SterlingException {
return lambda(state.define((Variable) visit(argument.getArgument(), state)), visit(state.popSource(), state));
}
@Override
public Expression visitStringLiteral(StringLiteral literal, TranslatorState state) throws SterlingException {
return constant(literal.getLiteral().getStringValue());
}
@Override
public Expression visitTernaryExpression(TernaryExpression ternary, TranslatorState state) throws SterlingException {
return conditional(
visit(ternary.getCondition(), state),
visit(ternary.getTruePath(), state),
visit(ternary.getFalsePath(), state)
);
}
@Override
public Expression visitTernaryExpressionTail(TernaryExpressionTail tail, TranslatorState state) throws SterlingException {
return visit(tail.getExpression(), state);
}
@Override
public Expression visitUnaryExpression(UnaryExpression unary, TranslatorState state) throws SterlingException {
return visitUnaryExpression(visit(unary.getOperand(), state), unary);
}
private Expression join(SourceNode primary, SourceNode maybe, TranslatorState state) throws SterlingException {
return join(visit(primary, state), maybe, state);
}
private Expression join(Expression tree, SourceNode maybe, TranslatorState state) throws SterlingException {
state.pushExpression(tree);
if (maybe.isEmpty()) {
return state.popExpression();
} else {
return visit(maybe, state);
}
}
private Expression visitLambdaArguments(SourceNode list, TranslatorState state) throws SterlingException {
if (list.isEmpty()) {
return visit(state.popSource(), state);
} else {
return visit(list, state);
}
}
private Expression visitTail(SourceNode tail, TranslatorState state) throws SterlingException {
if (tail.isEmpty()) {
return state.popExpression();
} else {
return visit(tail, state);
}
}
private Expression visitUnaryExpression(Expression operand, UnaryExpression unary) throws SterlingException {
if (unary.hasOperator()) {
String name = unary.getOperator().getValue();
if ("+".equals(name)) {
name = "positive";
} else if ("-".equals(name)) {
name = "negative";
}
return access(operand, symbol(name));
} else {
return operand;
}
}
}