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

org.snapscript.core.constraint.transform.AttributeRule Maven / Gradle / Ivy

package org.snapscript.core.constraint.transform;

import java.util.List;

import org.snapscript.core.attribute.Attribute;
import org.snapscript.core.constraint.Constraint;
import org.snapscript.core.convert.InstanceOfChecker;
import org.snapscript.core.error.InternalStateException;
import org.snapscript.core.function.Function;
import org.snapscript.core.function.Parameter;
import org.snapscript.core.scope.Scope;
import org.snapscript.core.scope.State;
import org.snapscript.core.scope.index.Table;
import org.snapscript.core.type.Type;

public class AttributeRule extends ConstraintRule {
   
   private final InstanceOfChecker checker;
   private final Attribute attribute;
   private final ConstraintRule rule;
   
   public AttributeRule(ConstraintRule rule, Attribute attribute) {
      this.checker = new InstanceOfChecker();
      this.attribute = attribute;
      this.rule = rule;
   }

   @Override
   public List getParameters(Scope scope, Function function) {
      Scope updated = getScope(scope);
      return rule.getParameters(updated, function);
   }

   @Override
   public Constraint getResult(Scope scope, Constraint returns) {
      Scope updated = getScope(scope);
      return rule.getResult(updated, returns);
   }

   protected Scope getScope(Scope scope) {
      List defaults = attribute.getGenerics();
      int count = defaults.size();

      if(count > 0) {
         Table table = scope.getTable();
         State state = scope.getState();
         Constraint first = table.getConstraint(0);

         for(int i = 0; i < count; i++) {
            Constraint parameter = table.getConstraint(i);
            Constraint constraint = defaults.get(i);
            String name = constraint.getName(scope);
            Constraint existing = state.getConstraint(name);

            if(parameter != null) {
               Type require = constraint.getType(scope);
               Type actual = parameter.getType(scope);

               if(!checker.isInstanceOf(scope, actual, require)) {
                  throw new InternalStateException("Generic parameter '" + name +"' is does not match '" + constraint + "'");
               }
               if(existing != null) {
                  Type current = existing.getType(scope);

                  if(current != actual) {
                     throw new InternalStateException("Generic parameter '" + name +"' has already been declared");
                  }
               } else {
                  state.addConstraint(name, parameter);
               }
            } else {
               if(first != null) {
                  throw new InternalStateException("Generic parameter '" + name +"' not specified");
               }
               if(existing != null) {
                  Type require = constraint.getType(scope);
                  Type current = existing.getType(scope);

                  if (current != require) {
                     throw new InternalStateException("Generic parameter '" + name + "' has already been declared");
                  }
               } else {
                  state.addConstraint(name, constraint);
               }
            }
         }
      }
      return scope;
   }

   @Override
   public Constraint getSource() {
      return rule.getSource();
   }      
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy