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

org.snapscript.tree.script.ScriptPackage Maven / Gradle / Ivy

package org.snapscript.tree.script;

import static org.snapscript.core.result.Result.NORMAL;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.snapscript.core.Execution;
import org.snapscript.core.Statement;
import org.snapscript.core.constraint.Constraint;
import org.snapscript.core.error.InternalStateException;
import org.snapscript.core.link.FutureExecution;
import org.snapscript.core.result.Result;
import org.snapscript.core.scope.Scope;

public class ScriptPackage extends Statement {

   private final AtomicReference reference;
   private final Statement[] statements;
   private final AtomicBoolean create;
   private final AtomicBoolean define;
   
   public ScriptPackage(Statement... statements) {
      this.reference = new AtomicReference();
      this.create = new AtomicBoolean(true);
      this.define = new AtomicBoolean(true);
      this.statements = statements;
   }
   
   @Override
   public void create(Scope scope) throws Exception {
      if(create.compareAndSet(true, false)) {
         for(Statement statement : statements) {
            statement.create(scope);
         }
      }
   }
   
   @Override
   public boolean define(Scope scope) throws Exception {
      if(define.compareAndSet(true, false)) {
         for(Statement statement : statements) {
            statement.define(scope);
         }
      }
      return true;
   }
   
   @Override
   public Execution compile(Scope scope, Constraint returns) throws Exception {
      Execution result = reference.get();
      
      if(result == null) {
         ScriptPackageTask job = new ScriptPackageTask(reference, scope, statements);
         FutureTask task = new FutureTask(job);
         FutureExecution execution = new FutureExecution(task, null);
         
         if(reference.compareAndSet(null, execution)) {
            task.run();
            return task.get();
         }
         return reference.get();
      }
      return result;
   }
   
   
   private static class ScriptPackageTask implements Callable {
      
      private final AtomicReference reference;
      private final Statement[] statements;
      private final Scope scope;
      
      public ScriptPackageTask(AtomicReference reference, Scope scope, Statement... statements) {
         this.reference = reference;
         this.statements = statements;
         this.scope = scope;
      }
      
      @Override
      public Execution call() throws Exception {         
         Execution[] executions = new Execution[statements.length];
         Execution execution = new ScriptPackageExecution(executions);
         
         for(int i = 0; i < statements.length; i++) {
            executions[i] = statements[i].compile(scope, null);
            statements[i] = null;
         }
         reference.set(execution);
         return execution;
      }
   }
   
   private static class ScriptPackageExecution extends Execution {
      
      private final Execution[] statements;
      private final AtomicBoolean execute;
      
      public ScriptPackageExecution(Execution... statements) {
         this.execute = new AtomicBoolean(true);
         this.statements = statements;
      }
      
   
      @Override
      public Result execute(Scope scope) throws Exception {
         Result last = NORMAL;
         
         if(execute.compareAndSet(true, false)) {
            for(int i = 0; i < statements.length; i++) {
               Result result = statements[i].execute(scope);
               
               if(!result.isNormal()){
                  throw new InternalStateException("Illegal statement");
               }
               statements[i] = null;
               last = result;
            }
         }
         return last;
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy