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

org.snapscript.tree.function.FunctionInvocation Maven / Gradle / Ivy

The newest version!
package org.snapscript.tree.function;

import static org.snapscript.core.constraint.Constraint.NONE;
import static org.snapscript.core.variable.Value.NULL;

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

import org.snapscript.core.Compilation;
import org.snapscript.core.Context;
import org.snapscript.core.Evaluation;
import org.snapscript.core.constraint.Constraint;
import org.snapscript.core.error.InternalStateException;
import org.snapscript.core.function.Function;
import org.snapscript.core.function.Invocation;
import org.snapscript.core.function.InvocationCache;
import org.snapscript.core.function.bind.FunctionBinder;
import org.snapscript.core.function.bind.FunctionMatcher;
import org.snapscript.core.function.dispatch.FunctionDispatcher;
import org.snapscript.core.link.ImplicitImportLoader;
import org.snapscript.core.module.Module;
import org.snapscript.core.module.Path;
import org.snapscript.core.scope.Scope;
import org.snapscript.core.scope.index.Address;
import org.snapscript.core.scope.index.ScopeIndex;
import org.snapscript.core.scope.index.LocalValueFinder;
import org.snapscript.core.trace.Trace;
import org.snapscript.core.trace.TraceEvaluation;
import org.snapscript.core.trace.TraceInterceptor;
import org.snapscript.core.type.Type;
import org.snapscript.core.type.TypeExtractor;
import org.snapscript.core.variable.Constant;
import org.snapscript.core.variable.Value;
import org.snapscript.tree.ArgumentList;
import org.snapscript.tree.NameReference;
import org.snapscript.tree.constraint.GenericList;
import org.snapscript.tree.constraint.GenericParameterExtractor;
import org.snapscript.tree.literal.TextLiteral;

public class FunctionInvocation implements Compilation {

   private final Evaluation[] evaluations;
   private final NameReference identifier;
   private final ArgumentList arguments;
   private final GenericList generics;
   
   public FunctionInvocation(TextLiteral identifier, GenericList generics, ArgumentList arguments, Evaluation... evaluations) {
      this.identifier = new NameReference(identifier);
      this.evaluations = evaluations;
      this.arguments = arguments;
      this.generics = generics;
   }
   
   @Override
   public Evaluation compile(Module module, Path path, int line) throws Exception {
      Context context = module.getContext();
      TraceInterceptor interceptor = context.getInterceptor();     
      Trace trace = Trace.getInvoke(module, path, line);
      Evaluation invocation = create(module, path, line);
      
      return new TraceEvaluation(interceptor, invocation, trace);
   }
   
   private Evaluation create(Module module, Path path, int line) throws Exception {
      Scope scope = module.getScope();
      Context context = module.getContext();
      String name = identifier.getName(scope);
      TypeExtractor extractor = context.getExtractor();
      FunctionBinder binder = context.getBinder();   
      FunctionMatcher matcher = binder.bind(name);
      
      return new CompileResult(matcher, extractor, generics, arguments, evaluations, name);     
   }
   
   private static class CompileResult extends Evaluation {   

      private final GenericParameterExtractor extractor;
      private final AtomicReference
location; private final Evaluation[] evaluations; // func()[1][x] private final ImplicitImportLoader loader; private final LocalValueFinder finder; private final FunctionMatcher matcher; private final ArgumentList arguments; private final InvocationCache cache; private final String name; public CompileResult(FunctionMatcher matcher, TypeExtractor extractor, GenericList generics, ArgumentList arguments, Evaluation[] evaluations, String name) { this.extractor = new GenericParameterExtractor(generics); this.cache = new InvocationCache(matcher, extractor); this.location = new AtomicReference
(); this.loader = new ImplicitImportLoader(); this.finder = new LocalValueFinder(name); this.evaluations = evaluations; this.arguments = arguments; this.matcher = matcher; this.name = name; } @Override public void define(Scope scope) throws Exception { ScopeIndex index = scope.getIndex(); Address address = index.get(name); if(address == null) { loader.loadImports(scope, name); } else { location.set(address); } arguments.define(scope); for(Evaluation evaluation : evaluations) { evaluation.define(scope); } } @Override public Constraint compile(Scope scope, Constraint left) throws Exception { Address address = location.get(); Value value = finder.findFunction(scope, address); if(value != null) { Constraint constraint = value.getConstraint(); Type type = constraint.getType(scope); if(type == null) { arguments.compile(scope); return NONE; } return compile(scope, name, constraint); } return compile(scope, name); } private Constraint compile(Scope scope, String name) throws Exception { Type[] array = arguments.compile(scope); Scope composite = extractor.extract(scope); FunctionDispatcher dispatcher = matcher.match(scope); Constraint result = dispatcher.compile(composite, NONE, array); for(Evaluation evaluation : evaluations) { if(result == null) { throw new InternalStateException("Result of '" + name + "' is null"); } result = evaluation.compile(composite, result); } return result; } private Constraint compile(Scope scope, String name, Constraint local) throws Exception { Type[] array = arguments.compile(scope); Scope composite = extractor.extract(scope); FunctionDispatcher dispatcher = matcher.match(scope); Constraint result = dispatcher.compile(composite, local, array); for(Evaluation evaluation : evaluations) { if(result == null) { throw new InternalStateException("Result of '" + name + "' is null"); } result = evaluation.compile(composite, result); } return result; } @Override public Value evaluate(Scope scope, Value left) throws Exception { Address address = location.get(); Value value = finder.findFunction(scope, address); if(value != null) { Object object = value.getValue(); Value constant = Constant.getConstant(value); if(Function.class.isInstance(object)) { return evaluate(scope, name, constant); } } return evaluate(scope, name); } private Value evaluate(Scope scope, String name) throws Exception { Object[] array = arguments.create(scope); Invocation connection = cache.fetch(scope, array); Object object = connection.invoke(scope, NULL, array); Value value = Value.getTransient(object); for(Evaluation evaluation : evaluations) { Object result = value.getValue(); if(result == null) { throw new InternalStateException("Result of '" + name + "' is null"); } value = evaluation.evaluate(scope, value); } return value; } private Value evaluate(Scope scope, String name, Value local) throws Exception { Object[] array = arguments.create(scope); Invocation connection = cache.fetch(scope, local, array); Object object = connection.invoke(scope, local, array); Value value = Value.getTransient(object); for(Evaluation evaluation : evaluations) { Object result = value.getValue(); if(result == null) { throw new InternalStateException("Result of '" + name + "' is null"); } value = evaluation.evaluate(scope, value); } return value; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy