153 lines
3.0 KiB
Java
153 lines
3.0 KiB
Java
package ssw.mj.codegen;
|
|
|
|
import ssw.mj.impl.Code;
|
|
import ssw.mj.impl.Code.CompOp;
|
|
import ssw.mj.impl.Parser;
|
|
import ssw.mj.impl.Tab;
|
|
import ssw.mj.symtab.Obj;
|
|
import ssw.mj.symtab.Struct;
|
|
|
|
import static ssw.mj.Errors.Message.ILLEGAL_OPERAND_KIND;
|
|
|
|
public class Operand {
|
|
/**
|
|
* Possible operands.
|
|
*/
|
|
public enum Kind {
|
|
Con(true),
|
|
Local(false),
|
|
Static(false),
|
|
Stack(true),
|
|
Fld(false),
|
|
Elem(false),
|
|
Meth(true),
|
|
Cond(true),
|
|
None(true);
|
|
|
|
public final boolean isReadOnly;
|
|
|
|
Kind(boolean isReadOnly) {
|
|
this.isReadOnly = isReadOnly;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Kind of the operand.
|
|
*/
|
|
public Kind kind;
|
|
/**
|
|
* The type of the operand (reference to symbol table).
|
|
*/
|
|
public Struct type;
|
|
/**
|
|
* Only for Con: Value of the constant.
|
|
*/
|
|
public int val;
|
|
/**
|
|
* Only for Local, Static, Fld, Meth: Offset of the element.
|
|
*/
|
|
public int adr;
|
|
/**
|
|
* Only for Cond: Relational operator.
|
|
*/
|
|
public CompOp op;
|
|
/**
|
|
* Only for Meth: Method object from the symbol table.
|
|
*/
|
|
public Obj obj;
|
|
/**
|
|
* Only for Cond: Target for true jumps.
|
|
*/
|
|
public Label tLabel;
|
|
/**
|
|
* Only for Cond: Target for false jumps.
|
|
*/
|
|
public Label fLabel;
|
|
|
|
/**
|
|
* Constructor for named objects: constants, variables, methods
|
|
*/
|
|
public Operand(Obj o, Parser parser) {
|
|
type = o.type;
|
|
val = o.val;
|
|
adr = o.adr;
|
|
switch (o.kind) {
|
|
case Con -> kind = Kind.Con;
|
|
case Var -> {
|
|
if (o.level == 0) {
|
|
kind = Kind.Static;
|
|
} else {
|
|
kind = Kind.Local;
|
|
}
|
|
}
|
|
case Meth -> {
|
|
kind = Kind.Meth;
|
|
obj = o;
|
|
}
|
|
default -> {
|
|
kind = Kind.None;
|
|
parser.error(ILLEGAL_OPERAND_KIND, o.kind);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructor for compare operations
|
|
*/
|
|
public Operand(CompOp op, Code code) {
|
|
this(code);
|
|
this.kind = Kind.Cond;
|
|
this.op = op;
|
|
}
|
|
|
|
public Operand(Code code) {
|
|
tLabel = new Label(code);
|
|
fLabel = new Label(code);
|
|
}
|
|
|
|
/**
|
|
* Constructor for stack operands
|
|
*/
|
|
public Operand(Struct type) {
|
|
this.kind = Kind.Stack;
|
|
this.type = type;
|
|
}
|
|
|
|
/**
|
|
* Constructor for integer constants
|
|
*/
|
|
public Operand(int x) {
|
|
kind = Kind.Con;
|
|
type = Tab.intType;
|
|
val = x;
|
|
}
|
|
|
|
public boolean isReadOnly() {
|
|
return kind.isReadOnly;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder sb = new StringBuilder("Op[");
|
|
switch (kind) {
|
|
case Con -> {
|
|
sb.append(type).append(' ');
|
|
sb.append(val);
|
|
}
|
|
case Local, Static, Fld -> {
|
|
sb.append(kind).append(' ');
|
|
sb.append(type).append(' ');
|
|
sb.append(adr);
|
|
}
|
|
case Cond -> sb.append(op);
|
|
case Meth -> sb.append(obj);
|
|
case Elem, Stack -> {
|
|
sb.append(kind).append(' ');
|
|
sb.append(type);
|
|
}
|
|
}
|
|
return sb.append(']').toString();
|
|
}
|
|
|
|
}
|