Documentation
¶
Index ¶
- func CallEntrypoint(rt *ModuleRuntime, inst *ModuleInstance, name string, args []eval.Value) (eval.Value, error)
- func GetArity(val eval.Value) (int, error)
- func GetExportNames(inst *ModuleInstance) []string
- type BuiltinOnlyResolver
- type BuiltinRegistry
- type ModuleInstance
- func (mi *ModuleInstance) GetBinding(name string) (eval.Value, error)
- func (mi *ModuleInstance) GetEvaluationError() error
- func (mi *ModuleInstance) GetExport(name string) (eval.Value, error)
- func (mi *ModuleInstance) HasExport(name string) bool
- func (mi *ModuleInstance) IsEvaluated() bool
- func (mi *ModuleInstance) ListExports() []string
- type ModuleRuntime
- func (rt *ModuleRuntime) DeleteInstance(modulePath string)
- func (rt *ModuleRuntime) GetEvaluator() *eval.CoreEvaluator
- func (rt *ModuleRuntime) GetInstance(modulePath string) *ModuleInstance
- func (rt *ModuleRuntime) GetLoader() *loader.ModuleLoader
- func (rt *ModuleRuntime) HasInstance(modulePath string) bool
- func (rt *ModuleRuntime) ListInstances() []string
- func (rt *ModuleRuntime) LoadAndEvaluate(modulePath string) (*ModuleInstance, error)
- func (rt *ModuleRuntime) PreloadModule(path string, loaded *loader.LoadedModule)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CallEntrypoint ¶
func CallEntrypoint(rt *ModuleRuntime, inst *ModuleInstance, name string, args []eval.Value) (eval.Value, error)
CallEntrypoint calls an exported entrypoint function from a module
This method handles function invocation for module entrypoints, supporting both 0-arg and multi-arg functions. The function is executed with a properly configured evaluator that can resolve cross-module references.
Parameters:
- rt: The ModuleRuntime instance
- inst: The module instance containing the entrypoint
- name: The name of the entrypoint function
- args: The arguments to pass to the function (can be empty for 0-arg)
Returns:
- The result value from executing the function
- An error if the entrypoint doesn't exist, isn't a function, or execution fails
Example:
result, err := CallEntrypoint(rt, inst, "main", []eval.Value{})
if err != nil {
return err
}
fmt.Println(result.String())
func GetArity ¶
getArity returns the arity (number of parameters) of a value
Parameters:
- val: The value to check (should be a FunctionValue)
Returns:
- The number of parameters the function takes
- An error if the value is not a function
func GetExportNames ¶
func GetExportNames(inst *ModuleInstance) []string
GetExportNames returns a sorted list of export names from a module instance
This is a helper function for error messages.
Parameters:
- inst: The module instance
Returns:
- A slice of export names
Types ¶
type BuiltinOnlyResolver ¶
type BuiltinOnlyResolver struct {
Builtins *BuiltinRegistry
}
BuiltinOnlyResolver resolves builtin functions for non-module execution
This resolver is used in the legacy pipeline execution path (non-module files) to provide access to the builtin registry. It only resolves:
- References to the synthetic $builtin module
- Names starting with underscore (e.g., _io_print)
It does NOT resolve user bindings or module imports, as those are handled by the module runtime's moduleGlobalResolver.
Thread-safety: Safe for concurrent use as it only reads from the registry.
func NewBuiltinOnlyResolver ¶
func NewBuiltinOnlyResolver(builtins *BuiltinRegistry) *BuiltinOnlyResolver
NewBuiltinOnlyResolver creates a new builtin-only resolver
This is a convenience constructor for creating resolvers with a cleaner API.
Parameters:
- builtins: The BuiltinRegistry to use for lookups
Returns:
- A new BuiltinOnlyResolver ready to use
func (*BuiltinOnlyResolver) ResolveValue ¶
ResolveValue attempts to resolve a global reference to a builtin function
Resolution logic:
- Check if it's a builtin reference (module="$builtin" or name starts with "_")
- Look up the builtin in the registry
- Return nil if not found (allows fallback to other resolution mechanisms)
Parameters:
- ref: The global reference to resolve
Returns:
- The builtin Value if found
- nil, nil if not a builtin (NOT an error - allows chaining resolvers)
Example:
resolver := &BuiltinOnlyResolver{Builtins: registry}
val, err := resolver.ResolveValue(core.GlobalRef{Module: "$builtin", Name: "add_Int"})
type BuiltinRegistry ¶
type BuiltinRegistry struct {
// contains filtered or unexported fields
}
BuiltinRegistry holds native Go implementations of builtin functions
Builtins are functions implemented in Go that can be called from AILANG modules. They are identified by names starting with underscore (e.g., _io_print).
The registry provides:
- Type-safe function implementations routed through the effect system
- Runtime access via GetBuiltin()
- Automatic registration of stdlib functions
Thread-safety: The registry is initialized once and read-only after that, so it is safe to use concurrently.
func NewBuiltinRegistry ¶
func NewBuiltinRegistry(evaluator *eval.CoreEvaluator) *BuiltinRegistry
NewBuiltinRegistry creates a new builtin registry with all stdlib functions registered
Parameters:
- evaluator: The evaluator (needed to access EffContext during builtin calls)
Returns:
- A fully-initialized BuiltinRegistry
func (*BuiltinRegistry) ClearGoroutineEvaluator ¶
func (br *BuiltinRegistry) ClearGoroutineEvaluator()
ClearGoroutineEvaluator removes the goroutine-local evaluator override.
func (*BuiltinRegistry) Get ¶
func (br *BuiltinRegistry) Get(name string) (eval.Value, bool)
Get looks up a builtin function by name
Parameters:
- name: The builtin function name (e.g., "_io_print")
Returns:
- The builtin function value if found
- A boolean indicating whether the builtin was found
func (*BuiltinRegistry) SetGoroutineEvaluator ¶
func (br *BuiltinRegistry) SetGoroutineEvaluator(e *eval.CoreEvaluator)
SetGoroutineEvaluator registers a forked evaluator for the current goroutine. Builtins will use this evaluator's EffContext instead of the shared one. Must be paired with ClearGoroutineEvaluator when the request completes.
type ModuleInstance ¶
type ModuleInstance struct {
// Identity
Path string // Module path (e.g., "stdlib/std/io")
// Static Information (from type-checking)
Iface *iface.Iface // Module interface (exports, types)
Core *core.Program // Compiled Core AST
CoreTI interface{} // Type info for Core expressions (types.CoreTypeInfo, interface{} to avoid import cycle)
// Runtime State
Bindings map[string]eval.Value // All top-level bindings
Exports map[string]eval.Value // Exported bindings only
Imports map[string]*ModuleInstance // Imported modules
// contains filtered or unexported fields
}
ModuleInstance represents a runtime module with evaluated bindings
A ModuleInstance is created from a LoadedModule after type-checking and contains the runtime state of the module, including:
- All top-level bindings (both exported and private)
- Exported bindings only (for cross-module access)
- Links to imported module instances
Thread-safety: Initialization is protected by sync.Once to ensure each module is evaluated exactly once, even with concurrent access.
func NewModuleInstance ¶
func NewModuleInstance(loaded *loader.LoadedModule) *ModuleInstance
NewModuleInstance creates a new module instance from a loaded module
The instance is created with empty Bindings and Exports maps, which will be populated during evaluation. The Iface and Core are copied from the LoadedModule.
Parameters:
- loaded: A LoadedModule containing the parsed, type-checked module
Returns:
- A new ModuleInstance ready for evaluation
func (*ModuleInstance) GetBinding ¶
func (mi *ModuleInstance) GetBinding(name string) (eval.Value, error)
GetBinding retrieves a binding by name (exported or private)
This method is used for internal module access during evaluation. Unlike GetExport, it can access private (non-exported) bindings.
Parameters:
- name: The name of the binding
Returns:
- The binding value if found
- An error if the binding does not exist
func (*ModuleInstance) GetEvaluationError ¶
func (mi *ModuleInstance) GetEvaluationError() error
GetEvaluationError returns the error from evaluation, if any
Returns:
- The evaluation error if evaluation failed
- nil if evaluation succeeded or hasn't been attempted
func (*ModuleInstance) GetExport ¶
func (mi *ModuleInstance) GetExport(name string) (eval.Value, error)
GetExport retrieves an exported value by name
This method is used for cross-module access to ensure encapsulation: only exported bindings are accessible from other modules.
Parameters:
- name: The name of the exported binding
Returns:
- The exported value if found
- An error if the export does not exist
Example:
val, err := moduleInst.GetExport("main")
if err != nil {
// Export "main" not found
}
func (*ModuleInstance) HasExport ¶
func (mi *ModuleInstance) HasExport(name string) bool
HasExport checks if a module exports a given name
Parameters:
- name: The name to check
Returns:
- true if the module exports the name, false otherwise
func (*ModuleInstance) IsEvaluated ¶
func (mi *ModuleInstance) IsEvaluated() bool
IsEvaluated returns whether the module has been evaluated
Returns:
- true if evaluation completed (successfully or with error)
- false if evaluation has not been attempted
func (*ModuleInstance) ListExports ¶
func (mi *ModuleInstance) ListExports() []string
ListExports returns a sorted list of export names
This is useful for error messages and debugging.
Returns:
- A slice of export names in the order they were added
type ModuleRuntime ¶
type ModuleRuntime struct {
// contains filtered or unexported fields
}
ModuleRuntime manages module instances and orchestrates evaluation
The ModuleRuntime is responsible for:
- Loading modules via the ModuleLoader
- Creating ModuleInstance objects
- Caching evaluated modules
- Evaluating modules in dependency order (topological sort)
- Linking imported modules
- Detecting circular imports
- Providing builtin function registry
Thread-safety: The runtime uses sync.Once within each ModuleInstance to ensure each module is evaluated exactly once.
func NewModuleRuntime ¶
func NewModuleRuntime(basePath string) *ModuleRuntime
NewModuleRuntime creates a new module runtime
The runtime is initialized with a base path for module resolution and creates a fresh module loader and core evaluator.
Parameters:
- basePath: The directory to use as the root for module resolution
Returns:
- A new ModuleRuntime ready to load and evaluate modules
Example:
rt := NewModuleRuntime("/path/to/project")
inst, err := rt.LoadAndEvaluate("examples/demo")
func (*ModuleRuntime) DeleteInstance ¶
func (rt *ModuleRuntime) DeleteInstance(modulePath string)
DeleteInstance removes a cached module instance, forcing re-evaluation on next load. This is used by hot reload to invalidate stale modules.
func (*ModuleRuntime) GetEvaluator ¶
func (rt *ModuleRuntime) GetEvaluator() *eval.CoreEvaluator
GetInstance retrieves a module instance from the cache
This is useful for debugging and testing.
Parameters:
- modulePath: The module path to look up
Returns:
- The cached ModuleInstance if found
- nil if not found
GetEvaluator returns the runtime's evaluator ¶
This allows external code to access the evaluator for setting the effect context or other configuration.
Returns:
- The CoreEvaluator used by this runtime
func (*ModuleRuntime) GetInstance ¶
func (rt *ModuleRuntime) GetInstance(modulePath string) *ModuleInstance
func (*ModuleRuntime) GetLoader ¶
func (rt *ModuleRuntime) GetLoader() *loader.ModuleLoader
GetLoader returns the module loader for cache management.
func (*ModuleRuntime) HasInstance ¶
func (rt *ModuleRuntime) HasInstance(modulePath string) bool
HasInstance checks if a module instance is cached
Parameters:
- modulePath: The module path to check
Returns:
- true if the module is cached, false otherwise
func (*ModuleRuntime) ListInstances ¶
func (rt *ModuleRuntime) ListInstances() []string
ListInstances returns a list of all cached module paths
This is useful for debugging and testing.
Returns:
- A slice of module paths in the cache
func (*ModuleRuntime) LoadAndEvaluate ¶
func (rt *ModuleRuntime) LoadAndEvaluate(modulePath string) (*ModuleInstance, error)
LoadAndEvaluate loads a module and all its dependencies, then evaluates them
This is the main entry point for module execution. It performs the following steps:
- Check cache for already-evaluated modules
- Load the module (parse, type-check, build interface)
- Create a ModuleInstance
- Recursively load and evaluate dependencies (topological sort)
- Evaluate this module (populate bindings and exports)
The evaluation order is deterministic: dependencies are evaluated before dependents (depth-first search).
Parameters:
- modulePath: The module path to load (e.g., "stdlib/std/io")
Returns:
- The evaluated ModuleInstance
- An error if loading or evaluation fails
Example:
inst, err := rt.LoadAndEvaluate("examples/hello")
if err != nil {
log.Fatal("Failed to evaluate module:", err)
}
main, _ := inst.GetExport("main")
func (*ModuleRuntime) PreloadModule ¶
func (rt *ModuleRuntime) PreloadModule(path string, loaded *loader.LoadedModule)
PreloadModule adds a pre-loaded module to the loader's cache
This is used to inject modules that were already loaded and elaborated by the pipeline, avoiding redundant loading and elaboration.
Parameters:
- path: The module path
- loaded: The LoadedModule with Core AST already populated