package org.reldb.rel.v0.storage;
import java.util.LinkedList;
import org.reldb.rel.exceptions.ExceptionSemantic;
import org.reldb.rel.v0.generator.Generator;
import org.reldb.rel.v0.generator.OperatorSignature;
import org.reldb.rel.v0.generator.References;
import org.reldb.rel.v0.interpreter.Interpreter;
import org.reldb.rel.v0.storage.catalog.Catalog;
import org.reldb.rel.v0.storage.catalog.RelvarTypes;
import org.reldb.rel.v0.types.Type;
import org.reldb.rel.v0.types.TypeAlpha;
import org.reldb.rel.v0.types.builtin.TypeBoolean;
import org.reldb.rel.v0.types.builtin.TypeCharacter;
import org.reldb.rel.v0.types.builtin.TypeInteger;
import org.reldb.rel.v0.types.builtin.TypeRational;
import org.reldb.rel.v0.values.TupleIterator;
import org.reldb.rel.v0.values.Value;
import org.reldb.rel.v0.values.ValueBoolean;
import org.reldb.rel.v0.values.ValueCharacter;
import org.reldb.rel.v0.values.ValueInteger;
import org.reldb.rel.v0.values.ValueRational;
import org.reldb.rel.v0.values.ValueRelation;
import org.reldb.rel.v0.values.ValueTuple;
import org.reldb.rel.v0.vm.Context;
import org.reldb.rel.v0.vm.NativeFunction;
import org.reldb.rel.v0.vm.VirtualMachine;
public class BuiltinTypeBuilder {
public final static String EQUALS = "OP_EQUALS";
public final static String NOTEQUALS = "OP_NOTEQUALS";
public final static String GREATERTHAN = "OP_GREATERTHAN";
public final static String LESSTHAN = "OP_LESSTHAN";
public final static String GREATERTHANOREQUALS = "OP_GREATERTHANOREQUALS";
public final static String LESSTHANOREQUALS = "OP_LESSTHANOREQUALS";
public final static String MAX = "OP_MAX";
public final static String MIN = "OP_MIN";
public final static String XOR = "OP_XOR";
public final static String OR = "OP_OR";
public final static String AND = "OP_AND";
public final static String NOT = "OP_NOT";
public final static String PLUS = "OP_PLUS";
public final static String MINUS = "OP_MINUS";
public final static String TIMES = "OP_TIMES";
public final static String DIVIDE = "OP_DIVIDE";
public final static String MODULO = "OP_MODULO";
public final static String UNARY_PLUS = "OP_UNARY_PLUS";
public final static String UNARY_MINUS = "OP_UNARY_MINUS";
public static final String SUBSET = "OP_SUBSET";
public static final String SUBSETOREQUAL = "OP_SUBSETOREQUAL";
public static final String SUPERSET = "OP_SUPERSET";
public static final String SUPERSETOREQUAL = "OP_SUPERSETOREQUAL";
private static LinkedList<String> subTypes = new LinkedList<String>();
private RelDatabase database;
private Generator generator;
private TypeAlpha type;
private boolean typeExists;
private static void loadSubtypes(RelDatabase database) {
Interpreter interpreter = new Interpreter(database, System.out);
Generator generator = interpreter.getGenerator();
for (String typeName: subTypes)
database.loadType(generator, typeName);
}
public BuiltinTypeBuilder(RelDatabase database, TypeAlpha type) {
this.database = database;
this.type = type;
typeExists = false;
Interpreter interpreter = new Interpreter(database, System.out);
generator = interpreter.getGenerator();
generator.beginCompilation();
String typeName = type.getTypeName();
if (database.isTypeExists(generator, typeName)) {
generator.beginTypeRetrieval();
generator.createTypeBuiltin(type);
generator.endTypeRetrieval();
RelvarTypes typesRelvar = (RelvarTypes)database.openGlobalRelvar(Catalog.relvarTypes);
ValueTuple typeTuple = typesRelvar.getTupleForKey(generator, typeName);
ValueRelation subTypeNames = (ValueRelation)typeTuple.getValues()[5];
for (TupleIterator it = subTypeNames.iterator(); it.hasNext();)
subTypes.add(it.next().getValues()[0].stringValue());
typeExists = true;
} else {
generator.createTypeBuiltin(type);
}
}
public void checkTypeOperatorUnary(String name, TypeAlpha returnType, final NativeFunction operator) {
String typeName = type.getTypeName();
References referenceToType = new References();
referenceToType.addReferenceToType(type.getTypeName());
OperatorSignature signature = new OperatorSignature(name);
signature.addParameter("%p0", type);
signature.setReturnType(returnType);
if (typeExists)
generator.beginTypeRetrieval();
generator.new OperatorAssociatedWithType(typeName, "Rel", signature, referenceToType) {
public Value evaluate(Value[] arguments) {
return operator.evaluate(arguments);
}
};
if (typeExists)
generator.endTypeRetrieval();
}
public void checkTypeOperatorBinary(String name, Type returnType, final NativeFunction operator) {
String typeName = type.getTypeName();
References referenceToType = new References();
referenceToType.addReferenceToType(type.getTypeName());
OperatorSignature signature = new OperatorSignature(name);
signature.addParameter("%p0", type);
signature.addParameter("%p1", type);
signature.setReturnType(returnType);
if (typeExists)
generator.beginTypeRetrieval();
generator.new OperatorAssociatedWithType(typeName, "Rel", signature, referenceToType) {
public Value evaluate(Value[] arguments) {
return operator.evaluate(arguments);
}
};
if (typeExists)
generator.endTypeRetrieval();
}
public void go() {
generator.endCompilation().call(new Context(generator, new VirtualMachine(generator, database, System.out)));
}
public static void buildTypes(RelDatabase relDatabase) {
final BuiltinTypeBuilder typeBuilderBoolean = new BuiltinTypeBuilder(relDatabase, TypeBoolean.getInstance());
final BuiltinTypeBuilder typeBuilderInteger = new BuiltinTypeBuilder(relDatabase, TypeInteger.getInstance());
final BuiltinTypeBuilder typeBuilderRational = new BuiltinTypeBuilder(relDatabase, TypeRational.getInstance());
final BuiltinTypeBuilder typeBuilderCharacter = new BuiltinTypeBuilder(relDatabase, TypeCharacter.getInstance());
typeBuilderBoolean.checkTypeOperatorBinary(EQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, arguments[0].booleanValue() == arguments[1].booleanValue());
}
});
typeBuilderBoolean.checkTypeOperatorBinary(NOTEQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, arguments[0].booleanValue() != arguments[1].booleanValue());
}
});
typeBuilderBoolean.checkTypeOperatorBinary(XOR, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, arguments[0].booleanValue() ^ arguments[1].booleanValue());
}
});
typeBuilderBoolean.checkTypeOperatorBinary(OR, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, arguments[0].booleanValue() | arguments[1].booleanValue());
}
});
typeBuilderBoolean.checkTypeOperatorBinary(AND, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, arguments[0].booleanValue() & arguments[1].booleanValue());
}
});
typeBuilderBoolean.checkTypeOperatorUnary(NOT, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderBoolean.generator, !arguments[0].booleanValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(EQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() == arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(NOTEQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() != arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(GREATERTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() >= arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(LESSTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() <= arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(LESSTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() < arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(GREATERTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderInteger.generator, arguments[0].longValue() > arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(MAX, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].longValue() > arguments[1].longValue())
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue());
else
return ValueInteger.select(typeBuilderInteger.generator, arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(MIN, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].longValue() < arguments[1].longValue())
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue());
else
return ValueInteger.select(typeBuilderInteger.generator, arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(PLUS, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue() + arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(MINUS, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue() - arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(TIMES, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue() * arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(DIVIDE, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[1].longValue() == 0)
throw new ExceptionSemantic("RS0207: Attempt to divide by zero.");
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue() / arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorBinary(MODULO, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[1].longValue() == 0)
throw new ExceptionSemantic("RS0419: Attempt to perform modulo by zero.");
return ValueInteger.select(typeBuilderInteger.generator, arguments[0].longValue() % arguments[1].longValue());
}
});
typeBuilderInteger.checkTypeOperatorUnary(UNARY_PLUS, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueInteger.select(typeBuilderInteger.generator, +arguments[0].longValue());
}
});
typeBuilderInteger.checkTypeOperatorUnary(UNARY_MINUS, TypeInteger.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueInteger.select(typeBuilderInteger.generator, -arguments[0].longValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(EQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() == arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(NOTEQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() != arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(GREATERTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() >= arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(LESSTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() <= arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(LESSTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() < arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(GREATERTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderRational.generator, arguments[0].doubleValue() > arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(MAX, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].doubleValue() > arguments[1].doubleValue())
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue());
else
return ValueRational.select(typeBuilderRational.generator, arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(MIN, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].doubleValue() < arguments[1].doubleValue())
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue());
else
return ValueRational.select(typeBuilderRational.generator, arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(PLUS, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue() + arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(MINUS, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue() - arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(TIMES, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue() * arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorBinary(DIVIDE, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, arguments[0].doubleValue() / arguments[1].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorUnary(UNARY_PLUS, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, +arguments[0].doubleValue());
}
});
typeBuilderRational.checkTypeOperatorUnary(UNARY_MINUS, TypeRational.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueRational.select(typeBuilderRational.generator, -arguments[0].doubleValue());
}
});
typeBuilderCharacter.checkTypeOperatorBinary(EQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())==0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(NOTEQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())!=0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(GREATERTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())>=0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(LESSTHANOREQUALS, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())<=0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(LESSTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())<0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(GREATERTHAN, TypeBoolean.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
return ValueBoolean.select(typeBuilderCharacter.generator, arguments[0].stringValue().compareTo(arguments[1].stringValue())>0);
}
});
typeBuilderCharacter.checkTypeOperatorBinary(MAX, TypeCharacter.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].stringValue().compareTo(arguments[1].stringValue())>0)
return ValueCharacter.select(typeBuilderCharacter.generator, arguments[0].stringValue());
else
return ValueCharacter.select(typeBuilderCharacter.generator, arguments[1].stringValue());
}
});
typeBuilderCharacter.checkTypeOperatorBinary(MIN, TypeCharacter.getInstance(), new NativeFunction() {
public Value evaluate(Value[] arguments) {
if (arguments[0].stringValue().compareTo(arguments[1].stringValue())<0)
return ValueCharacter.select(typeBuilderCharacter.generator, arguments[0].stringValue());
else
return ValueCharacter.select(typeBuilderCharacter.generator, arguments[1].stringValue());
}
});
typeBuilderBoolean.go();
typeBuilderInteger.go();
typeBuilderRational.go();
typeBuilderCharacter.go();
loadSubtypes(relDatabase);
}
}