Source code for concepts.dsl.executors.executor_base

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File   : executor_base.py
# Author : Jiayuan Mao
# Email  : maojiayuan@gmail.com
# Date   : 10/25/2022
#
# This file is part of Project Concepts.
# Distributed under terms of the MIT license.

"""The baseclass for all executors of domain-specific languages."""

from abc import ABC, abstractmethod
from typing import Any, Dict, Callable

from concepts.dsl.dsl_domain import DSLDomainBase
from concepts.dsl.expression import Expression

__all__ = ['DSLExecutorBase', 'DSLExecutionError']


[docs]class DSLExecutorBase(ABC): """The baseclass for all executors of domain-specific languages."""
[docs] def __init__(self, domain: DSLDomainBase): """Initialize the executor. Args: domain: the domain of the executor. """ self._domain = domain self._function_implementations = dict()
@property def domain(self) -> DSLDomainBase: """The domain of the executor.""" return self._domain @property def function_implementations(self) -> Dict[str, Callable]: """The implementations of functions, which is a mapping from function names to implementations.""" return self._function_implementations
[docs] def register_function(self, name: str, func: Callable): """Register an implementation for a function to the executor. Alias for :meth:`register_function_implementation`. Args: name: the name of the function. func: the implementation of the function. """ self.register_function_implementation(name, func)
[docs] def register_function_implementation(self, name: str, func: Callable): """Register an implementation for a function. Args: name: the name of the function. func: the implementation of the function. """ self._function_implementations[name] = func
[docs] def get_function_implementation(self, name: str) -> Callable: """Get the implementation of a function. When the executor does not have an implementation for the function, the implementation of the function in the domain will be returned. If that is also None, a `KeyError` will be raised. Args: name: the name of the function. Returns: the implementation of the function. """ if name in self._function_implementations: return self._function_implementations[name] elif name in self._domain.functions: function_body = self._domain.functions[name].function_body if function_body is None: raise KeyError(f'No implementation for function {name}.') return function_body raise KeyError(f'No implementation for function {name}.')
[docs] def has_function_implementation(self, name: str) -> bool: """Check whether the executor has an implementation for a function. Args: name: the name of the function. Returns: whether the executor has an implementation for the function. """ return name in self._function_implementations or (name in self.domain.functions and self.domain.functions[name].function_body is not None)
[docs] @abstractmethod def execute(self, expression: Expression) -> Any: """Execute an expression. Args: expression: the expression to execute. Returns: the result of the execution. """ raise NotImplementedError()
[docs]class DSLExecutionError(Exception): """The exception raised when an execution error occurs."""