expressions: Replace is*-methods with an is(type) method.

This cleans up the code a lot and allows us to more easily reason over types.
27 files changed, 117 insertions(+), 225 deletions(-)

M src/main/java/nl/grauw/glass/Scope.java
M src/main/java/nl/grauw/glass/SourceBuilder.java
M src/main/java/nl/grauw/glass/expressions/Add.java
M src/main/java/nl/grauw/glass/expressions/Annotation.java
M src/main/java/nl/grauw/glass/expressions/BinaryOperator.java
M src/main/java/nl/grauw/glass/expressions/CharacterLiteral.java
M src/main/java/nl/grauw/glass/expressions/ContextLiteral.java
M src/main/java/nl/grauw/glass/expressions/ErrorLiteral.java
M src/main/java/nl/grauw/glass/expressions/Expression.java
M src/main/java/nl/grauw/glass/expressions/Flag.java
M src/main/java/nl/grauw/glass/expressions/FlagOrRegister.java
M src/main/java/nl/grauw/glass/expressions/Group.java
M src/main/java/nl/grauw/glass/expressions/IfElse.java
M src/main/java/nl/grauw/glass/expressions/Instruction.java
M src/main/java/nl/grauw/glass/expressions/IntegerLiteral.java
M src/main/java/nl/grauw/glass/expressions/Member.java
M src/main/java/nl/grauw/glass/expressions/Not.java
M src/main/java/nl/grauw/glass/expressions/Passthrough.java
M src/main/java/nl/grauw/glass/expressions/Register.java
M src/main/java/nl/grauw/glass/expressions/Schema.java
M src/main/java/nl/grauw/glass/expressions/SectionContextLiteral.java
M src/main/java/nl/grauw/glass/expressions/StringLiteral.java
M src/main/java/nl/grauw/glass/expressions/Subtract.java
A => src/main/java/nl/grauw/glass/expressions/Type.java
M src/main/java/nl/grauw/glass/expressions/UnaryOperator.java
M src/main/java/nl/grauw/glass/instructions/Section.java
M src/test/java/nl/grauw/glass/expressions/ExpressionTest.java
M src/main/java/nl/grauw/glass/Scope.java +4 -3
@@ 11,6 11,7 @@ import nl.grauw.glass.expressions.Contex
 import nl.grauw.glass.expressions.ErrorLiteral;
 import nl.grauw.glass.expressions.EvaluationException;
 import nl.grauw.glass.expressions.Expression;
+import nl.grauw.glass.expressions.Type;
 
 public class Scope implements Context {
 

          
@@ 99,7 100,7 @@ public class Scope implements Context {
 		int index = name.length();
 		while ((index = name.lastIndexOf('.', index - 1)) != -1) {
 			Expression result = symbols.get(name.substring(0, index));
-			if (result != null && result.isContext())
+			if (result != null && result.is(Type.CONTEXT))
 				return ((Scope)result.getContext()).getLocalSymbolOrNull(name.substring(index + 1));
 		}
 		return null;

          
@@ 134,14 135,14 @@ public class Scope implements Context {
 		for (Map.Entry<String, Expression> entry : sortedMap.entrySet()) {
 			String name = namePrefix + entry.getKey();
 			Expression value = entry.getValue();
-			if (value.isInteger()) {
+			if (value.is(Type.INTEGER)) {
 				try {
 					builder.append(name + ": equ " + value.getHexValue() + "\n");
 				} catch (EvaluationException e) {
 					// ignore
 				}
 			}
-			if (value.isContext()) {
+			if (value.is(Type.CONTEXT)) {
 				try {
 					Scope context = (Scope)value.getContext();
 					builder.append(context.serializeSymbols(name + "."));

          
M src/main/java/nl/grauw/glass/SourceBuilder.java +2 -1
@@ 23,6 23,7 @@ import nl.grauw.glass.directives.Termina
 import nl.grauw.glass.expressions.Annotation;
 import nl.grauw.glass.expressions.Expression;
 import nl.grauw.glass.expressions.Sequence;
+import nl.grauw.glass.expressions.Type;
 
 public class SourceBuilder {
 

          
@@ 179,7 180,7 @@ public class SourceBuilder {
 		}
 		if (line.getArguments() instanceof Sequence)
 			throw new AssemblyException("Include only accepts 1 argument.");
-		if (!argument.isString())
+		if (!argument.is(Type.STRING))
 			throw new AssemblyException("A string literal is expected.");
 		SourceBuilder sourceBuilder = new SourceBuilder(source.getScope(), END_TERMINATORS, includePaths);
 		sourceBuilder.parseInclude(argument, sourceFile, once);

          
M src/main/java/nl/grauw/glass/expressions/Add.java +13 -10
@@ 20,22 20,25 @@ public class Add extends BinaryOperator 
 	}
 
 	@Override
+	public boolean is(Type type) {
+		if (type == Type.REGISTER) {
+			if (term1.is(Type.REGISTER)) {
+				Register register = term1.getRegister();
+				return register.isIndex() && register.isPair();
+			}
+			return false;
+		}
+		return super.is(type);
+	}
+
+	@Override
 	public int getInteger() {
 		return term1.getInteger() + term2.getInteger();
 	}
 
 	@Override
-	public boolean isRegister() {
-		if (term1.isRegister()) {
-			Register register = term1.getRegister();
-			return register.isIndex() && register.isPair();
-		}
-		return false;
-	}
-
-	@Override
 	public Register getRegister() {
-		if (term1.isRegister()) {
+		if (term1.is(Type.REGISTER)) {
 			Register register = term1.getRegister();
 			if (register.isIndex() && register.isPair())
 				return new Register(register, new Add(register.getIndexOffset(), term2));

          
M src/main/java/nl/grauw/glass/expressions/Annotation.java +5 -0
@@ 23,6 23,11 @@ public class Annotation extends Expressi
 		return annotee;
 	}
 
+	@Override
+	public boolean is(Type type) {
+		return type == Type.ANNOTATION;
+	}
+
 	public String toString() {
 		return "" + annotation + " " + annotee;
 	}

          
M src/main/java/nl/grauw/glass/expressions/BinaryOperator.java +2 -2
@@ 21,8 21,8 @@ public abstract class BinaryOperator ext
 	}
 
 	@Override
-	public boolean isInteger() {
-		return term1.isInteger() && term2.isInteger();
+	public boolean is(Type type) {
+		return type == Type.INTEGER && term1.is(type) && term2.is(type);
 	}
 
 	public String toString() {

          
M src/main/java/nl/grauw/glass/expressions/CharacterLiteral.java +2 -2
@@ 18,8 18,8 @@ public class CharacterLiteral extends Li
 	}
 
 	@Override
-	public boolean isInteger() {
-		return true;
+	public boolean is(Type type) {
+		return type == Type.INTEGER;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/ContextLiteral.java +2 -7
@@ 14,18 14,13 @@ public class ContextLiteral extends Lite
 	}
 
 	@Override
-	public boolean isContext() {
-		return true;
-	}
-
-	@Override
 	public Context getContext() {
 		return context;
 	}
 
 	@Override
-	public boolean isInteger() {
-		return true;
+	public boolean is(Type type) {
+		return type == Type.INTEGER || type == Type.CONTEXT;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/ErrorLiteral.java +1 -36
@@ 21,7 21,7 @@ public class ErrorLiteral extends Litera
 	}
 
 	@Override
-	public boolean isInteger() {
+	public boolean is(Type type) {
 		return true;
 	}
 

          
@@ 31,41 31,21 @@ public class ErrorLiteral extends Litera
 	}
 
 	@Override
-	public boolean isString() {
-		return true;
-	}
-
-	@Override
 	public String getString() {
 		throw exception;
 	}
 
 	@Override
-	public boolean isRegister() {
-		return true;
-	}
-
-	@Override
 	public Register getRegister() {
 		throw exception;
 	}
 
 	@Override
-	public boolean isFlag() {
-		return true;
-	}
-
-	@Override
 	public Flag getFlag() {
 		throw exception;
 	}
 
 	@Override
-	public boolean isGroup() {
-		return true;
-	}
-
-	@Override
 	public Identifier getAnnotation() {
 		throw exception;
 	}

          
@@ 76,31 56,16 @@ public class ErrorLiteral extends Litera
 	}
 
 	@Override
-	public boolean isInstruction() {
-		return true;
-	}
-
-	@Override
 	public InstructionFactory getInstruction() {
 		throw exception;
 	}
 
 	@Override
-	public boolean isContext() {
-		return true;
-	}
-
-	@Override
 	public Context getContext() {
 		throw exception;
 	}
 
 	@Override
-	public boolean isSectionContext() {
-		return true;
-	}
-
-	@Override
 	public SectionContext getSectionContext() {
 		throw exception;
 	}

          
M src/main/java/nl/grauw/glass/expressions/Expression.java +2 -32
@@ 11,46 11,28 @@ public abstract class Expression {
 
 	public abstract Expression copy(Context context);
 
+	public abstract boolean is(Type type);
+
 	public Expression resolve() {
 		return this;
 	}
 
-	public boolean isInteger() {
-		return false;
-	}
-
 	public int getInteger() {
 		throw new EvaluationException("Not an integer.");
 	}
 
-	public boolean isString() {
-		return false;
-	}
-
 	public String getString() {
 		throw new EvaluationException("Not a string.");
 	}
 
-	public boolean isRegister() {
-		return false;
-	}
-
 	public Register getRegister() {
 		throw new EvaluationException("Not a register.");
 	}
 
-	public boolean isFlag() {
-		return false;
-	}
-
 	public Flag getFlag() {
 		throw new EvaluationException("Not a flag.");
 	}
 
-	public boolean isGroup() {
-		return false;
-	}
-
 	public Identifier getAnnotation() {
 		return null;
 	}

          
@@ 59,26 41,14 @@ public abstract class Expression {
 		return this;
 	}
 
-	public boolean isInstruction() {
-		return false;
-	}
-
 	public InstructionFactory getInstruction() {
 		throw new EvaluationException("Not an instruction.");
 	}
 
-	public boolean isContext() {
-		return false;
-	}
-
 	public Context getContext() {
 		throw new EvaluationException("Not a context.");
 	}
 
-	public boolean isSectionContext() {
-		return false;
-	}
-
 	public SectionContext getSectionContext() {
 		throw new EvaluationException("Not a context.");
 	}

          
M src/main/java/nl/grauw/glass/expressions/Flag.java +2 -2
@@ 29,8 29,8 @@ public class Flag extends Literal {
 	}
 
 	@Override
-	public boolean isFlag() {
-		return true;
+	public boolean is(Type type) {
+		return type == Type.FLAG;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/FlagOrRegister.java +4 -9
@@ 18,23 18,18 @@ public class FlagOrRegister extends Lite
 	}
 
 	@Override
-	public boolean isFlag() {
-		return true;
-	}
-
-	@Override
 	public Flag getFlag() {
 		return flag;
 	}
 
 	@Override
-	public boolean isRegister() {
-		return true;
+	public Register getRegister() {
+		return register;
 	}
 
 	@Override
-	public Register getRegister() {
-		return register;
+	public boolean is(Type type) {
+		return type == Type.FLAG || type == Type.REGISTER;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/Group.java +2 -2
@@ 23,8 23,8 @@ public class Group extends Passthrough {
 	}
 
 	@Override
-	public boolean isGroup() {
-		return true;
+	public boolean is(Type type) {
+		return type == Type.GROUP || super.is(type);
 	}
 
 	public String toString() {

          
M src/main/java/nl/grauw/glass/expressions/IfElse.java +2 -22
@@ 39,28 39,8 @@ public class IfElse extends Passthrough 
 	}
 
 	@Override
-	public boolean isInteger() {
-		return (trueTerm.isInteger() && falseTerm.isInteger()) || super.isInteger();
-	}
-
-	@Override
-	public boolean isString() {
-		return (trueTerm.isString() && falseTerm.isString()) || super.isString();
-	}
-
-	@Override
-	public boolean isRegister() {
-		return (trueTerm.isRegister() && falseTerm.isRegister()) || super.isRegister();
-	}
-
-	@Override
-	public boolean isFlag() {
-		return (trueTerm.isFlag() && falseTerm.isFlag()) || super.isFlag();
-	}
-
-	@Override
-	public boolean isContext() {
-		return (trueTerm.isContext() && falseTerm.isContext()) || super.isContext();
+	public boolean is(Type type) {
+		return (trueTerm.is(type) && falseTerm.is(type)) || super.is(type);
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/Instruction.java +4 -9
@@ 18,23 18,18 @@ public class Instruction extends Express
 	}
 
 	@Override
-	public boolean isInstruction() {
-		return true;
-	}
-
-	@Override
 	public InstructionFactory getInstruction() {
 		return instruction;
 	}
 
 	@Override
-	public boolean isContext() {
-		return true;
+	public Context getContext() {
+		return context;
 	}
 
 	@Override
-	public Context getContext() {
-		return context;
+	public boolean is(Type type) {
+		return type == Type.INSTRUCTION || type == Type.CONTEXT;
 	}
 
 	public String toString() {

          
M src/main/java/nl/grauw/glass/expressions/IntegerLiteral.java +4 -4
@@ 17,13 17,13 @@ public class IntegerLiteral extends Lite
 	}
 
 	@Override
-	public boolean isInteger() {
-		return true;
+	public int getInteger() {
+		return value;
 	}
 
 	@Override
-	public int getInteger() {
-		return value;
+	public boolean is(Type type) {
+		return type == Type.INTEGER;
 	}
 
 	public String toString() {

          
M src/main/java/nl/grauw/glass/expressions/Member.java +1 -1
@@ 25,7 25,7 @@ public class Member extends Passthrough 
 
 	@Override
 	public Expression resolve() {
-		if (!object.isContext())
+		if (!object.is(Type.CONTEXT))
 			return new ErrorLiteral(new EvaluationException("Object not found."));
 		return object.getContext().getLocalSymbol(subject.getName());
 	}

          
M src/main/java/nl/grauw/glass/expressions/Not.java +4 -4
@@ 14,13 14,13 @@ public class Not extends UnaryOperator {
 	}
 
 	@Override
-	public int getInteger() {
-		return term.getInteger() == 0 ? -1 : 0;
+	public boolean is(Type type) {
+		return type == Type.FLAG && term.is(Type.FLAG) || super.is(type);
 	}
 
 	@Override
-	public boolean isFlag() {
-		return term.isFlag();
+	public int getInteger() {
+		return term.getInteger() == 0 ? -1 : 0;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/Passthrough.java +2 -37
@@ 5,8 5,8 @@ import nl.grauw.glass.instructions.Instr
 public abstract class Passthrough extends Expression {
 
 	@Override
-	public boolean isInteger() {
-		return resolve().isInteger();
+	public boolean is(Type type) {
+		return resolve().is(type);
 	}
 
 	@Override

          
@@ 15,66 15,31 @@ public abstract class Passthrough extend
 	}
 
 	@Override
-	public boolean isString() {
-		return resolve().isString();
-	}
-
-	@Override
 	public String getString() {
 		return resolve().getString();
 	}
 
 	@Override
-	public boolean isRegister() {
-		return resolve().isRegister();
-	}
-
-	@Override
 	public Register getRegister() {
 		return resolve().getRegister();
 	}
 
 	@Override
-	public boolean isFlag() {
-		return resolve().isFlag();
-	}
-
-	@Override
 	public Flag getFlag() {
 		return resolve().getFlag();
 	}
 
 	@Override
-	public boolean isGroup() {
-		return resolve().isGroup();
-	}
-
-	@Override
-	public boolean isInstruction() {
-		return resolve().isInstruction();
-	}
-
-	@Override
 	public InstructionFactory getInstruction() {
 		return resolve().getInstruction();
 	}
 
 	@Override
-	public boolean isContext() {
-		return resolve().isContext();
-	}
-
-	@Override
 	public Context getContext() {
 		return resolve().getContext();
 	}
 
 	@Override
-	public boolean isSectionContext() {
-		return resolve().isSectionContext();
-	}
-
-	@Override
 	public SectionContext getSectionContext() {
 		return resolve().getSectionContext();
 	}

          
M src/main/java/nl/grauw/glass/expressions/Register.java +2 -2
@@ 95,8 95,8 @@ public class Register extends Literal {
 	}
 
 	@Override
-	public boolean isRegister() {
-		return true;
+	public boolean is(Type type) {
+		return type == Type.REGISTER;
 	}
 
 	@Override

          
M src/main/java/nl/grauw/glass/expressions/Schema.java +9 -9
@@ 64,13 64,13 @@ public class Schema implements SchemaTyp
 
 	public static class IsDirect implements SchemaType {
 		public boolean check(Expression argument) {
-			return !argument.isGroup();
+			return !argument.is(Type.GROUP);
 		}
 	}
 
 	public static class IsIndirect implements SchemaType {
 		public boolean check(Expression argument) {
-			return argument.isGroup();
+			return argument.is(Type.GROUP);
 		}
 	}
 

          
@@ 86,13 86,13 @@ public class Schema implements SchemaTyp
 
 	public static class IsInteger implements SchemaType {
 		public boolean check(Expression argument) {
-			return argument.isInteger();
+			return argument.is(Type.INTEGER);
 		}
 	}
 
 	public static class IsString implements SchemaType {
 		public boolean check(Expression argument) {
-			return argument.isString();
+			return argument.is(Type.STRING);
 		}
 	}
 

          
@@ 108,7 108,7 @@ public class Schema implements SchemaTyp
 			this.registers = registers;
 		}
 		public boolean check(Expression argument) {
-			if (argument.isRegister()) {
+			if (argument.is(Type.REGISTER)) {
 				Register register = argument.getRegister();
 				for (Register expected : registers)
 					if (register == expected)

          
@@ 120,7 120,7 @@ public class Schema implements SchemaTyp
 
 	public static class IsRegister8Bit implements SchemaType {
 		public boolean check(Expression argument) {
-			if (argument.isRegister()) {
+			if (argument.is(Type.REGISTER)) {
 				Register register = argument.getRegister();
 				return !register.isPair() && register != Register.I && register != Register.R;
 			}

          
@@ 130,7 130,7 @@ public class Schema implements SchemaTyp
 
 	public static class IsDirectRIndirectHLIXIY implements SchemaType {
 		public boolean check(Expression argument) {
-			if (argument.isRegister()) {
+			if (argument.is(Type.REGISTER)) {
 				Register register = argument.getRegister();
 				return DIRECT.check(argument) && !register.isPair() && register != Register.I && register != Register.R ||
 						INDIRECT.check(argument) && (register == Register.HL || register.isIndex());

          
@@ 141,13 141,13 @@ public class Schema implements SchemaTyp
 
 	public static class IsFlag implements SchemaType {
 		public boolean check(Expression argument) {
-			return argument.isFlag();
+			return argument.is(Type.FLAG);
 		}
 	}
 
 	public static class IsFlagZC implements SchemaType {
 		public boolean check(Expression argument) {
-			return argument.isFlag() && argument.getFlag().getCode() < 4;
+			return argument.is(Type.FLAG) && argument.getFlag().getCode() < 4;
 		}
 	}
 

          
M src/main/java/nl/grauw/glass/expressions/SectionContextLiteral.java +5 -5
@@ 10,13 10,13 @@ public class SectionContextLiteral exten
 	}
 
 	@Override
-	public boolean isSectionContext() {
-		return true;
-	}
-
-	@Override
 	public SectionContext getSectionContext() {
 		return sectionContext;
 	}
 
+	@Override
+	public boolean is(Type type) {
+		return type == Type.SECTIONCONTEXT || super.is(type);
+	}
+
 }

          
M src/main/java/nl/grauw/glass/expressions/StringLiteral.java +6 -11
@@ 15,9 15,13 @@ public class StringLiteral extends Liter
 		return this;
 	}
 
+	public String getString() {
+		return string;
+	}
+
 	@Override
-	public boolean isInteger() {
-		return string.length() == 1;
+	public boolean is(Type type) {
+		return type == Type.STRING || (type == Type.INTEGER && string.length() == 1);
 	}
 
 	@Override

          
@@ 28,15 32,6 @@ public class StringLiteral extends Liter
 	}
 
 	@Override
-	public boolean isString() {
-		return true;
-	}
-
-	public String getString() {
-		return string;
-	}
-
-	@Override
 	protected void addToList(List<Expression> list) {
 		for (int i = 0, length = string.length(); i < length; i++)
 			list.add(new CharacterLiteral(string.charAt(i)));

          
M src/main/java/nl/grauw/glass/expressions/Subtract.java +13 -10
@@ 20,22 20,25 @@ public class Subtract extends BinaryOper
 	}
 
 	@Override
+	public boolean is(Type type) {
+		if (type == Type.REGISTER) {
+			if (term1.is(Type.REGISTER) && term2.is(Type.INTEGER)) {
+				Register register = term1.getRegister();
+				return register.isIndex() && register.isPair();
+			}
+			return false;
+		}
+		return super.is(type);
+	}
+
+	@Override
 	public int getInteger() {
 		return term1.getInteger() - term2.getInteger();
 	}
 
 	@Override
-	public boolean isRegister() {
-		if (term1.isRegister() && term2.isInteger()) {
-			Register register = term1.getRegister();
-			return register.isIndex() && register.isPair();
-		}
-		return false;
-	}
-
-	@Override
 	public Register getRegister() {
-		if (term1.isRegister() && term2.isInteger()) {
+		if (term1.is(Type.REGISTER) && term2.is(Type.INTEGER)) {
 			Register register = term1.getRegister();
 			if (register.isIndex() && register.isPair())
 				return new Register(register, new Subtract(register.getIndexOffset(), term2));

          
A => src/main/java/nl/grauw/glass/expressions/Type.java +18 -0
@@ 0,0 1,18 @@ 
+package nl.grauw.glass.expressions;
+
+public class Type {
+
+	public static final Type INTEGER = new Type();
+	public static final Type STRING = new Type();
+	public static final Type REGISTER = new Type();
+	public static final Type FLAG = new Type();
+	public static final Type GROUP = new Type();
+	public static final Type ANNOTATION = new Type();
+	public static final Type INSTRUCTION = new Type();
+	public static final Type CONTEXT = new Type();
+	public static final Type SECTIONCONTEXT = new Type();
+
+	Type() {
+	}
+
+}

          
M src/main/java/nl/grauw/glass/expressions/UnaryOperator.java +2 -2
@@ 15,8 15,8 @@ public abstract class UnaryOperator exte
 	}
 
 	@Override
-	public boolean isInteger() {
-		return term.isInteger();
+	public boolean is(Type type) {
+		return type == Type.INTEGER && term.is(type);
 	}
 
 	public String toString() {

          
M src/main/java/nl/grauw/glass/instructions/Section.java +2 -1
@@ 7,6 7,7 @@ import nl.grauw.glass.Scope;
 import nl.grauw.glass.Source;
 import nl.grauw.glass.expressions.Expression;
 import nl.grauw.glass.expressions.Schema;
+import nl.grauw.glass.expressions.Type;
 
 public class Section extends InstructionFactory {
 

          
@@ 27,7 28,7 @@ public class Section extends Instruction
 		if (!ARGUMENTS.check(line.getArguments()))
 			throw new ArgumentException();
 
-		if (!line.getArguments().isSectionContext())
+		if (!line.getArguments().is(Type.SECTIONCONTEXT))
 			throw new ArgumentException("Argument does not reference a section context.");
 
 		line.getArguments().getSectionContext().addSection(this);

          
M src/test/java/nl/grauw/glass/expressions/ExpressionTest.java +2 -2
@@ 204,9 204,9 @@ public class ExpressionTest extends Test
 
 	@Test
 	public void testTernaryNeverTaken() {
-		assertEquals(true, parse("1 ? 2 : $.x").isInteger());
+		assertEquals(true, parse("1 ? 2 : $.x").is(Type.INTEGER));
 		assertEquals(2, parse("1 ? 2 : $.x").getInteger());
-		assertEquals(true, parse("0 ? $.x : 3").isInteger());
+		assertEquals(true, parse("0 ? $.x : 3").is(Type.INTEGER));
 		assertEquals(3, parse("0 ? $.x : 3").getInteger());
 	}