org.snapscript.tree.define.ModuleBody 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.define;
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.link.FutureExecution;
import org.snapscript.core.module.Module;
import org.snapscript.core.result.Result;
import org.snapscript.core.scope.Scope;
public class ModuleBody extends Statement {
private final AtomicReference reference;
private final Statement[] statements;
private final Statement[] executable;
private final ModulePart[] parts;
private final AtomicBoolean create;
private final AtomicBoolean define;
public ModuleBody(ModulePart... parts) {
this.reference = new AtomicReference();
this.statements = new Statement[parts.length];
this.executable = new Statement[parts.length];
this.define = new AtomicBoolean(true);
this.create = new AtomicBoolean(true);
this.parts = parts;
}
@Override
public void create(Scope scope) throws Exception {
if(create.compareAndSet(true, false)) {
Module module = scope.getModule();
for(int i = 0; i < parts.length; i++) {
ModulePart part = parts[i];
Statement statement = part.define(this, module);
statement.create(scope);
statements[i] = statement;
parts[i] = null;
}
}
}
@Override
public boolean define(Scope scope) throws Exception {
if(define.compareAndSet(true, false)) {
for(int i = 0; i < statements.length; i++) {
Statement statement = statements[i];
if(statement.define(scope)){
executable[i] = statement;
statements[i] = null;
}
}
}
return true;
}
@Override
public Execution compile(Scope scope, Constraint returns) throws Exception {
Execution result = reference.get();
if(result == null) {
ModuleTask job = new ModuleTask(scope, statements, executable);
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 class ModuleTask implements Callable {
private final Statement[] executable;
private final Statement[] statements;
private final Scope module;
public ModuleTask(Scope module, Statement[] statements, Statement[] executable) {
this.statements = statements;
this.executable = executable;
this.module = module;
}
@Override
public Execution call() throws Exception {
Execution[] executions = new Execution[statements.length];
Execution execution = new ModuleExecution(module, executions);
for(int i = 0; i < executable.length; i++) {
Statement statement = executable[i];
if(statement != null) {
executions[i] = statement.compile(module, null);
}
}
for(int i = 0; i < statements.length; i++) {
Statement statement = statements[i];
if(statement != null) {
executions[i] = statement.compile(module, null);
}
}
reference.set(execution);
return execution;
}
}
private class ModuleExecution extends Execution {
private final Execution[] executions;
private final AtomicBoolean execute;
private final Scope module;
public ModuleExecution(Scope module, Execution[] executions) {
this.execute = new AtomicBoolean(true);
this.executions = executions;
this.module = module;
}
@Override
public Result execute(Scope scope) throws Exception {
Result last = NORMAL;
if(execute.compareAndSet(true, false)) {
Module parent = module.getModule();
Scope root = parent.getScope();
for(int i = 0; i < executions.length; i++) {
Result result = executions[i].execute(root);
if(!result.isNormal()){
return result;
}
last = result;
}
}
return last;
}
}
}