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

org.snapscript.tree.Import Maven / Gradle / Ivy

package org.snapscript.tree;

import org.snapscript.core.Compilation;
import org.snapscript.core.Context;
import org.snapscript.core.Evaluation;
import org.snapscript.core.InternalStateException;
import org.snapscript.core.Module;
import org.snapscript.core.NameBuilder;
import org.snapscript.core.NoStatement;
import org.snapscript.core.Path;
import org.snapscript.core.Result;
import org.snapscript.core.ResultType;
import org.snapscript.core.Scope;
import org.snapscript.core.Statement;
import org.snapscript.core.TypeLoader;
import org.snapscript.core.TypeNameBuilder;
import org.snapscript.core.Value;
import org.snapscript.core.link.ImportManager;
import org.snapscript.core.link.Package;
import org.snapscript.core.link.PackageDefinition;

public class Import implements Compilation {

   private final Qualifier qualifier;
   private final Evaluation alias;   
   
   public Import(Qualifier qualifier) {
      this(qualifier, null);
   }
   
   public Import(Qualifier qualifier, Evaluation alias) {
      this.qualifier = qualifier;
      this.alias = alias;
   }
   
   @Override
   public Object compile(Module module, Path path, int line) throws Exception {
      Context context = module.getContext();
      TypeLoader loader = context.getLoader();
      String location = qualifier.getLocation();
      String target = qualifier.getTarget();
      String name = qualifier.getName();
      
      if(target == null) {
         Package library = loader.importPackage(location);
         
         if(library != null) {
            return new CompileResult(library, path, location, null, name);
         }
      }
      Package library = loader.importType(location, target);

      if(library != null) {
         if(alias != null) {
            Scope scope = module.getScope();
            Value value = alias.evaluate(scope, null);
            String alias = value.getString();
            
            return new CompileResult(library, path, location, target, alias);
         } 
         return new CompileResult(library, path, location, target, target, name);
      }
      return new NoStatement();
   }
   
   private static class CompileResult extends Statement {
      
      private PackageDefinition definition;
      private NameBuilder builder;
      private Statement statement;
      private Package library;
      private String location;
      private String target;
      private Path path;
      private String[] alias;

      public CompileResult(Package library, Path path, String location, String target, String... alias) {
         this.builder = new TypeNameBuilder();
         this.location = location;
         this.library = library;
         this.target = target;
         this.alias = alias;
         this.path = path;
      }
      
      @Override
      public Result define(Scope scope) throws Exception {
         if(library == null) {
            throw new InternalStateException("Import '" + location + "' was not loaded");
         }
         if(definition == null) { // define once
            definition = create(scope);
         }
         return ResultType.getNormal(); 
      }

      @Override
      public Result compile(Scope scope) throws Exception {
         if(definition == null) {
            throw new InternalStateException("Import '" + location + "' was not defined");
         }
         if(statement == null) { // compile once
            statement = definition.compile(scope, path);
         }
         return ResultType.getNormal();
      }
      
      @Override
      public Result execute(Scope scope) throws Exception {
         if(statement == null) {
            throw new InternalStateException("Import '" + location + "' was not compiled");
         }
         return statement.execute(scope); // execute many times
      }
      
      private PackageDefinition create(Scope scope) throws Exception {
         Module module = scope.getModule();
         ImportManager manager = module.getManager();
         String type = builder.createFullName(location, target);
             
         if(target == null) {
            manager.addImport(location); // import game.tetris.*;
         }  else {
            if(alias != null) {
               for(String name : alias) {
                  if(name != null) {
                     manager.addImport(type, name); // import game.tetris.Block as Shape;
                  }
               }
            } else {
               manager.addImport(type, target); // import game.tetris.Block;
            }
         }
         return library.define(scope);
      }
   }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy