Source code for concepts.dsl.dsl_domain
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File : dsl_domain.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 base calss for domain definitions: containing custom types, constants, and functions."""
import inspect
from typing import Optional, Union, Dict, Callable
from concepts.dsl.dsl_types import ObjectType, ValueType, ObjectConstant
from concepts.dsl.dsl_functions import Function
from concepts.dsl.value import Value
__all__ = ['DSLDomainBase']
[docs]
class DSLDomainBase(object):
"""The baseclass for the domain definition of a domain-specific language."""
[docs]
def __init__(self, name: Optional[str] = None):
"""Initialize the domain.
Args:
name: the name of the domain. If not specified, the name of the class will be used.
"""
if name is None:
name = type(self).__name__
self.name = name
self.types = dict()
self.functions = dict()
self.constants = dict()
name: str
"""The name of the domain."""
types: Dict[str, Union[ObjectType, ValueType]]
"""The types defined in the domain, as a dictionary from type names to types."""
functions: Dict[str, Function]
"""The functions defined in the domain, as a dictionary from function names to functions."""
constants: Dict[str, Union[ObjectConstant, Value]]
"""The constants defined in the domain, as a dictionary from the name to the :class:`~concepts.dsl.value.Value` objects."""
[docs]
def define_type(self, t: Union[ObjectType, ValueType]) -> Union[ObjectType, ValueType]:
"""Define a type in the domain.
Args:
t: the type to be defined.
Returns:
the type that is defined.
"""
if not isinstance(t, (ObjectType, ValueType)):
raise TypeError('Types can only be object types and value types.')
if t.typename in self.types:
raise NameError(f'Type {t.typename} already defined.')
self.types[t.typename] = t
return t
[docs]
def define_function(self, function: Union[Function, Callable], implementation: bool = True) -> Function:
"""Define a function in the domain.
Args:
function: the function to be defined.
implementation: whether to store the function body of `function` as the implementation of the function.
Returns:
the function that is defined.
"""
if not isinstance(function, Function):
assert inspect.isfunction(function)
function = Function.from_function(function, implementation=implementation)
if function.name in self.functions:
raise ValueError(f'Function {function.name} already defined.')
self.functions[function.name] = function
return function
[docs]
def define_const(self, dtype: Union[ObjectType, ValueType], value: str):
"""Define a constant with the given type and value.
Args:
dtype: the type of the constant.
value: the value of the constant. The value should be a string that is the name of the constant.
"""
if value in self.constants:
raise ValueError(f'Constant {value} already defined.')
if isinstance(dtype, ObjectType):
self.constants[value] = ObjectConstant(dtype, value)
else:
self.constants[value] = Value(dtype, value)
[docs]
def has_function(self, name: str) -> bool:
"""Check whether the domain has a function with the given name.
Args:
name: the name of the function.
Returns:
whether the domain has a function with the given name.
"""
return name in self.functions
[docs]
def get_function(self, name: str) -> Function:
"""Get the function with the given name.
Args:
name: the name of the function.
Returns:
the function with the given name.
"""
if name not in self.functions:
raise KeyError(f'Function {name} not found.')
return self.functions[name]
def __str__(self) -> str:
return f'{type(self).__name__}({self.name})'
def __repr__(self) -> str:
return str(self)