org.snapscript.tree.define.ClassHierarchy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap Show documentation
Show all versions of snap Show documentation
Dynamic scripting for the JVM
package org.snapscript.tree.define;
import java.util.List;
import org.snapscript.core.Compilation;
import org.snapscript.core.InternalStateException;
import org.snapscript.core.constraint.AnyConstraint;
import org.snapscript.core.constraint.Constraint;
import org.snapscript.core.constraint.ConstraintVerifier;
import org.snapscript.core.module.Module;
import org.snapscript.core.module.Path;
import org.snapscript.core.scope.Scope;
import org.snapscript.core.type.Type;
import org.snapscript.tree.constraint.ClassConstraint;
import org.snapscript.tree.constraint.TraitConstraint;
public class ClassHierarchy implements Compilation {
private final TraitConstraint[] traits;
private final ClassConstraint base;
public ClassHierarchy(TraitConstraint... traits) {
this(null, traits);
}
public ClassHierarchy(ClassConstraint base, TraitConstraint... traits) {
this.traits = traits;
this.base = base;
}
@Override
public TypeHierarchy compile(Module module, Path path, int line) throws Exception {
return new CompileResult(base, traits, path, line);
}
private static class CompileResult implements TypeHierarchy {
private final ConstraintVerifier verifier;
private final TraitConstraint[] traits;
private final ClassConstraint base;
private final Constraint any;
private final Path path;
private final int line;
public CompileResult(ClassConstraint base, TraitConstraint[] traits, Path path, int line) {
this.verifier = new ConstraintVerifier();
this.any = new AnyConstraint();
this.traits = traits;
this.base = base;
this.path = path;
this.line = line;
}
@Override
public void define(Scope scope, Type type) throws Exception {
List types = type.getTypes();
if(base == null) {
types.add(any);
} else {
Type match = base.getType(scope);
if(match == null) {
throw new InternalStateException("Invalid super class for type '" + type + "' in " + path + " at line " + line);
}
types.add(base);
}
for(int i = 0; i < traits.length; i++) {
Constraint trait = traits[i];
Type match = trait.getType(scope);
if(match == null) {
throw new InternalStateException("Invalid trait for type '" + type + "' in " + path + " at line " + line);
}
types.add(trait);
}
}
@Override
public void compile(Scope scope, Type type) throws Exception {
List types = type.getTypes();
for(Constraint base : types) {
try {
verifier.verify(scope, base);
} catch(Exception e) {
throw new InternalStateException("Invalid constraint for '" + type + "' in " + path + " at line " + line, e);
}
}
for(int i = 0; i < traits.length; i++) {
Constraint trait = traits[i];
Type match = trait.getType(scope);
Class real = match.getType();
if(real != null) {
if(!real.isInterface()) {
throw new InternalStateException("Invalid trait '" + trait + "' in " + path + " at line " + line);
}
}
}
}
}
}