All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snapscript.tree.define.ClassHierarchy Maven / Gradle / Ivy

There is a newer version: 1.4.6
Show newest version
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);
               }
            }
         }
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy