wyjc.core.JavaFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wyjc Show documentation
Show all versions of wyjc Show documentation
The Whiley2JavaCompiler is responsible for translating Whiley
Intermediate Language (WyIL) files into JVM Bytecodes
The newest version!
// Copyright (c) 2011, David J. Pearce ([email protected])
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.
package wyjc.core;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import wybs.lang.CompilationUnit;
import wybs.util.AbstractCompilationUnit;
import wyfs.lang.Content;
import wyfs.lang.Path;
import wyjc.io.JavaFileWriter;
public class JavaFile extends AbstractCompilationUnit {
// =========================================================================
// Content Type
// =========================================================================
/**
* Responsible for identifying and reading/writing WyilFiles. The normal
* extension is ".wyil" for WyilFiles.
*/
public static final Content.Type ContentType = new Content.Type() {
public Path.Entry accept(Path.Entry> e) {
if (e.contentType() == this) {
return (Path.Entry) e;
}
return null;
}
@Override
public JavaFile read(Path.Entry e, InputStream input) throws IOException {
// At this stage, parsing java files is strictly off-limits :)
throw new UnsupportedOperationException();
}
@Override
public void write(OutputStream output, JavaFile jf) throws IOException {
new JavaFileWriter(output).write(jf);
}
@Override
public String toString() {
return "Content-Type: java";
}
@Override
public String getSuffix() {
return "java";
}
};
/**
* The list of top-level declarations within this file.
*/
private List declarations;
public JavaFile(Path.Entry extends CompilationUnit> entry) {
super(entry);
this.declarations = new ArrayList<>();
}
public List getDeclarations() {
return declarations;
}
/**
* A declaration (e.g. class or method) within a Java file
*
* @author David J. Pearce
*
*/
public interface Declaration extends Term {
List getModifiers();
}
public enum Modifier {
PUBLIC,
PROTECTED,
PRIVATE,
FINAL,
STATIC
}
private static class AbstractDeclaration implements Declaration {
/**
* The name of the class in question
*/
private final String name;
/**
* The modifiers associated with this class
*/
private final List modifiers = new ArrayList<>();
public AbstractDeclaration(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public List getModifiers() {
return modifiers;
}
}
public static class Import implements Declaration {
private final List components;
public Import(List components) {
this.components = new ArrayList<>(components);
}
public Import(String... components) {
this.components = Arrays.asList(components);
}
public List getComponents() {
return components;
}
@Override
public List getModifiers() {
return Collections.EMPTY_LIST;
}
}
public static class Class extends AbstractDeclaration implements Declaration {
/**
* The set of declarations within the class
*/
private final List declarations = new ArrayList<>();
public Class(String name) {
super(name);
}
public List getDeclarations() {
return declarations;
}
}
/**
* Represents a method declaration within a given Java class.
*
* @author David J. Pearce
*
*/
public static class Method extends AbstractDeclaration implements Declaration {
private Type returnType;
private List parameters = new ArrayList<>();
private Block body;
public Method(String name, Type returnType) {
super(name);
this.returnType = returnType;
}
public Type getReturnType() {
return returnType;
}
public List getParameters() {
return parameters;
}
public Block getBody() {
return body;
}
public void setBody(Block block) {
this.body = block;
}
}
public static class Constructor extends AbstractDeclaration implements Declaration {
private List parameters = new ArrayList<>();
private Block body;
public Constructor(String name) {
super(name);
}
public List getParameters() {
return parameters;
}
public Block getBody() {
return body;
}
public void setBody(Block block) {
this.body = block;
}
}
public static class Field extends VariableDeclaration implements Declaration {
public Field(Type type, String name) {
super(type,name);
}
public Field(Type type, String name, Term initialiser) {
super(type,name,initialiser);
}
}
public static class VariableDeclaration extends AbstractDeclaration implements Term {
private Type type;
private Term initialiser;
public VariableDeclaration(Type type, String name) {
super(name);
this.type = type;
}
public VariableDeclaration(Type type, String name, Term initialiser) {
super(name);
this.type = type;
this.initialiser = initialiser;
}
public Type getType() {
return type;
}
public boolean hasInitialisr() {
return initialiser != null;
}
public Term getInitialiser() {
return initialiser;
}
}
/**
* Represents either a statement or expression in a Java source file.
*
* @author David J. Pearce
*
*/
public interface Term {
}
public static class Block implements Term {
private List terms;
public Block() {
terms = new ArrayList<>();
}
public Block(List terms) {
this.terms = new ArrayList<>(terms);
}
public List getTerms() {
return terms;
}
}
public static class ArrayAccess implements Term {
private Term src;
private Term index;
public ArrayAccess(Term src, Term index) {
this.src = src;
this.index = index;
}
public Term getSource() {
return src;
}
public Term getIndex() {
return index;
}
}
public static class Assert implements Term {
private Term operand;
public Assert(Term operand) {
this.operand = operand;
}
public Term getOperand() {
return operand;
}
}
public static class Assignment implements Term {
private Term lhs;
private Term rhs;
public Assignment(Term lhs, Term rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
public Term getLefthandSide() {
return lhs;
}
public Term getRighthandSide() {
return rhs;
}
}
public static class Break implements Term {
}
public static class Cast implements Term {
private Type type;
private Term source;
public Cast(Type type, Term source) {
this.type = type;
this.source = source;
}
public Type getType() {
return type;
}
public Term getSource() {
return source;
}
}
public static class Continue implements Term {
}
public static class Constant implements Term {
private Object value;
public Constant(Object value) {
if (value == null || value instanceof Boolean || value instanceof Byte || value instanceof Integer
|| value instanceof Long || value instanceof String) {
this.value = value;
} else {
throw new IllegalArgumentException("invalid constant value: " + value);
}
}
public Object getValue() {
return value;
}
}
public static class DoWhile implements Term {
private Block body;
private Term condition;
public DoWhile(Block body, Term condition) {
this.condition = condition;
this.body = body;
}
public Term getCondition() {
return condition;
}
public Block getBody() {
return body;
}
}
public static class For implements Term {
private VariableDeclaration initialiser;
private Term condition;
private Term increment;
private Block body;
public For(VariableDeclaration initialiser, Term condition, Term increment, Block body) {
this.initialiser = initialiser;
this.condition = condition;
this.increment = increment;
this.body = body;
}
public VariableDeclaration getInitialiser() {
return initialiser;
}
public Term getCondition() {
return condition;
}
public Term getIncrement() {
return increment;
}
public Block getBody() {
return body;
}
}
public static class FieldAccess implements Term {
private Term src;
private String field;
public FieldAccess(Term src, String field) {
this.src = src;
this.field = field;
}
public Term getSource() {
return src;
}
public String getField() {
return field;
}
}
public static class If implements Term {
private Term condition;
private Block trueBranch;
private Block falseBranch;
public If(Term condition, Block trueBranch, Block falseBranch) {
this.condition = condition;
this.trueBranch = trueBranch;
this.falseBranch = falseBranch;
}
public Term getCondition() {
return condition;
}
public Block getTrueBranch() {
return trueBranch;
}
public Block getFalseBranch() {
return falseBranch;
}
}
public static class IfElse implements Term {
private List cases;
public IfElse(List cases) {
this.cases = cases;
}
public List getCases() {
return cases;
}
public static class Case implements Term {
private Term condition;
private Block body;
public Case(Term label, Block body) {
this.condition = label;
this.body = body;
}
public Term getLabel() {
return condition;
}
public Block getBlock() {
return body;
}
}
}
public static class InstanceOf implements Term {
private Term lhs;
private Type rhs;
public InstanceOf(Term lhs, Type rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
public Term getLefthandSide() {
return lhs;
}
public Type getRighthandSide() {
return rhs;
}
}
public static class Invoke implements Term {
private List typeArguments;
private Term receiver;
private List path;
private List arguments;
public Invoke(Term receiver, String name, Term... arguments) {
this.receiver = receiver;
this.path = new ArrayList<>();
this.path.add(name);
this.arguments = Arrays.asList(arguments);
}
public Invoke(Type[] typeArgs, Term receiver, String name, Term... arguments) {
this.typeArguments = Arrays.asList(typeArgs);
this.receiver = receiver;
this.path = new ArrayList<>();
this.path.add(name);
this.arguments = Arrays.asList(arguments);
}
public Invoke(Term receiver, String[] path, Term... arguments) {
this.receiver = receiver;
this.path = Arrays.asList(path);
this.arguments = Arrays.asList(arguments);
}
public Invoke(Term receiver, String name, List arguments) {
this.receiver = receiver;
this.path = new ArrayList<>();
this.path.add(name);
this.arguments = new ArrayList<>(arguments);
}
public Invoke(Term receiver, List path, List arguments) {
this.receiver = receiver;
this.path = new ArrayList<>(path);
this.arguments = new ArrayList<>(arguments);
}
public List getTypeArguments() {
return typeArguments;
}
public Term getReceiver() {
return receiver;
}
public List getPath() {
return path;
}
public List getArguments() {
return arguments;
}
}
public static class Lambda implements Term {
private List parameters;
private Term body;
public Lambda(List parameters, Term body) {
this.parameters = parameters;
this.body = body;
}
public List getParameters() {
return parameters;
}
public Term getBody() {
return body;
}
}
public static class NewArray implements Term {
private Array type;
private Term size;
private List initialisers;
public NewArray(Array type, Term size, List initialisers) {
this.type = type;
this.size = size;
this.initialisers = new ArrayList<>(initialisers);
}
public Array getType() {
return type;
}
public Term getSizeOperand() {
return size;
}
public List getInitialisers() {
return initialisers;
}
}
public static class New implements Term {
private Reference type;
private List parameters;
public New(Reference type, List parameters) {
this.type = type;
this.parameters = new ArrayList<>(parameters);
}
public Type getType() {
return type;
}
public List getParameters() {
return parameters;
}
}
public static class Operator implements Term {
public enum Kind {
NOT, NEG, EQ, NEQ, LT, LTEQ, GT, GTEQ, ADD, SUB, MUL, DIV, REM, AND, OR, BITWISEOR, BITWISEXOR, BITWISEAND, BITWISEINVERT, LEFTSHIFT, RIGHTSHIFT
}
private Kind kind;
private List operands;
public Operator(Kind kind, List operands) {
this.kind = kind;
this.operands = operands;
}
public Operator(Kind kind, Term... operands) {
this.kind = kind;
this.operands = Arrays.asList(operands);
}
public Kind getKind() {
return kind;
}
public List getOperands() {
return operands;
}
}
public static class Return implements Term {
private Term initialiser;
public Return(Term initialiser) {
this.initialiser = initialiser;
}
public Term getInitialiser() {
return initialiser;
}
}
public static class Case implements Term {
private Constant label;
private Term body;
public Case(Constant label, Term body) {
this.label = label;
this.body = body;
}
public Constant getLabel() {
return label;
}
public Term getBody() {
return body;
}
}
public static class Switch implements Term {
private Term condition;
private List cases;
public Switch(Term condition, List cases) {
this.condition = condition;
this.cases = cases;
}
public Term getCondition() {
return condition;
}
public List getCases() {
return cases;
}
}
public static class Throw implements Term {
private JavaFile.Term term;
public Throw(JavaFile.Term term) {
this.term = term;
}
public Term getClause() {
return term;
}
}
public static class VariableAccess implements Term {
private String name;
public VariableAccess(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class While implements Term {
private Term condition;
private Block body;
public While(Term condition, Block body) {
this.condition = condition;
this.body = body;
}
public Term getCondition() {
return condition;
}
public Block getBody() {
return body;
}
}
/**
* Represents a type in a Java source. Such types do not have to be fully
* qualified, though they can be.
*
* @author David J. Pearce
*
*/
public interface Type extends Term {
}
/**
* A generic class for representing primitive types in Java (e.g. boolean,
* int, etc)
*
* @author David J. Pearce
*
*/
public static class Primitive implements Type {
public enum Kind {
VOID, BOOLEAN, BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE
}
private Kind kind;
public Primitive(Kind kind) {
this.kind = kind;
}
public Kind getKind() { return kind; }
}
public static final Primitive VOID = new Primitive(Primitive.Kind.VOID);
public static final Primitive BOOLEAN = new Primitive(Primitive.Kind.BOOLEAN);
public static final Primitive BYTE = new Primitive(Primitive.Kind.BYTE);
public static final Primitive CHAR = new Primitive(Primitive.Kind.CHAR);
public static final Primitive SHORT = new Primitive(Primitive.Kind.SHORT);
public static final Primitive INT = new Primitive(Primitive.Kind.INT);
public static final Primitive LONG = new Primitive(Primitive.Kind.LONG);
public static class Array implements Type {
private Type element;
public Array(Type element) {
this.element = element;
}
public Type getElement() {
return element;
}
}
public static class Reference implements Type {
private String[] elements;
// FIXME: missing generics
public Reference(String... elements) {
this.elements = elements;
}
public String[] getElements() {
return elements;
}
public int size() {
return elements.length;
}
public String get(int i) {
return elements[i];
}
}
}