Class DefaultContext

java.lang.Object
org.daiitech.naftah.parser.DefaultContext
Direct Known Subclasses:
REPLContext

public class DefaultContext extends Object
Represents the default execution context used to manage variables, functions, loops, and class loading information during runtime.

This class handles:

  • Contextual stacks for function calls and loops
  • Unique identifier generation for functions, parameters, arguments, and loops
  • Class scanning and loading tasks executed asynchronously
  • Storage and management of loaded classes, accessible and instantiable classes
  • Management of JVM and builtin functions

Contexts are arranged hierarchically with possible parent-child relationships, and multiple contexts are tracked globally via a static map keyed by depth.

This class also provides thread-safe lazy loading of classes and functions, with configurable bootstrap behavior.

Note: This class uses custom types such as DeclaredFunction, DeclaredVariable, DeclaredParameter, JvmFunction, BuiltinFunction, and others related to the execution environment and parser.

Author:
Chakib Daii
  • Field Details

    • CACHE_PATH

      public static final Path CACHE_PATH
      The path used for caching runtime data.
    • MINIMAL_CACHE_PATH

      public static final Path MINIMAL_CACHE_PATH
      The path used for caching minimal runtime data.
    • CONTEXTS

      protected static final ConcurrentHashMap<Integer,CopyOnWriteArrayList<DefaultContext>> CONTEXTS
      Global map holding contexts indexed by their depth.
    • CALL_STACK

      protected static final ThreadLocal<Deque<Triple<DeclaredFunction<?>,Map<String,Object>,Object>>> CALL_STACK
      Stack representing the call stack containing pairs of function and argument maps, along with the returned value.
    • LOOP_STACK

      protected static final InheritableThreadLocal<Deque<Pair<String,? extends org.antlr.v4.runtime.ParserRuleContext>>> LOOP_STACK
      Stack representing loop labels and their associated parser rule contexts.
    • LOADER_TASK

      protected static final Supplier<ClassScanningResult> LOADER_TASK
      A supplier task that performs a full asynchronous scan, loading, filtering, and extraction of JVM and builtin functions from the classpath.

      The task executes the following steps:

      1. Scans all available classes.
      2. Generates class qualifiers and their Arabic transliterations.
      3. Loads the Class objects for all discovered classes.
      4. Filters classes into accessible and instantiable sets.
      5. Retrieves JVM class initializers (constructors) for instantiable classes.
      6. Retrieves all JVM and builtin functions for accessible and instantiable classes.

      All operations are executed asynchronously using a fixed thread pool (2 threads), and results are collected into a ClassScanningResult instance. In case of interruption or execution errors, a NaftahBugError is thrown.

    • MINIMAL_LOADER_TASK

      protected static final Supplier<ClassScanningResult> MINIMAL_LOADER_TASK
      A minimal supplier task that performs an asynchronous scan of classes and computes class qualifiers and their Arabic transliterations.

      Unlike LOADER_TASK, this task does not load Class objects, filter them, or retrieve constructors and functions. It is suitable for lightweight operations where only class name metadata is needed.

      All operations are executed asynchronously using a single-thread executor.

    • CURRENT_CONTEXT

      protected static final ThreadLocal<DefaultContext> CURRENT_CONTEXT
      Holds the current thread's DefaultContext in a thread-local variable.
    • CURRENT_TASK_SCOPE

      protected static ThreadLocal<List<Task<?>>> CURRENT_TASK_SCOPE
      Thread-local list holding all tasks spawned in the current scope for this thread.
    • CLASS_NAMES

      protected static volatile Set<String> CLASS_NAMES
    • CLASS_QUALIFIERS

      protected static volatile Set<String> CLASS_QUALIFIERS
    • ARABIC_CLASS_QUALIFIERS

      protected static volatile Map<String,String> ARABIC_CLASS_QUALIFIERS
    • CLASSES

      protected static volatile Map<String,Class<?>> CLASSES
    • ACCESSIBLE_CLASSES

      protected static volatile Map<String,Class<?>> ACCESSIBLE_CLASSES
    • INSTANTIABLE_CLASSES

      protected static volatile Map<String,Class<?>> INSTANTIABLE_CLASSES
    • JVM_FUNCTIONS

      protected static volatile Map<String,List<JvmFunction>> JVM_FUNCTIONS
    • CURRENT_LOOKUP_JVM_FUNCTIONS

      protected static volatile ThreadLocal<List<JvmFunction>> CURRENT_LOOKUP_JVM_FUNCTIONS
    • JVM_CLASS_INITIALIZERS

      protected static volatile Map<String,List<JvmClassInitializer>> JVM_CLASS_INITIALIZERS
    • CURRENT_LOOKUP_JVM_CLASS_INITIALIZERS

      protected static volatile ThreadLocal<List<JvmClassInitializer>> CURRENT_LOOKUP_JVM_CLASS_INITIALIZERS
    • BUILTIN_FUNCTIONS

      protected static volatile Map<String,List<BuiltinFunction>> BUILTIN_FUNCTIONS
    • IMPORTS

      protected static volatile Map<String,String> IMPORTS
    • SHOULD_BOOT_STRAP

      protected static volatile boolean SHOULD_BOOT_STRAP
    • FORCE_BOOT_STRAP

      protected static volatile boolean FORCE_BOOT_STRAP
    • ASYNC_BOOT_STRAP

      protected static volatile boolean ASYNC_BOOT_STRAP
    • BOOT_STRAP_FAILED

      protected static volatile boolean BOOT_STRAP_FAILED
    • BOOT_STRAPPED

      protected static volatile boolean BOOT_STRAPPED
    • LOADER_CONSUMER

      protected static final BiConsumer<? super ClassScanningResult,? super Throwable> LOADER_CONSUMER
      A consumer to handle the result or error from the full class scanning and loading task.

      If an error occurs (non-null throwable), it triggers a default bootstrap and marks BOOT_STRAP_FAILED as true. Otherwise, it sets the scanning context from the ClassScanningResult and optionally caches the result if CACHE_SCANNING_RESULTS_PROPERTY is enabled.

    • MINIMAL_LOADER_CONSUMER

      protected static final BiConsumer<? super ClassScanningResult,? super Throwable> MINIMAL_LOADER_CONSUMER
      A consumer to handle the result or error from the minimal class scanning task.

      If an error occurs (non-null throwable), it simply marks BOOT_STRAP_FAILED as true. Otherwise, it sets the scanning context from the ClassScanningResult.

      Unlike LOADER_CONSUMER, this consumer does not perform caching or default bootstrapping.

    • owner

      protected final Thread owner
    • pendingTasks

      protected final AtomicInteger pendingTasks
    • parent

      protected final DefaultContext parent
    • depth

      protected final int depth
    • variables

      protected final InheritableThreadLocal<Map<String,DeclaredVariable>> variables
    • functions

      protected final InheritableThreadLocal<Map<String,DeclaredFunction<?>>> functions
    • implementations

      protected final InheritableThreadLocal<Map<String,DeclaredImplementation>> implementations
    • pendingRemoval

      protected volatile boolean pendingRemoval
    • functionCallId

      protected ThreadLocal<String> functionCallId
    • implementationName

      protected InheritableThreadLocal<String> implementationName
    • parsingFunctionCallId

      protected ThreadLocal<Boolean> parsingFunctionCallId
    • parsingAssignment

      protected ThreadLocal<Boolean> parsingAssignment
    • creatingObject

      protected ThreadLocal<Boolean> creatingObject
    • awaitingTask

      protected ThreadLocal<Boolean> awaitingTask
    • declarationOfAssignment

      protected ThreadLocal<Pair<DeclaredVariable,Boolean>> declarationOfAssignment
    • loopLabel

      protected ThreadLocal<String> loopLabel
    • loopVariables

      protected InheritableThreadLocal<Map<String,Object>> loopVariables
    • parseTreeExecution

      protected InheritableThreadLocal<NaftahParseTreeProperty<Boolean>> parseTreeExecution
    • blockImports

      protected InheritableThreadLocal<Map<String,String>> blockImports
    • parameters

    • arguments

      protected InheritableThreadLocal<Map<String,Object>> arguments
  • Constructor Details

    • DefaultContext

      protected DefaultContext()
      Constructs a default context with no parent, block imports, parameters, or arguments.
    • DefaultContext

      protected DefaultContext(Map<String,DeclaredParameter> parameters, Map<String,Object> arguments)
      Constructs a context with specified parameters and arguments, but no parent.
      Parameters:
      parameters - function parameters map
      arguments - function arguments map
    • DefaultContext

      protected DefaultContext(DefaultContext parent, Map<String,String> blockImports, Map<String,DeclaredParameter> parameters, Map<String,Object> arguments)
      Constructs a new DefaultContext with an optional parent context and optional initial state.

      This constructor initializes a context with references to its parent, lexical depth, and any provided block imports, parameters, or arguments. Supplied maps are used as the initial thread-local state for the context.

      Context creation is restricted: if the environment is not a REPL (as indicated by INSIDE_REPL_PROPERTY), a root context may only be created when no other contexts already exist. Violating this invariant results in a NaftahBugError.

      When a parent context is provided, selected thread-local metadata (such as the current function call identifier and implementation name) is inherited from the parent if present.

      Parameters:
      parent - The parent context, or null if this is a root context.
      blockImports - Initial block-level imports for this context, or null if none.
      parameters - Initial function parameters for this context, or null if none.
      arguments - Initial function arguments for this context, or null if none.
      Throws:
      NaftahBugError - If this constructor is invoked in an invalid context-creation scenario (for example, creating a root context outside the REPL when contexts already exist).
  • Method Details

    • generateLoopId

      public static String generateLoopId(int depth)
      Generates a unique loop identifier string based on the loop's depth and a random UUID.

      This is used to create unique labels for unnamed loops, helping to distinguish nested or recursive loops during parsing or execution.

      Parameters:
      depth - the depth level of the current loop
      Returns:
      a unique loop ID in the format <depth>-loop-<uuid>
    • generateParameterOrArgumentName

      public static String generateParameterOrArgumentName(String functionName, String name)
      Generates a unique name for a function parameter or argument by combining the function name with the parameter or argument name.

      Useful for creating internally consistent identifiers across contexts such as code generation, interpretation, or debugging.

      Parameters:
      functionName - the name of the function
      name - the name of the parameter or argument
      Returns:
      a unique identifier in the format <functionName>-<name>
    • getVariable

      public static VariableLookupResult<Object> getVariable(String varName, DefaultContext context)
      Resolves a variable's value from the given context using the variable name.

      The lookup order is:

      1. Loop variables
      2. Function arguments
      3. Function parameters
      4. Declared variables

      If the variable is not found in any of these, a notFound result is returned.

      Parameters:
      varName - the name of the variable to look up
      context - the current execution context in which to resolve the variable
      Returns:
      a VariableLookupResult containing the variable name and its resolved value, or a not-found result if the variable does not exist in the context
    • generateCallId

      public static String generateCallId(int depth, String functionName)
      Generates a unique function call identifier string based on the call's depth, the function name, and a random UUID.

      This is typically used to track or label function calls uniquely during parsing or execution, especially in recursive or nested calls.

      Parameters:
      depth - the current call depth
      functionName - the name of the function being called
      Returns:
      a unique call ID in the format <depth>-<functionName>-<uuid>
    • registerContext

      public static DefaultContext registerContext()
      Registers a new default context with no parent, parameters, or arguments.
      Returns:
      a new DefaultContext instance
    • registerContext

      public static DefaultContext registerContext(Map<String,DeclaredParameter> parameters, Map<String,Object> arguments)
      Registers a new default context with the specified parameters and arguments.
      Parameters:
      parameters - the function parameters map
      arguments - the function arguments map
      Returns:
      a new DefaultContext instance
    • registerContext

      public static DefaultContext registerContext(DefaultContext parent)
      Registers a new DefaultContext with the specified parent context.

      This method creates a new context instance that inherits settings, variables, and configurations from the given parent context.

      Parameters:
      parent - the parent DefaultContext to inherit from; may be null
      Returns:
      a newly created DefaultContext instance
    • registerContext

      public static DefaultContext registerContext(DefaultContext parent, Map<String,String> blockImports)
      Registers a new DefaultContext with the specified parent context and a custom set of block imports.

      This method allows specifying a map of block imports that will be associated with the new context in addition to inheriting properties from the parent.

      Parameters:
      parent - the parent DefaultContext to inherit from; may be null
      blockImports - a map of block import definitions for the new context; may be null
      Returns:
      a newly created DefaultContext instance
    • registerContext

      public static DefaultContext registerContext(DefaultContext parent, Map<String,DeclaredParameter> parameters, Map<String,Object> arguments)
      Creates and registers a new DefaultContext instance with the specified parent context, parameters, and arguments.

      This overload can be used when no explicit block imports are required. The created context inherits any imports from its parent.

      Parameters:
      parent - the parent DefaultContext to associate with this new context; may be null if this is the root context
      parameters - a map of declared function parameters, where keys are parameter names and values are DeclaredParameter definitions
      arguments - a map of argument values corresponding to the provided parameters
      Returns:
      a new DefaultContext instance linked to the given parent
    • registerContext

      public static DefaultContext registerContext(DefaultContext parent, Map<String,String> blockImports, Map<String,DeclaredParameter> parameters, Map<String,Object> arguments)
      Creates and registers a new DefaultContext instance with the specified parent context, block imports, parameters, and arguments.

      This overload allows specifying custom imports that will be available within the new context, such as additional modules or namespaces.

      Parameters:
      parent - the parent DefaultContext to associate with this new context; may be null if this is the root context
      blockImports - a map of imported blocks or namespaces, where keys represent import names and values represent their corresponding qualified paths
      parameters - a map of declared function parameters, where keys are parameter names and values are DeclaredParameter definitions
      arguments - a map of argument values corresponding to the provided parameters
      Returns:
      a new DefaultContext instance linked to the given parent and imports
    • getCurrentContext

      public static DefaultContext getCurrentContext()
      Returns the current thread’s active context.

      This retrieves the value stored in the thread-local CURRENT_CONTEXT. Each thread always sees its own context, independent of other threads.

      Returns:
      the DefaultContext bound to the current thread, or null if none is set
    • setCurrentContext

      public static void setCurrentContext(DefaultContext currentContext)
      Sets the active context for the current thread.

      This assigns a DefaultContext to the calling thread’s thread-local storage. Each thread maintains a separate context pointer.

      Parameters:
      currentContext - the context to bind to this thread
    • getContextsByDepth

      public static List<DefaultContext> getContextsByDepth(int depth)
      Retrieves all contexts registered at a specific depth.

      Multiple contexts may exist at the same depth when asynchronous tasks or concurrent scopes are active. The returned list is thread-safe but is not a defensive copy; modifications affect global state.

      Parameters:
      depth - the depth level whose contexts should be returned
      Returns:
      a list of DefaultContext objects at that depth; an empty list if none exist
    • deregisterContext

      public static void deregisterContext()
      Deregisters and removes the context associated with the specified depth. If the removed context and its parent both have parse tree execution properties, copies the parse tree execution state from the removed context to its parent.
    • deregisterContext

      public static void deregisterContext(DefaultContext context)
      Attempts to detach the given DefaultContext from its parent context, performing state propagation when necessary.

      If the context can be safely deregistered (i.e., no pending tasks and no unresolved execution state), tryDeregisterContext(DefaultContext) is invoked. When deregistration succeeds, any active parse-tree execution metadata from the child context is copied into the parent to preserve execution continuity.

      If deregistration fails—typically due to pending asynchronous tasks or execution markers that must remain valid—the method falls back to copyDeclarationsToParent(DefaultContext) to propagate variable and function declarations from the child context into the parent. This prevents redefinition conflicts or loss of symbol information while the child context remains active.

      Calling this method has no effect if the given context is null or has no parent.

      Parameters:
      context - the context to deregister; may be null
    • copyDeclarationsToParent

      public static void copyDeclarationsToParent(DefaultContext context)
      Copies variable, function, and implementation declarations from a child context into its parent context.

      This method is used as a fallback when a child context cannot be safely deregistered (for example, due to pending tasks or deferred cleanup). By propagating declarations upward, the parent context gains visibility into symbols introduced by the child, avoiding loss of symbol information if the child remains active longer than expected.

      In a REPL environment (indicated by INSIDE_REPL_PROPERTY), all declarations declared at depth 1 are copied directly to the parent.

      Outside of a REPL environment, only declarations whose declared depth is less than or equal to context.depth - 1 are copied. This prevents propagation of symbols that are local to deeper lexical scopes.

      Parameters:
      context - The child DefaultContext whose declarations should be copied into its parent context.
      Throws:
      NullPointerException - If context or its parent context is null.
    • markForRemoval

      public static void markForRemoval(DefaultContext context)
      Marks the given context as eligible for removal once it becomes safe to do so.

      This flag does not remove the context immediately. A context may be marked for removal when:

      • its owning scope has ended, or
      • a thread attempts to deregister the context but it still has pending asynchronous tasks, or
      • any of its descendant contexts still have active work.

      Contexts marked for removal will be deleted automatically once:

      • the context itself has zero pending tasks, and
      • all of its descendant contexts have zero pending tasks.

      This prevents premature cleanup while ensuring that no contexts leak after they become fully inactive.

      Parameters:
      context - the DefaultContext to mark for future removal; must not be null
    • tryDeregisterContext

      public static boolean tryDeregisterContext(DefaultContext context)
      Attempts to remove a context from the global context registry.

      The removal is conditional. This method will only deregister the given context when all the following conditions are satisfied:

      • The context has no pending asynchronous tasks.
      • No descendant context has pending tasks.
      • The context has been properly registered in the CONTEXTS structure.

      If removal is not yet possible, the context is marked for later cleanup via markForRemoval(DefaultContext).

      If the context is the current context of the calling thread, the thread-local pointer CURRENT_CONTEXT will be updated to the parent context. Otherwise, the caller's thread-local context remains unchanged.

      The method is thread-safe and may be called concurrently from multiple threads. Removal will occur exactly once.

      Parameters:
      context - the context to attempt to deregister
      Returns:
      true if the context was removed, false if removal was deferred
    • pushCall

      public static void pushCall(DeclaredFunction<?> function, Map<String,Object> arguments)
      Pushes a function call frame onto the call stack.
      Parameters:
      function - the DeclaredFunction being called
      arguments - the map of argument names to values
    • popCall

      public static Triple<DeclaredFunction<?>,Map<String,Object>,Object> popCall()
      Pops the most recent function call frame from the call stack.
      Returns:
      the popped function call frame as a pair containing function, arguments, and return value
      Throws:
      NaftahBugError - if the call stack is empty
    • peekCall

      public static Triple<DeclaredFunction<?>,Map<String,Object>,Object> peekCall()
      Returns (without removing) the most recent function call frame from the call stack.
      Returns:
      the top function call frame, or null if the stack is empty
    • currentLoopLabel

      public static String currentLoopLabel(String label, int depth)
      Retrieves the current loop label based on the given label context or generates a unique one.
      Parameters:
      label - the parsed label, may be null
      depth - the depth to use for label generation if none provided
      Returns:
      the current loop label as a string
    • pushLoop

      public static <T extends org.antlr.v4.runtime.ParserRuleContext> void pushLoop(String label, T loopCtx)
      Pushes a loop label and its associated parser context onto the loop stack.
      Type Parameters:
      T - the type of the parser context
      Parameters:
      label - the loop label
      loopCtx - the parser context associated with the loop
    • startScope

      public static void startScope()
      Initializes a new task scope for the current thread.

      All tasks spawned after this call will be tracked in this scope and can later be awaited or cleaned up. Must be called before spawning tasks if no scope is active.

    • getCurrentLookupJvmFunctions

      public static List<JvmFunction> getCurrentLookupJvmFunctions()
      Retrieves and clears the thread-local list of JVM functions for the current lookup context.

      This method returns the current thread's JvmFunction list stored in CURRENT_LOOKUP_JVM_FUNCTIONS and removes it from the thread-local storage, preventing accidental reuse across lookups.

      Returns:
      the list of JvmFunction for the current lookup, or null if none is set
    • setCurrentLookupJvmFunctions

      public static void setCurrentLookupJvmFunctions(List<JvmFunction> lookupJvmFunctions)
      Sets the thread-local list of JVM functions for the current lookup context.

      If the thread-local variable CURRENT_LOOKUP_JVM_FUNCTIONS is not initialized, it is created. This allows subsequent calls to getCurrentLookupJvmFunctions() to retrieve the list in the same thread.

      Parameters:
      lookupJvmFunctions - the list of JvmFunction to store for the current thread
    • getCurrentLookupJvmClassInitializers

      public static List<JvmClassInitializer> getCurrentLookupJvmClassInitializers()
      Retrieves and clears the thread-local list of JVM class initializers for the current lookup context.

      This method returns the current thread's JvmClassInitializer list stored in CURRENT_LOOKUP_JVM_CLASS_INITIALIZERS and removes it from the thread-local storage to prevent accidental reuse across lookups.

      Returns:
      the list of JvmClassInitializer for the current lookup, or null if none is set
    • setCurrentLookupJvmClassInitializers

      public static void setCurrentLookupJvmClassInitializers(List<JvmClassInitializer> lookupJvmClassInitializers)
      Sets the thread-local list of JVM class initializers for the current lookup context.

      If the thread-local variable CURRENT_LOOKUP_JVM_CLASS_INITIALIZERS is not initialized, it is created. This allows subsequent calls to getCurrentLookupJvmClassInitializers() to retrieve the list in the same thread.

      Parameters:
      lookupJvmClassInitializers - the list of JvmClassInitializer to store for the current thread
    • endScope

      public static void endScope()
      Finalizes the current task scope for the thread.

      Removes all tasks tracked in the current scope and clears the thread-local reference. After this call, no tasks are associated with the scope until startScope() is called again.

    • getLoopLabels

      public static List<String> getLoopLabels()
      Returns a list of all loop labels currently in the loop stack.
      Returns:
      a list of loop labels
    • loopContainsLabel

      public static boolean loopContainsLabel(String label)
      Checks if the loop stack contains a loop with the given label.
      Parameters:
      label - the label to check
      Returns:
      true if the loop stack contains the label, false otherwise
    • popLoop

      public static Pair<String,? extends org.antlr.v4.runtime.ParserRuleContext> popLoop()
      Pops the most recent loop label and context from the loop stack.
      Returns:
      the popped loop label and parser context pair
      Throws:
      NaftahBugError - if the loop stack is empty
    • setContextFromClassScanningResult

      protected static void setContextFromClassScanningResult(ClassScanningResult result)
      Updates the context static fields from the given ClassScanningResult. Marks bootstrapping as completed.
      Parameters:
      result - the class scanning result containing loaded class information
    • defaultBootstrap

      public static void defaultBootstrap()
      Loads the default builtin functions into the context.
    • processBuiltin

      private static void processBuiltin(String builtinProp, Consumer<String> builtinConsumer)
      Processes a comma-separated list of built-in property names by applying the specified Consumer to each non-empty, trimmed element.

      This method splits the given string by commas (,), trims whitespace from each part, filters out any empty entries, and then passes each resulting value to the provided consumer.

      Example:

      
       processBuiltin("foo, bar, baz", System.out::println);
       // Output:
       // foo
       // bar
       // baz
       
      Parameters:
      builtinProp - a comma-separated string of property names; may contain whitespace
      builtinConsumer - a Consumer that will process each non-empty, trimmed property name
      Throws:
      NullPointerException - if builtinProp or builtinConsumer is null
    • callLoader

      protected static void callLoader(boolean async, Supplier<ClassScanningResult> loaderTask, BiConsumer<? super ClassScanningResult,? super Throwable> loaderConsumer)
      Calls the loader task to scan and load classes, optionally asynchronously.
      Parameters:
      async - true to run asynchronously, false to run synchronously
    • serializeClassScanningResult

      protected static void serializeClassScanningResult(ClassScanningResult result, Path cachePath)
      Serializes the class scanning result to a cache file.
      Parameters:
      result - the class scanning result to serialize
      cachePath - the file path where the Base64 string should be saved
      Throws:
      NaftahBugError - if serialization fails
    • deserializeClassScanningResult

      protected static void deserializeClassScanningResult(Path cachePath, Runnable loaderRunnable)
      Attempts to deserialize a previously cached class scanning result. If deserialization fails, triggers class loading asynchronously if configured.
      Parameters:
      cachePath - the file path where the Base64 string should be saved
      loaderRunnable - the loader call in case of deserialization failure
    • getCompletions

      public static List<String> getCompletions()
      Returns a list of all completion candidates combining builtin functions, JVM functions, and instantiable classes.
      Returns:
      list of completion names
    • bootstrap

      public static void bootstrap(boolean async)
      Performs the bootstrap process to load classes and functions, either synchronously or asynchronously, based on configuration flags.
      Parameters:
      async - true for asynchronous bootstrap, false for synchronous
    • doGetJavaType

      protected static Class<?> doGetJavaType(String qualifiedName)
      Gets the Java Class corresponding to the given qualified name from cached maps.
      Parameters:
      qualifiedName - the fully qualified class name
      Returns:
      the Class object if found, or Object class as fallback
    • getJavaType

      public static Class<?> getJavaType(String qualifiedName)
      Gets the Java Class corresponding to the given qualified name. Blocks if the context is bootstrapping.
      Parameters:
      qualifiedName - the fully qualified class name
      Returns:
      the Class object if found, or Object class as fallback
    • newNaftahBugVariableNotFoundError

      public static NaftahBugError newNaftahBugVariableNotFoundError(String name)
      Creates a new NaftahBugError indicating that a variable was not found in the current context.

      The error message is in Arabic and includes the variable name in the form:
      "المتغير '%s' غير موجود في السياق الحالي."

      This overload does not include line or column information and uses -1 for both.

      Parameters:
      name - the name of the variable that was not found
      Returns:
      a new NaftahBugError with the formatted message
    • newNaftahBugVariableNotFoundError

      public static NaftahBugError newNaftahBugVariableNotFoundError(String name, int line, int column)
      Creates a new NaftahBugError indicating that a variable was not found at a specific source location.

      The error message is in Arabic and includes the variable name in the form:
      "المتغير '%s' غير موجود في السياق الحالي."

      Parameters:
      name - the name of the variable that was not found
      line - the source line number where the error occurred, or -1 if unknown
      column - the source column number where the error occurred, or -1 if unknown
      Returns:
      a new NaftahBugError with the formatted message and position data
    • newNaftahBugForeachTargetDuplicatesError

      public static NaftahBugError newNaftahBugForeachTargetDuplicatesError(String name, int line, int column)
      Creates a NaftahBugError for a duplicate (foreach) target with specified line and column.
      Parameters:
      name - The name of the duplicated element.
      line - The line number where the duplicate occurs.
      column - The column number where the duplicate occurs.
      Returns:
      NaftahBugError with a detailed message about the duplicate.
    • newNaftahBugForeachTargetDuplicatesError

      public static NaftahBugError newNaftahBugForeachTargetDuplicatesError(String name, NaftahParser.ForeachTargetContext foreachTargetContext)
      Creates a NaftahBugError when there is a duplicate in a (foreach) loop target.
      Parameters:
      name - The name of the duplicated element.
      foreachTargetContext - The context of the (foreach) target from the Naftah parser.
      Returns:
      NaftahBugError containing line and column information for the duplicate element.
    • newNaftahBugExistentFunctionArgumentError

      public static NaftahBugError newNaftahBugExistentFunctionArgumentError(String name)
      Creates a NaftahBugError when a function argument already exists in the current context.
      Parameters:
      name - The name of the duplicated argument.
      Returns:
      NaftahBugError indicating the argument already exists.
    • newNaftahBugExistentFunctionParameterError

      public static NaftahBugError newNaftahBugExistentFunctionParameterError(String name)
      Creates a NaftahBugError when a function parameter already exists in the current context.
      Parameters:
      name - The name of the duplicated parameter.
      Returns:
      NaftahBugError indicating the parameter already exists.
    • newNaftahBugExistentFunctionError

      public static NaftahBugError newNaftahBugExistentFunctionError(String name)
      Creates a NaftahBugError when a function already exists in the current context.
      Parameters:
      name - The name of the duplicated function.
      Returns:
      NaftahBugError indicating the function already exists.
    • newNaftahBugExistentImplementationError

      public static NaftahBugError newNaftahBugExistentImplementationError(String name)
      Creates a NaftahBugError indicating that an implementation with the given name already exists in the current context.
      Parameters:
      name - the name of the duplicated implementation
      Returns:
      a NaftahBugError describing the duplication
    • newNaftahBugExistentVariableError

      public static NaftahBugError newNaftahBugExistentVariableError(String name)
      Creates a NaftahBugError when a variable already exists in the current context.
      Parameters:
      name - The name of the duplicated variable.
      Returns:
      NaftahBugError indicating the variable already exists.
    • putAllInBuiltinFunctions

      public static void putAllInBuiltinFunctions(Map<String,List<BuiltinFunction>> builtinFunctions)
      Adds all entries from the given map into the global built-in functions map.

      This method is synchronized to ensure thread-safe updates.

      Parameters:
      builtinFunctions - a map of function names to lists of BuiltinFunction to add.
    • getBuiltinFunctions

      public static Map<String,List<BuiltinFunction>> getBuiltinFunctions()
      Returns the global map of built-in functions.
      Returns:
      an unmodifiable view or reference to the map of built-in functions.
    • setBuiltinFunctions

      public static void setBuiltinFunctions(Map<String,List<BuiltinFunction>> builtinFunctions)
      Replaces the global built-in functions map with the provided one.

      This method is synchronized to ensure thread-safe updates.

      Parameters:
      builtinFunctions - the new map of built-in functions to set.
    • getJvmFunctions

      public static Map<String,List<JvmFunction>> getJvmFunctions()
      Returns the global map of JVM functions.
      Returns:
      a map of function names to lists of JvmFunction.
    • getJvmClassInitializers

      public static Map<String,List<JvmClassInitializer>> getJvmClassInitializers()
    • getClasses

      public static Map<String,Class<?>> getClasses()
      Returns the global map of all registered classes.
      Returns:
      a map of class names to Class objects.
    • getAccessibleClasses

      public static Map<String,Class<?>> getAccessibleClasses()
      Returns the global map of classes that are marked as accessible.
      Returns:
      a map of class names to Class objects which are accessible.
    • getInstantiableClasses

      public static Map<String,Class<?>> getInstantiableClasses()
      Returns the global map of classes that can be instantiated.
      Returns:
      a map of class names to Class objects that can be instantiated.
    • defineImport

      public static void defineImport(DefaultContext currentContext, org.antlr.v4.runtime.ParserRuleContext ctx, String alias, String importElement)
      Defines an import within the given DefaultContext, handling both block-level and global imports.

      If the provided ctx (parse context) is part of a block (i.e., has a parent of type NaftahParser.BlockContext), the import is registered as a block-level import within the current context. Otherwise, the import is added to the global IMPORTS map.

      Parameters:
      currentContext - the active DefaultContext where the import should be defined
      ctx - the current ParserRuleContext representing the parse location
      alias - the alias to associate with the imported element (e.g., a shorthand name)
      importElement - the fully qualified name or path of the element being imported
    • cleanClassThreadLocals

      public static void cleanClassThreadLocals()
      Clears all static ThreadLocal fields used by this class, removing global per-thread interpreter state such as the execution call stack, loop stack, and the currently active evaluation context.

      This method should be called when global per-thread state is no longer needed—for example, when shutting down an interpreter instance, resetting internal state between isolated evaluations, or cleaning up after thread reuse in pooled environments.

      Only thread-local data for the current thread is removed. This method does not modify shared global structures or affect the state of other threads. If the class maintains optional ThreadLocal fields, they are removed only when non-null to ensure safe cleanup regardless of initialization order.

    • lookupJvmClassInitializer

      public static boolean lookupJvmClassInitializer(String arabicQualifiedName)
      Looks up JVM class initializers by the Arabic-transliterated qualified class name.

      If the class is found, it loads the corresponding Class object, retrieves its constructors as JvmClassInitializer instances, stores them in the thread-local CURRENT_LOOKUP_JVM_CLASS_INITIALIZERS, and returns true. Otherwise, it returns false.

      Parameters:
      arabicQualifiedName - the Arabic-transliterated fully qualified class name
      Returns:
      true if the class and its initializers were successfully found; false otherwise
    • lookupJvmFunctions

      public static boolean lookupJvmFunctions(String arabicQualifiedCall)
      Looks up JVM functions by the Arabic-transliterated qualified call.

      The qualified call should contain the class and method name separated by ClassUtils.QUALIFIED_CALL_SEPARATOR. If the class is found and contains the corresponding method, the matching JvmFunction instances are stored in the thread-local CURRENT_LOOKUP_JVM_FUNCTIONS and true is returned.

      Parameters:
      arabicQualifiedCall - the Arabic-transliterated fully qualified call (class + method)
      Returns:
      true if the function(s) were successfully found; false otherwise
    • containsJvmClassInitializer

      public boolean containsJvmClassInitializer(String qualifiedName)
      Checks whether a JVM class initializer exists for the specified qualified name.

      If SHOULD_BOOT_STRAP is enabled, this checks both the bootstrap-loaded initializers and performs a lookup if necessary. Otherwise, it checks the current thread-local lookup context.

      Parameters:
      qualifiedName - the Arabic-transliterated qualified class name
      Returns:
      true if a class initializer exists; false otherwise
    • getJvmClassInitializer

      public Pair<Integer,Object> getJvmClassInitializer(String arabicQualifiedName, boolean safe)
      Retrieves the JVM class initializer(s) for the specified Arabic-transliterated qualified name.

      Depending on the bootstrap and lookup state, this method retrieves initializers from the global JVM_CLASS_INITIALIZERS map or from the current thread-local lookup context. If only one initializer exists, it is returned directly; otherwise, the list of initializers is returned.

      Parameters:
      arabicQualifiedName - the Arabic-transliterated qualified class name
      safe - if false, throws NaftahBugError if no initializer is found; if * true, returns null instead
      Returns:
      a Pair containing the current depth and the initializer(s), or null if not found and * safe is true
      Throws:
      NaftahBugError - if the initializer does not exist and safe is false
    • registerTask

      public void registerTask(Task<?> task)
      Registers a newly created asynchronous task in both the current task scope and the associated execution context.

      This method must be called whenever a task is spawned that logically belongs to this context. It performs two things:

      1. Increments the pendingTasks counter to prevent premature deregistration of the context while the task is running.
      2. Adds the task to the current thread's task scope (CURRENT_TASK_SCOPE) so it can be tracked and awaited when the scope ends.

      If no scope is currently active for this thread, the task is only registered in the context.

      Parameters:
      task - the asynchronous task to register; must not be null
    • completeTask

      public void completeTask()
      Marks a previously registered asynchronous task as completed.

      This method performs two actions:

      1. Decrements the pendingTasks counter, indicating that one of the tasks associated with this context has finished execution.
      2. If the context was previously marked for removal (pendingRemoval), this triggers a deregistration attempt via deregisterContext(DefaultContext).

      The caller must ensure that completeTask() is invoked exactly once for every successful registerTask(Task), typically after the task finishes and its result has been consumed or awaited.

      Even when a task is tracked in a scope (via CURRENT_TASK_SCOPE), this method should still be called to update the context's pending task count and enable proper lifecycle management.

      See Also:
    • cleanThreadLocals

      public void cleanThreadLocals()
      Clears all ThreadLocal values associated with this context.

      This removes per-thread state such as variables, functions, implementations, temporary execution markers, and parsing-related metadata.

      This method should be called when a task executing under this context completes or when the context is being cleaned up. Proper invocation prevents memory leaks and ensures no stale state is retained across threads, which is especially important in asynchronous or multi-threaded environments where contexts may be reused or migrated.

      Only non-null ThreadLocal fields are removed, ensuring safe cleanup even if the context was only partially initialized.

      Calling this method affects only per-thread execution state. Shared state, global registries, or parent/child context relationships remain unchanged.

    • containsVariable

      public boolean containsVariable(String name, int depth)
      Determines whether a variable with the given name exists in this context or in any of its ancestor contexts.

      This method performs a hierarchical lookup: it first checks the current context's variable map, and if not found, recursively checks parent contexts. This allows child contexts to inherit variables from their enclosing execution scopes.

      Parameters:
      depth - the depth of look up
      name - the name of the variable to look up
      Returns:
      true if the variable exists in this context or any parent context; false otherwise
    • containsLocalVariable

      public boolean containsLocalVariable(Map<String,DeclaredVariable> variableMap, String variableName)
      Checks whether a variable with the given name exists in the provided local variable map or in any sibling contexts.

      This method performs a “horizontal” lookup: it does not traverse upward to parent contexts but instead inspects the current context's variable map (the provided variableMap) and then the variable maps of sibling contexts returned by getSiblings(boolean).

      This is useful in block-level or parallel-scope visibility rules where sibling contexts may share declarations that should not be inherited from parent scopes but must still be detected to prevent name conflicts.

      Parameters:
      variableMap - the variable map belonging to the current context
      variableName - the variable name to check
      Returns:
      true if the variable exists locally or in any sibling context; false otherwise
    • getVariable

      public Pair<Integer,DeclaredVariable> getVariable(String name, boolean safe)
      Retrieves a variable by name from the current context or parent contexts.
      Parameters:
      name - the variable name
      safe - if true, returns null instead of throwing an error if not found
      Returns:
      a pair of the context depth and the DeclaredVariable instance
      Throws:
      NaftahBugError - if variable not found and safe is false
    • setVariable

      public DeclaredVariable setVariable(String name, DeclaredVariable value)
      Sets the value of a variable in the current context or, if it exists, in a parent context. If the variable does not exist, it defines it in the current context.
      Parameters:
      name - the variable name
      value - the new DeclaredVariable value
    • defineVariable

      public void defineVariable(String name, DeclaredVariable value)
      Defines a new variable in the current context.
      Parameters:
      name - the variable name
      value - the DeclaredVariable to define
      Throws:
      NaftahBugError - if the variable already exists in the current context
    • defineVariables

      public void defineVariables(Map<String,DeclaredVariable> variables)
      Defines multiple variables in the current context.
      Parameters:
      variables - map of variable names to DeclaredVariable objects
      Throws:
      NaftahBugError - if any variable already exists in the current context
    • removeVariable

      public void removeVariable(String name, boolean lenient)
      Removes a variable from the current context.

      If the variable does not exist and lenient is false, an error is thrown. If lenient is true, the method will silently do nothing.

      Parameters:
      name - the name of the variable to remove
      lenient - whether to suppress errors when the variable is not found
      Throws:
      NaftahBugError - if the variable does not exist and lenient is false
    • containsFunction

      public boolean containsFunction(String name, int depth)
      Checks if the function with the given name exists in the current context, built-in functions, JVM functions (if bootstrapped), or any parent context.
      Parameters:
      depth - the depth of look up
      name - the function name
      Returns:
      true if the function exists, false otherwise
    • containsDeclaredFunction

      public boolean containsDeclaredFunction(String name, int depth)
      Checks whether a function with the specified name exists in this context or any parent context up to the given depth.
      Parameters:
      name - the name of the function to check
      depth - the maximum depth to search; use -1 to ignore depth limits
      Returns:
      true if the function exists, false otherwise
    • containsDeclaredImplementation

      public boolean containsDeclaredImplementation(String qualifiedCall, int depth)
      Checks whether a declared implementation with the specified qualified call exists in this context or any parent context up to the given depth.
      Parameters:
      qualifiedCall - the qualified implementation call (format: "implId.functionName")
      depth - the maximum depth to search; use -1 to ignore depth limits
      Returns:
      true if the implementation exists, false otherwise
    • containsDeclaredImplementation

      public boolean containsDeclaredImplementation(String qualifiedCall, boolean implementationOnly, int depth)
      Checks whether a declared implementation with the specified qualified call exists in this context or any parent context up to the given depth.
      Parameters:
      qualifiedCall - the qualified implementation call (format: "implId.functionName")
      implementationOnly - if true, only checks for the implementation existence, ignoring specific function names
      depth - the maximum depth to search; use -1 to ignore depth limits
      Returns:
      true if the implementation exists according to the search rules, false otherwise
    • getDeclaredImplementationFunction

      public DeclaredFunction<?> getDeclaredImplementationFunction(String qualifiedCall, boolean safe)
      Retrieves the DeclaredFunction corresponding to a qualified implementation call from this context or any parent context.
      Parameters:
      qualifiedCall - the qualified implementation call (format: "implId.functionName")
      safe - if true, returns null when the function is not found; if false, throws an exception
      Returns:
      the corresponding DeclaredFunction, or null if not found and safe is * true
      Throws:
      NaftahBugError - if the function is not found and safe is false
    • getFunction

      public Pair<Integer,Object> getFunction(String name, boolean safe)
      Retrieves a function by name from the current context, built-in functions, JVM functions, or parent contexts.
      Parameters:
      name - the function name
      safe - if true, returns null instead of throwing an error if not found
      Returns:
      a pair of the context depth and the function object(s)
      Throws:
      NaftahBugError - if function not found and safe is false
    • setFunction

      public void setFunction(String name, DeclaredFunction<?> value)
      Sets the value of a function in the current context or, if it exists, in a parent context. If the function does not exist, it defines it in the current context.
      Parameters:
      name - the function name
      value - the new DeclaredFunction value
    • defineFunction

      public void defineFunction(String name, DeclaredFunction<?> value)
      Defines a new function in the current context.

      The function is added to this context's local function registry. If a function with the same name already exists in the current context at the same depth, a NaftahBugError is thrown.

      Parameters:
      name - the name of the function to define
      value - the DeclaredFunction to associate with the name
      Throws:
      NaftahBugError - if a function with the same name already exists in the current context
    • setImplementation

      public void setImplementation(String name, DeclaredImplementation value)
      Sets or updates an implementation in the current context or in a parent context.

      If the implementation already exists in the current context, it is updated. Otherwise, if a function with the same name exists in a parent context, the implementation is updated there. If neither exists, the implementation is defined locally in this context.

      Parameters:
      name - the name of the implementation
      value - the DeclaredImplementation to set
    • defineImplementation

      public void defineImplementation(String name, DeclaredImplementation value)
      Defines a new implementation in the current context.

      If an implementation with the same name already exists in this context (or matching the search criteria in the depth hierarchy), a NaftahBugError is thrown. Otherwise, the implementation is added to the current context's registry.

      Parameters:
      name - the name of the implementation to define
      value - the DeclaredImplementation to associate with the name
      Throws:
      NaftahBugError - if the implementation already exists according to the context's depth rules
    • getFunctionParameterName

      public String getFunctionParameterName(String name)
      Generates the canonical name for a function parameter based on the current function call ID.
      Parameters:
      name - the original parameter name
      Returns:
      the canonical function parameter name
    • containsFunctionParameter

      public boolean containsFunctionParameter(String name, int depth)
      Checks if a function parameter with the given name exists in the current or parent contexts.
      Parameters:
      depth - the depth of look up
      name - the parameter name
      Returns:
      true if the function parameter exists, false otherwise
    • getFunctionParameter

      public Pair<Integer,DeclaredParameter> getFunctionParameter(String name, boolean safe)
      Retrieves a function parameter by name from the current or parent contexts.
      Parameters:
      name - the parameter name
      safe - if true, returns null instead of throwing an error if not found
      Returns:
      a pair of the context depth and the DeclaredParameter object
      Throws:
      NaftahBugError - if parameter not found and safe is false
    • setFunctionParameter

      public void setFunctionParameter(String name, DeclaredParameter value)
      Sets the value of a function parameter in the current or parent context. Defines the parameter locally if it does not exist.
      Parameters:
      name - the parameter name
      value - the new DeclaredParameter value
    • defineFunctionParameter

      public void defineFunctionParameter(String name, DeclaredParameter value, boolean lenient)
      Defines a new function parameter in the current context.
      Parameters:
      name - the parameter name
      value - the DeclaredParameter to define
      lenient - if true, silently ignores if parameter already exists
      Throws:
      NaftahBugError - if parameter already exists and lenient is false
    • defineFunctionParameters

      public void defineFunctionParameters(Map<String,DeclaredParameter> parameters, boolean lenient)
      Defines multiple function parameters in the current context.
      Parameters:
      parameters - map of parameter names to DeclaredParameter objects
      lenient - if true, silently ignores if any parameter already exists
      Throws:
      NaftahBugError - if any parameter already exists and lenient is false
    • getFunctionArgumentName

      public String getFunctionArgumentName(String name)
      Generates the canonical name for a function argument based on the current function call ID.
      Parameters:
      name - the original argument name
      Returns:
      the canonical function argument name
    • containsFunctionArgument

      public boolean containsFunctionArgument(String name, int depth)
      Checks if a function argument with the given name exists in the current or parent contexts.
      Parameters:
      depth - the depth of look up
      name - the argument name
      Returns:
      true if the function argument exists, false otherwise
    • getFunctionArgument

      public Pair<Integer,Object> getFunctionArgument(String name, boolean safe)
      Retrieves a function argument by name from the current or parent contexts.
      Parameters:
      name - the argument name
      safe - if true, returns null instead of throwing an error if not found
      Returns:
      a pair of the context depth and the DeclaredArgument object
      Throws:
      NaftahBugError - if argument not found and safe is false
    • setFunctionArgument

      public void setFunctionArgument(String name, Object value, int depth)
      Sets the value of a function argument in the current or parent context. Defines the argument locally if it does not exist.
      Parameters:
      depth - the depth of look up
      name - the argument name
      value - the new DeclaredArgument value
    • defineFunctionArgument

      public void defineFunctionArgument(String name, Object value, int depth)
      Defines a new function argument in the current context.
      Parameters:
      depth - the depth of look up
      name - the argument name
      value - the DeclaredArgument to define
      Throws:
      NaftahBugError - if argument already exists and lenient is false
    • defineFunctionArguments

      public void defineFunctionArguments(Map<String,Object> arguments, int depth)
      Defines multiple function arguments in the current context.
      Parameters:
      depth - the depth of look up
      arguments - map of argument names to DeclaredArgument objects
      Throws:
      NaftahBugError - if any argument already exists and lenient is false
    • prepareLoopVariable

      protected void prepareLoopVariable()
      Ensures that the thread-local map used to store loop-scoped variables is initialized.

      This method lazily creates an instance of SuppliedInheritableThreadLocal that provides a HashMap for storing loop variables. The first supplier creates the initial map for the current thread, while the second supplier provides a copy for child threads, ensuring that loop-scoped variables are inherited but remain isolated between threads.

      If the loop variable storage has already been initialized, this method performs no action.

    • getLoopVariableName

      public String getLoopVariableName(String name)
      Generates the canonical name for a loop variable based on the current loop ID.
      Parameters:
      name - the original loop variable name
      Returns:
      the canonical loop variable name
    • getLoopVariableNames

      public List<String> getLoopVariableNames(String name)
      Generates a list of canonical loop variable names by combining loop labels with the given variable name. If the loopVariables map is uninitialized, it initializes it first.
      Parameters:
      name - the base name of the loop variable
      Returns:
      a list of loop variable names prefixed by each loop label followed by a hyphen
    • containsLoopVariable

      public boolean containsLoopVariable(String name, int depth)
      Checks if a loop variable with the given name exists in the current or parent contexts.
      Parameters:
      depth - the depth of look up
      name - the loop variable name
      Returns:
      true if the loop variable exists, false otherwise
    • getLoopVariable

      public Pair<Integer,Object> getLoopVariable(String name, boolean safe)
      Retrieves a loop variable by name from the current or parent contexts.
      Parameters:
      name - the loop variable name
      safe - if true, returns null instead of throwing an error if not found
      Returns:
      a pair of the context depth and the DeclaredVariable object
      Throws:
      NaftahBugError - if loop variable not found and safe is false
    • setLoopVariable

      public Object setLoopVariable(String name, Object value)
      Sets the value of a loop variable in the current or parent context. Defines the loop variable locally if it does not exist.
      Parameters:
      name - the loop variable name
      value - the new DeclaredVariable value
    • defineLoopVariable

      public void defineLoopVariable(String name, Object value, boolean lenient)
      Defines a new loop variable in the current context.
      Parameters:
      name - the loop variable name
      value - the DeclaredVariable to define
      Throws:
      NaftahBugError - if the loop variable already exists in the current context
    • removeLoopVariable

      public void removeLoopVariable(String name, boolean lenient)
      Removes a loop variable with the specified name from the current context. Throws an error if the variable exists and lenient is false.
      Parameters:
      name - the name of the loop variable to remove
      lenient - if true, silently ignores if the variable exists; otherwise throws an error
      Throws:
      NaftahBugError - if the variable exists in the current context and lenient is false
    • markExecuted

      public void markExecuted(org.antlr.v4.runtime.tree.ParseTree node)
      Marks the given parse tree node as executed in the execution tracking map.
      Parameters:
      node - the parse tree node to mark as executed
    • isExecuted

      public boolean isExecuted(org.antlr.v4.runtime.tree.ParseTree node)
      Checks whether the specified parse tree node has been marked as executed.
      Parameters:
      node - the parse tree node to check
      Returns:
      true if the node has been executed, false otherwise
    • hasAnyExecutedChildOrSubChildOfType

      public <T extends org.antlr.v4.runtime.tree.Tree> boolean hasAnyExecutedChildOrSubChildOfType(org.antlr.v4.runtime.tree.ParseTree node, Class<T> type)
      Checks if any child or sub-child of the given parse tree node, within the contexts, has been executed and is of the specified tree type.
      Type Parameters:
      T - the type of the tree node to look for
      Parameters:
      node - the parse tree node to check children of
      type - the class type of the tree nodes to look for
      Returns:
      true if any child or sub-child of the specified type has been executed, false otherwise
    • prepareParseTreeExecution

      protected boolean prepareParseTreeExecution()
      Prepares the parse tree execution map if not already initialized.
      Returns:
      true if the execution map was already initialized, false if it was just created
    • getParseTreeExecution

      protected NaftahParseTreeProperty<Boolean> getParseTreeExecution()
    • getDepth

      public int getDepth()
      Gets the depth of the current context.
      Returns:
      the depth as an integer
    • getChildren

      public List<DefaultContext> getChildren()
      Returns the child contexts of the current context, excluding the parent context.
      Returns:
      list of child DefaultContext objects
    • getChildren

      public List<DefaultContext> getChildren(boolean includeParent)
      Returns the child contexts of the current context.
      Parameters:
      includeParent - if true, includes contexts at the same depth or greater; otherwise only deeper contexts
      Returns:
      list of child DefaultContext objects matching the criteria
    • getSiblings

      public List<DefaultContext> getSiblings(boolean includeSelf)
      Returns the sibling contexts of the current context.

      Siblings are contexts that share the same depth as this context. If includeSelf is true, the returned list also includes this context; otherwise, this context is excluded.

      Parameters:
      includeSelf - if true, the returned list will include this context itself
      Returns:
      a list of DefaultContext objects at the same depth
    • getFunctionCallId

      public String getFunctionCallId()
      Gets the identifier of the current function call being parsed.
      Returns:
      the function call ID as a string
    • setFunctionCallId

      public void setFunctionCallId(String functionCallId)
      Sets the identifier for the current function call being in execution.

      This value is stored in a ThreadLocal to allow each thread to independently track the current function call ID. If the thread-local is uninitialized, it is created; otherwise, the value is updated.

      Parameters:
      functionCallId - the function call ID to set
    • getImplementationName

      public String getImplementationName()
      Returns the current implementation name for this context.

      The implementation name is stored in a thread-local variable. If the thread-local is uninitialized, this method returns null.

      Returns:
      the current implementation name, or null if none is set
    • setImplementationName

      public void setImplementationName(String implementationName)
      Sets the implementation name for this context.

      The value is stored in a thread-local variable to allow independent tracking per thread. If the thread-local is uninitialized, it is created; otherwise, the value is updated.

      Parameters:
      implementationName - the implementation name to set
    • isParsingFunctionCallId

      public boolean isParsingFunctionCallId()
      Checks whether the parser is currently processing a function call ID.

      This flag is tracked using a thread-local variable. If the thread-local is uninitialized, this method returns false.

      Returns:
      true if a function call ID is being parsed, false otherwise
    • setParsingFunctionCallId

      public void setParsingFunctionCallId(boolean parsingFunctionCallId)
      Sets the flag indicating whether the parser is currently parsing a function call ID.
      Parameters:
      parsingFunctionCallId - true to indicate parsing a function call ID, false otherwise
    • isParsingAssignment

      public boolean isParsingAssignment()
      Checks if the parser is currently parsing an assignment statement.
      Returns:
      true if parsing an assignment, false otherwise
    • setParsingAssignment

      public void setParsingAssignment(boolean parsingAssignment)
      Sets the flag indicating whether the parser is currently parsing an assignment. If parsing is set to false, clears the declaration of assignment.
      Parameters:
      parsingAssignment - true to indicate parsing an assignment, false otherwise
    • getDeclarationOfAssignment

      public Pair<DeclaredVariable,Boolean> getDeclarationOfAssignment()
      Gets the declaration of the current assignment as a pair of DeclaredVariable and a boolean flag.
      Returns:
      the declaration of assignment, or null if none
    • setDeclarationOfAssignment

      public void setDeclarationOfAssignment(Pair<DeclaredVariable,Boolean> declarationOfAssignment)
      Sets the declaration of the current assignment.
      Parameters:
      declarationOfAssignment - a pair containing the declared variable and a boolean flag
    • isCreatingObject

      public boolean isCreatingObject()
      Checks if the parser is currently creating an object.
      Returns:
      true if creating an object, false otherwise
    • setCreatingObject

      public void setCreatingObject(boolean creatingObject)
      Sets the flag indicating whether the parser is currently creating an object.
      Parameters:
      creatingObject - true to indicate creating an object, false otherwise
    • isAwaitingTask

      public boolean isAwaitingTask()
      Checks whether the current thread is awaiting the completion of a task within this context.

      This uses a ThreadLocal boolean to track if the current thread is awaiting a task, allowing multiple threads to track their own state independently.

      Returns:
      true if the current thread is awaiting a task; false otherwise
    • setAwaitingTask

      public void setAwaitingTask(boolean awaitingTask)
      Sets the awaiting state for the current thread in this context.

      If the underlying ThreadLocal has not been initialized yet, it will be created and initialized with the provided value. Otherwise, it updates the current thread's value.

      Parameters:
      awaitingTask - true if the current thread is awaiting a task, false otherwise
    • getLoopLabel

      public String getLoopLabel()
      Retrieves the label of the current loop context. If not set locally, retrieves from the parent context if available.
      Returns:
      the loop label string, or null if none is set
    • setLoopLabel

      public void setLoopLabel(String loopLabel)
      Sets the label for the current loop context.
      Parameters:
      loopLabel - the loop label string to set
    • defineBlockImport

      private void defineBlockImport(String alias, String importElement)
      Defines a block-level import for this context.

      The specified alias is associated with the given import element and stored in the local blockImports map. This import will only be visible within the current block or its child contexts.

      Parameters:
      alias - the alias used to reference the imported element
      importElement - the fully qualified name or path of the element being imported
    • matchImport

      public String matchImport(String alias)
      Resolves the fully qualified import corresponding to the specified alias.

      This method attempts to match the alias against local block imports, parent contexts, and finally the global import registry. It supports qualified aliases (e.g., my.module.Class) by recursively matching the base part of the alias and appending the remainder if a match is found.

      Parameters:
      alias - the alias or qualified name to resolve
      Returns:
      the fully qualified import path if found; otherwise null
    • doMatchImport

      private String doMatchImport(String alias)
      Recursively searches for an import matching the given alias.

      The search order is:

      1. Local block imports in the current context
      2. Parent context (if available)
      3. Global imports
      Parameters:
      alias - the alias to match
      Returns:
      the fully qualified import path if found; otherwise null
    • matchVariable

      public Triple<String,Boolean,Object> matchVariable(String qualifiedCall)
      Attempts to resolve a variable reference into a fully qualified call and retrieve its underlying value.

      This method processes expressions of the form variableId:propertyName. If the identifier corresponds to a known variable within this context or any parent context, the method returns a Triple containing:

      • Triple.left — the fully qualified call string, in the form qualifiedVariableClassName:propertyName
      • Triple.middle — a boolean indicating whether the variable's runtime class differs from its declared type
      • Triple.right — the resolved variable value, with automatic unwrapping of NaftahObject instances

      Special handling:

      • If the variable is a NaftahObject, it is unwrapped to obtain the underlying value, and a flag is set to indicate whether it originates from Java.
      • If the variable is an instance of Actor or a subclass, the fully qualified type is reported as Actor.class.

      If the input string does not match the id:property format, or if the variable cannot be found in this context or any parent, the method returns null.

      Parameters:
      qualifiedCall - a variable reference in the form id:property
      Returns:
      a Triple containing:
      • the fully qualified call string
      • a boolean indicating if the runtime class differs from the declared type
      • the resolved variable value
      Returns null if resolution fails.
    • clear

      public static void clear()
      Clears all stored contexts from the global CONTEXTS map.

      This removes every DefaultContext instance, effectively resetting the entire context tracking system. After calling this method, any previously stored contexts are lost.