org.snapscript.tree.script.ScriptPackage 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.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;
}
}
}