├── src ├── __init__.py └── nucleoid │ ├── lang │ ├── __init__.py │ ├── estree │ │ └── __init__.py │ ├── ast │ │ └── __init__.py │ ├── nuc │ │ └── __init__.py │ └── Evaluation.py │ ├── nuc │ ├── FUNCTION.py │ ├── REFERENCE.py │ ├── BREAK.py │ ├── RETURN.py │ ├── ALIAS.py │ ├── OBJECT_INSTANCE.py │ ├── DELETE_VARIABLE.py │ ├── LET_OBJECT.py │ ├── THROW.py │ ├── BLOCK.py │ ├── BLOCK_INSTANCE.py │ ├── LET_CLASS.py │ ├── VARIABLE.py │ ├── EXPRESSION_INSTANCE.py │ ├── LET_INSTANCE.py │ ├── __init__.py │ ├── IF_INSTANCE.py │ ├── FOR.py │ ├── DELETE_OBJECT.py │ ├── OBJECT_CLASS.py │ ├── PROPERTY_CLASS.py │ ├── PROPERTY_INSTANCE.py │ ├── LET.py │ ├── IF_CLASS.py │ ├── DELETE.py │ ├── IF.py │ ├── PROPERTY.py │ ├── CLASS.py │ ├── BLOCK_CLASS.py │ ├── NODE.py │ └── OBJECT.py │ ├── lib │ ├── __init__.py │ ├── test.py │ ├── random.py │ ├── statement.py │ ├── deep.py │ └── serialize.py │ ├── routes │ ├── __init__.py │ ├── logs.py │ ├── metrics.py │ ├── graph.py │ ├── openapi.py │ └── terminal.py │ ├── ast │ ├── __New__.py │ ├── __Literal__.py │ ├── __init__.py │ ├── __Template__.py │ ├── __Array__.py │ ├── __Object__.py │ ├── convert.py │ ├── __Operator__.py │ └── __Node__.py │ ├── __nuc__ │ ├── __RETURN__.py │ ├── __THROW__.py │ ├── __FOR__.py │ ├── __FUNCTION__.py │ ├── __NUC__.py │ ├── __VARIABLE__.py │ ├── __ALIAS__.py │ ├── __CLASS__.py │ ├── __init__.py │ ├── __DELETE__.py │ ├── __CALL__.py │ ├── __EXPRESSION__.py │ ├── __PROPERTY__.py │ ├── __IF__.py │ ├── revive.py │ ├── __INSTANCE__.py │ ├── __ASSIGNMENT__.py │ ├── __BLOCK__.py │ └── __LET__.py │ ├── Instruction.py │ ├── graph.py │ ├── event.py │ ├── types.py │ ├── nucleoid.py │ ├── prototype.py │ ├── context.py │ ├── cache.py │ ├── datastore.py │ ├── config.py │ ├── transaction.py │ ├── runtime.py │ └── process.py ├── tests ├── lib │ ├── __init__.py │ ├── test_random.py │ ├── test_test.py │ ├── test_deep.py │ ├── test_statement.py │ └── test_serialize.py └── test___nuc__.py ├── .github ├── media │ ├── banner.gif │ ├── banner.png │ ├── graph.gif │ └── neuro-symbolic.png └── workflows │ ├── test.yml │ ├── beta.yml │ └── tag.yml ├── .gitattributes ├── requirements.txt ├── pytest.ini ├── .gitignore ├── pyproject.toml ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md /src/__init__.py: -------------------------------------------------------------------------------- 1 | """Nucleoid - Python Implementation""" 2 | -------------------------------------------------------------------------------- /tests/lib/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for lib utilities""" 2 | -------------------------------------------------------------------------------- /src/nucleoid/lang/__init__.py: -------------------------------------------------------------------------------- 1 | """Language implementation module""" 2 | -------------------------------------------------------------------------------- /src/nucleoid/lang/estree/__init__.py: -------------------------------------------------------------------------------- 1 | """ESTree standard compatibility""" 2 | -------------------------------------------------------------------------------- /src/nucleoid/lang/ast/__init__.py: -------------------------------------------------------------------------------- 1 | """Abstract Syntax Tree implementation""" 2 | -------------------------------------------------------------------------------- /src/nucleoid/lang/nuc/__init__.py: -------------------------------------------------------------------------------- 1 | """Nucleoid language operators and instructions""" 2 | -------------------------------------------------------------------------------- /.github/media/banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NucleoidAI/Nucleoid/HEAD/.github/media/banner.gif -------------------------------------------------------------------------------- /.github/media/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NucleoidAI/Nucleoid/HEAD/.github/media/banner.png -------------------------------------------------------------------------------- /.github/media/graph.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NucleoidAI/Nucleoid/HEAD/.github/media/graph.gif -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.js linguist-detectable=false 3 | *.ts linguist-language=TypeScript 4 | -------------------------------------------------------------------------------- /.github/media/neuro-symbolic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NucleoidAI/Nucleoid/HEAD/.github/media/neuro-symbolic.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Python dependencies for Nucleoid project 2 | fastapi>=0.104.0 3 | uvicorn>=0.24.0 4 | httpx>=0.25.0 # Required for TestClient 5 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests 3 | python_files = test_*.py 4 | python_classes = Test* 5 | python_functions = test_* 6 | addopts = -v --tb=short 7 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/FUNCTION.py: -------------------------------------------------------------------------------- 1 | """ 2 | FUNCTION runtime node class. 3 | """ 4 | from .NODE import NODE 5 | 6 | 7 | class FUNCTION(NODE): 8 | """Function declaration node.""" 9 | pass 10 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/REFERENCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | REFERENCE runtime node class. 3 | """ 4 | from .EXPRESSION import EXPRESSION 5 | 6 | 7 | class REFERENCE(EXPRESSION): 8 | """Reference expression node.""" 9 | pass 10 | -------------------------------------------------------------------------------- /src/nucleoid/lib/__init__.py: -------------------------------------------------------------------------------- 1 | """Utility library and helper functions""" 2 | 3 | from nucleoid.lib import deep, openapi, random, serialize, statement, test 4 | 5 | __all__ = ["deep", "openapi", "random", "serialize", "statement", "test"] 6 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/BREAK.py: -------------------------------------------------------------------------------- 1 | """ 2 | BREAK runtime node class. 3 | """ 4 | from typing import Any 5 | 6 | 7 | class BREAK: 8 | """Break statement node.""" 9 | 10 | def __init__(self, block: Any = None) -> None: 11 | """ 12 | Initialize a BREAK instance. 13 | 14 | Args: 15 | block: The block to break from 16 | """ 17 | self.block: Any = block 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: [main] 5 | pull_request: 6 | branches: [main] 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 18 15 | - run: npm ci 16 | - run: npm test 17 | - run: npm run lint 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.claude 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # Virtual environment 10 | venv/ 11 | .venv/ 12 | 13 | # Distribution / packaging 14 | build/ 15 | dist/ 16 | *.egg-info/ 17 | 18 | # Unit test / coverage reports 19 | .coverage 20 | htmlcov/ 21 | .coverage.* 22 | 23 | # Jupyter checkpoints 24 | .ipynb_checkpoints/ 25 | 26 | # Environment files 27 | .env 28 | .env.* 29 | -------------------------------------------------------------------------------- /src/nucleoid/routes/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | routes module - Flask routes and application endpoints. 3 | """ 4 | 5 | from .graph import graph_bp 6 | from .logs import logs_bp 7 | from .metrics import metrics_bp 8 | from .openapi import openapi_bp 9 | from .terminal import terminal, create_terminal_app 10 | 11 | __all__ = [ 12 | 'graph_bp', 13 | 'logs_bp', 14 | 'metrics_bp', 15 | 'openapi_bp', 16 | 'terminal', 17 | 'create_terminal_app', 18 | ] 19 | -------------------------------------------------------------------------------- /src/nucleoid/lib/test.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test utility for clearing application state. 3 | Used for test isolation and cleanup between test runs. 4 | """ 5 | 6 | from nucleoid import datastore, state, graph 7 | 8 | 9 | def clear() -> None: 10 | """ 11 | Clear all application state including state, graph, and datastore. 12 | This is useful for resetting the application between test runs. 13 | """ 14 | state.clear() 15 | graph.clear() 16 | datastore.clear() 17 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/RETURN.py: -------------------------------------------------------------------------------- 1 | """ 2 | RETURN runtime node class. 3 | """ 4 | from typing import Any 5 | from .NODE import NODE 6 | 7 | 8 | class RETURN(NODE): 9 | """Return statement node.""" 10 | 11 | def __init__(self, statement: Any = None) -> None: 12 | """ 13 | Initialize a RETURN instance. 14 | 15 | Args: 16 | statement: The return statement 17 | """ 18 | super().__init__() 19 | self.statement: Any = statement 20 | -------------------------------------------------------------------------------- /src/nucleoid/routes/logs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Logs route - provides access to system logs. 3 | """ 4 | from flask import Blueprint, jsonify, request 5 | from typing import Any 6 | 7 | 8 | logs_bp = Blueprint('logs', __name__) 9 | 10 | 11 | @logs_bp.route('/logs', methods=['GET']) 12 | def get_logs() -> Any: 13 | """ 14 | Get recent logs. 15 | 16 | Returns: 17 | JSON response with recent log entries 18 | """ 19 | from ..datastore import datastore_instance 20 | 21 | return jsonify(datastore_instance.tail()) 22 | -------------------------------------------------------------------------------- /.github/workflows/beta.yml: -------------------------------------------------------------------------------- 1 | name: Beta 2 | on: 3 | push: 4 | tags-ignore: 5 | - v[0-9]+.[0-9]+.[0-9]+ 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: 18 14 | registry-url: "https://registry.npmjs.org" 15 | - run: npm ci 16 | - run: npm test 17 | - run: npm publish --tag beta 18 | env: 19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 20 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/ALIAS.py: -------------------------------------------------------------------------------- 1 | """ 2 | ALIAS runtime node class. 3 | """ 4 | from typing import Any 5 | from .VARIABLE import VARIABLE 6 | 7 | 8 | class ALIAS(VARIABLE): 9 | """Alias variable node.""" 10 | 11 | def __init__(self, value: Any) -> None: 12 | """ 13 | Initialize an ALIAS instance. 14 | 15 | Args: 16 | value: The value node 17 | """ 18 | super().__init__(value) 19 | self.alias: Any = None 20 | self.name: Any = None 21 | self.value: Any = None 22 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/OBJECT_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | OBJECT_INSTANCE runtime node class. 3 | """ 4 | from typing import Any 5 | from .NODE import NODE 6 | 7 | 8 | class OBJECT_INSTANCE(NODE): 9 | """Object instance node.""" 10 | 11 | def __init__(self, key: Any = None) -> None: 12 | """ 13 | Initialize an OBJECT_INSTANCE. 14 | 15 | Args: 16 | key: The object instance key 17 | """ 18 | super().__init__(key) 19 | self.class_ref: Any = None 20 | self.object: Any = None 21 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__New__.py: -------------------------------------------------------------------------------- 1 | """ 2 | New expression AST node. 3 | """ 4 | from typing import Optional, Union, Dict, Any 5 | from .__Node__ import __Node__ 6 | 7 | 8 | class __New__(__Node__): 9 | """New expression node.""" 10 | pass 11 | 12 | 13 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __New__: 14 | """ 15 | Builder function for creating new expression instances. 16 | 17 | Args: 18 | node: The new expression node 19 | 20 | Returns: 21 | A __New__ instance 22 | """ 23 | return __New__(node) 24 | 25 | 26 | __new__ = build 27 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/DELETE_VARIABLE.py: -------------------------------------------------------------------------------- 1 | """ 2 | DELETE_VARIABLE runtime node class. 3 | """ 4 | from .DELETE import DELETE 5 | 6 | 7 | class DELETE_VARIABLE(DELETE): 8 | """Delete variable statement node.""" 9 | 10 | def graph(self) -> None: 11 | """Build dependency graph.""" 12 | from .. import graph 13 | 14 | node = graph.retrieve(self.variable.key) 15 | 16 | # Remove previous connections 17 | for key in list(node.previous.keys()): 18 | if key in node.next: 19 | del node.next[key] 20 | 21 | # Delete from graph 22 | del graph.graph_instance[node.key] 23 | -------------------------------------------------------------------------------- /src/nucleoid/lang/Evaluation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Evaluation class for Nucleoid language processing. 3 | """ 4 | 5 | 6 | class Evaluation: 7 | """Represents an evaluation result.""" 8 | 9 | def __init__(self, value: str) -> None: 10 | """ 11 | Initialize an Evaluation instance. 12 | 13 | Args: 14 | value: The evaluation value 15 | """ 16 | self.value: str = value 17 | 18 | def __str__(self) -> str: 19 | """ 20 | String representation of the evaluation. 21 | 22 | Returns: 23 | The evaluation value as a string 24 | """ 25 | return self.value 26 | -------------------------------------------------------------------------------- /src/nucleoid/routes/metrics.py: -------------------------------------------------------------------------------- 1 | """ 2 | Metrics route - provides system metrics and resource usage information. 3 | """ 4 | from flask import Blueprint, jsonify, request 5 | import psutil 6 | from typing import Any 7 | 8 | 9 | metrics_bp = Blueprint('metrics', __name__) 10 | 11 | 12 | @metrics_bp.route('/metrics', methods=['GET']) 13 | def get_metrics() -> Any: 14 | """ 15 | Get system metrics including memory usage. 16 | 17 | Returns: 18 | JSON response with free and total memory 19 | """ 20 | memory = psutil.virtual_memory() 21 | 22 | return jsonify({ 23 | 'free': memory.available, 24 | 'total': memory.total, 25 | }) 26 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__RETURN__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(statement: Any) -> "__RETURN__": 6 | """Build a __RETURN__ statement.""" 7 | return_statement = __RETURN__() 8 | return_statement.stm = statement 9 | return return_statement 10 | 11 | 12 | class __RETURN__(__NUC__): 13 | """Represents a return statement.""" 14 | 15 | def __init__(self) -> None: 16 | super().__init__() 17 | self.stm: Any = None 18 | 19 | def run(self, scope: Any = None) -> Any: 20 | """Execute the return statement.""" 21 | from ...nuc.return_ import RETURN 22 | return RETURN(self.stm) 23 | -------------------------------------------------------------------------------- /.github/workflows/tag.yml: -------------------------------------------------------------------------------- 1 | name: Tag 2 | on: 3 | push: 4 | tags: 5 | - v[0-9]+.[0-9]+.[0-9]+ 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: 18 14 | registry-url: "https://registry.npmjs.org" 15 | - run: npm ci 16 | - run: npm test 17 | - run: npm publish --tag latest 18 | env: 19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 20 | - uses: actions/create-release@latest 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | with: 24 | tag_name: ${{ github.ref }} 25 | release_name: ${{ github.ref }} 26 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__THROW__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(exception: Any) -> "__THROW__": 6 | """Build a __THROW__ statement.""" 7 | statement = __THROW__() 8 | statement.exc = exception 9 | return statement 10 | 11 | 12 | class __THROW__(__NUC__): 13 | """Represents a throw statement.""" 14 | 15 | def __init__(self) -> None: 16 | super().__init__() 17 | self.exc: Any = None 18 | 19 | def run(self, scope: Any = None) -> Any: 20 | """Execute the throw statement.""" 21 | from ..ast.__expression__ import __Expression__ 22 | from ...nuc.throw import THROW 23 | exception = __Expression__(self.exc) 24 | return THROW(exception) 25 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=61.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "nucleoid" 7 | version = "0.1.0" 8 | description = "Nucleoid Python Implementation" 9 | readme = "README.md" 10 | requires-python = ">=3.9" 11 | dependencies = [] 12 | 13 | [project.optional-dependencies] 14 | dev = [ 15 | "pytest>=7.0.0", 16 | "pytest-cov>=4.0.0", 17 | "black>=23.0.0", 18 | "flake8>=6.0.0", 19 | "mypy>=1.0.0", 20 | ] 21 | 22 | [tool.black] 23 | line-length = 88 24 | target-version = ['py39'] 25 | 26 | [tool.mypy] 27 | python_version = "3.9" 28 | warn_return_any = true 29 | warn_unused_configs = true 30 | disallow_untyped_defs = true 31 | 32 | [tool.pytest.ini_options] 33 | testpaths = ["src"] 34 | python_files = "test_*.py" 35 | python_classes = "Test*" 36 | python_functions = "test_*" 37 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Literal__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Literal AST node. 3 | """ 4 | from typing import Any, Optional, Union, Dict 5 | from .__Node__ import __Node__ 6 | 7 | 8 | class __Literal__(__Node__): 9 | """Literal value node.""" 10 | 11 | def generate(self, scope: Any = None) -> str: 12 | """ 13 | Generate literal code. 14 | 15 | Args: 16 | scope: Unused for literals 17 | 18 | Returns: 19 | The raw literal string 20 | """ 21 | return self.node.get("raw", "") 22 | 23 | 24 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __Literal__: 25 | """ 26 | Builder function for creating literal instances. 27 | 28 | Args: 29 | node: The literal node 30 | 31 | Returns: 32 | A __Literal__ instance 33 | """ 34 | return __Literal__(node) 35 | 36 | 37 | __literal__ = build 38 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/LET_OBJECT.py: -------------------------------------------------------------------------------- 1 | """ 2 | LET_OBJECT runtime node class. 3 | """ 4 | from typing import Any, Dict 5 | from .LET import LET 6 | 7 | 8 | class LET_OBJECT(LET): 9 | """Let object for object-based variable declarations.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize a LET_OBJECT.""" 13 | super().__init__() 14 | self.object: Any = None 15 | 16 | def before(self) -> None: 17 | """Execute before the main run.""" 18 | pass 19 | 20 | def run(self, scope: Any) -> Dict[str, str]: 21 | """ 22 | Execute let object. 23 | 24 | Args: 25 | scope: The execution scope 26 | 27 | Returns: 28 | Dictionary with value 29 | """ 30 | from ..lang.Evaluation import Evaluation 31 | 32 | evaluation = Evaluation(self.object.key) 33 | value = scope.assign(self.name, f"state.{evaluation}") 34 | return {"value": value} 35 | 36 | def graph(self) -> None: 37 | """Build dependency graph.""" 38 | pass 39 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/THROW.py: -------------------------------------------------------------------------------- 1 | """ 2 | THROW runtime node class. 3 | """ 4 | from typing import Any 5 | from .NODE import NODE 6 | 7 | 8 | class THROW(NODE): 9 | """Throw exception statement node.""" 10 | 11 | def __init__(self, exception: Any = None) -> None: 12 | """ 13 | Initialize a THROW instance. 14 | 15 | Args: 16 | exception: The exception to throw 17 | """ 18 | super().__init__() 19 | self.exception: Any = exception 20 | 21 | def before(self) -> None: 22 | """Execute before the main run.""" 23 | pass 24 | 25 | def run(self, scope: Any) -> None: 26 | """ 27 | Execute throw statement. 28 | 29 | Args: 30 | scope: The execution scope 31 | """ 32 | from ..state import state_instance 33 | 34 | if self.exception and hasattr(self.exception, 'generate'): 35 | state_instance.throw(scope, self.exception.generate(scope)) 36 | 37 | def graph(self) -> None: 38 | """Build dependency graph.""" 39 | pass 40 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/BLOCK.py: -------------------------------------------------------------------------------- 1 | """ 2 | BLOCK runtime node class. 3 | """ 4 | from typing import Any, List 5 | from .NODE import NODE 6 | 7 | 8 | class BLOCK(NODE): 9 | """Block statement node containing multiple statements.""" 10 | 11 | def __init__(self, key: Any = None) -> None: 12 | """ 13 | Initialize a BLOCK instance. 14 | 15 | Args: 16 | key: The block key identifier 17 | """ 18 | super().__init__(key) 19 | self.statements: List[Any] = [] 20 | self.skip: bool = False 21 | 22 | def run(self, scope: Any) -> List[Any]: 23 | """ 24 | Execute the block statements. 25 | 26 | Args: 27 | scope: The execution scope 28 | 29 | Returns: 30 | List of Instruction instances 31 | """ 32 | # Lazy import to avoid circular dependencies 33 | from ..Instruction import Instruction 34 | 35 | return [ 36 | Instruction(scope, statement, None, None, None, None) 37 | for statement in self.statements 38 | ] 39 | -------------------------------------------------------------------------------- /src/nucleoid/lib/random.py: -------------------------------------------------------------------------------- 1 | """Random string generation utilities""" 2 | 3 | import random as py_random 4 | import string 5 | 6 | # Character sets for random string generation 7 | ALPHANUMERIC_CHARS = string.ascii_letters + string.digits 8 | ALPHA_CHARS = string.ascii_letters 9 | 10 | 11 | def random(length: int = 16, alphanumeric: bool = False) -> str: 12 | """ 13 | Generate a random string of specified length. 14 | 15 | Args: 16 | length: Length of the random string (default: 16) 17 | alphanumeric: If True, include digits; if False, only letters (default: False) 18 | 19 | Returns: 20 | A random string starting with a letter, followed by random characters 21 | """ 22 | # First character is always a letter 23 | result = py_random.choice(ALPHA_CHARS) 24 | 25 | # Choose character set based on alphanumeric flag 26 | chars = ALPHANUMERIC_CHARS if alphanumeric else ALPHA_CHARS 27 | 28 | # Generate remaining characters 29 | for _ in range(1, length): 30 | result += py_random.choice(chars) 31 | 32 | return result 33 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/BLOCK_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | BLOCK_INSTANCE runtime node class. 3 | """ 4 | from typing import Any, List, Dict 5 | from .BLOCK import BLOCK 6 | 7 | 8 | class BLOCK_INSTANCE(BLOCK): 9 | """Block instance for class-based execution.""" 10 | 11 | def __init__(self, key: Any) -> None: 12 | """ 13 | Initialize a BLOCK_INSTANCE. 14 | 15 | Args: 16 | key: The block instance key 17 | """ 18 | super().__init__(str(key)) 19 | self.instance: Dict[str, Any] = {} 20 | self.declaration: Any = None 21 | self.break_flag: bool = False 22 | self.type: str = "INSTANCE" 23 | 24 | def run(self, scope: Any) -> List[Any]: 25 | """ 26 | Execute the block instance. 27 | 28 | Args: 29 | scope: The execution scope 30 | 31 | Returns: 32 | List of Instruction instances 33 | """ 34 | scope.dollar_instance = self.instance 35 | 36 | if self.break_flag: 37 | self.statements = self.declaration.statements 38 | self.break_flag = False 39 | 40 | return super().run(scope) 41 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__FOR__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(variable: Any, array: Any, statements: list[__NUC__]) -> "__FOR__": 6 | """Build a __FOR__ statement.""" 7 | statement = __FOR__() 8 | statement.var = variable 9 | statement.arr = array 10 | statement.stms = statements 11 | return statement 12 | 13 | 14 | class __FOR__(__NUC__): 15 | """Represents a for loop statement.""" 16 | 17 | def __init__(self) -> None: 18 | super().__init__() 19 | self.var: Any = None 20 | self.arr: Any = None 21 | self.stms: list[__NUC__] = [] 22 | 23 | def run(self, scope: Any) -> Any: 24 | """Execute the for loop statement.""" 25 | from ...nuc.for_ import FOR 26 | from ...instruction import Instruction 27 | from ..ast.__identifier__ import __Identifier__ 28 | 29 | statement = FOR() 30 | statement.variable = __Identifier__(self.var) 31 | statement.array = __Identifier__(self.arr) 32 | statement.statements = self.stms 33 | return Instruction(scope, statement, False, True, False, False) 34 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__FUNCTION__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, TYPE_CHECKING 2 | from .__NUC__ import __NUC__ 3 | 4 | if TYPE_CHECKING: 5 | from typing import Optional 6 | 7 | 8 | def build(name: Any, args: list[Any], block: "__BLOCK__") -> "__FUNCTION__": 9 | """Build a __FUNCTION__ statement.""" 10 | statement = __FUNCTION__() 11 | statement.nme = name 12 | statement.args = args 13 | statement.blk = block 14 | return statement 15 | 16 | 17 | class __FUNCTION__(__NUC__): 18 | """Represents a function declaration statement.""" 19 | 20 | def __init__(self) -> None: 21 | super().__init__() 22 | self.nme: Any = None 23 | self.args: list[Any] = [] 24 | self.blk: Optional["__BLOCK__"] = None 25 | 26 | def run(self, scope: Any = None) -> Any: 27 | """Execute the function declaration.""" 28 | from ..ast.__identifier__ import __Identifier__ 29 | from ...nuc.function import FUNCTION 30 | 31 | name = __Identifier__(self.nme) 32 | statement = FUNCTION(name) 33 | statement.name = name 34 | statement.arguments = self.args 35 | statement.block = self.blk 36 | return statement 37 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__NUC__.py: -------------------------------------------------------------------------------- 1 | # TODO Rename to NODE 2 | from typing import Any, Optional, Union 3 | from abc import ABC 4 | 5 | 6 | class __NUC__(ABC): 7 | """Base class for all statement types.""" 8 | 9 | def __init__(self) -> None: 10 | self.type: str = self.__class__.__name__ 11 | self.iof: str = self.__class__.__name__ 12 | self._pre: bool = False 13 | self.asg: bool = False 14 | 15 | def before(self, scope: Any) -> None: 16 | """Called before the statement is executed.""" 17 | pass 18 | 19 | def run(self, scope: Any) -> Optional[Union["NODE", list["NODE"], "__NUC__"]]: 20 | """Execute the statement and return the result.""" 21 | return None 22 | 23 | def graph(self, scope: Any) -> None: 24 | """Build the dependency graph for this statement.""" 25 | pass 26 | 27 | def after(self) -> None: 28 | """Called after the statement is executed.""" 29 | pass 30 | 31 | @property 32 | def prepared(self) -> bool: 33 | """Whether the statement has been prepared.""" 34 | return self._pre 35 | 36 | @prepared.setter 37 | def prepared(self, value: bool) -> None: 38 | """Set the prepared state.""" 39 | self._pre = value 40 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__VARIABLE__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(name: Any, value: Any) -> "__VARIABLE__": 6 | """Build a __VARIABLE__ statement.""" 7 | statement = __VARIABLE__() 8 | statement.nme = name 9 | statement.val = value 10 | return statement 11 | 12 | 13 | class __VARIABLE__(__NUC__): 14 | """Represents a variable declaration statement.""" 15 | 16 | def __init__(self) -> None: 17 | super().__init__() 18 | self.nme: Any = None 19 | self.val: Any = None 20 | 21 | def before(self, scope: Any) -> None: 22 | """Prepare the variable statement by evaluating the value.""" 23 | from .__EXPRESSION__ import __expression__ 24 | expression = __expression__(self.val) 25 | self.val = expression.run(scope) 26 | 27 | def run(self, scope: Any = None) -> "VARIABLE": 28 | """Execute the variable statement.""" 29 | from ..ast.__identifier__ import __Identifier__ 30 | from ...nuc.variable import VARIABLE 31 | name = __Identifier__(self.nme) 32 | statement = VARIABLE(name) 33 | statement.name = name 34 | statement.value = self.val 35 | return statement 36 | 37 | 38 | __variable__ = build 39 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ast module - AST node types for Nucleoid language processing. 3 | """ 4 | 5 | from .__Node__ import __Node__, build as __node__ 6 | from .__Expression__ import __Expression__, build as __expression__ 7 | from .__Array__ import __Array__, build as __array__ 8 | from .__Call__ import __Call__, build as __call__ 9 | from .__Function__ import __Function__, build as __function__ 10 | from .__Identifier__ import __Identifier__, build as __identifier__ 11 | from .__Literal__ import __Literal__, build as __literal__ 12 | from .__New__ import __New__, build as __new__ 13 | from .__Object__ import __Object__, build as __object__ 14 | from .__Operator__ import __Operator__, build as __operator__ 15 | from .__Template__ import __Template__, build as __template__ 16 | from .convert import AST 17 | 18 | __all__ = [ 19 | "__Node__", 20 | "__Expression__", 21 | "__Array__", 22 | "__Call__", 23 | "__Function__", 24 | "__Identifier__", 25 | "__Literal__", 26 | "__New__", 27 | "__Object__", 28 | "__Operator__", 29 | "__Template__", 30 | "__node__", 31 | "__expression__", 32 | "__array__", 33 | "__call__", 34 | "__function__", 35 | "__identifier__", 36 | "__literal__", 37 | "__new__", 38 | "__object__", 39 | "__operator__", 40 | "__template__", 41 | "AST", 42 | ] 43 | -------------------------------------------------------------------------------- /src/nucleoid/lib/statement.py: -------------------------------------------------------------------------------- 1 | """ 2 | Statement compilation utility using Python's AST parser. 3 | Provides a simple interface for parsing Python code strings into AST nodes. 4 | """ 5 | 6 | import ast 7 | from typing import Any, List 8 | 9 | 10 | class Statement: 11 | """Statement compiler for parsing code strings.""" 12 | 13 | def compile(self, source: str) -> List[Any]: 14 | """ 15 | Parse source code into AST nodes. 16 | 17 | Args: 18 | source: Source code as a string 19 | 20 | Returns: 21 | List of AST statement nodes 22 | 23 | Raises: 24 | SyntaxError: If the source code is invalid 25 | """ 26 | try: 27 | tree = ast.parse(source) 28 | return tree.body 29 | except SyntaxError as e: 30 | raise SyntaxError(f"Failed to parse source code: {e}") from e 31 | 32 | 33 | # Create singleton instance 34 | statement_instance = Statement() 35 | 36 | 37 | def compile(source: str) -> List[ast.stmt]: 38 | """ 39 | Parse source code into AST nodes. 40 | 41 | Args: 42 | source: Source code as a string 43 | 44 | Returns: 45 | List of AST statement nodes 46 | 47 | Raises: 48 | SyntaxError: If the source code is invalid Python 49 | """ 50 | return statement_instance.compile(source) 51 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/LET_CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | LET_CLASS runtime node class. 3 | """ 4 | from typing import Any, Dict, Optional 5 | import copy 6 | from .NODE import NODE 7 | 8 | 9 | class LET_CLASS(NODE): 10 | """Let class for class-based variable declarations.""" 11 | 12 | def __init__(self) -> None: 13 | """Initialize a LET_CLASS instance.""" 14 | super().__init__() 15 | self.name: Any = None 16 | self.value: Any = None 17 | self.class_ref: Any = None 18 | self.type: str = "CLASS" 19 | 20 | def before(self) -> None: 21 | """Execute before the main run.""" 22 | pass 23 | 24 | def run(self, scope: Any) -> Optional[Dict[str, Any]]: 25 | """ 26 | Execute let class. 27 | 28 | Args: 29 | scope: The execution scope 30 | 31 | Returns: 32 | Dictionary with next statement or None 33 | """ 34 | from .LET_INSTANCE import LET_INSTANCE 35 | 36 | dollar_instance = getattr(scope, 'dollar_instance', None) 37 | 38 | if dollar_instance: 39 | statement = LET_INSTANCE() 40 | statement.class_ref = self.class_ref 41 | statement.instance = dollar_instance 42 | statement.name = self.name 43 | statement.value = copy.deepcopy(self.value) 44 | return {"next": statement} 45 | 46 | return None 47 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__ALIAS__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__EXPRESSION__ import __EXPRESSION__, __expression__ 3 | from .__NUC__ import __NUC__ 4 | 5 | 6 | def build(alias: Any, name: str, value: "__EXPRESSION__") -> "__ALIAS__": 7 | """Build a __ALIAS__ statement.""" 8 | statement = __ALIAS__() 9 | statement.als = alias 10 | statement.nme = name 11 | statement.val = value 12 | return statement 13 | 14 | 15 | class __ALIAS__(__NUC__): 16 | """Represents an alias statement.""" 17 | 18 | def __init__(self) -> None: 19 | super().__init__() 20 | self.als: Any = None 21 | self.nme: str = "" 22 | self.val: Any = None 23 | 24 | def before(self, scope: Any) -> None: 25 | """Prepare the alias statement by evaluating the value expression.""" 26 | expression = __expression__(self.val) 27 | self.val = expression.run(scope) 28 | 29 | def run(self, scope: Any) -> Any: 30 | """Execute the alias statement.""" 31 | # Imports moved here to avoid circular dependencies 32 | from ..ast.__identifier__ import __Identifier__ 33 | from ...nuc.alias import ALIAS 34 | 35 | name = __Identifier__(self.nme) 36 | statement = ALIAS() 37 | statement.alias = __Identifier__(self.als) 38 | statement.name = name 39 | statement.value = self.val 40 | return statement 41 | -------------------------------------------------------------------------------- /src/nucleoid/Instruction.py: -------------------------------------------------------------------------------- 1 | """ 2 | Instruction class for statement execution. 3 | """ 4 | from typing import Any, Optional, Callable 5 | 6 | 7 | class Instruction: 8 | """Represents an execution instruction.""" 9 | 10 | def __init__( 11 | self, 12 | scope: Any, 13 | statement: Any, 14 | before: Optional[Callable[[], None]], 15 | run: Optional[Callable[[], None]], 16 | graph: Optional[Callable[[], None]], 17 | after: Optional[Callable[[], None]], 18 | derivative: bool = True, 19 | priority: bool = False 20 | ) -> None: 21 | """ 22 | Initialize an Instruction. 23 | 24 | Args: 25 | scope: Execution scope 26 | statement: Statement to execute 27 | before: Before hook 28 | run: Run hook 29 | graph: Graph hook 30 | after: After hook 31 | derivative: Whether this is a derivative instruction 32 | priority: Whether this instruction has priority 33 | """ 34 | self.scope: Any = scope 35 | self.statement: Any = statement 36 | self.before: Optional[Callable[[], None]] = before 37 | self.run: Optional[Callable[[], None]] = run 38 | self.graph: Optional[Callable[[], None]] = graph 39 | self.after: Optional[Callable[[], None]] = after 40 | self.derivative: bool = derivative 41 | self.priority: bool = priority 42 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__CLASS__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(name: Any, methods: list["__FUNCTION__"] = None) -> "__CLASS__": 6 | """Build a __CLASS__ statement.""" 7 | if methods is None: 8 | methods = [] 9 | statement = __CLASS__() 10 | statement.nme = name 11 | statement.mths = methods 12 | return statement 13 | 14 | 15 | class __CLASS__(__NUC__): 16 | """Represents a class declaration statement.""" 17 | 18 | def __init__(self) -> None: 19 | super().__init__() 20 | self.nme: Any = None 21 | self.mths: list[Any] = [] 22 | 23 | def run(self, scope: Any = None) -> Any: 24 | """Execute the class declaration.""" 25 | from ..ast.__identifier__ import __Identifier__ 26 | from ...nuc.class_ import CLASS 27 | 28 | name = __Identifier__(self.nme) 29 | statement = CLASS(f"${name}") 30 | statement.name = __Identifier__(f"${name}") 31 | statement.list = name 32 | 33 | methods = {} 34 | for method in self.mths: 35 | identifier = method.nme 36 | if hasattr(identifier, "name") and identifier.name == "constructor": 37 | identifier.name = "$constructor" 38 | method_name = identifier.name if hasattr(identifier, "name") else str(identifier) 39 | methods[method_name] = method 40 | 41 | statement.methods = methods 42 | return statement 43 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Template__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Template literal AST node. 3 | """ 4 | from typing import Any, Optional, Union, Dict 5 | import copy 6 | from .__Node__ import __Node__ 7 | 8 | 9 | class __Template__(__Node__): 10 | """Template literal node.""" 11 | 12 | def resolve(self, scope: Any) -> Dict[str, Any]: 13 | """ 14 | Resolve template expressions in the given scope. 15 | 16 | Args: 17 | scope: The scope to resolve in 18 | 19 | Returns: 20 | Resolved template node 21 | """ 22 | if scope: 23 | # Lazy import to avoid circular dependencies 24 | from .__Identifier__ import __Identifier__ 25 | 26 | clone = copy.deepcopy(self.node) 27 | expressions = clone.get("expressions", []) 28 | 29 | clone["expressions"] = [ 30 | __Identifier__(expression).resolve(scope) 31 | for expression in expressions 32 | ] 33 | 34 | return clone 35 | else: 36 | return self.node 37 | 38 | 39 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __Template__: 40 | """ 41 | Builder function for creating template instances. 42 | 43 | Args: 44 | node: The template node 45 | 46 | Returns: 47 | A __Template__ instance 48 | """ 49 | return __Template__(node) 50 | 51 | 52 | __template__ = build 53 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/VARIABLE.py: -------------------------------------------------------------------------------- 1 | """ 2 | VARIABLE runtime node class. 3 | """ 4 | from typing import Any, Dict 5 | from .NODE import NODE 6 | 7 | 8 | class VARIABLE(NODE): 9 | """Variable assignment node.""" 10 | 11 | def __init__(self, value: NODE) -> None: 12 | """ 13 | Initialize a VARIABLE instance. 14 | 15 | Args: 16 | value: The value node 17 | """ 18 | super().__init__() 19 | self._value: NODE = value 20 | self.name: Any = None # Set by subclasses 21 | 22 | def before(self, scope: Any) -> None: 23 | """ 24 | Execute before the main run. 25 | 26 | Args: 27 | scope: The execution scope 28 | """ 29 | self._value.before(scope) 30 | 31 | def run(self, scope: Any) -> Dict[str, Any]: 32 | """ 33 | Execute variable assignment. 34 | 35 | Args: 36 | scope: The execution scope 37 | 38 | Returns: 39 | Dictionary with the assigned value 40 | """ 41 | from ..state import state_instance 42 | 43 | evaluation = self._value.run(scope) 44 | value = state_instance.assign(scope, self.name, evaluation) 45 | 46 | return {"value": value} 47 | 48 | def graph(self, scope: Any) -> Any: 49 | """ 50 | Build dependency graph. 51 | 52 | Args: 53 | scope: The execution scope 54 | 55 | Returns: 56 | Graph result from value node 57 | """ 58 | return self._value.graph(scope) 59 | -------------------------------------------------------------------------------- /tests/lib/test_random.py: -------------------------------------------------------------------------------- 1 | """Tests for random string generation utilities""" 2 | 3 | import pytest 4 | from nucleoid.lib.random import random 5 | 6 | 7 | class TestRandomLib: 8 | """Test suite for random lib""" 9 | 10 | def test_returns_random_string_with_default_length(self): 11 | """Test that random() returns a string with default length of 16""" 12 | result = random() 13 | assert len(result) == 16 14 | 15 | def test_returns_random_string_with_given_length(self): 16 | """Test that random() returns a string with the specified length""" 17 | result = random(32) 18 | assert len(result) == 32 19 | 20 | def test_random_string_starts_with_letter(self): 21 | """Test that random string always starts with a letter""" 22 | result = random() 23 | assert result[0].isalpha() 24 | 25 | def test_alpha_only_contains_letters(self): 26 | """Test that alphanumeric=False produces only letters""" 27 | result = random(100, alphanumeric=False) 28 | assert result.isalpha() 29 | 30 | def test_alphanumeric_can_contain_digits(self): 31 | """Test that alphanumeric=True allows digits (though not guaranteed)""" 32 | # Generate multiple strings to increase chance of getting digits 33 | # This test just verifies the function runs with alphanumeric=True 34 | for _ in range(10): 35 | result = random(50, alphanumeric=True) 36 | assert len(result) == 50 37 | assert result[0].isalpha() # First char is always alpha 38 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Array__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Array AST node. 3 | """ 4 | from typing import Any, List, Optional, Union, Dict 5 | from .__Node__ import __Node__ 6 | 7 | 8 | class __Array__(__Node__): 9 | """Array expression node.""" 10 | 11 | def __init__(self, elements: Union[List["__Node__"], Dict[str, Any], str, None]) -> None: 12 | """ 13 | Initialize an array node. 14 | 15 | Args: 16 | elements: List of element nodes or an AST node 17 | """ 18 | if isinstance(elements, list): 19 | super().__init__(None) 20 | self.elements = elements 21 | else: 22 | super().__init__(elements) 23 | self.elements = elements if isinstance(elements, list) else [] 24 | 25 | def generate(self, scope: Any) -> str: 26 | """ 27 | Generate array literal code. 28 | 29 | Args: 30 | scope: The scope to generate in 31 | 32 | Returns: 33 | Generated array literal string 34 | """ 35 | element_strs = [el.generate(scope) for el in self.elements] 36 | return f"[{','.join(element_strs)}]" 37 | 38 | 39 | def build(elements: Union[List["__Node__"], Dict[str, Any], str, None] = None) -> __Array__: 40 | """ 41 | Builder function for creating array instances. 42 | 43 | Args: 44 | elements: The array elements 45 | 46 | Returns: 47 | An __Array__ instance 48 | """ 49 | return __Array__(elements) 50 | 51 | 52 | __array__ = build 53 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/EXPRESSION_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | EXPRESSION_INSTANCE runtime node class. 3 | """ 4 | from typing import Any 5 | from .EXPRESSION import EXPRESSION 6 | 7 | 8 | class EXPRESSION_INSTANCE(EXPRESSION): 9 | """Expression instance for class-based execution.""" 10 | 11 | def before(self, scope: Any) -> None: 12 | """ 13 | Execute before the main run. 14 | 15 | Args: 16 | scope: The execution scope 17 | """ 18 | dollar_instance = getattr(scope, 'dollar_instance', None) 19 | 20 | if dollar_instance: 21 | def process_node(node: Any) -> None: 22 | identifiers = [] 23 | walk_result = node.walk() 24 | # Flatten the result 25 | if isinstance(walk_result, list): 26 | for item in walk_result: 27 | if isinstance(item, list): 28 | identifiers.extend(item) 29 | else: 30 | identifiers.append(item) 31 | else: 32 | identifiers.append(walk_result) 33 | 34 | for identifier in identifiers: 35 | if (hasattr(identifier, 'first') and 36 | str(identifier.first) == str(dollar_instance.class_ref.name)): 37 | identifier.first = dollar_instance.resolve() 38 | 39 | if hasattr(self.tokens, 'traverse'): 40 | self.tokens.traverse(process_node) 41 | 42 | super().before(scope) 43 | -------------------------------------------------------------------------------- /tests/lib/test_test.py: -------------------------------------------------------------------------------- 1 | """Tests for test utility module""" 2 | 3 | import pytest 4 | 5 | from nucleoid import datastore, state, graph 6 | from nucleoid.lib.test import clear 7 | 8 | 9 | class TestTestUtil: 10 | """Test suite for test utility""" 11 | 12 | def test_clear_resets_all_modules(self): 13 | """Test that clear() resets state, graph, and datastore""" 14 | # Set some values in each module 15 | state.set("key1", "value1") 16 | graph.add_node("node1", {"data": "test"}) 17 | datastore.set("key2", "value2") 18 | 19 | # Verify values are set 20 | assert state.get("key1") == "value1" 21 | assert datastore.get("key2") == "value2" 22 | 23 | # Clear everything 24 | clear() 25 | 26 | # Verify everything is cleared 27 | assert state.get("key1") is None 28 | assert datastore.get("key2") is None 29 | 30 | def test_clear_is_idempotent(self): 31 | """Test that calling clear() multiple times is safe""" 32 | state.set("key", "value") 33 | 34 | # Clear multiple times 35 | clear() 36 | clear() 37 | clear() 38 | 39 | # Should not raise any errors and state should still be clear 40 | assert state.get("key") is None 41 | 42 | def test_clear_with_empty_modules(self): 43 | """Test that clear() works when modules are already empty""" 44 | # Ensure modules are empty 45 | clear() 46 | 47 | # Clear again - should not raise errors 48 | clear() 49 | 50 | # Verify still empty 51 | assert state.get("anything") is None 52 | assert datastore.get("anything") is None 53 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/LET_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | LET_INSTANCE runtime node class. 3 | """ 4 | from typing import Any 5 | from .LET import LET 6 | 7 | 8 | class LET_INSTANCE(LET): 9 | """Let instance for class-based variable declarations.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize a LET_INSTANCE.""" 13 | super().__init__() 14 | self.class_ref: Any = None 15 | self.instance: Any = None 16 | 17 | def before(self, scope: Any) -> None: 18 | """ 19 | Execute before the main run. 20 | 21 | Args: 22 | scope: The execution scope 23 | """ 24 | # Process value tokens to replace class name with instance 25 | def process_node(node: Any) -> None: 26 | identifiers = [] 27 | walk_result = node.walk() 28 | 29 | # Flatten walk result 30 | if isinstance(walk_result, list): 31 | for item in walk_result: 32 | if isinstance(item, list): 33 | identifiers.extend(item) 34 | else: 35 | identifiers.append(item) 36 | else: 37 | identifiers.append(walk_result) 38 | 39 | for identifier in identifiers: 40 | if (hasattr(identifier, 'first') and 41 | hasattr(self, 'class_ref') and 42 | hasattr(self.class_ref, 'name')): 43 | if str(identifier.first) == str(self.class_ref.name): 44 | identifier.first = self.instance.resolve() 45 | 46 | if hasattr(self.value, 'tokens') and hasattr(self.value.tokens, 'traverse'): 47 | self.value.tokens.traverse(process_node) 48 | 49 | super().before(scope) 50 | -------------------------------------------------------------------------------- /src/nucleoid/graph.py: -------------------------------------------------------------------------------- 1 | """ 2 | Graph module for managing dependency graphs. 3 | """ 4 | from typing import Any, Dict, Optional, Union 5 | 6 | 7 | class Graph: 8 | """Manages dependency graph for Nucleoid.""" 9 | 10 | def __init__(self) -> None: 11 | """Initialize graph with classes node.""" 12 | self.dollar: Dict[str, Any] = { 13 | 'classes': { 14 | 'name': 'classes' 15 | } 16 | } 17 | 18 | def retrieve(self, identifier: Union[str, Any]) -> Optional[Any]: 19 | """ 20 | Retrieve a node from the graph. 21 | 22 | Args: 23 | identifier: String identifier or object with generate() method 24 | 25 | Returns: 26 | Node value or None 27 | """ 28 | if isinstance(identifier, str): 29 | return self.dollar.get(identifier) 30 | else: 31 | # Object with generate() method 32 | if hasattr(identifier, 'generate'): 33 | key = identifier.generate() 34 | return self.dollar.get(key) 35 | return None 36 | 37 | def clear(self) -> None: 38 | """Clear the dependency graph.""" 39 | self.dollar.clear() 40 | self.dollar['classes'] = {'name': 'classes'} 41 | 42 | 43 | # Create singleton instance 44 | graph_instance = Graph() 45 | 46 | 47 | def retrieve(identifier: Union[str, Any]) -> Optional[Any]: 48 | """ 49 | Retrieve a node from the graph. 50 | 51 | Args: 52 | identifier: String identifier or object with generate() method 53 | 54 | Returns: 55 | Node value or None 56 | """ 57 | return graph_instance.retrieve(identifier) 58 | 59 | 60 | def clear() -> None: 61 | """Clear the graph.""" 62 | graph_instance.clear() 63 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks to declarative programming, we have a brand-new approach to data and logic. As we are still discovering what we can do with this powerful programming model, please join us with any types of contribution! 4 | 5 | ## Declarative Runtime Environment 6 | 7 | Nucleoid is a declarative runtime environment that applies declarative programming at the runtime as rerendering JavaScript statements and creating the graph, so as a result, the declarative runtime system isolates a behavior definition of a program from its technical instructions and executes declarative statements, which represent logical intention without carrying any technical detail. 8 | 9 | Learn more at [nucleoid.com/docs/runtime](https://nucleoid.com/docs/runtime/) 10 | 11 | ## Join our [Thinkers Club](https://github.com/NucleoidJS/Nucleoid/discussions/categories/thinkers-club) 12 | 13 | If you have an opinion, you are already a philosopher. We are working on brand-new approach to data and logic. Come join us in [discussions](https://github.com/NucleoidJS/Nucleoid/discussions/categories/thinkers-club). 14 | 15 | [![Nobel](https://cdn.nucleoid.com/media/nobel.png)](https://github.com/NucleoidJS/Nucleoid/discussions/categories/thinkers-club) 16 | 17 | ### Pinned Discussions 18 | 19 | [![Discussion 25](https://cdn.nucleoid.com/media/discussion-25x500.png)](https://github.com/NucleoidJS/Nucleoid/discussions/25) 20 | [![Discussion 26](https://cdn.nucleoid.com/media/discussion-26x500.png)](https://github.com/NucleoidJS/Nucleoid/discussions/26) 21 | [![Discussion 28](https://cdn.nucleoid.com/media/discussion-28x500.png)](https://github.com/NucleoidJS/Nucleoid/discussions/28) 22 | 23 | ## Code of Conduct 24 | 25 | Please read our [Code of Conduct](https://github.com/NucleoidJS/Nucleoid/blob/main/CODE_OF_CONDUCT.md) 26 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Object__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Object expression AST node. 3 | """ 4 | from typing import Any, Optional, Union, Dict 5 | import copy 6 | from .__Node__ import __Node__ 7 | 8 | 9 | class __Object__(__Node__): 10 | """Object expression node.""" 11 | 12 | def resolve(self, scope: Any) -> Dict[str, Any]: 13 | """ 14 | Resolve object properties in the given scope. 15 | 16 | Args: 17 | scope: The scope to resolve in 18 | 19 | Returns: 20 | Resolved object node 21 | """ 22 | if scope: 23 | # Lazy import to avoid circular dependencies 24 | from .__Identifier__ import __Identifier__ 25 | 26 | cloned = copy.deepcopy(self.node) 27 | 28 | # Walk through properties and resolve identifiers 29 | properties = cloned.get("properties", []) 30 | for prop in properties: 31 | if prop.get("type") == "Property": 32 | value = prop.get("value", {}) 33 | value_type = value.get("type", "") 34 | 35 | # Check if value is an identifier type 36 | if value_type in __Identifier__.types: 37 | identifier = __Identifier__(value) 38 | prop["value"] = identifier.resolve(scope) 39 | 40 | return cloned 41 | else: 42 | return self.node 43 | 44 | 45 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __Object__: 46 | """ 47 | Builder function for creating object instances. 48 | 49 | Args: 50 | node: The object node 51 | 52 | Returns: 53 | An __Object__ instance 54 | """ 55 | return __Object__(node) 56 | 57 | 58 | __object__ = build 59 | -------------------------------------------------------------------------------- /src/nucleoid/event.py: -------------------------------------------------------------------------------- 1 | """ 2 | Event module for tracking runtime events. 3 | """ 4 | import json 5 | from typing import Any, Dict, List, Optional, Union 6 | 7 | 8 | EventData = Dict[str, Union[str, int, bool, None]] 9 | 10 | 11 | class Event: 12 | """Event tracker for runtime events.""" 13 | 14 | def __init__(self) -> None: 15 | """Initialize event tracker.""" 16 | self.events: List[Dict[str, str]] = [] 17 | 18 | def event(self, name: str, data: EventData) -> None: 19 | """ 20 | Record an event. 21 | 22 | Args: 23 | name: Event name 24 | data: Event data 25 | """ 26 | self.events.append({ 27 | 'name': name, 28 | 'data': json.dumps(data) 29 | }) 30 | 31 | def list(self) -> Optional[List[Dict[str, str]]]: 32 | """ 33 | Get list of events. 34 | 35 | Returns: 36 | List of events or None if empty 37 | """ 38 | if self.events: 39 | return self.events 40 | return None 41 | 42 | def clear(self) -> None: 43 | """Clear all events.""" 44 | self.events = [] 45 | 46 | 47 | # Create singleton instance 48 | event_instance = Event() 49 | 50 | 51 | def event(name: str, data: EventData) -> None: 52 | """ 53 | Record an event to the singleton instance. 54 | 55 | Args: 56 | name: Event name 57 | data: Event data 58 | """ 59 | event_instance.event(name, data) 60 | 61 | 62 | def list() -> Optional[List[Dict[str, str]]]: 63 | """ 64 | Get list of events from the singleton instance. 65 | 66 | Returns: 67 | List of events or None if empty 68 | """ 69 | return event_instance.list() 70 | 71 | 72 | def clear() -> None: 73 | """Clear all events from the singleton instance.""" 74 | event_instance.clear() 75 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | __nuc__ module - Core statement types for Nucleoid language processing. 3 | """ 4 | 5 | from .__NUC__ import __NUC__ 6 | from .__ALIAS__ import __ALIAS__, build as __alias__ 7 | from .__ASSIGNMENT__ import __ASSIGNMENT__, build as __assignment__ 8 | from .__BLOCK__ import __BLOCK__, build as __block__ 9 | from .__CALL__ import __CALL__, build as __call__ 10 | from .__CLASS__ import __CLASS__, build as __class__ 11 | from .__DELETE__ import __DELETE__, build as __delete__ 12 | from .__EXPRESSION__ import __EXPRESSION__, build as __expression__ 13 | from .__FOR__ import __FOR__, build as __for__ 14 | from .__FUNCTION__ import __FUNCTION__, build as __function__ 15 | from .__IF__ import __IF__, build as __if__ 16 | from .__INSTANCE__ import __INSTANCE__, build as __instance__ 17 | from .__LET__ import __LET__, build as __let__ 18 | from .__PROPERTY__ import __PROPERTY__, build as __property__ 19 | from .__RETURN__ import __RETURN__, build as __return__ 20 | from .__THROW__ import __THROW__, build as __throw__ 21 | from .__VARIABLE__ import __VARIABLE__, build as __variable__ 22 | from .revive import revive 23 | 24 | __all__ = [ 25 | "__NUC__", 26 | "__ALIAS__", 27 | "__ASSIGNMENT__", 28 | "__BLOCK__", 29 | "__CALL__", 30 | "__CLASS__", 31 | "__DELETE__", 32 | "__EXPRESSION__", 33 | "__FOR__", 34 | "__FUNCTION__", 35 | "__IF__", 36 | "__INSTANCE__", 37 | "__LET__", 38 | "__PROPERTY__", 39 | "__RETURN__", 40 | "__THROW__", 41 | "__VARIABLE__", 42 | "__alias__", 43 | "__assignment__", 44 | "__block__", 45 | "__call__", 46 | "__class__", 47 | "__delete__", 48 | "__expression__", 49 | "__for__", 50 | "__function__", 51 | "__if__", 52 | "__instance__", 53 | "__let__", 54 | "__property__", 55 | "__return__", 56 | "__throw__", 57 | "__variable__", 58 | "revive", 59 | ] 60 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | nuc module - Runtime node types for Nucleoid execution. 3 | """ 4 | 5 | from .NODE import NODE 6 | from .ALIAS import ALIAS 7 | from .BLOCK import BLOCK 8 | from .BLOCK_CLASS import BLOCK_CLASS 9 | from .BLOCK_INSTANCE import BLOCK_INSTANCE 10 | from .BREAK import BREAK 11 | from .CLASS import CLASS 12 | from .DELETE import DELETE 13 | from .DELETE_OBJECT import DELETE_OBJECT 14 | from .DELETE_VARIABLE import DELETE_VARIABLE 15 | from .EXPRESSION import EXPRESSION 16 | from .EXPRESSION_INSTANCE import EXPRESSION_INSTANCE 17 | from .FOR import FOR 18 | from .FUNCTION import FUNCTION 19 | from .IF import IF 20 | from .IF_CLASS import IF_CLASS 21 | from .IF_INSTANCE import IF_INSTANCE 22 | from .LET import LET 23 | from .LET_CLASS import LET_CLASS 24 | from .LET_INSTANCE import LET_INSTANCE 25 | from .LET_OBJECT import LET_OBJECT 26 | from .OBJECT import OBJECT 27 | from .OBJECT_CLASS import OBJECT_CLASS 28 | from .OBJECT_INSTANCE import OBJECT_INSTANCE 29 | from .PROPERTY import PROPERTY 30 | from .PROPERTY_CLASS import PROPERTY_CLASS 31 | from .PROPERTY_INSTANCE import PROPERTY_INSTANCE 32 | from .REFERENCE import REFERENCE 33 | from .RETURN import RETURN 34 | from .THROW import THROW 35 | from .VARIABLE import VARIABLE 36 | 37 | __all__ = [ 38 | "NODE", 39 | "ALIAS", 40 | "BLOCK", 41 | "BLOCK_CLASS", 42 | "BLOCK_INSTANCE", 43 | "BREAK", 44 | "CLASS", 45 | "DELETE", 46 | "DELETE_OBJECT", 47 | "DELETE_VARIABLE", 48 | "EXPRESSION", 49 | "EXPRESSION_INSTANCE", 50 | "FOR", 51 | "FUNCTION", 52 | "IF", 53 | "IF_CLASS", 54 | "IF_INSTANCE", 55 | "LET", 56 | "LET_CLASS", 57 | "LET_INSTANCE", 58 | "LET_OBJECT", 59 | "OBJECT", 60 | "OBJECT_CLASS", 61 | "OBJECT_INSTANCE", 62 | "PROPERTY", 63 | "PROPERTY_CLASS", 64 | "PROPERTY_INSTANCE", 65 | "REFERENCE", 66 | "RETURN", 67 | "THROW", 68 | "VARIABLE", 69 | ] 70 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/IF_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | IF_INSTANCE runtime node class. 3 | """ 4 | from typing import Any 5 | from .IF import IF 6 | 7 | 8 | class IF_INSTANCE(IF): 9 | """If instance for class-based conditional execution.""" 10 | 11 | def before(self, scope: Any) -> None: 12 | """ 13 | Execute before the main run. 14 | 15 | Args: 16 | scope: The execution scope 17 | 18 | Raises: 19 | ValueError: If instance is missing in scope 20 | """ 21 | dollar_instance = getattr(scope, 'dollar_instance', None) 22 | 23 | if not dollar_instance: 24 | raise ValueError("Declaration missing instance in scope") 25 | 26 | # Process condition tokens to replace class name with instance 27 | def process_node(node: Any) -> None: 28 | identifiers = [] 29 | walk_result = node.walk() 30 | 31 | # Flatten walk result 32 | if isinstance(walk_result, list): 33 | for item in walk_result: 34 | if isinstance(item, list): 35 | identifiers.extend(item) 36 | else: 37 | identifiers.append(item) 38 | else: 39 | identifiers.append(walk_result) 40 | 41 | for identifier in identifiers: 42 | if (hasattr(dollar_instance, 'class_ref') and 43 | hasattr(dollar_instance.class_ref, 'name') and 44 | hasattr(identifier, 'first')): 45 | if str(dollar_instance.class_ref.name) == str(identifier.first): 46 | identifier.first = dollar_instance.resolve() 47 | 48 | if hasattr(self.condition, 'tokens') and hasattr(self.condition.tokens, 'traverse'): 49 | self.condition.tokens.traverse(process_node) 50 | 51 | self.key = f"if({self.condition.tokens})" 52 | 53 | super().before(scope) 54 | -------------------------------------------------------------------------------- /src/nucleoid/routes/graph.py: -------------------------------------------------------------------------------- 1 | """ 2 | Graph route - provides graph visualization and inspection endpoints. 3 | """ 4 | from flask import Blueprint, jsonify, request 5 | from typing import Dict, Any, List 6 | 7 | 8 | graph_bp = Blueprint('graph', __name__) 9 | 10 | 11 | @graph_bp.route('/', methods=['GET']) 12 | def get_graph() -> Any: 13 | """ 14 | Get the current graph state. 15 | 16 | Returns: 17 | JSON response with graph nodes and their relationships 18 | """ 19 | from ..lib.graph import graph as graph_instance 20 | 21 | result: Dict[str, Any] = {} 22 | 23 | for key in graph_instance: 24 | node = graph_instance[key] 25 | 26 | if hasattr(node, 'key') and node.key: 27 | tmp: Dict[str, Any] = { 28 | 'id': node.key, 29 | 'type': node.__class__.__name__, 30 | } 31 | 32 | # Process node properties 33 | for prop in dir(node): 34 | if prop.startswith('_'): 35 | continue 36 | 37 | try: 38 | obj = getattr(node, prop) 39 | 40 | # Handle single object with key 41 | if hasattr(obj, 'key') and obj.key: 42 | tmp[prop] = obj.key 43 | 44 | # Handle dict of objects 45 | elif isinstance(obj, dict) and obj: 46 | obj_list: List[str] = [] 47 | 48 | for inner_prop in obj: 49 | inner_object = obj[inner_prop] 50 | 51 | if hasattr(inner_object, 'key') and inner_object.key: 52 | obj_list.append(inner_object.key) 53 | 54 | if obj_list: 55 | tmp[prop] = obj_list 56 | 57 | except (AttributeError, TypeError): 58 | # Skip properties that can't be accessed 59 | continue 60 | 61 | result[key] = tmp 62 | 63 | return jsonify(result) 64 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/FOR.py: -------------------------------------------------------------------------------- 1 | """ 2 | FOR runtime node class. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | import copy 6 | 7 | 8 | class FOR: 9 | """For loop statement node.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize a FOR instance.""" 13 | self.index: int = 0 14 | self.array: str = "" 15 | self.variable: Any = None 16 | self.statements: List[Any] = [] 17 | 18 | def run(self, scope: Any) -> Optional[Dict[str, List[Any]]]: 19 | """ 20 | Execute for loop. 21 | 22 | Args: 23 | scope: The execution scope 24 | 25 | Returns: 26 | Dictionary with next instructions or None 27 | 28 | Raises: 29 | TypeError: If array is not iterable 30 | """ 31 | from ..lang.Evaluation import Evaluation 32 | from ..state import state_instance 33 | from .. import graph 34 | from ..Instruction import Instruction 35 | from ...__nuc__ import __LET__, __BLOCK__ 36 | 37 | # Get the array to iterate over 38 | array = state_instance.expression(scope, Evaluation(f"state.{self.array}")) 39 | 40 | if not isinstance(array, list): 41 | raise TypeError(f"{self.array} is not iterable") 42 | 43 | if self.index < len(array): 44 | result_list: List[Any] = [] 45 | item = array[self.index] 46 | key = item.get('id') if isinstance(item, dict) else None 47 | 48 | if key is not None and key in graph.graph_instance: 49 | obj_id = array[self.index].get('id') 50 | self.index += 1 51 | 52 | statements = [__LET__(self.variable.node, obj_id)] 53 | result_list.append( 54 | __BLOCK__(statements + copy.deepcopy(self.statements), True) 55 | ) 56 | else: 57 | self.index += 1 58 | 59 | result_list.append(Instruction(scope, self, False, True, False, False)) 60 | return {"next": result_list} 61 | 62 | return None 63 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__DELETE__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(key: Any) -> "__DELETE__": 6 | """Build a __DELETE__ statement.""" 7 | statement = __DELETE__() 8 | statement.key = key 9 | return statement 10 | 11 | 12 | class __DELETE__(__NUC__): 13 | """Represents a delete statement.""" 14 | 15 | def __init__(self) -> None: 16 | super().__init__() 17 | self.key: Any = None 18 | 19 | def run(self, scope: Any) -> Any: 20 | """Execute the delete statement.""" 21 | from ..ast.__identifier__ import __Identifier__ 22 | from ...graph import graph 23 | from ...nuc.variable import VARIABLE 24 | from ...nuc.delete_variable import DELETE_VARIABLE 25 | from ...nuc.delete_object import DELETE_OBJECT 26 | from ...nuc.object import OBJECT 27 | from ...nuc.delete import DELETE 28 | from .__EXPRESSION__ import __expression__ 29 | from ...state import state 30 | 31 | identifier = __Identifier__(self.key) 32 | variable = graph.retrieve(identifier) 33 | 34 | if not variable: 35 | try: 36 | expression = __expression__(self.key) 37 | expr_result = expression.run(scope) 38 | item = expr_result.run(scope) 39 | result = state.expression(scope, {"value": item}) 40 | id_value = result.get("id") if isinstance(result, dict) else getattr(result, "id", None) 41 | variable = graph.retrieve(id_value) 42 | except Exception: 43 | pass 44 | 45 | if isinstance(variable, VARIABLE): 46 | statement = DELETE_VARIABLE() 47 | statement.variable = variable 48 | return statement 49 | elif isinstance(variable, OBJECT): 50 | statement = DELETE_OBJECT() 51 | statement.variable = variable 52 | return statement 53 | else: 54 | statement = DELETE() 55 | statement.variable = variable 56 | return statement 57 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__CALL__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional, Union 2 | import copy 3 | from .__NUC__ import __NUC__ 4 | 5 | 6 | def build(func: Any, args: list[Any]) -> "__CALL__": 7 | """Build a __CALL__ statement.""" 8 | call = __CALL__() 9 | call.func = func 10 | call.args = args 11 | return call 12 | 13 | 14 | class __CALL__(__NUC__): 15 | """Represents a function call statement.""" 16 | 17 | def __init__(self) -> None: 18 | super().__init__() 19 | self.func: Any = None 20 | self.args: list[Any] = [] 21 | self.result: Any = None 22 | 23 | def run(self, scope: Any) -> Optional[Union[__NUC__, "NODE", list["NODE"]]]: 24 | """Execute the function call.""" 25 | from .__FUNCTION__ import __FUNCTION__ 26 | from ..ast.__identifier__ import __Identifier__ 27 | from ...graph import retrieve 28 | from .__LET__ import __let__ 29 | from .__BLOCK__ import __block__ 30 | 31 | block = None 32 | args = None 33 | 34 | if self.func.__class__.__name__ == "__FUNCTION__": 35 | func = self.func 36 | block = func.blk 37 | args = func.args 38 | else: 39 | name = __Identifier__(self.func) 40 | func = retrieve(name) 41 | block = func.block if hasattr(func, "block") else None 42 | args = func.arguments if hasattr(func, "arguments") else None 43 | 44 | if block and args: 45 | values = self.args 46 | statements = copy.deepcopy(block.stms) 47 | 48 | for i in range(len(args) - 1, -1, -1): 49 | value = values[i] if i < len(values) else { 50 | "type": "Literal", 51 | "value": None, 52 | "raw": "null", 53 | } 54 | statements.insert(0, __let__(args[i], value)) 55 | 56 | block_instance = __block__(statements) 57 | self.result = block_instance.run(scope) 58 | return self 59 | else: 60 | raise TypeError("This is not a function") 61 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/DELETE_OBJECT.py: -------------------------------------------------------------------------------- 1 | """ 2 | DELETE_OBJECT runtime node class. 3 | """ 4 | from typing import Any, Dict, List 5 | from .DELETE import DELETE 6 | 7 | 8 | class DELETE_OBJECT(DELETE): 9 | """Delete object statement node.""" 10 | 11 | def run(self, scope: Any) -> Dict[str, Any]: 12 | """ 13 | Execute object delete operation. 14 | 15 | Args: 16 | scope: The execution scope 17 | 18 | Returns: 19 | Dictionary with next instructions and value 20 | 21 | Raises: 22 | ReferenceError: If object has properties and cannot be deleted 23 | """ 24 | from .. import graph, state 25 | 26 | node = graph.retrieve(self.variable.key) 27 | name = node.name 28 | 29 | # Check if object has properties 30 | if hasattr(node, 'properties') and len(node.properties) > 0: 31 | raise ReferenceError(f"Cannot delete object '{self.variable.key}'") 32 | 33 | if hasattr(node, 'object') and node.object: 34 | del node.object.properties[name] 35 | else: 36 | # Delete from class list 37 | list_name = str(node.class_ref.list) 38 | state.state_instance.delete(scope, f"{list_name}.{name}") 39 | 40 | # Find and remove from state list 41 | index = None 42 | for i, obj in enumerate(state.state_instance.dollar[list_name]): 43 | if obj.get('id') == node.key: 44 | index = i 45 | break 46 | 47 | if index is not None: 48 | state.state_instance.dollar[list_name].pop(index) 49 | 50 | return super().run(scope) 51 | 52 | def graph(self) -> None: 53 | """Build dependency graph.""" 54 | from .. import graph 55 | 56 | node = graph.retrieve(self.variable.key) 57 | 58 | # Remove previous connections 59 | for key in list(node.previous.keys()): 60 | if key in node.next: 61 | del node.next[key] 62 | 63 | # Delete from graph 64 | del graph.graph_instance[node.key] 65 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/OBJECT_CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | OBJECT_CLASS runtime node class. 3 | """ 4 | from typing import Any, Dict, List 5 | from .NODE import NODE 6 | 7 | 8 | class OBJECT_CLASS(NODE): 9 | """Object class for class-based object creation.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize an OBJECT_CLASS instance.""" 13 | super().__init__() 14 | self.class_ref: Any = None 15 | self.name: str = "" 16 | self.type: str = "CLASS" 17 | 18 | def run(self, scope: Any) -> Dict[str, List[NODE]]: 19 | """ 20 | Execute object class. 21 | 22 | Args: 23 | scope: The execution scope 24 | 25 | Returns: 26 | Dictionary with next instructions 27 | """ 28 | from .OBJECT_INSTANCE import OBJECT_INSTANCE 29 | from ..Scope import Scope 30 | from ..Instruction import Instruction 31 | from .. import graph 32 | 33 | # Get instances to process 34 | current = getattr(scope, 'dollar_instance', None) 35 | all_instances = [current] if current else list(self.class_ref.instances.values()) 36 | 37 | statements: List[NODE] = [] 38 | 39 | for inst in all_instances: 40 | inst_name = getattr(inst, 'name', '') 41 | obj_id = f"{inst_name}.{self.name}" 42 | 43 | statement = OBJECT_INSTANCE(obj_id) 44 | statement.class_ref = self.class_ref 45 | statement.object = graph.retrieve(inst_name) 46 | statement.name = self.name 47 | 48 | instance_scope = Scope(scope, statement) 49 | instance_scope.dollar_instance = inst 50 | 51 | instr = Instruction( 52 | instance_scope, 53 | statement, 54 | lambda: None, 55 | lambda: None, 56 | None, 57 | None 58 | ) 59 | 60 | statements.append(instr) 61 | 62 | return {"next": statements} 63 | 64 | def graph(self) -> None: 65 | """Build dependency graph.""" 66 | if self.class_ref: 67 | self.class_ref.declarations[self.key] = self 68 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/PROPERTY_CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | PROPERTY_CLASS runtime node class. 3 | """ 4 | from typing import Any, Dict, List 5 | import copy 6 | from .NODE import NODE 7 | 8 | 9 | class PROPERTY_CLASS(NODE): 10 | """Property class for class-based property assignments.""" 11 | 12 | def __init__(self) -> None: 13 | """Initialize a PROPERTY_CLASS instance.""" 14 | super().__init__() 15 | self.class_ref: Any = None 16 | self.name: str = "" 17 | self.value: Any = None 18 | self.type: str = "CLASS" 19 | 20 | def run(self, scope: Any) -> Dict[str, List[NODE]]: 21 | """ 22 | Execute property class. 23 | 24 | Args: 25 | scope: The execution scope 26 | 27 | Returns: 28 | Dictionary with next instructions 29 | """ 30 | from .PROPERTY_INSTANCE import PROPERTY_INSTANCE 31 | from ..Scope import Scope 32 | from ..Instruction import Instruction 33 | 34 | # Get instances to process 35 | instance = getattr(scope, 'dollar_instance', None) 36 | all_instances = [instance] if instance else list(self.class_ref.instances.values()) 37 | 38 | statements: List[NODE] = [] 39 | 40 | for inst in all_instances: 41 | inst_name = getattr(inst, 'name', '') 42 | prop_id = f"{inst_name}.{self.name}" 43 | 44 | statement = PROPERTY_INSTANCE(prop_id) 45 | statement.object = inst 46 | statement.name = self.name 47 | statement.value = copy.deepcopy(self.value) 48 | 49 | instance_scope = Scope(scope, statement) 50 | instance_scope.dollar_instance = inst 51 | 52 | instr = Instruction( 53 | instance_scope, 54 | statement, 55 | lambda: None, 56 | lambda: None, 57 | None, 58 | None 59 | ) 60 | 61 | statements.append(instr) 62 | 63 | return {"next": statements} 64 | 65 | def graph(self) -> None: 66 | """Build dependency graph.""" 67 | if self.class_ref: 68 | self.class_ref.declarations[self.key] = self 69 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__EXPRESSION__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Union 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(tokens: Union[str, Any, "__Expression__"]) -> "__EXPRESSION__": 6 | """Build a __EXPRESSION__ statement.""" 7 | from ..ast.__expression__ import __Expression__ 8 | from ..estree.parser import parse 9 | 10 | if not isinstance(tokens, __Expression__): 11 | if isinstance(tokens, str): 12 | string = tokens 13 | tokens = __Expression__(parse(string, False)) 14 | else: 15 | tokens = __Expression__(tokens) 16 | 17 | statement = __EXPRESSION__() 18 | statement.tkns = tokens 19 | return statement 20 | 21 | 22 | class __EXPRESSION__(__NUC__): 23 | """Represents an expression statement.""" 24 | 25 | def __init__(self) -> None: 26 | super().__init__() 27 | self.tkns: Any = None 28 | 29 | def run(self, scope: Any) -> Any: 30 | """Execute the expression statement.""" 31 | from ..ast.__identifier__ import __Identifier__ 32 | from ...nuc.expression import EXPRESSION 33 | from ...nuc.reference import REFERENCE 34 | from ...graph import graph 35 | from ...nuc.expression_instance import EXPRESSION_INSTANCE 36 | 37 | if hasattr(self.tkns, "node") and hasattr(self.tkns.node, "type"): 38 | node_type = self.tkns.node.type 39 | if node_type in __Identifier__.types: 40 | identifier = __Identifier__(self.tkns.node) 41 | if scope.retrieve(identifier): 42 | return EXPRESSION(self.tkns) 43 | link = graph.retrieve(identifier) 44 | if link: 45 | statement = REFERENCE(self.tkns) 46 | statement.link = identifier 47 | return statement 48 | else: 49 | return EXPRESSION(self.tkns) 50 | 51 | __instance = getattr(scope, "$instance", None) if hasattr(scope, "$instance") else None 52 | if __instance: 53 | return EXPRESSION_INSTANCE(self.tkns) 54 | else: 55 | return EXPRESSION(self.tkns) 56 | 57 | 58 | __expression__ = build 59 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/PROPERTY_INSTANCE.py: -------------------------------------------------------------------------------- 1 | """ 2 | PROPERTY_INSTANCE runtime node class. 3 | """ 4 | from typing import Any 5 | from .PROPERTY import PROPERTY 6 | 7 | 8 | class PROPERTY_INSTANCE(PROPERTY): 9 | """Property instance for class-based property assignments.""" 10 | 11 | def __init__(self, key: Any = None) -> None: 12 | """ 13 | Initialize a PROPERTY_INSTANCE. 14 | 15 | Args: 16 | key: The property instance key 17 | """ 18 | super().__init__() 19 | self.key = str(key) if key else "" 20 | 21 | def before(self, scope: Any) -> None: 22 | """ 23 | Execute before the main run. 24 | 25 | Args: 26 | scope: The execution scope 27 | 28 | Raises: 29 | ValueError: If instance is missing in scope 30 | """ 31 | dollar_instance = getattr(scope, 'dollar_instance', None) 32 | 33 | if not dollar_instance: 34 | raise ValueError("Declaration missing instance in scope") 35 | 36 | # Process value tokens to replace class name with instance 37 | if hasattr(self.value, 'tokens'): 38 | tokens = self.value.tokens 39 | 40 | def process_node(node: Any) -> None: 41 | identifiers = [] 42 | walk_result = node.walk() 43 | 44 | # Flatten walk result 45 | if isinstance(walk_result, list): 46 | for item in walk_result: 47 | if isinstance(item, list): 48 | identifiers.extend(item) 49 | else: 50 | identifiers.append(item) 51 | else: 52 | identifiers.append(walk_result) 53 | 54 | for identifier in identifiers: 55 | if (hasattr(dollar_instance, 'class_ref') and 56 | hasattr(dollar_instance.class_ref, 'name') and 57 | hasattr(identifier, 'first')): 58 | if str(dollar_instance.class_ref.name) == str(identifier.first): 59 | identifier.first = dollar_instance.resolve() 60 | 61 | tokens.traverse(process_node) 62 | 63 | super().before(scope) 64 | -------------------------------------------------------------------------------- /src/nucleoid/ast/convert.py: -------------------------------------------------------------------------------- 1 | """ 2 | AST conversion utilities. 3 | """ 4 | from typing import Union, Dict, Any 5 | from .__Node__ import __Node__ 6 | 7 | 8 | class AST: 9 | """AST conversion utility class.""" 10 | 11 | @staticmethod 12 | def convert(node: Union[Dict[str, Any], str]) -> __Node__: 13 | """ 14 | Convert a node to the appropriate AST class. 15 | 16 | Args: 17 | node: The node to convert 18 | 19 | Returns: 20 | An instance of the appropriate AST class 21 | """ 22 | # Lazy imports to avoid circular dependencies 23 | from .__Literal__ import __Literal__ 24 | from .__Identifier__ import __Identifier__ 25 | from .__Array__ import __Array__ 26 | from .__New__ import __New__ 27 | from .__Object__ import __Object__ 28 | from .__Function__ import __Function__ 29 | from .__Template__ import __Template__ 30 | from .__Operator__ import __Operator__ 31 | 32 | if isinstance(node, str): 33 | from ..lang.estree.parser import parse 34 | node = parse(node, False) 35 | 36 | node_type = node.get("type") 37 | 38 | if node_type == "Literal": 39 | return __Literal__(node) 40 | 41 | elif node_type in ["Identifier", "MemberExpression"]: 42 | return __Identifier__(node) 43 | 44 | elif node_type == "ArrayExpression": 45 | elements = node.get("elements", []) 46 | converted_elements = [AST.convert(el) for el in elements if el] 47 | return __Array__(converted_elements) 48 | 49 | elif node_type == "NewExpression": 50 | return __New__(node) 51 | 52 | elif node_type == "ObjectExpression": 53 | return __Object__(node) 54 | 55 | elif node_type in ["FunctionExpression", "ArrowFunctionExpression"]: 56 | return __Function__(node) 57 | 58 | # Uncomment when needed: 59 | # elif node_type == "CallExpression": 60 | # return __Call__(node) 61 | 62 | elif node_type == "TemplateLiteral": 63 | return __Template__(node) 64 | 65 | else: 66 | # Default to operator for binary/logical/unary expressions 67 | return __Operator__(node) 68 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/LET.py: -------------------------------------------------------------------------------- 1 | """ 2 | LET runtime node class. 3 | """ 4 | from typing import Any, Dict, Optional 5 | from .NODE import NODE 6 | 7 | 8 | class LET(NODE): 9 | """Let/const variable declaration node.""" 10 | 11 | def __init__(self, name: Any = None, value: Any = None) -> None: 12 | """ 13 | Initialize a LET instance. 14 | 15 | Args: 16 | name: Variable name 17 | value: Variable value 18 | """ 19 | super().__init__() 20 | self.name: Any = name 21 | self.value: Any = value 22 | self.reassign: bool = False 23 | 24 | def before(self) -> None: 25 | """Execute before the main run.""" 26 | pass 27 | 28 | def run(self, scope: Any) -> Optional[Dict[str, Any]]: 29 | """ 30 | Execute let declaration. 31 | 32 | Args: 33 | scope: The execution scope 34 | 35 | Returns: 36 | Dictionary with value or None 37 | 38 | Raises: 39 | TypeError: If attempting to reassign constant variable 40 | """ 41 | if self.reassign: 42 | instance = scope.retrieve_graph(self.name.first) if hasattr(self.name, 'first') else None 43 | 44 | if instance and getattr(instance, 'constant', False): 45 | raise TypeError("Assignment to constant variable.") 46 | 47 | evaluation = self.value.run(scope, False, False) if self.value else None 48 | 49 | if not evaluation: 50 | return None 51 | 52 | value = scope.assign(self.name, evaluation, self.reassign) 53 | return {"value": value} 54 | 55 | def before_graph(self, scope: Any) -> None: 56 | """ 57 | Execute before graph operations. 58 | 59 | Args: 60 | scope: The execution scope 61 | """ 62 | if not self.reassign: 63 | scope.graph[self.name] = self 64 | 65 | def graph(self, scope: Any) -> Any: 66 | """ 67 | Build dependency graph. 68 | 69 | Args: 70 | scope: The execution scope 71 | 72 | Returns: 73 | Graph result from value 74 | """ 75 | if hasattr(scope, 'block') and scope.block is not None: 76 | return self.value.graph(scope) if self.value else None 77 | return None 78 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/IF_CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | IF_CLASS runtime node class. 3 | """ 4 | from typing import Any, Dict, List 5 | import copy 6 | import uuid as uuid_module 7 | from .NODE import NODE 8 | 9 | 10 | class IF_CLASS(NODE): 11 | """If class for class-based conditional execution.""" 12 | 13 | def __init__(self) -> None: 14 | """Initialize an IF_CLASS instance.""" 15 | super().__init__() 16 | self.condition: Any = None 17 | self.true: Any = None 18 | self.false: Any = None 19 | self.class_ref: Any = None 20 | self.type: str = "CLASS" 21 | 22 | def run(self, scope: Any) -> Dict[str, List[Any]]: 23 | """ 24 | Execute if class. 25 | 26 | Args: 27 | scope: The execution scope 28 | 29 | Returns: 30 | Dictionary with next instructions 31 | """ 32 | from .IF_INSTANCE import IF_INSTANCE 33 | from ..Scope import Scope 34 | from ..Instruction import Instruction 35 | from ...__nuc__ import __BLOCK__ 36 | 37 | # Get instances to process 38 | dollar_instance = getattr(scope, 'dollar_instance', None) 39 | if dollar_instance: 40 | instances = [dollar_instance] 41 | else: 42 | instances = list(self.class_ref.instances.values()) if self.class_ref else [] 43 | 44 | statements: List[Any] = [] 45 | 46 | for instance in instances: 47 | statement = IF_INSTANCE(str(uuid_module.uuid4())) 48 | statement.condition = copy.deepcopy(self.condition) 49 | statement.true = __BLOCK__(copy.deepcopy(self.true.stms)) 50 | 51 | if self.false and hasattr(self.false, 'iof'): 52 | if self.false.iof == "$IF": 53 | statement.false = copy.deepcopy(self.false) 54 | elif self.false.iof == "$BLOCK": 55 | statement.false = __BLOCK__(copy.deepcopy(self.false.stms)) 56 | 57 | instance_scope = Scope(scope) 58 | instance_scope.dollar_instance = instance 59 | 60 | statements.append( 61 | Instruction(instance_scope, statement, True, True, True, True) 62 | ) 63 | 64 | return {"next": statements} 65 | 66 | def graph(self) -> None: 67 | """Build dependency graph.""" 68 | if self.class_ref: 69 | self.class_ref.declarations[self.key] = self 70 | -------------------------------------------------------------------------------- /src/nucleoid/routes/openapi.py: -------------------------------------------------------------------------------- 1 | """ 2 | OpenAPI route - handles OpenAPI specification and runtime configuration. 3 | """ 4 | from flask import Blueprint, jsonify, request, make_response 5 | from typing import Any, Dict, List, Optional 6 | import json 7 | 8 | 9 | openapi_bp = Blueprint('openapi', __name__) 10 | 11 | 12 | @openapi_bp.route('/openapi', methods=['GET']) 13 | def get_openapi_status() -> Any: 14 | """ 15 | Get OpenAPI status. 16 | 17 | Returns: 18 | JSON response with OpenAPI status 19 | """ 20 | from ..lib.openapi import openapi_instance 21 | 22 | return jsonify(openapi_instance.status()) 23 | 24 | 25 | @openapi_bp.route('/openapi', methods=['POST']) 26 | def post_openapi() -> Any: 27 | """ 28 | Configure OpenAPI runtime. 29 | 30 | Expected request body: 31 | { 32 | "x-nuc-action": "start", 33 | "x-nuc-functions": [{"definition": "..."}], 34 | "x-nuc-declarations": [{"definition": "..."}], 35 | "x-nuc-port": 3000 36 | } 37 | 38 | Returns: 39 | Empty response 40 | """ 41 | from ..lib.openapi import openapi_instance 42 | from ..context import context_instance 43 | 44 | # Validate request body 45 | if not request.json: 46 | return make_response(jsonify({'error': 'Invalid request body'}), 400) 47 | 48 | data: Dict[str, Any] = request.json 49 | 50 | # Extract fields with defaults 51 | action: str = data.get('x-nuc-action', '') 52 | functions: List[Dict[str, str]] = data.get('x-nuc-functions', []) 53 | declarations: List[Dict[str, str]] = data.get('x-nuc-declarations', []) 54 | port: Optional[int] = data.get('x-nuc-port') 55 | 56 | # Validate required fields 57 | if not action: 58 | return make_response(jsonify({'error': 'x-nuc-action is required'}), 400) 59 | 60 | if action == 'start': 61 | # Process functions 62 | context_instance.run([ 63 | {'definition': func['definition']} 64 | for func in functions 65 | ]) 66 | 67 | # Process declarations 68 | context_instance.run([ 69 | { 70 | 'definition': decl['definition'], 71 | 'options': {'declarative': True} 72 | } 73 | for decl in declarations 74 | ]) 75 | 76 | # Initialize and load OpenAPI 77 | openapi_instance.init() 78 | openapi_instance.load(data) 79 | 80 | return make_response('', 200) 81 | -------------------------------------------------------------------------------- /src/nucleoid/types.py: -------------------------------------------------------------------------------- 1 | """ 2 | Type definitions for Nucleoid runtime. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | from datetime import datetime 6 | from dataclasses import dataclass, field 7 | 8 | 9 | @dataclass 10 | class Options: 11 | """Runtime execution options.""" 12 | 13 | declarative: bool = False 14 | details: bool = False 15 | 16 | 17 | @dataclass 18 | class PortConfig: 19 | """Port configuration.""" 20 | 21 | terminal: int = 8448 22 | cluster: int = 4000 23 | openapi: int = 3000 24 | 25 | 26 | @dataclass 27 | class DataConfig: 28 | """Data configuration.""" 29 | 30 | encryption: bool = True 31 | 32 | 33 | @dataclass 34 | class Config: 35 | """Runtime configuration.""" 36 | 37 | path: Optional[str] = None 38 | port: PortConfig = field(default_factory=PortConfig) 39 | options: Dict[str, Any] = field(default_factory=dict) 40 | cache: bool = False 41 | data: DataConfig = field(default_factory=DataConfig) 42 | id: Optional[str] = None 43 | test: bool = False 44 | 45 | 46 | @dataclass 47 | class Event: 48 | """Event data structure.""" 49 | 50 | topic: str 51 | data: str 52 | 53 | 54 | @dataclass 55 | class Result: 56 | """Execution result structure.""" 57 | 58 | nuc: List[Any] = field(default_factory=list) 59 | value: Any = None 60 | 61 | def to_dict(self) -> Dict[str, Any]: 62 | """Convert to dictionary.""" 63 | return { 64 | '$nuc': self.nuc, 65 | 'value': self.value 66 | } 67 | 68 | 69 | @dataclass 70 | class Data: 71 | """Execution data structure.""" 72 | 73 | string: str 74 | result: Result 75 | time: float 76 | date: datetime 77 | declarative: bool = False 78 | error: bool = False 79 | events: List[Event] = field(default_factory=list) 80 | 81 | def to_dict(self) -> Dict[str, Any]: 82 | """Convert to dictionary.""" 83 | return { 84 | 'string': self.string, 85 | 'declarative': self.declarative, 86 | 'result': self.result.to_dict() if isinstance(self.result, Result) else self.result, 87 | 'time': self.time, 88 | 'date': self.date.isoformat() if isinstance(self.date, datetime) else self.date, 89 | 'error': self.error, 90 | 'events': [ 91 | {'topic': e.topic, 'data': e.data} if isinstance(e, Event) else e 92 | for e in self.events 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /src/nucleoid/nucleoid.py: -------------------------------------------------------------------------------- 1 | """ 2 | Nucleoid - Main entry point for the Nucleoid runtime. 3 | """ 4 | from typing import Any, Callable, Dict, Optional, Union 5 | from . import context 6 | from . import config 7 | from . import runtime 8 | from .types import Config, Data, Options 9 | 10 | 11 | def start(cfg: Optional[Dict[str, Any]] = None) -> None: 12 | """ 13 | Start the Nucleoid runtime. 14 | 15 | Args: 16 | cfg: Configuration dictionary 17 | 18 | Example: 19 | >>> import nucleoid 20 | >>> nucleoid.start({'cache': True}) 21 | """ 22 | if cfg is None: 23 | cfg = {} 24 | 25 | config.init(cfg) 26 | 27 | try: 28 | print("🌿 Nucleoid runtime is started") 29 | print("🌎 Inspired by Nature\n") 30 | except UnicodeEncodeError: 31 | # Fallback if terminal doesn't support Unicode 32 | print("Nucleoid runtime is started") 33 | print("Inspired by Nature\n") 34 | 35 | # Note: process.init() is commented out in TypeScript version 36 | # from . import process 37 | # process.init() 38 | 39 | 40 | def run(statement: str, options: Optional[Dict[str, Any]] = None) -> Union[Data, Any]: 41 | """ 42 | Run a statement in the Nucleoid runtime. 43 | 44 | Args: 45 | statement: Code statement to execute 46 | options: Execution options (declarative, details) 47 | 48 | Returns: 49 | Execution result or detailed data 50 | 51 | Example: 52 | >>> nucleoid.run("let x = 5") 53 | >>> nucleoid.run("x + 10", {'details': True}) 54 | """ 55 | if options is None: 56 | options = {} 57 | 58 | return runtime.runtime_instance.process(statement, options) 59 | 60 | 61 | def register(fn: Union[Callable, str]) -> None: 62 | """ 63 | Register a function in declarative mode. 64 | 65 | Args: 66 | fn: Function to register (callable or string definition) 67 | 68 | Example: 69 | >>> def my_function(): 70 | ... return "hello" 71 | >>> nucleoid.register(my_function) 72 | """ 73 | # Convert function to string if it's callable 74 | if callable(fn): 75 | import inspect 76 | definition = inspect.getsource(fn) 77 | else: 78 | definition = str(fn) 79 | 80 | context.load([ 81 | { 82 | 'definition': definition, 83 | 'options': {'declarative': True} 84 | } 85 | ]) 86 | 87 | 88 | # Module-level exports 89 | __all__ = ['start', 'run', 'register'] 90 | -------------------------------------------------------------------------------- /src/nucleoid/prototype.py: -------------------------------------------------------------------------------- 1 | """ 2 | Prototype module for extending built-in types. 3 | 4 | This module adds custom attributes to built-in Python types for Nucleoid runtime. 5 | """ 6 | import datetime 7 | from typing import Any 8 | 9 | 10 | def init() -> None: 11 | """ 12 | Initialize prototype extensions. 13 | 14 | Note: Python doesn't allow direct modification of built-in types like JavaScript does. 15 | This function serves as a placeholder for any prototype-related initialization 16 | that might be needed in the Python implementation. 17 | """ 18 | # In JavaScript, we can add properties to built-ins: 19 | # Date.now.value = true 20 | # Array.prototype.push.write = true 21 | 22 | # In Python, we can't modify built-ins directly, but we can: 23 | # 1. Create wrapper classes 24 | # 2. Use monkey patching (not recommended for built-ins) 25 | # 3. Track these properties separately in the runtime 26 | 27 | # For now, this is a placeholder that documents the behavior 28 | # without actually modifying built-ins 29 | pass 30 | 31 | 32 | # Custom attributes that would be on built-ins in JavaScript version 33 | BUILTIN_ATTRIBUTES = { 34 | 'datetime.datetime.now': {'value': True}, 35 | 'list.append': {'write': True}, 36 | } 37 | 38 | 39 | def has_attribute(obj: Any, attr: str, key: str) -> bool: 40 | """ 41 | Check if a built-in function has a custom attribute. 42 | 43 | Args: 44 | obj: Object type or instance 45 | attr: Attribute name 46 | key: Attribute key 47 | 48 | Returns: 49 | True if attribute exists 50 | """ 51 | type_name = f"{obj.__module__}.{obj.__class__.__name__}" if hasattr(obj, '__class__') else str(obj) 52 | full_key = f"{type_name}.{attr}" 53 | 54 | if full_key in BUILTIN_ATTRIBUTES: 55 | return key in BUILTIN_ATTRIBUTES[full_key] 56 | 57 | return False 58 | 59 | 60 | def get_attribute(obj: Any, attr: str, key: str) -> Any: 61 | """ 62 | Get a custom attribute from a built-in function. 63 | 64 | Args: 65 | obj: Object type or instance 66 | attr: Attribute name 67 | key: Attribute key 68 | 69 | Returns: 70 | Attribute value or None 71 | """ 72 | type_name = f"{obj.__module__}.{obj.__class__.__name__}" if hasattr(obj, '__class__') else str(obj) 73 | full_key = f"{type_name}.{attr}" 74 | 75 | if full_key in BUILTIN_ATTRIBUTES: 76 | return BUILTIN_ATTRIBUTES[full_key].get(key) 77 | 78 | return None 79 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/DELETE.py: -------------------------------------------------------------------------------- 1 | """ 2 | DELETE runtime node class. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | from .NODE import NODE 6 | 7 | 8 | class DELETE: 9 | """Delete statement node.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize a DELETE instance.""" 13 | self.variable: Optional[Any] = None 14 | 15 | def before(self) -> None: 16 | """Execute before the main run.""" 17 | pass 18 | 19 | def run(self, scope: Any) -> Dict[str, Any]: 20 | """ 21 | Execute delete operation. 22 | 23 | Args: 24 | scope: The execution scope 25 | 26 | Returns: 27 | Dictionary with next instructions and value 28 | """ 29 | from ..Instruction import Instruction 30 | from .. import graph, state 31 | 32 | if self.variable: 33 | key = self.variable.key 34 | state.state_instance.delete(scope, key) 35 | 36 | result_list: List[Instruction] = [] 37 | 38 | node = graph.retrieve(key) 39 | for next_node_key in node.next: 40 | statement = graph.retrieve(next_node_key) 41 | result_list.append( 42 | Instruction(scope.root, statement, False, True, False, False) 43 | ) 44 | 45 | return {"next": result_list, "value": True} 46 | else: 47 | return {"value": False} 48 | 49 | def before_graph(self) -> None: 50 | """Execute before graph operations.""" 51 | pass 52 | 53 | def graph(self) -> None: 54 | """Build dependency graph.""" 55 | if not self.variable: 56 | return 57 | 58 | from .. import graph 59 | 60 | node = graph.retrieve(self.variable.key) 61 | 62 | # Remove previous connections 63 | for key in list(node.previous.keys()): 64 | if key in node.next: 65 | del node.next[key] 66 | 67 | # Create empty node 68 | empty = NODE(node.key) 69 | 70 | # Transfer next connections 71 | for key in list(node.next.keys()): 72 | empty.next[key] = node.next[key] 73 | del node.next[key] 74 | 75 | # Delete from graph 76 | name = node.name 77 | if hasattr(node, 'object') and node.object and hasattr(node.object, 'properties'): 78 | del node.object.properties[name] 79 | 80 | del graph.graph_instance[node.key] 81 | graph.graph_instance[node.key] = empty 82 | -------------------------------------------------------------------------------- /src/nucleoid/context.py: -------------------------------------------------------------------------------- 1 | """ 2 | Context module for loading and running definitions. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | 6 | 7 | class ContextItem: 8 | """Represents a context item with definition and options.""" 9 | 10 | def __init__(self, definition: str, options: Optional[Dict[str, Any]] = None) -> None: 11 | """ 12 | Initialize a context item. 13 | 14 | Args: 15 | definition: Code definition 16 | options: Execution options 17 | """ 18 | self.definition: str = definition 19 | self.options: Dict[str, Any] = options or {} 20 | 21 | 22 | class Context: 23 | """Manages context loading and execution.""" 24 | 25 | def __init__(self) -> None: 26 | """Initialize context with empty list.""" 27 | self._context: List[ContextItem] = [] 28 | 29 | def load(self, context: List[Dict[str, Any]]) -> None: 30 | """ 31 | Load context items. 32 | 33 | Args: 34 | context: List of context items with definition and options 35 | """ 36 | items = [ 37 | ContextItem( 38 | definition=item.get('definition', ''), 39 | options=item.get('options') 40 | ) 41 | for item in context 42 | ] 43 | self._context.extend(items) 44 | 45 | def run(self, context: Optional[List[Dict[str, Any]]] = None) -> None: 46 | """ 47 | Run all context definitions. 48 | 49 | Args: 50 | context: Optional additional context items to load 51 | """ 52 | # Lazy import to avoid circular dependency 53 | from . import nucleoid 54 | 55 | if context: 56 | self.load(context) 57 | 58 | for item in self._context: 59 | nucleoid.run(item.definition, item.options) 60 | 61 | self._context = [] 62 | 63 | 64 | # Create singleton instance 65 | context_instance = Context() 66 | 67 | 68 | def load(context: List[Dict[str, Any]]) -> None: 69 | """ 70 | Load context items to the singleton instance. 71 | 72 | Args: 73 | context: List of context items with definition and options 74 | """ 75 | context_instance.load(context) 76 | 77 | 78 | def run(context: Optional[List[Dict[str, Any]]] = None) -> None: 79 | """ 80 | Run all context definitions from the singleton instance. 81 | 82 | Args: 83 | context: Optional additional context items to load 84 | """ 85 | context_instance.run(context) 86 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/IF.py: -------------------------------------------------------------------------------- 1 | """ 2 | IF runtime node class. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | import copy 6 | from .NODE import NODE 7 | 8 | 9 | class IF(NODE): 10 | """If conditional statement node.""" 11 | 12 | def __init__(self) -> None: 13 | """Initialize an IF instance.""" 14 | super().__init__() 15 | self.condition: Any = None 16 | self.true: Any = None 17 | self.false: Optional[Any] = None 18 | 19 | def before(self, scope: Any) -> None: 20 | """ 21 | Execute before the main run. 22 | 23 | Args: 24 | scope: The execution scope 25 | """ 26 | if self.condition: 27 | self.condition.before(scope) 28 | 29 | def run(self, scope: Any) -> Dict[str, List[Any]]: 30 | """ 31 | Execute if statement. 32 | 33 | Args: 34 | scope: The execution scope 35 | 36 | Returns: 37 | Dictionary with next instructions 38 | """ 39 | from ..Scope import Scope 40 | from ..Instruction import Instruction 41 | from ..state import state_instance 42 | 43 | local_scope = Scope(scope) 44 | 45 | # Evaluate condition 46 | if hasattr(scope, 'block') and scope.block and getattr(scope.block, 'skip', False): 47 | condition = self.condition.run(scope, True) 48 | else: 49 | condition = self.condition.run(scope, True) 50 | 51 | # Execute based on condition 52 | if state_instance.expression(scope, condition): 53 | true_statement = copy.deepcopy(self.true) 54 | return { 55 | "next": [ 56 | Instruction(local_scope, true_statement, True, True, False, False), 57 | Instruction(local_scope, true_statement, False, False, True, True), 58 | ] 59 | } 60 | elif self.false: 61 | false_statement = copy.deepcopy(self.false) 62 | return { 63 | "next": [ 64 | Instruction(local_scope, false_statement, True, True, False, False), 65 | Instruction(local_scope, false_statement, False, False, True, True), 66 | ] 67 | } 68 | 69 | return {"next": []} 70 | 71 | def graph(self, scope: Any) -> Any: 72 | """ 73 | Build dependency graph. 74 | 75 | Args: 76 | scope: The execution scope 77 | 78 | Returns: 79 | Graph result from condition 80 | """ 81 | return self.condition.graph(scope) 82 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/PROPERTY.py: -------------------------------------------------------------------------------- 1 | """ 2 | PROPERTY runtime node class. 3 | """ 4 | from typing import Any, Dict, Optional 5 | from .NODE import NODE 6 | 7 | 8 | class PROPERTY(NODE): 9 | """Property assignment node.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize a PROPERTY instance.""" 13 | super().__init__() 14 | self.object: Any = None 15 | self.name: Any = None 16 | self.value: Any = None 17 | 18 | def before(self, scope: Any) -> None: 19 | """ 20 | Execute before the main run. 21 | 22 | Args: 23 | scope: The execution scope 24 | """ 25 | if self.value: 26 | self.value.before(scope) 27 | 28 | def run(self, scope: Any) -> Optional[Dict[str, Any]]: 29 | """ 30 | Execute property assignment. 31 | 32 | Args: 33 | scope: The execution scope 34 | 35 | Returns: 36 | Dictionary with value or None 37 | """ 38 | from .. import graph, state 39 | from ..lang.ast import __Identifier__ 40 | from ..lang.estree.estree import append 41 | from .REFERENCE import REFERENCE 42 | 43 | evaluation = self.value.run(scope) if self.value else None 44 | 45 | # Determine target object 46 | ref = self.object.value if hasattr(self.object, 'value') else None 47 | if isinstance(ref, REFERENCE): 48 | target = graph.retrieve(ref.link) 49 | else: 50 | target = self.object 51 | 52 | # Build variable path 53 | appended = append(target.resolve().node, self.name.node) 54 | variable = __Identifier__(appended) 55 | 56 | if not evaluation: 57 | state.state_instance.delete(scope, str(variable)) 58 | return None 59 | 60 | assigned = state.state_instance.assign(scope, str(variable), evaluation) 61 | return {"value": assigned} 62 | 63 | def graph(self, scope: Any) -> Any: 64 | """ 65 | Build dependency graph. 66 | 67 | Args: 68 | scope: The execution scope 69 | 70 | Returns: 71 | Graph result from value 72 | """ 73 | from .. import graph 74 | from .REFERENCE import REFERENCE 75 | 76 | # Determine target object 77 | ref = self.object.value if hasattr(self.object, 'value') else None 78 | if isinstance(ref, REFERENCE): 79 | target = graph.retrieve(ref.link) 80 | else: 81 | target = self.object 82 | 83 | target.properties[str(self.name)] = self 84 | return self.value.graph(scope) if self.value else None 85 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | CLASS runtime node class. 3 | """ 4 | from typing import Any, Dict, List, Optional, Union 5 | from .NODE import NODE 6 | 7 | 8 | class CLASS(NODE): 9 | """Class declaration node.""" 10 | 11 | def __init__(self, key: str) -> None: 12 | """ 13 | Initialize a CLASS instance. 14 | 15 | Args: 16 | key: The class key identifier 17 | """ 18 | super().__init__(key) 19 | self.methods: List[Any] = [] 20 | self.instances: Dict[str, Any] = {} 21 | self.declarations: Dict[str, Any] = {} 22 | self.name: Any = None 23 | self.list: Any = None 24 | self.destroyed: Optional[bool] = None 25 | 26 | def run(self, scope: Dict[str, Any]) -> Union[NODE, List[NODE], None]: 27 | """ 28 | Execute class declaration. 29 | 30 | Args: 31 | scope: The execution scope 32 | 33 | Returns: 34 | NODE, list of NODEs, or None 35 | """ 36 | # Lazy imports 37 | from .. import graph, state 38 | from ..lang.Evaluation import Evaluation 39 | from ...__nuc__ import __ALIAS__, __EXPRESSION__ 40 | 41 | cls = graph.retrieve(self.name) 42 | 43 | if cls: 44 | # Check if methods are equal (deep comparison) 45 | import json 46 | if json.dumps(self.methods, sort_keys=True) == json.dumps(cls.methods, sort_keys=True): 47 | self.destroyed = True 48 | return None 49 | 50 | state.state_instance.assign( 51 | scope, self.name, Evaluation(f"class {self.name}{{}}") 52 | ) 53 | 54 | result_list: List[NODE] = [] 55 | 56 | if not cls: 57 | state.state_instance.call( 58 | scope, "classes.push", [f"state.{self.name}"] 59 | ) 60 | 61 | empty: Dict[str, Any] = {"type": "ArrayExpression", "elements": []} 62 | 63 | alias = __ALIAS__(self.name.node, self.list.node, empty) 64 | result_list.append(alias) 65 | 66 | result_list.append( 67 | __EXPRESSION__({"type": "Literal", "value": None, "raw": "null"}) 68 | ) 69 | 70 | return result_list 71 | 72 | def before_graph(self) -> Optional[Dict[str, bool]]: 73 | """ 74 | Execute before graph operations. 75 | 76 | Returns: 77 | Dictionary with destroyed flag or None 78 | """ 79 | if self.destroyed: 80 | return {"destroyed": True} 81 | 82 | from .. import graph 83 | 84 | cls = graph.retrieve(self.key) 85 | 86 | if isinstance(cls, CLASS): 87 | self.declarations = cls.declarations 88 | 89 | return None 90 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__PROPERTY__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build(object_: Any, name: Any, value: Any) -> "__PROPERTY__": 6 | """Build a __PROPERTY__ statement.""" 7 | statement = __PROPERTY__() 8 | statement.obj = object_ 9 | statement.nme = name 10 | statement.val = value 11 | return statement 12 | 13 | 14 | class __PROPERTY__(__NUC__): 15 | """Represents a property assignment statement.""" 16 | 17 | def __init__(self) -> None: 18 | super().__init__() 19 | self.obj: Any = None 20 | self.nme: Any = None 21 | self.val: Any = None 22 | self._val: Any = None 23 | 24 | def before(self, scope: Any) -> None: 25 | """Prepare the property statement by evaluating the value.""" 26 | from .__EXPRESSION__ import __expression__ 27 | expression = __expression__(self.val) 28 | self._val = expression.run(scope) 29 | 30 | def run(self, scope: Any) -> Any: 31 | """Execute the property statement.""" 32 | from ..ast.__identifier__ import __Identifier__ 33 | from ...graph import graph 34 | from ...nuc.class_ import CLASS 35 | from ...nuc.object_class import OBJECT_CLASS 36 | from ...nuc.function import FUNCTION 37 | from ...nuc.property_class import PROPERTY_CLASS 38 | from ...nuc.property import PROPERTY 39 | from ...instruction import Instruction 40 | 41 | object_id = __Identifier__(self.obj) 42 | name = __Identifier__(self.nme) 43 | 44 | if object_id.to_string(scope) == "this": 45 | object_id = scope.retrieve_object() 46 | 47 | if not graph.retrieve(object_id): 48 | raise ReferenceError(f"{object_id} is not defined") 49 | 50 | if ( 51 | name.to_string(scope) == "value" 52 | and not isinstance(graph.get(object_id), FUNCTION) 53 | ): 54 | raise TypeError("Cannot use 'value' as a name") 55 | 56 | cls = graph.retrieve(object_id) 57 | if isinstance(cls, (CLASS, OBJECT_CLASS)): 58 | statement = PROPERTY_CLASS(f"{object_id}.{name}") 59 | setattr(statement, "class", cls) 60 | statement.object = graph.retrieve(object_id) 61 | statement.name = name 62 | statement.value = self.val 63 | return [ 64 | Instruction(scope, statement, True, True, False, False), 65 | Instruction(scope, statement, False, False, True, True), 66 | ] 67 | 68 | statement = PROPERTY(f"{object_id}.{name}") 69 | statement.object = graph.retrieve(object_id) 70 | statement.name = name 71 | statement.value = self.val 72 | return Instruction(scope, statement, True, True, True, True) 73 | 74 | 75 | __property__ = build 76 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__IF__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build( 6 | condition: Any, true_statement: "__BLOCK__", false_statement: Optional["__BLOCK__"] 7 | ) -> "__IF__": 8 | """Build a __IF__ statement.""" 9 | statement = __IF__() 10 | statement.con = condition 11 | statement.tru = true_statement 12 | statement.fls = false_statement 13 | return statement 14 | 15 | 16 | class __IF__(__NUC__): 17 | """Represents an if statement.""" 18 | 19 | def __init__(self) -> None: 20 | super().__init__() 21 | self.con: Any = None 22 | self.tru: Optional["__BLOCK__"] = None 23 | self.fls: Optional["__BLOCK__"] = None 24 | 25 | def before(self, scope: Any) -> None: 26 | """Prepare the if statement by evaluating the condition.""" 27 | from ..ast.__expression__ import __Expression__ 28 | from .__EXPRESSION__ import __expression__ 29 | 30 | condition = __Expression__(self.con) 31 | expression = __expression__(condition) 32 | self.con = expression.run(scope) 33 | 34 | def run(self, scope: Any) -> Any: 35 | """Execute the if statement.""" 36 | from ...nuc.expression import EXPRESSION 37 | from ..ast.__identifier__ import __Identifier__ 38 | from ...graph import graph 39 | from ...nuc.class_ import CLASS 40 | from ...nuc.if_class import IF_CLASS 41 | from ...nuc.if_ import IF 42 | from ...instruction import Instruction 43 | 44 | con = self.con 45 | declarations = con.graph(scope) if hasattr(con, "graph") else None 46 | 47 | if declarations and len(declarations) > 0: 48 | declaration = declarations[0] 49 | key = getattr(declaration, "key", None) 50 | if key: 51 | identifier = __Identifier__(key) 52 | cls = graph.retrieve(identifier.first) 53 | if isinstance(cls, CLASS): 54 | statement = IF_CLASS(f"if({con.tokens})") 55 | setattr(statement, "class", cls) 56 | statement.condition = con 57 | statement.true = self.tru 58 | if self.fls: 59 | setattr(statement, "false", self.fls) 60 | return [ 61 | Instruction(scope, statement, True, True, False, False), 62 | Instruction(scope, statement, False, False, True, True), 63 | ] 64 | 65 | statement = IF(f"if({con.tokens})") 66 | statement.condition = con 67 | statement.true = self.tru 68 | setattr(statement, "false", self.fls) 69 | return [ 70 | Instruction(scope, statement, True, True, False, False), 71 | Instruction(scope, statement, False, False, True, True), 72 | ] 73 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/BLOCK_CLASS.py: -------------------------------------------------------------------------------- 1 | """ 2 | BLOCK_CLASS runtime node class. 3 | """ 4 | from typing import Any, List, Optional, Dict 5 | from .NODE import NODE 6 | import uuid 7 | 8 | 9 | class BLOCK_CLASS(NODE): 10 | """Block class for class-based statement execution.""" 11 | 12 | def __init__(self, key: Any) -> None: 13 | """ 14 | Initialize a BLOCK_CLASS. 15 | 16 | Args: 17 | key: The block class key 18 | """ 19 | super().__init__(str(key) if not isinstance(key, str) else key) 20 | self.statements: List[Any] = [] 21 | self.type: str = "CLASS" 22 | self.class_ref: Any = None # Reference to the class 23 | self.id: str = "" 24 | 25 | def run(self, scope: Any) -> Optional[List[NODE]]: 26 | """ 27 | Execute the block class. 28 | 29 | Args: 30 | scope: The execution scope 31 | 32 | Returns: 33 | List of NODE instances or None 34 | """ 35 | # Lazy imports 36 | from .BLOCK_INSTANCE import BLOCK_INSTANCE 37 | from ..Instruction import Instruction 38 | from ..Scope import Scope 39 | 40 | # Get instances to process 41 | if hasattr(scope, 'dollar_instance') and scope.dollar_instance: 42 | instances = [scope.dollar_instance] 43 | else: 44 | instances = list(self.class_ref.instances.values()) if self.class_ref else [] 45 | 46 | instructions: List[NODE] = [] 47 | 48 | for instance in instances: 49 | statement = BLOCK_INSTANCE(uuid.uuid4()) 50 | statement.id = str(uuid.uuid4()) 51 | statement.class_ref = self.class_ref 52 | statement.instance = instance 53 | statement.statements = self.statements 54 | statement.declaration = self 55 | 56 | parent_scope = scope if hasattr(scope, 'block') else None 57 | instance_scope = Scope(parent_scope, statement) 58 | instance_scope.dollar_instance = self 59 | 60 | instructions.append( 61 | Instruction( 62 | instance_scope, 63 | statement, 64 | lambda: None, 65 | lambda: None, 66 | None, 67 | None 68 | ) 69 | ) 70 | 71 | instructions.append( 72 | Instruction( 73 | instance_scope, 74 | statement, 75 | lambda: None, 76 | lambda: None, 77 | None, 78 | None 79 | ) 80 | ) 81 | 82 | return instructions if instructions else None 83 | 84 | def graph(self) -> None: 85 | """Build dependency graph.""" 86 | if self.class_ref: 87 | self.class_ref.declarations[self.id] = self 88 | -------------------------------------------------------------------------------- /src/nucleoid/cache.py: -------------------------------------------------------------------------------- 1 | """ 2 | Cache module for storing runtime data. 3 | """ 4 | import json 5 | from typing import Any, Dict, List 6 | 7 | 8 | class Cache: 9 | """In-memory cache for data storage.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize cache.""" 13 | self.cache: List[str] = [] 14 | 15 | def init(self, config: Dict[str, Any]) -> None: 16 | """ 17 | Initialize cache with configuration. 18 | 19 | Args: 20 | config: Configuration dictionary 21 | """ 22 | if config.get('cache', False): 23 | print("Cache is enabled") 24 | 25 | def read(self) -> List[Dict[str, Any]]: 26 | """ 27 | Read all cached data. 28 | 29 | Returns: 30 | List of data objects 31 | """ 32 | return [json.loads(data) for data in self.cache] 33 | 34 | def write(self, data: Dict[str, Any]) -> Dict[str, Any]: 35 | """ 36 | Write data to cache. 37 | 38 | Args: 39 | data: Data to cache 40 | 41 | Returns: 42 | Written data 43 | """ 44 | self.cache.append(json.dumps(data)) 45 | return data 46 | 47 | def clear(self) -> None: 48 | """Clear all cached data.""" 49 | self.cache = [] 50 | 51 | def tail(self, n: int = 10) -> List[Dict[str, Any]]: 52 | """ 53 | Get last n entries from cache. 54 | 55 | Args: 56 | n: Number of entries to retrieve 57 | 58 | Returns: 59 | List of last n data objects 60 | """ 61 | return [json.loads(data) for data in reversed(self.cache)][:n] 62 | 63 | 64 | # Create singleton instance 65 | cache_instance = Cache() 66 | 67 | 68 | def init(config: Dict[str, Any]) -> None: 69 | """ 70 | Initialize cache with configuration. 71 | 72 | Args: 73 | config: Configuration dictionary 74 | """ 75 | cache_instance.init(config) 76 | 77 | 78 | def read() -> List[Dict[str, Any]]: 79 | """ 80 | Read all cached data. 81 | 82 | Returns: 83 | List of data objects 84 | """ 85 | return cache_instance.read() 86 | 87 | 88 | def write(data: Dict[str, Any]) -> Dict[str, Any]: 89 | """ 90 | Write data to cache. 91 | 92 | Args: 93 | data: Data to cache 94 | 95 | Returns: 96 | Written data 97 | """ 98 | return cache_instance.write(data) 99 | 100 | 101 | def clear() -> None: 102 | """Clear all cached data.""" 103 | cache_instance.clear() 104 | 105 | 106 | def tail(n: int = 10) -> List[Dict[str, Any]]: 107 | """ 108 | Get last n entries from cache. 109 | 110 | Args: 111 | n: Number of entries to retrieve 112 | 113 | Returns: 114 | List of last n data objects 115 | """ 116 | return cache_instance.tail(n) 117 | -------------------------------------------------------------------------------- /src/nucleoid/lib/deep.py: -------------------------------------------------------------------------------- 1 | """ 2 | Deep comparison and merge utilities for objects. 3 | 4 | Note: This module is deprecated in favor of more robust libraries, 5 | but maintained for compatibility. 6 | """ 7 | 8 | from typing import Any 9 | 10 | 11 | def deep_equal(obj1: object, obj2: object) -> bool: 12 | """ 13 | Recursively compare two objects for deep equality. 14 | 15 | Args: 16 | obj1: First object to compare 17 | obj2: Second object to compare 18 | 19 | Returns: 20 | True if objects are deeply equal, False otherwise 21 | """ 22 | # Same object reference 23 | if obj1 is obj2: 24 | return True 25 | 26 | # Check if both are None or if types differ 27 | if obj1 is None or obj2 is None: 28 | return False 29 | 30 | if type(obj1) != type(obj2): 31 | return False 32 | 33 | # For non-dict/non-list objects, use regular equality 34 | if not isinstance(obj1, (dict, list)): 35 | return obj1 == obj2 36 | 37 | # Handle lists 38 | if isinstance(obj1, list) and isinstance(obj2, list): 39 | if len(obj1) != len(obj2): 40 | return False 41 | return all(deep_equal(a, b) for a, b in zip(obj1, obj2)) 42 | 43 | # Handle dictionaries 44 | if isinstance(obj1, dict) and isinstance(obj2, dict): 45 | keys1 = list(obj1.keys()) 46 | keys2 = list(obj2.keys()) 47 | 48 | if len(keys1) != len(keys2): 49 | return False 50 | 51 | for key in keys1: 52 | if key not in keys2: 53 | return False 54 | if not deep_equal(obj1[key], obj2[key]): 55 | return False 56 | 57 | return True 58 | 59 | # Default to regular equality 60 | return obj1 == obj2 61 | 62 | 63 | def equal(actual: Any, expected: Any) -> bool: 64 | """ 65 | Simple equality comparison. 66 | 67 | Args: 68 | actual: Actual value 69 | expected: Expected value 70 | 71 | Returns: 72 | True if values are equal, False otherwise 73 | """ 74 | return actual == expected 75 | 76 | 77 | def deep_merge(target: dict, source: dict) -> dict: 78 | """ 79 | Recursively merge source dictionary into target dictionary. 80 | 81 | Args: 82 | target: Target dictionary to merge into 83 | source: Source dictionary to merge from 84 | 85 | Returns: 86 | A new dictionary with merged values 87 | """ 88 | output = {**target} 89 | 90 | for key in source: 91 | if key in source: 92 | if _is_object(source[key]) and key in target and _is_object(target[key]): 93 | output[key] = deep_merge(target[key], source[key]) 94 | else: 95 | output[key] = source[key] 96 | 97 | return output 98 | 99 | 100 | def _is_object(item: Any) -> bool: 101 | """ 102 | Check if an item is a plain dictionary object. 103 | 104 | Args: 105 | item: Item to check 106 | 107 | Returns: 108 | True if item is a dict (not a list or None), False otherwise 109 | """ 110 | return bool(item and isinstance(item, dict) and not isinstance(item, list)) 111 | -------------------------------------------------------------------------------- /src/nucleoid/routes/terminal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Terminal route - main application entry point with route aggregation. 3 | """ 4 | from flask import Flask, request, jsonify, make_response 5 | from flask_cors import CORS 6 | from typing import Any, Dict, Optional 7 | import json 8 | 9 | 10 | def create_terminal_app() -> Flask: 11 | """ 12 | Create and configure the terminal Flask application. 13 | 14 | Returns: 15 | Configured Flask application 16 | """ 17 | app = Flask(__name__) 18 | CORS(app) 19 | 20 | # Import blueprints 21 | from .graph import graph_bp 22 | from .logs import logs_bp 23 | from .metrics import metrics_bp 24 | from .openapi import openapi_bp 25 | 26 | # Main runtime endpoint 27 | @app.route('/', methods=['POST']) 28 | def process_runtime() -> Any: 29 | """ 30 | Process runtime code execution. 31 | 32 | Expects: 33 | Content-Type: application/javascript 34 | Body: JavaScript code to execute 35 | 36 | Returns: 37 | Execution details 38 | """ 39 | # Check content type 40 | if request.content_type != 'application/javascript': 41 | return make_response('', 415) 42 | 43 | # Get body as text 44 | code = request.get_data(as_text=True) 45 | 46 | if not code: 47 | return make_response('', 400) 48 | 49 | # Process the code 50 | from ..runtime import runtime_instance 51 | 52 | try: 53 | details = runtime_instance.process(code, options={'details': True}) 54 | return make_response(details, 200) 55 | except Exception as e: 56 | return make_response(str(e), 500) 57 | 58 | # Register blueprints 59 | app.register_blueprint(graph_bp) 60 | app.register_blueprint(openapi_bp) 61 | app.register_blueprint(logs_bp) 62 | app.register_blueprint(metrics_bp) 63 | 64 | # Error handlers 65 | @app.errorhandler(400) 66 | def bad_request(error: Exception) -> Any: 67 | """Handle bad request errors.""" 68 | if isinstance(error, str): 69 | return jsonify({'error': error}), 400 70 | return jsonify({'error': str(error)}), 400 71 | 72 | @app.errorhandler(422) 73 | def unprocessable_entity(error: Exception) -> Any: 74 | """Handle JSON parsing errors.""" 75 | return make_response('', 422) 76 | 77 | @app.errorhandler(500) 78 | def internal_error(error: Exception) -> Any: 79 | """Handle internal server errors.""" 80 | if isinstance(error, dict) and 'error' in error: 81 | return jsonify(error), 400 82 | return make_response(str(error), 500) 83 | 84 | # General error handler 85 | @app.errorhandler(Exception) 86 | def handle_exception(error: Exception) -> Any: 87 | """Handle all unhandled exceptions.""" 88 | if isinstance(error, str): 89 | return jsonify({'error': error}), 400 90 | 91 | if hasattr(error, 'message'): 92 | return jsonify({'message': error.message}), 400 93 | 94 | if isinstance(error, dict) and 'error' in error: 95 | return jsonify(error), 400 96 | 97 | return make_response(str(error), 500) 98 | 99 | return app 100 | 101 | 102 | # Create the terminal app instance 103 | terminal = create_terminal_app() 104 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/revive.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Union 2 | from .__NUC__ import __NUC__ 3 | from .__ALIAS__ import __ALIAS__ 4 | from .__ASSIGNMENT__ import __ASSIGNMENT__ 5 | from .__BLOCK__ import __BLOCK__ 6 | from .__CALL__ import __CALL__ 7 | from .__CLASS__ import __CLASS__ 8 | from .__DELETE__ import __DELETE__ 9 | from .__EXPRESSION__ import __EXPRESSION__ 10 | from .__FOR__ import __FOR__ 11 | from .__FUNCTION__ import __FUNCTION__ 12 | from .__IF__ import __IF__ 13 | from .__INSTANCE__ import __INSTANCE__ 14 | from .__LET__ import __LET__ 15 | from .__PROPERTY__ import __PROPERTY__ 16 | from .__RETURN__ import __RETURN__ 17 | from .__THROW__ import __THROW__ 18 | from .__VARIABLE__ import __VARIABLE__ 19 | 20 | # Mapping of class names to their class objects 21 | __NUC_CLASSES__ = { 22 | "__ALIAS__": __ALIAS__, 23 | "__ASSIGNMENT__": __ASSIGNMENT__, 24 | "__BLOCK__": __BLOCK__, 25 | "__CALL__": __CALL__, 26 | "__CLASS__": __CLASS__, 27 | "__DELETE__": __DELETE__, 28 | "__EXPRESSION__": __EXPRESSION__, 29 | "__FOR__": __FOR__, 30 | "__FUNCTION__": __FUNCTION__, 31 | "__IF__": __IF__, 32 | "__INSTANCE__": __INSTANCE__, 33 | "__LET__": __LET__, 34 | "__PROPERTY__": __PROPERTY__, 35 | "__RETURN__": __RETURN__, 36 | "__THROW__": __THROW__, 37 | "__VARIABLE__": __VARIABLE__, 38 | } 39 | 40 | 41 | def revive(statements: Union[list[__NUC__], __NUC__, dict, Any]) -> Any: 42 | """ 43 | Revive statements from serialized form by reconstructing the objects. 44 | 45 | Args: 46 | statements: A list of statement objects, a single statement, or a dict/value 47 | 48 | Returns: 49 | The revived statement(s) with proper class instances 50 | """ 51 | # Handle list of statements 52 | if isinstance(statements, list): 53 | return [revive(statement) for statement in statements] 54 | 55 | # Handle dict/object 56 | if isinstance(statements, dict) or (hasattr(statements, '__dict__') and not isinstance(statements, __NUC__)): 57 | # Get the class name from iof attribute if present 58 | iof = None 59 | if isinstance(statements, dict): 60 | iof = statements.get('iof') 61 | else: 62 | iof = getattr(statements, 'iof', None) 63 | 64 | # Create new instance of the appropriate class 65 | if iof and iof in __NUC_CLASSES__: 66 | obj = __NUC_CLASSES__[iof]() 67 | else: 68 | obj = {} 69 | 70 | # Copy properties 71 | items = statements.items() if isinstance(statements, dict) else vars(statements).items() 72 | for key, property_value in items: 73 | # Recursively revive nested objects/arrays 74 | if isinstance(property_value, (list, dict)) or ( 75 | hasattr(property_value, '__dict__') 76 | and not isinstance(property_value, (str, int, float, bool, type(None))) 77 | and property_value is not None 78 | ): 79 | if isinstance(obj, dict): 80 | obj[key] = revive(property_value) 81 | else: 82 | setattr(obj, key, revive(property_value)) 83 | else: 84 | if isinstance(obj, dict): 85 | obj[key] = property_value 86 | else: 87 | setattr(obj, key, property_value) 88 | 89 | return obj 90 | 91 | # Return as-is if already a proper object or primitive 92 | return statements 93 | -------------------------------------------------------------------------------- /src/nucleoid/datastore.py: -------------------------------------------------------------------------------- 1 | """ 2 | Datastore module for managing runtime data storage. 3 | """ 4 | from typing import Any, Dict, List, Optional 5 | from . import cache 6 | 7 | 8 | class Datastore: 9 | """Datastore wrapper around cache with data transformation.""" 10 | 11 | def __init__(self) -> None: 12 | """Initialize datastore.""" 13 | self.cache = cache.cache_instance 14 | 15 | def init(self, config: Optional[Dict[str, Any]] = None) -> None: 16 | """ 17 | Initialize datastore with configuration. 18 | 19 | Args: 20 | config: Configuration dictionary with cache settings 21 | """ 22 | if config is None: 23 | config = {'cache': True} 24 | self.cache.init(config) 25 | 26 | def clear(self) -> None: 27 | """Clear all stored data.""" 28 | self.cache.clear() 29 | 30 | def read(self) -> List[Dict[str, Any]]: 31 | """ 32 | Read all data with result transformation. 33 | 34 | Returns: 35 | List of data objects with revived $nuc nodes 36 | """ 37 | from .lang.__nuc__.revive import revive 38 | 39 | result = [] 40 | for data in self.cache.read(): 41 | transformed = data.copy() 42 | if 'result' in data and isinstance(data['result'], dict): 43 | transformed['result'] = { 44 | '$nuc': revive(data['result'].get('$nuc', [])), 45 | 'value': data['result'].get('value') 46 | } 47 | result.append(transformed) 48 | 49 | return result 50 | 51 | def write(self, data: Dict[str, Any]) -> Dict[str, Any]: 52 | """ 53 | Write data to datastore. 54 | 55 | Args: 56 | data: Data to store 57 | 58 | Returns: 59 | Written data 60 | """ 61 | return self.cache.write(data) 62 | 63 | def tail(self, n: int = 10) -> List[Dict[str, Any]]: 64 | """ 65 | Get last n entries. 66 | 67 | Args: 68 | n: Number of entries to retrieve 69 | 70 | Returns: 71 | List of last n data objects 72 | """ 73 | return self.cache.tail(n) 74 | 75 | 76 | # Create singleton instance 77 | datastore_instance = Datastore() 78 | 79 | 80 | def init(config: Optional[Dict[str, Any]] = None) -> None: 81 | """ 82 | Initialize datastore with configuration. 83 | 84 | Args: 85 | config: Configuration dictionary with cache settings 86 | """ 87 | datastore_instance.init(config) 88 | 89 | 90 | def clear() -> None: 91 | """Clear all stored data.""" 92 | datastore_instance.clear() 93 | 94 | 95 | def read() -> List[Dict[str, Any]]: 96 | """ 97 | Read all data with result transformation. 98 | 99 | Returns: 100 | List of data objects with revived $nuc nodes 101 | """ 102 | return datastore_instance.read() 103 | 104 | 105 | def write(data: Dict[str, Any]) -> Dict[str, Any]: 106 | """ 107 | Write data to datastore. 108 | 109 | Args: 110 | data: Data to store 111 | 112 | Returns: 113 | Written data 114 | """ 115 | return datastore_instance.write(data) 116 | 117 | 118 | def tail(n: int = 10) -> List[Dict[str, Any]]: 119 | """ 120 | Get last n entries. 121 | 122 | Args: 123 | n: Number of entries to retrieve 124 | 125 | Returns: 126 | List of last n data objects 127 | """ 128 | return datastore_instance.tail(n) 129 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__INSTANCE__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build( 6 | cls: Any, 7 | args: Optional[list[Any]] = None, 8 | object_: Optional[Any] = None, 9 | name: Optional[Any] = None, 10 | ) -> "__INSTANCE__": 11 | """Build a __INSTANCE__ statement.""" 12 | if args is None: 13 | args = [] 14 | statement = __INSTANCE__() 15 | statement.cls = cls 16 | statement.obj = object_ 17 | statement.nme = name 18 | statement.args = args 19 | return statement 20 | 21 | 22 | class __INSTANCE__(__NUC__): 23 | """Represents an instance creation statement.""" 24 | 25 | def __init__(self) -> None: 26 | super().__init__() 27 | self.cls: Any = None 28 | self.args: list[Any] = [] 29 | self.obj: Optional[Any] = None 30 | self.nme: Optional[Any] = None 31 | 32 | def before(self, scope: Any = None) -> None: 33 | """Prepare the instance creation.""" 34 | from ...lib.random import random 35 | if not self.obj and not self.nme: 36 | self.nme = random(16, True) 37 | 38 | def run(self, scope: Any) -> Any: 39 | """Execute the instance creation.""" 40 | from ..ast.__identifier__ import __Identifier__ 41 | from ...graph import graph 42 | from ...nuc.class_ import CLASS 43 | from ...nuc.object import OBJECT 44 | from ...nuc.object_class import OBJECT_CLASS 45 | from ...instruction import Instruction 46 | 47 | cls_name = f"${self.cls.name}" if hasattr(self.cls, "name") else f"${self.cls}" 48 | cls = __Identifier__(cls_name) 49 | name = __Identifier__(self.nme) if self.nme else None 50 | 51 | args = [] 52 | for arg in self.args: 53 | if hasattr(arg, "type") and arg.type == "Identifier": 54 | args.append(__Identifier__(arg)) 55 | else: 56 | args.append(__Identifier__(arg)) 57 | 58 | if not graph.retrieve(cls): 59 | raise ReferenceError(f"{cls} is not defined") 60 | 61 | if self.obj and name and name.to_string(scope) == "value": 62 | raise TypeError("Cannot use 'value' as a property") 63 | 64 | if self.obj: 65 | object_identifier = __Identifier__(self.obj) 66 | if not graph.retrieve(object_identifier): 67 | raise ReferenceError(f"{__Identifier__(self.obj)} is not defined") 68 | 69 | if isinstance(graph.retrieve(object_identifier.first), CLASS): 70 | statement = OBJECT_CLASS(f"{object_identifier}.{name}") 71 | setattr(statement, "class", graph.retrieve(cls)) 72 | statement.name = name 73 | statement.object = graph.retrieve(object_identifier) 74 | return [ 75 | Instruction(scope, statement, True, True, False, False), 76 | Instruction(scope, statement, False, False, True, True), 77 | ] 78 | else: 79 | statement = OBJECT(f"{object_identifier}.{name}") 80 | setattr(statement, "class", graph.retrieve(cls)) 81 | statement.name = name 82 | statement.object = graph.retrieve(object_identifier) 83 | statement.arguments = args 84 | return statement 85 | 86 | statement = OBJECT(name) 87 | setattr(statement, "class", graph.retrieve(cls)) 88 | statement.name = name 89 | statement.arguments = args 90 | return statement 91 | 92 | 93 | __instance__ = build 94 | -------------------------------------------------------------------------------- /tests/lib/test_deep.py: -------------------------------------------------------------------------------- 1 | """Tests for deep comparison and merge utilities""" 2 | 3 | import pytest 4 | 5 | from nucleoid.lib.deep import deep_equal, deep_merge, equal 6 | 7 | 8 | class TestDeepLib: 9 | """Test suite for deep lib""" 10 | 11 | def test_compares_two_objects(self): 12 | """Test that deep_equal() correctly compares nested objects""" 13 | obj1 = {"a": 1, "b": 2, "c": {"d": 3, "e": 4}} 14 | obj2 = {"a": 1, "b": 2, "c": {"d": 3, "e": 4}} 15 | obj3 = {"a": 1, "b": 2, "c": {"d": 3, "e": 5}} 16 | 17 | assert deep_equal(obj1, obj2) is True 18 | assert deep_equal(obj1, obj3) is False 19 | 20 | def test_merges_two_objects(self): 21 | """Test that deep_merge() correctly merges nested objects""" 22 | obj1 = {"a": 1, "b": 2, "c": {"d": 3, "e": 4}} 23 | obj2 = {"b": 3, "c": {"d": 4, "f": 5}, "g": 6} 24 | obj3 = {"a": 1, "b": 3, "c": {"d": 4, "e": 4, "f": 5}, "g": 6} 25 | 26 | result = deep_merge(obj1, obj2) 27 | assert result == obj3 28 | 29 | def test_deep_equal_with_same_reference(self): 30 | """Test that deep_equal returns True for same object reference""" 31 | obj = {"a": 1, "b": 2} 32 | assert deep_equal(obj, obj) is True 33 | 34 | def test_deep_equal_with_none(self): 35 | """Test that deep_equal handles None values""" 36 | assert deep_equal(None, None) is True 37 | assert deep_equal(None, {"a": 1}) is False 38 | assert deep_equal({"a": 1}, None) is False 39 | 40 | def test_deep_equal_with_lists(self): 41 | """Test that deep_equal correctly compares lists""" 42 | list1 = [1, 2, [3, 4]] 43 | list2 = [1, 2, [3, 4]] 44 | list3 = [1, 2, [3, 5]] 45 | 46 | assert deep_equal(list1, list2) is True 47 | assert deep_equal(list1, list3) is False 48 | 49 | def test_deep_equal_with_different_types(self): 50 | """Test that deep_equal returns False for different types""" 51 | assert deep_equal({"a": 1}, [1, 2]) is False 52 | assert deep_equal(123, "123") is False 53 | 54 | def test_deep_equal_with_primitives(self): 55 | """Test that deep_equal works with primitive values""" 56 | assert deep_equal(42, 42) is True 57 | assert deep_equal(42, 43) is False 58 | assert deep_equal("hello", "hello") is True 59 | assert deep_equal("hello", "world") is False 60 | 61 | def test_equal_function(self): 62 | """Test that equal() performs simple equality comparison""" 63 | assert equal(42, 42) is True 64 | assert equal(42, 43) is False 65 | assert equal("hello", "hello") is True 66 | assert equal([1, 2], [1, 2]) is True 67 | 68 | def test_deep_merge_preserves_target(self): 69 | """Test that deep_merge doesn't modify the original target""" 70 | obj1 = {"a": 1, "b": 2} 71 | obj2 = {"b": 3, "c": 4} 72 | result = deep_merge(obj1, obj2) 73 | 74 | # Original should be unchanged 75 | assert obj1 == {"a": 1, "b": 2} 76 | # Result should have merged values 77 | assert result == {"a": 1, "b": 3, "c": 4} 78 | 79 | def test_deep_merge_with_nested_objects(self): 80 | """Test that deep_merge correctly handles deeply nested objects""" 81 | obj1 = {"a": {"b": {"c": 1}}} 82 | obj2 = {"a": {"b": {"d": 2}}} 83 | result = deep_merge(obj1, obj2) 84 | 85 | assert result == {"a": {"b": {"c": 1, "d": 2}}} 86 | 87 | def test_deep_merge_overwrites_non_object_values(self): 88 | """Test that deep_merge overwrites non-object values""" 89 | obj1 = {"a": 1, "b": "hello"} 90 | obj2 = {"a": 2, "b": "world"} 91 | result = deep_merge(obj1, obj2) 92 | 93 | assert result == {"a": 2, "b": "world"} 94 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__ASSIGNMENT__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Literal, Optional 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build( 6 | kind: Optional[Literal["VAR", "LET", "CONST"]], left: Any, right: Any 7 | ) -> "__ASSIGNMENT__": 8 | """Build a __ASSIGNMENT__ statement.""" 9 | statement = __ASSIGNMENT__() 10 | statement.knd = kind 11 | statement.lft = left 12 | statement.rgt = right 13 | return statement 14 | 15 | 16 | class __ASSIGNMENT__(__NUC__): 17 | """Represents an assignment statement.""" 18 | 19 | def __init__(self) -> None: 20 | super().__init__() 21 | self.knd: Optional[Literal["VAR", "LET", "CONST", "PROPERTY"]] = None 22 | self.lft: Any = None 23 | self.rgt: Any = None 24 | self._stmt: Optional[__NUC__] = None 25 | 26 | def before(self, scope: Any) -> None: 27 | """Prepare the assignment by determining the types and creating the appropriate statement.""" 28 | from ..ast.__identifier__ import __Identifier__ 29 | from ...graph import graph 30 | from ...nuc.class_ import CLASS 31 | from .__VARIABLE__ import __variable__ 32 | from .__INSTANCE__ import __instance__ 33 | from .__PROPERTY__ import __property__ 34 | from .__LET__ import __let__ 35 | 36 | name = __Identifier__(self.lft) 37 | left_kind = self.knd 38 | reassign = not self.knd 39 | 40 | if not left_kind: 41 | if scope.retrieve(name): 42 | left_kind = "LET" 43 | else: 44 | if hasattr(self.lft, "type") and self.lft.type == "Identifier": 45 | left_kind = "VAR" 46 | else: 47 | left_kind = "PROPERTY" 48 | 49 | right_kind = None 50 | if not self.rgt: 51 | raise SyntaxError("Missing definition") 52 | 53 | if hasattr(self.rgt, "type") and self.rgt.type == "NewExpression": 54 | if ( 55 | hasattr(self.rgt, "callee") 56 | and hasattr(self.rgt.callee, "name") 57 | and isinstance(graph.retrieve(f"${self.rgt.callee.name}"), CLASS) 58 | ): 59 | right_kind = "INSTANCE" 60 | else: 61 | right_kind = "EXPRESSION" 62 | else: 63 | right_kind = "EXPRESSION" 64 | 65 | if left_kind == "VAR" and right_kind == "EXPRESSION": 66 | self._stmt = __variable__(self.lft, self.rgt) 67 | elif left_kind == "VAR" and right_kind == "INSTANCE": 68 | rgt = self.rgt 69 | self._stmt = __instance__( 70 | rgt.callee, rgt.arguments if hasattr(rgt, "arguments") else [], None, self.lft 71 | ) 72 | elif left_kind == "PROPERTY" and right_kind == "EXPRESSION": 73 | identifier = __Identifier__(self.lft) 74 | self._stmt = __property__( 75 | identifier.object.node, identifier.last.node, self.rgt 76 | ) 77 | elif left_kind == "PROPERTY" and right_kind == "INSTANCE": 78 | identifier = __Identifier__(self.lft) 79 | rgt = self.rgt 80 | self._stmt = __instance__( 81 | rgt.callee, 82 | rgt.arguments if hasattr(rgt, "arguments") else [], 83 | identifier.object.node, 84 | identifier.last.node, 85 | ) 86 | elif left_kind in ["LET", "CONST"]: 87 | self._stmt = __let__(self.lft, self.rgt, left_kind == "CONST", reassign) 88 | 89 | if self._stmt: 90 | self._stmt.asg = True 91 | 92 | def run(self, scope: Any) -> Any: 93 | """Execute the assignment statement.""" 94 | from ...instruction import Instruction 95 | return Instruction(scope, self._stmt, None, True, None, None, None) 96 | -------------------------------------------------------------------------------- /tests/lib/test_statement.py: -------------------------------------------------------------------------------- 1 | """Tests for statement compilation utility""" 2 | 3 | import ast 4 | 5 | import pytest 6 | 7 | from nucleoid.lib.statement import compile 8 | 9 | 10 | class TestStatement: 11 | """Test suite for statement compilation""" 12 | 13 | def test_compile_simple_assignment(self): 14 | """Test compiling a simple assignment statement""" 15 | source = "x = 42" 16 | nodes = compile(source) 17 | 18 | assert len(nodes) == 1 19 | assert isinstance(nodes[0], ast.Assign) 20 | assert isinstance(nodes[0].targets[0], ast.Name) 21 | assert nodes[0].targets[0].id == "x" 22 | 23 | def test_compile_function_definition(self): 24 | """Test compiling a function definition""" 25 | source = """ 26 | def foo(x): 27 | return x + 1 28 | """ 29 | nodes = compile(source) 30 | 31 | assert len(nodes) == 1 32 | assert isinstance(nodes[0], ast.FunctionDef) 33 | assert nodes[0].name == "foo" 34 | 35 | def test_compile_multiple_statements(self): 36 | """Test compiling multiple statements""" 37 | source = """ 38 | x = 1 39 | y = 2 40 | z = x + y 41 | """ 42 | nodes = compile(source) 43 | 44 | assert len(nodes) == 3 45 | assert all(isinstance(node, ast.Assign) for node in nodes) 46 | 47 | def test_compile_expression(self): 48 | """Test compiling an expression""" 49 | source = "42 + 3" 50 | nodes = compile(source) 51 | 52 | assert len(nodes) == 1 53 | assert isinstance(nodes[0], ast.Expr) 54 | assert isinstance(nodes[0].value, ast.BinOp) 55 | 56 | def test_compile_class_definition(self): 57 | """Test compiling a class definition""" 58 | source = """ 59 | class MyClass: 60 | def __init__(self): 61 | self.value = 42 62 | """ 63 | nodes = compile(source) 64 | 65 | assert len(nodes) == 1 66 | assert isinstance(nodes[0], ast.ClassDef) 67 | assert nodes[0].name == "MyClass" 68 | 69 | def test_compile_invalid_syntax(self): 70 | """Test that invalid syntax raises SyntaxError""" 71 | source = "x = = 42" # Invalid syntax 72 | 73 | with pytest.raises(SyntaxError) as exc_info: 74 | compile(source) 75 | 76 | assert "Failed to parse source code" in str(exc_info.value) 77 | 78 | def test_compile_empty_string(self): 79 | """Test compiling an empty string""" 80 | source = "" 81 | nodes = compile(source) 82 | 83 | assert len(nodes) == 0 84 | 85 | def test_compile_comment_only(self): 86 | """Test compiling a comment-only string""" 87 | source = "# This is just a comment" 88 | nodes = compile(source) 89 | 90 | assert len(nodes) == 0 91 | 92 | def test_compile_if_statement(self): 93 | """Test compiling an if statement""" 94 | source = """ 95 | if x > 0: 96 | print("positive") 97 | else: 98 | print("non-positive") 99 | """ 100 | nodes = compile(source) 101 | 102 | assert len(nodes) == 1 103 | assert isinstance(nodes[0], ast.If) 104 | 105 | def test_compile_for_loop(self): 106 | """Test compiling a for loop""" 107 | source = """ 108 | for i in range(10): 109 | print(i) 110 | """ 111 | nodes = compile(source) 112 | 113 | assert len(nodes) == 1 114 | assert isinstance(nodes[0], ast.For) 115 | 116 | def test_compile_import_statement(self): 117 | """Test compiling import statements""" 118 | source = "import os" 119 | nodes = compile(source) 120 | 121 | assert len(nodes) == 1 122 | assert isinstance(nodes[0], ast.Import) 123 | 124 | def test_compile_returns_list(self): 125 | """Test that compile always returns a list""" 126 | source = "x = 1" 127 | nodes = compile(source) 128 | 129 | assert isinstance(nodes, list) 130 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/NODE.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base NODE class for Nucleoid runtime nodes. 3 | """ 4 | from typing import Any, Dict, Optional 5 | 6 | 7 | # Module-level sequence counter 8 | _sequence = 0 9 | 10 | 11 | class NODE: 12 | """Base class for all runtime node types.""" 13 | 14 | def __init__(self, key: Optional[Any] = None) -> None: 15 | """ 16 | Initialize a NODE instance. 17 | 18 | Args: 19 | key: The key identifier for this node 20 | """ 21 | global _sequence 22 | 23 | if key is not None: 24 | self.key: str = str(key) 25 | else: 26 | self.key = "" 27 | 28 | self.next: Dict[str, Any] = {} 29 | self.previous: Dict[str, Any] = {} 30 | self.sequence: int = _sequence 31 | _sequence += 1 32 | 33 | def before(self, scope: Optional[Any] = None) -> None: 34 | """ 35 | Execute before the main run. 36 | 37 | Args: 38 | scope: The execution scope 39 | """ 40 | pass 41 | 42 | def run(self, scope: Optional[Any] = None) -> Any: 43 | """ 44 | Execute the node. 45 | 46 | Args: 47 | scope: The execution scope 48 | 49 | Returns: 50 | Execution result 51 | """ 52 | pass 53 | 54 | def before_graph(self, scope: Optional[Any] = None) -> Any: 55 | """ 56 | Execute before graph operations. 57 | 58 | Args: 59 | scope: The execution scope 60 | """ 61 | pass 62 | 63 | def graph(self, scope: Optional[Any] = None) -> Any: 64 | """ 65 | Build dependency graph. 66 | 67 | Args: 68 | scope: The execution scope 69 | """ 70 | pass 71 | 72 | def after(self, scope: Optional[Any] = None) -> None: 73 | """ 74 | Execute after the main run. 75 | 76 | Args: 77 | scope: The execution scope 78 | """ 79 | pass 80 | 81 | @staticmethod 82 | def register(key: str, node: "NODE") -> None: 83 | """ 84 | Register a node in the graph. 85 | 86 | Args: 87 | key: The key to register under 88 | node: The node to register 89 | """ 90 | # Lazy import to avoid circular dependencies 91 | from .. import transaction 92 | from ..graph import graph_instance as dollar 93 | 94 | transaction.register(dollar, key, node) 95 | 96 | @staticmethod 97 | def replace(source_key: str, target_node: "NODE") -> None: 98 | """ 99 | Replace a node in the graph. 100 | 101 | Args: 102 | source_key: The key of the source node 103 | target_node: The target node to replace with 104 | """ 105 | from .. import transaction 106 | from ..graph import graph_instance as dollar 107 | 108 | transaction.register(target_node.block, dollar[source_key].block) 109 | 110 | for node in dollar[source_key].next: 111 | transaction.register(target_node.next, node, dollar[source_key].next[node]) 112 | transaction.register(dollar[source_key].next, node, None) 113 | 114 | for node in dollar[source_key].previous: 115 | transaction.register(dollar[node].next, source_key, None) 116 | 117 | transaction.register(dollar, source_key, target_node) 118 | 119 | @staticmethod 120 | def direct(source_key: str, target_key: str, target_node: "NODE") -> None: 121 | """ 122 | Create a direct connection between nodes. 123 | 124 | Args: 125 | source_key: The source node key 126 | target_key: The target node key 127 | target_node: The target node 128 | """ 129 | from .. import transaction 130 | from ..graph import graph_instance as dollar 131 | 132 | transaction.register(dollar[source_key].next, target_key, target_node) 133 | transaction.register(target_node.previous, source_key, dollar[source_key]) 134 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__BLOCK__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, TYPE_CHECKING 2 | import copy 3 | from .__NUC__ import __NUC__ 4 | from uuid import uuid4 5 | 6 | if TYPE_CHECKING: 7 | from typing import Optional 8 | 9 | 10 | def build(statements: list[__NUC__], skip: bool = False) -> "__BLOCK__": 11 | """Build a __BLOCK__ statement.""" 12 | statement = __BLOCK__() 13 | statement.stms = statements 14 | statement.skp = skip 15 | return statement 16 | 17 | 18 | class __BLOCK__(__NUC__): 19 | """Represents a block of statements.""" 20 | 21 | def __init__(self) -> None: 22 | super().__init__() 23 | self.stms: list[__NUC__] = [] 24 | self.skp: bool = False 25 | 26 | def run(self, scope: Any) -> Any: 27 | """Execute the block of statements.""" 28 | from ...scope import Scope 29 | from ...nuc.block import BLOCK 30 | from ...nuc.block_class import BLOCK_CLASS 31 | from ...instruction import Instruction 32 | from ...nuc.reference import REFERENCE 33 | from ...nuc.property_class import PROPERTY_CLASS 34 | from ...nuc.object_class import OBJECT_CLASS 35 | 36 | test = Scope(scope, {}) 37 | test.object = scope.object 38 | class_obj: Any = None 39 | statements_copy = copy.deepcopy(self.stms) 40 | 41 | for statement in statements_copy: 42 | while isinstance(statement, __): 43 | if statement.iof == "__ASSIGNMENT__": 44 | if not statement.prepared: 45 | statement.before(test) 46 | statement.prepared = True 47 | statement.graph(test) 48 | statement = statement.run(test) 49 | statement = statement.statement 50 | 51 | if not statement.prepared: 52 | statement.before(test) 53 | statement.prepared = True 54 | statement = statement.run(test) 55 | 56 | results = [statement] 57 | while any(isinstance(r, list) for r in results): 58 | new_results = [] 59 | for r in results: 60 | if isinstance(r, list): 61 | new_results.extend(r) 62 | else: 63 | new_results.append(r) 64 | results = new_results 65 | 66 | result = results[0] if results else statement 67 | from ...instruction import Instruction 68 | 69 | if isinstance(result, Instruction): 70 | result = result.statement 71 | 72 | if not isinstance(getattr(result, "value", None), REFERENCE): 73 | result.before() 74 | result.run(test) 75 | if hasattr(statement, "beforeGraph"): 76 | statement.beforeGraph(test) 77 | statement.graph(test) 78 | continue 79 | elif result.type == "CLASS": 80 | if isinstance(result, PROPERTY_CLASS) or isinstance(statement, OBJECT_CLASS): 81 | class_obj = result.object 82 | else: 83 | class_obj = result.get("class") if hasattr(result, "get") else getattr(result, "class", None) 84 | break 85 | else: 86 | break 87 | 88 | if class_obj: 89 | statement = BLOCK_CLASS(str(uuid4())) 90 | setattr(statement, "class", class_obj) 91 | statement.statements = self.stms 92 | return [ 93 | Instruction(scope, statement, None, None, None, None), 94 | Instruction(scope, statement, None, None, None, None), 95 | ] 96 | else: 97 | statement = BLOCK(str(uuid4())) 98 | statement.statements = self.stms 99 | statement.skip = self.skp 100 | return [ 101 | Instruction(scope, statement, None, None, None, None), 102 | Instruction(scope, statement, None, None, None, None), 103 | ] 104 | -------------------------------------------------------------------------------- /src/nucleoid/lib/serialize.py: -------------------------------------------------------------------------------- 1 | """ 2 | Serializes Python values to a string representation. 3 | Handles circular references by using a reference system. 4 | """ 5 | 6 | import json 7 | import re 8 | from datetime import datetime 9 | from typing import Any 10 | 11 | 12 | def serialize( 13 | value: Any, source: str, refs: dict[int, str] | None = None 14 | ) -> str: 15 | """ 16 | Serializes Python values to a string representation. 17 | Handles circular references by using a reference system. 18 | 19 | Args: 20 | value: The value to serialize 21 | source: Source identifier for reference tracking 22 | refs: Internal parameter used for tracking object references 23 | 24 | Returns: 25 | A string representation of the value 26 | """ 27 | if refs is None: 28 | refs = {} 29 | 30 | # Handle None 31 | if value is None: 32 | return "null" 33 | 34 | # Get the type of the value 35 | value_type = type(value) 36 | 37 | # Handle strings 38 | if isinstance(value, str): 39 | return json.dumps(value) 40 | 41 | # Handle numbers (int and float) 42 | if isinstance(value, (int, float)) and not isinstance(value, bool): 43 | return str(value) 44 | 45 | # Handle booleans (must come after numbers since bool is a subclass of int) 46 | if isinstance(value, bool): 47 | return "true" if value else "false" 48 | 49 | # Handle functions 50 | if callable(value) and not isinstance(value, type): 51 | # For functions, return their source code representation 52 | import inspect 53 | try: 54 | source_code = inspect.getsource(value).strip() 55 | # Clean up indentation 56 | lines = source_code.split('\n') 57 | # Remove common leading whitespace 58 | if lines: 59 | min_indent = min( 60 | len(line) - len(line.lstrip()) 61 | for line in lines if line.strip() 62 | ) 63 | source_code = '\n'.join( 64 | line[min_indent:] if len(line) > min_indent else line 65 | for line in lines 66 | ) 67 | return source_code 68 | except (OSError, TypeError): 69 | # If we can't get the source, return a generic representation 70 | return f"function {value.__name__}" 71 | 72 | # Handle objects (must check for circular references) 73 | if isinstance(value, (dict, list, set, datetime)) or hasattr(value, '__dict__'): 74 | # Check for circular references using object id 75 | obj_id = id(value) 76 | if obj_id in refs: 77 | return f"{{$ref:{{id:'{refs[obj_id]}',source:'{source}'}}}}" 78 | 79 | # Handle lists 80 | if isinstance(value, list): 81 | return json.dumps(value) 82 | 83 | # Handle datetime 84 | if isinstance(value, datetime): 85 | # Convert to milliseconds timestamp 86 | timestamp = int(value.timestamp() * 1000) 87 | return f"new Date({timestamp})" 88 | 89 | # Handle regex patterns 90 | if isinstance(value, re.Pattern): 91 | return value.pattern if hasattr(value, 'pattern') else str(value) 92 | 93 | # Handle sets 94 | if isinstance(value, set): 95 | values = [serialize(v, source, refs) for v in value] 96 | return f"new Set([{','.join(values)}])" 97 | 98 | # Handle dictionaries (Map-like) 99 | if isinstance(value, dict): 100 | # Check if this is a regular dict or should be treated as a Map 101 | # For now, treat all dicts as objects unless they need special handling 102 | 103 | # Store the reference ID for this object if it has an 'id' field 104 | if 'id' in value: 105 | refs[obj_id] = str(value['id']) 106 | 107 | # Check if it's a plain dictionary 108 | entries = [f"{k}:{serialize(v, source, refs)}" for k, v in value.items()] 109 | return f"{{{','.join(entries)}}}" 110 | 111 | # Default: convert to string 112 | return str(value) 113 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Operator__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Operator AST node (binary, logical, unary). 3 | """ 4 | from typing import Any, List, Optional, Union, Dict 5 | import copy 6 | from .__Node__ import __Node__ 7 | 8 | 9 | class __Operator__(__Node__): 10 | """Operator node for binary, logical, and unary expressions.""" 11 | 12 | def resolve(self, scope: Any) -> Dict[str, Any]: 13 | """ 14 | Resolve operator expressions in the given scope. 15 | 16 | Args: 17 | scope: The scope to resolve in 18 | 19 | Returns: 20 | Resolved operator node 21 | """ 22 | if scope: 23 | cloned = copy.deepcopy(self.node) 24 | _traverse_resolve(scope, cloned) 25 | return cloned 26 | else: 27 | return self.node 28 | 29 | def walk(self) -> List["__Node__"]: 30 | """ 31 | Walk the operator tree. 32 | 33 | Returns: 34 | List of child nodes 35 | """ 36 | return _traverse_walk(self.node) 37 | 38 | def graph(self, scope: Any) -> List["__Node__"]: 39 | """ 40 | Build dependency graph for operator. 41 | 42 | Args: 43 | scope: The scope to analyze 44 | 45 | Returns: 46 | List of dependent nodes 47 | """ 48 | return _traverse_graph(scope, self.node) 49 | 50 | 51 | def _traverse_walk(node: Dict[str, Any], acc: Optional[List["__Node__"]] = None) -> List["__Node__"]: 52 | """ 53 | Walk through operator tree recursively. 54 | 55 | Args: 56 | node: The node to walk 57 | acc: Accumulator list 58 | 59 | Returns: 60 | List of nodes 61 | """ 62 | if acc is None: 63 | acc = [] 64 | 65 | node_type = node.get("type") 66 | 67 | if node_type in ["BinaryExpression", "LogicalExpression"]: 68 | _traverse_walk(node.get("left", {}), acc) 69 | _traverse_walk(node.get("right", {}), acc) 70 | elif node_type in ["UnaryExpression", "UpdateExpression"]: 71 | _traverse_walk(node.get("argument", {}), acc) 72 | else: 73 | # Lazy import to avoid circular dependencies 74 | from .convert import AST 75 | acc.extend(AST.convert(node).walk()) 76 | 77 | return acc 78 | 79 | 80 | def _traverse_resolve(scope: Any, node: Dict[str, Any]) -> None: 81 | """ 82 | Resolve operator tree recursively, modifying node in place. 83 | 84 | Args: 85 | scope: The scope to resolve in 86 | node: The node to resolve (modified in place) 87 | """ 88 | node_type = node.get("type") 89 | 90 | if node_type in ["BinaryExpression", "LogicalExpression"]: 91 | _traverse_resolve(scope, node.get("left", {})) 92 | _traverse_resolve(scope, node.get("right", {})) 93 | elif node_type in ["UnaryExpression", "UpdateExpression"]: 94 | _traverse_resolve(scope, node.get("argument", {})) 95 | else: 96 | # Lazy import to avoid circular dependencies 97 | from .convert import AST 98 | ast = AST.convert(copy.deepcopy(node)) 99 | resolved = ast.resolve(scope) 100 | 101 | # Clear and update node in place 102 | node.clear() 103 | node.update(resolved) 104 | 105 | 106 | def _traverse_graph(scope: Any, node: Dict[str, Any], acc: Optional[List["__Node__"]] = None) -> List["__Node__"]: 107 | """ 108 | Build graph from operator tree recursively. 109 | 110 | Args: 111 | scope: The scope to analyze 112 | node: The node to graph 113 | acc: Accumulator list 114 | 115 | Returns: 116 | List of dependent nodes 117 | """ 118 | if acc is None: 119 | acc = [] 120 | 121 | node_type = node.get("type") 122 | 123 | if node_type in ["BinaryExpression", "LogicalExpression"]: 124 | _traverse_graph(scope, node.get("left", {}), acc) 125 | _traverse_graph(scope, node.get("right", {}), acc) 126 | elif node_type in ["UnaryExpression", "UpdateExpression"]: 127 | _traverse_graph(scope, node.get("argument", {}), acc) 128 | else: 129 | # Lazy import to avoid circular dependencies 130 | from .convert import AST 131 | acc.extend(AST.convert(node).graph(scope)) 132 | 133 | return acc 134 | 135 | 136 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __Operator__: 137 | """ 138 | Builder function for creating operator instances. 139 | 140 | Args: 141 | node: The operator node 142 | 143 | Returns: 144 | An __Operator__ instance 145 | """ 146 | return __Operator__(node) 147 | 148 | 149 | __operator__ = build 150 | -------------------------------------------------------------------------------- /src/nucleoid/config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Configuration management for Nucleoid. 3 | """ 4 | import os 5 | import json 6 | import uuid as uuid_module 7 | from typing import Dict, Any, Optional 8 | from pathlib import Path 9 | 10 | 11 | class Config: 12 | """Configuration class.""" 13 | 14 | def __init__(self) -> None: 15 | """Initialize configuration with default values.""" 16 | home = str(Path.home()) 17 | 18 | self.path: str = os.path.join(home, '.nuc') 19 | self.port: Dict[str, int] = { 20 | 'terminal': 8448, 21 | 'cluster': 4000, 22 | 'openapi': 3000, 23 | } 24 | self.options: Dict[str, Any] = {} 25 | self.cache: bool = False 26 | self.data: Dict[str, bool] = { 27 | 'encryption': True, 28 | } 29 | self.id: Optional[str] = None 30 | 31 | 32 | # Global config instance 33 | _config = Config() 34 | 35 | 36 | def init(config: Optional[Dict[str, Any]] = None) -> Config: 37 | """ 38 | Initialize configuration. 39 | 40 | Args: 41 | config: Configuration overrides 42 | 43 | Returns: 44 | Initialized configuration 45 | """ 46 | global _config 47 | 48 | if config is None: 49 | config = {} 50 | 51 | # Merge with defaults 52 | from .lib.deep import deep_merge 53 | 54 | default_dict = { 55 | 'path': _config.path, 56 | 'port': _config.port, 57 | 'options': _config.options, 58 | 'cache': _config.cache, 59 | 'data': _config.data, 60 | } 61 | 62 | merged = deep_merge(default_dict, config) 63 | 64 | _config.path = merged.get('path', _config.path) 65 | _config.port = merged.get('port', _config.port) 66 | _config.options = merged.get('options', _config.options) 67 | _config.cache = merged.get('cache', _config.cache) 68 | _config.data = merged.get('data', _config.data) 69 | 70 | # Create directories 71 | os.makedirs(_config.path, exist_ok=True) 72 | 73 | # Load .env if exists 74 | env_path = os.path.join(_config.path, '.env') 75 | if os.path.exists(env_path): 76 | try: 77 | from dotenv import load_dotenv 78 | load_dotenv(env_path) 79 | except ImportError: 80 | pass # dotenv not installed 81 | 82 | # Create subdirectories 83 | for subdir in ['data', 'openapi', 'native', 'extensions']: 84 | os.makedirs(os.path.join(_config.path, subdir), exist_ok=True) 85 | 86 | # Write nucleoid.js placeholder 87 | nucleoid_js_path = os.path.join(_config.path, 'nucleoid.js') 88 | with open(nucleoid_js_path, 'w') as f: 89 | f.write('/* eslint-disable */ let _nucleoid; module.exports = (nucleoid) => { if (nucleoid) { _nucleoid = nucleoid; } return _nucleoid; };') 90 | 91 | # Handle test mode 92 | if config.get('test'): 93 | _config.id = config.get('id') or str(uuid_module.uuid4()) 94 | _config.cache = True 95 | else: 96 | # Try to load config.json 97 | config_json_path = os.path.join(_config.path, 'config.json') 98 | if os.path.exists(config_json_path): 99 | try: 100 | with open(config_json_path, 'r') as f: 101 | json_config = json.load(f) 102 | _config.port.update(json_config.get('port', {})) 103 | _config.options.update(json_config.get('options', {})) 104 | except (json.JSONDecodeError, IOError): 105 | pass 106 | 107 | # Get or create ID 108 | id_value = config.get('id') or _config.id 109 | if not id_value: 110 | default_id_path = os.path.join(_config.path, 'default') 111 | try: 112 | with open(default_id_path, 'r') as f: 113 | id_value = f.read().strip() 114 | except (IOError, OSError): 115 | id_value = str(uuid_module.uuid4()) 116 | 117 | # Write default ID 118 | if id_value: 119 | default_id_path = os.path.join(_config.path, 'default') 120 | with open(default_id_path, 'w') as f: 121 | f.write(id_value) 122 | 123 | _config.id = id_value 124 | 125 | # Handle CLI arguments (if available) 126 | # In Python, you'd use argparse for this 127 | # For now, we'll skip CLI arg handling 128 | 129 | return _config 130 | 131 | 132 | def get_options() -> Dict[str, Any]: 133 | """ 134 | Get configuration options. 135 | 136 | Returns: 137 | Configuration options dictionary 138 | """ 139 | return _config.options 140 | 141 | 142 | def get_config() -> Config: 143 | """ 144 | Get current configuration. 145 | 146 | Returns: 147 | Current configuration instance 148 | """ 149 | return _config 150 | 151 | 152 | # Export config instance 153 | config_instance = _config 154 | -------------------------------------------------------------------------------- /src/nucleoid/__nuc__/__LET__.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Union 2 | from .__NUC__ import __NUC__ 3 | 4 | 5 | def build( 6 | name: Any, value: Any, constant: bool = False, reassign: bool = False 7 | ) -> "__LET__": 8 | """Build a __LET__ statement.""" 9 | statement = __LET__() 10 | statement.nme = name 11 | statement.val = value 12 | statement.cst = constant 13 | statement.ras = reassign 14 | return statement 15 | 16 | 17 | class __LET__(__NUC__): 18 | """Represents a let/const statement.""" 19 | 20 | def __init__(self) -> None: 21 | super().__init__() 22 | self.nme: Any = None 23 | self.val: Any = None 24 | self.cst: bool = False 25 | self.ras: bool = False 26 | 27 | def before(self, scope: Any) -> None: 28 | """Prepare the let statement by evaluating the value.""" 29 | from ...graph import graph 30 | from ...nuc.class_ import CLASS 31 | from .__INSTANCE__ import __instance__ 32 | from .__EXPRESSION__ import __expression__ 33 | 34 | if ( 35 | hasattr(self.val, "type") 36 | and self.val.type == "NewExpression" 37 | and hasattr(self.val, "callee") 38 | and hasattr(self.val.callee, "name") 39 | and isinstance(graph.retrieve(f"${self.val.callee.name}"), CLASS) 40 | ): 41 | args = self.val.arguments if hasattr(self.val, "arguments") else [] 42 | self.val = __instance__(self.val.callee, args) 43 | self.val.before(scope) 44 | else: 45 | expression = __expression__(self.val) 46 | self.val = expression.run(scope) 47 | 48 | def run(self, scope: Any) -> Any: 49 | """Execute the let statement.""" 50 | from ..ast.__identifier__ import __Identifier__ 51 | from ...nuc.expression import EXPRESSION 52 | from ...nuc.reference import REFERENCE 53 | from ...graph import graph 54 | from ...nuc.class_ import CLASS 55 | from ...nuc.let_class import LET_CLASS 56 | from ...nuc.let import LET 57 | from ...nuc.let_object import LET_OBJECT 58 | 59 | name = __Identifier__(self.nme) 60 | 61 | if name.type == "MemberExpression" and not scope.retrieve(name.object, True): 62 | raise ReferenceError(f"{name.object} is not defined") 63 | 64 | if ( 65 | name.type == "MemberExpression" 66 | and hasattr(name, "last") 67 | and name.last 68 | and name.last.to_string(scope) == "value" 69 | ): 70 | raise TypeError("Cannot use 'value' in local") 71 | 72 | value = self.val 73 | 74 | if isinstance(value, (EXPRESSION, REFERENCE)): 75 | cls = None 76 | if hasattr(value, "tokens"): 77 | for node in value.tokens: 78 | if hasattr(node, "walk"): 79 | identifiers = [] 80 | walked = node.walk() 81 | if isinstance(walked, list): 82 | stack = [walked] 83 | while stack: 84 | current = stack.pop() 85 | if isinstance(current, list): 86 | stack.extend(current) 87 | else: 88 | identifiers.append(current) 89 | else: 90 | identifiers = [walked] 91 | 92 | for identifier in identifiers: 93 | if hasattr(identifier, "first"): 94 | cls_candidate = graph.retrieve(identifier.first) 95 | if isinstance(cls_candidate, CLASS): 96 | cls = cls_candidate 97 | break 98 | if cls: 99 | break 100 | 101 | if cls: 102 | statement = LET_CLASS() 103 | setattr(statement, "class", cls) 104 | statement.name = name 105 | statement.value = value 106 | statement.constant = self.cst 107 | return statement 108 | 109 | statement = LET() 110 | statement.name = name 111 | statement.value = value 112 | statement.constant = self.cst 113 | statement.reassign = self.ras 114 | return statement 115 | elif hasattr(value, "type") and value.type == "__INSTANCE__": 116 | obj = value.run(scope) 117 | statement = LET_OBJECT() 118 | statement.name = name 119 | statement.object = obj 120 | statement.constant = self.cst 121 | return [obj, statement] 122 | 123 | 124 | __let__ = build 125 | -------------------------------------------------------------------------------- /tests/lib/test_serialize.py: -------------------------------------------------------------------------------- 1 | """Tests for serialize utilities""" 2 | 3 | import json 4 | import re 5 | from datetime import datetime, timezone 6 | 7 | import pytest 8 | 9 | from nucleoid.lib.serialize import serialize 10 | 11 | 12 | class TestSerializeLib: 13 | """Test suite for serialize lib""" 14 | 15 | def test_serializes_an_array(self): 16 | """Test that serialize() correctly serializes a list""" 17 | input_value = [1, 2, 3] 18 | output = serialize(input_value, "source") 19 | assert json.loads(output) == [1, 2, 3] 20 | 21 | def test_serializes_a_map(self): 22 | """Test that serialize() correctly serializes a dict as a Map""" 23 | # In Python, we'll use dict but format it as a Map-like structure 24 | # For this test, we need to treat it as a plain object 25 | input_value = {"key": "value"} 26 | output = serialize(input_value, "source") 27 | assert output == '{key:"value"}' 28 | 29 | def test_serializes_a_set(self): 30 | """Test that serialize() correctly serializes a set""" 31 | input_value = {1, 2, 3} 32 | output = serialize(input_value, "source") 33 | # Sets are unordered, so we need to check all possible orderings 34 | # or we can check that it starts with "new Set([" and contains all elements 35 | assert output.startswith("new Set([") 36 | assert output.endswith("])") 37 | assert "1" in output 38 | assert "2" in output 39 | assert "3" in output 40 | 41 | def test_serializes_a_date(self): 42 | """Test that serialize() correctly serializes a datetime""" 43 | # Create a datetime equivalent to "2023-05-17T00:00:00Z" 44 | input_value = datetime(2023, 5, 17, 0, 0, 0, tzinfo=timezone.utc) 45 | output = serialize(input_value, "source") 46 | timestamp = int(input_value.timestamp() * 1000) 47 | assert output == f"new Date({timestamp})" 48 | 49 | def test_serializes_a_string(self): 50 | """Test that serialize() correctly serializes a string""" 51 | input_value = "hello" 52 | output = serialize(input_value, "source") 53 | assert output == '"hello"' 54 | 55 | def test_serializes_a_number(self): 56 | """Test that serialize() correctly serializes a number""" 57 | input_value = 123 58 | output = serialize(input_value, "source") 59 | assert output == "123" 60 | 61 | def test_serializes_a_boolean(self): 62 | """Test that serialize() correctly serializes a boolean""" 63 | input_value = True 64 | output = serialize(input_value, "source") 65 | assert output == "true" 66 | 67 | def test_serializes_a_function(self): 68 | """Test that serialize() correctly serializes a function""" 69 | def test_func(): 70 | return "hello" 71 | 72 | output = serialize(test_func, "source") 73 | # Check that the output contains the function definition 74 | assert "def test_func" in output or "function test_func" in output 75 | assert "return" in output and "hello" in output 76 | 77 | def test_serializes_a_regexp(self): 78 | """Test that serialize() correctly serializes a regex pattern""" 79 | input_value = re.compile(r"hello", re.IGNORECASE) 80 | output = serialize(input_value, "source") 81 | # Python regex doesn't have the same string representation as JS 82 | # We just check that it contains the pattern 83 | assert "hello" in output 84 | 85 | def test_serializes_an_object(self): 86 | """Test that serialize() correctly serializes a dict""" 87 | input_value = {"key": "value"} 88 | output = serialize(input_value, "source") 89 | assert output == '{key:"value"}' 90 | 91 | def test_serializes_an_object_with_reference(self): 92 | """Test that serialize() handles circular references""" 93 | input_value = {"id": "id1", "prop": {"test": {}}} 94 | # Create circular reference 95 | input_value["prop"]["test"] = input_value 96 | 97 | output = serialize(input_value, "source") 98 | assert output == "{id:\"id1\",prop:{test:{$ref:{id:'id1',source:'source'}}}}" 99 | 100 | def test_serializes_none(self): 101 | """Test that serialize() correctly serializes None as null""" 102 | output = serialize(None, "source") 103 | assert output == "null" 104 | 105 | def test_serializes_float(self): 106 | """Test that serialize() correctly serializes floats""" 107 | input_value = 123.456 108 | output = serialize(input_value, "source") 109 | assert output == "123.456" 110 | 111 | def test_serializes_nested_objects(self): 112 | """Test that serialize() correctly serializes nested dictionaries""" 113 | input_value = {"outer": {"inner": "value"}} 114 | output = serialize(input_value, "source") 115 | assert output == '{outer:{inner:"value"}}' 116 | -------------------------------------------------------------------------------- /src/nucleoid/ast/__Node__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base AST node class for Nucleoid language processing. 3 | """ 4 | from typing import Any, Dict, Type, Optional, Union, List 5 | from abc import ABC 6 | 7 | 8 | class __Node__(ABC): 9 | """Base class for all AST node types.""" 10 | 11 | registry: Dict[str, Type["__Node__"]] = {} 12 | 13 | def __init__(self, node: Optional[Union[Dict[str, Any], str]] = None) -> None: 14 | """ 15 | Initialize a node. 16 | 17 | Args: 18 | node: Either a dict representing an AST node, a string to parse, or None 19 | """ 20 | self.iof: str = self.__class__.__name__ 21 | 22 | if node is None: 23 | # Default to null literal 24 | self.node: Dict[str, Any] = { 25 | "type": "Literal", 26 | "value": None, 27 | "raw": "null" 28 | } 29 | elif isinstance(node, dict) and "type" in node: 30 | self.node = node 31 | elif isinstance(node, str): 32 | # Lazy import to avoid circular dependencies 33 | from ..lang.estree.parser import parse 34 | self.node = parse(node, False) 35 | else: 36 | self.node = node 37 | 38 | @classmethod 39 | def convert(cls, node: Optional[Union[Dict[str, Any], str]]) -> "__Node__": 40 | """ 41 | Convert a node to the appropriate AST class instance. 42 | 43 | Args: 44 | node: The node to convert 45 | 46 | Returns: 47 | An instance of the appropriate AST class 48 | """ 49 | if not node: 50 | return cls() 51 | 52 | # Parse string nodes 53 | if isinstance(node, str): 54 | from ..lang.estree.parser import parse 55 | node_obj = parse(node, False) 56 | else: 57 | node_obj = node 58 | 59 | node_type = node_obj.get("type") 60 | 61 | # Look up the appropriate class in the registry 62 | node_class = cls.registry.get(node_type) 63 | if node_class: 64 | return node_class(node_obj) 65 | 66 | return cls(node_obj) 67 | 68 | @classmethod 69 | def register(cls, node_type: str, node_class: Type["__Node__"]) -> None: 70 | """ 71 | Register a node class for a specific type. 72 | 73 | Args: 74 | node_type: The AST node type string 75 | node_class: The class to use for this type 76 | """ 77 | cls.registry[node_type] = node_class 78 | 79 | @property 80 | def type(self) -> str: 81 | """Get the node type.""" 82 | return self.node.get("type", "") 83 | 84 | @property 85 | def first(self) -> Optional["__Node__"]: 86 | """Get the first node in a chain (for identifiers).""" 87 | return None 88 | 89 | @property 90 | def object(self) -> Optional["__Node__"]: 91 | """Get the object node (for member expressions).""" 92 | return None 93 | 94 | @property 95 | def last(self) -> Optional["__Node__"]: 96 | """Get the last node in a chain (for identifiers).""" 97 | return None 98 | 99 | def resolve(self, scope: Any) -> Dict[str, Any]: 100 | """ 101 | Resolve the node in the given scope. 102 | 103 | Args: 104 | scope: The scope to resolve in 105 | 106 | Returns: 107 | The resolved node 108 | """ 109 | return self.node 110 | 111 | def generate(self, scope: Any) -> str: 112 | """ 113 | Generate code for this node. 114 | 115 | Args: 116 | scope: The scope to generate in 117 | 118 | Returns: 119 | Generated code string 120 | """ 121 | from ..lang.estree.generator import ESTree 122 | resolved = self.resolve(scope) 123 | return ESTree.generate(resolved) 124 | 125 | def graph(self, scope: Any) -> List["__Node__"]: 126 | """ 127 | Get graph of dependencies. 128 | 129 | Args: 130 | scope: The scope to analyze 131 | 132 | Returns: 133 | List of dependent nodes 134 | """ 135 | return [] 136 | 137 | def walk(self) -> List["__Node__"]: 138 | """ 139 | Walk the AST tree. 140 | 141 | Returns: 142 | List of child nodes 143 | """ 144 | return [] 145 | 146 | def __str__(self) -> str: 147 | """String representation.""" 148 | return self.generate(None) 149 | 150 | 151 | def build(node: Optional[Union[Dict[str, Any], str]] = None) -> __Node__: 152 | """ 153 | Builder function for creating node instances. 154 | 155 | Args: 156 | node: The node to wrap 157 | 158 | Returns: 159 | A __Node__ instance 160 | """ 161 | return __Node__(node) 162 | 163 | 164 | __node__ = build 165 | -------------------------------------------------------------------------------- /src/nucleoid/nuc/OBJECT.py: -------------------------------------------------------------------------------- 1 | """ 2 | OBJECT runtime node class. 3 | """ 4 | from typing import Any, Dict, List 5 | from .NODE import NODE 6 | 7 | 8 | class OBJECT(NODE): 9 | """Object creation node.""" 10 | 11 | def __init__(self, key: Any) -> None: 12 | """ 13 | Initialize an OBJECT instance. 14 | 15 | Args: 16 | key: The object key 17 | """ 18 | super().__init__(key) 19 | self.properties: Dict[str, Any] = {} 20 | self.name: Any = None 21 | self.object: Any = None 22 | self.class_ref: Any = None 23 | self.arguments: List[Any] = [] 24 | 25 | def run(self, scope: Any) -> Dict[str, List[Any]]: 26 | """ 27 | Execute object creation. 28 | 29 | Args: 30 | scope: The execution scope 31 | 32 | Returns: 33 | Dictionary with next instructions 34 | """ 35 | from ..lang.ast import __Identifier__ 36 | from ..lang.Evaluation import Evaluation 37 | from ..lang.estree.estree import append 38 | from ..state import state_instance 39 | from ..Instruction import Instruction 40 | from ..Scope import Scope 41 | from ...__nuc__ import __EXPRESSION__, __CALL__ 42 | 43 | scope.object = self 44 | name = self.name 45 | 46 | # Determine variable path 47 | if self.object: 48 | variable = __Identifier__( 49 | append(self.object.resolve().node, self.name.node) 50 | ) 51 | else: 52 | variable = self.name 53 | 54 | # Assign new instance 55 | state_instance.assign( 56 | scope, 57 | variable, 58 | Evaluation(f"new state.{self.class_ref.name}()"), 59 | False 60 | ) 61 | 62 | # Assign ID 63 | state_instance.assign( 64 | scope, 65 | __Identifier__(f"{variable}.id"), 66 | Evaluation(f'"{name}"') 67 | ) 68 | 69 | result_list: List[Any] = [] 70 | 71 | # Handle non-nested objects 72 | if not self.object: 73 | state_instance.call(scope, f"{self.class_ref.list}.push", [f"state.{name}"]) 74 | state_instance.assign( 75 | scope, 76 | __Identifier__(f'{self.class_ref.list}["{self.name}"]'), 77 | Evaluation(f"state.{name}") 78 | ) 79 | 80 | # Call constructor if exists 81 | constructor = self.class_ref.methods.get("$constructor") if self.class_ref else None 82 | if constructor: 83 | call = __CALL__( 84 | constructor, 85 | [arg.node for arg in self.arguments] 86 | ) 87 | result_list.append(call) 88 | 89 | # Process class declarations 90 | if self.class_ref: 91 | for node_key in self.class_ref.declarations: 92 | declaration = self.class_ref.declarations[node_key] 93 | decl_scope = Scope() 94 | decl_scope.dollar_instance = self 95 | 96 | result_list.append( 97 | Instruction( 98 | decl_scope, 99 | declaration, 100 | True, 101 | True, 102 | False, 103 | False, 104 | True, 105 | True 106 | ) 107 | ) 108 | result_list.append( 109 | Instruction( 110 | decl_scope, 111 | declaration, 112 | False, 113 | False, 114 | True, 115 | True, 116 | True, 117 | True 118 | ) 119 | ) 120 | 121 | # Add expression 122 | expression = Instruction( 123 | scope, 124 | __EXPRESSION__(variable.node), 125 | True, 126 | True, 127 | False, 128 | False 129 | ) 130 | expression.derivative = False 131 | result_list.append(expression) 132 | 133 | return {"next": result_list} 134 | 135 | def graph(self) -> None: 136 | """Build dependency graph.""" 137 | if self.object is not None: 138 | self.object.properties[str(self.name)] = self 139 | 140 | if self.class_ref: 141 | self.class_ref.instances[self.key] = self 142 | 143 | def resolve(self) -> Any: 144 | """ 145 | Resolve object path. 146 | 147 | Returns: 148 | Identifier with full path 149 | """ 150 | from ..lang.ast import __Identifier__ 151 | from ..lang.estree.estree import append 152 | 153 | current = self 154 | resolved = self.name.node 155 | 156 | while current.object: 157 | current = current.object 158 | resolved = append(current.name.node, resolved) 159 | 160 | return __Identifier__(resolved) 161 | -------------------------------------------------------------------------------- /src/nucleoid/transaction.py: -------------------------------------------------------------------------------- 1 | """ 2 | Transaction module for managing state changes with rollback capability. 3 | """ 4 | from typing import Any, Dict, List, Optional, Union 5 | 6 | 7 | class VariableTransaction: 8 | """Transaction for variable changes.""" 9 | 10 | def __init__(self, variable: str, before: Any) -> None: 11 | """ 12 | Initialize a variable transaction. 13 | 14 | Args: 15 | variable: Variable name 16 | before: Previous value 17 | """ 18 | self.variable: str = variable 19 | self.before: Any = before 20 | 21 | 22 | class ObjectTransaction: 23 | """Transaction for object property changes.""" 24 | 25 | def __init__(self, obj: Dict[str, Any], property: str, before: Any) -> None: 26 | """ 27 | Initialize an object transaction. 28 | 29 | Args: 30 | obj: Object being modified 31 | property: Property name 32 | before: Previous value 33 | """ 34 | self.object: Dict[str, Any] = obj 35 | self.property: str = property 36 | self.before: Any = before 37 | 38 | 39 | Transaction = Union[VariableTransaction, ObjectTransaction] 40 | 41 | 42 | class TransactionManager: 43 | """Manages transactions with start, end, and rollback.""" 44 | 45 | def __init__(self) -> None: 46 | """Initialize transaction manager.""" 47 | self.list: List[Transaction] = [] 48 | 49 | def start(self) -> None: 50 | """Start a new transaction.""" 51 | self.list = [] 52 | 53 | def end(self) -> List[Transaction]: 54 | """ 55 | End current transaction and return list. 56 | 57 | Returns: 58 | List of transactions 59 | """ 60 | result = self.list 61 | self.list = [] 62 | return result 63 | 64 | def register_variable(self, variable: str, value: Any, scope: Dict[str, Any]) -> Any: 65 | """ 66 | Register a variable transaction. 67 | 68 | Args: 69 | variable: Variable name 70 | value: New value 71 | scope: Scope containing the variable 72 | 73 | Returns: 74 | New value after assignment 75 | """ 76 | # Capture old value 77 | before = scope.get(variable) 78 | 79 | # Apply new value 80 | scope[variable] = value 81 | 82 | # Record transaction 83 | self.list.append(VariableTransaction(variable, before)) 84 | 85 | return value 86 | 87 | def register_object(self, obj: Dict[str, Any], property: str, value: Any) -> None: 88 | """ 89 | Register an object property transaction. 90 | 91 | Args: 92 | obj: Object being modified 93 | property: Property name 94 | value: New value 95 | """ 96 | # Capture old value 97 | before = obj.get(property) 98 | 99 | # Record transaction 100 | self.list.append(ObjectTransaction(obj, property, before)) 101 | 102 | # Apply new value 103 | obj[property] = value 104 | 105 | def rollback(self) -> None: 106 | """Rollback all transactions in reverse order.""" 107 | while self.list: 108 | transaction = self.list.pop() 109 | 110 | if isinstance(transaction, VariableTransaction): 111 | # Variable transaction - would need scope to restore 112 | # In practice, this requires passing scope to rollback 113 | pass 114 | elif isinstance(transaction, ObjectTransaction): 115 | # Object property transaction 116 | if transaction.before is None: 117 | # Remove property if it didn't exist before 118 | transaction.object.pop(transaction.property, None) 119 | else: 120 | # Restore previous value 121 | transaction.object[transaction.property] = transaction.before 122 | 123 | 124 | # Create singleton instance 125 | transaction_manager = TransactionManager() 126 | 127 | 128 | def start() -> None: 129 | """Start a new transaction.""" 130 | transaction_manager.start() 131 | 132 | 133 | def end() -> List[Transaction]: 134 | """ 135 | End current transaction and return list. 136 | 137 | Returns: 138 | List of transactions 139 | """ 140 | return transaction_manager.end() 141 | 142 | 143 | def register_variable(variable: str, value: Any, scope: Dict[str, Any]) -> Any: 144 | """ 145 | Register a variable transaction. 146 | 147 | Args: 148 | variable: Variable name 149 | value: New value 150 | scope: Scope containing the variable 151 | 152 | Returns: 153 | New value after assignment 154 | """ 155 | return transaction_manager.register_variable(variable, value, scope) 156 | 157 | 158 | def register_object(obj: Dict[str, Any], property: str, value: Any) -> None: 159 | """ 160 | Register an object property transaction. 161 | 162 | Args: 163 | obj: Object being modified 164 | property: Property name 165 | value: New value 166 | """ 167 | transaction_manager.register_object(obj, property, value) 168 | 169 | 170 | def rollback() -> None: 171 | """Rollback all transactions in reverse order.""" 172 | transaction_manager.rollback() 173 | -------------------------------------------------------------------------------- /src/nucleoid/runtime.py: -------------------------------------------------------------------------------- 1 | """ 2 | Runtime module for processing code statements. 3 | """ 4 | from typing import Any, Dict, Optional 5 | import time 6 | from datetime import datetime 7 | 8 | 9 | class Options: 10 | """Runtime execution options.""" 11 | 12 | def __init__( 13 | self, 14 | declarative: bool = False, 15 | details: bool = False, 16 | **kwargs: Any 17 | ) -> None: 18 | """ 19 | Initialize options. 20 | 21 | Args: 22 | declarative: Whether to run in declarative mode 23 | details: Whether to return detailed execution data 24 | **kwargs: Additional options 25 | """ 26 | self.declarative: bool = declarative 27 | self.details: bool = details 28 | self.__dict__.update(kwargs) 29 | 30 | 31 | class Data: 32 | """Execution data result.""" 33 | 34 | def __init__( 35 | self, 36 | string: str, 37 | declarative: bool, 38 | result: Any, 39 | time: float, 40 | date: datetime, 41 | error: bool, 42 | events: list 43 | ) -> None: 44 | """ 45 | Initialize execution data. 46 | 47 | Args: 48 | string: Input code string 49 | declarative: Whether run in declarative mode 50 | result: Execution result 51 | time: Execution time in milliseconds 52 | date: Execution timestamp 53 | error: Whether an error occurred 54 | events: List of events 55 | """ 56 | self.string: str = string 57 | self.declarative: bool = declarative 58 | self.result: Any = result 59 | self.time: float = time 60 | self.date: datetime = date 61 | self.error: bool = error 62 | self.events: list = events 63 | 64 | def to_dict(self) -> Dict[str, Any]: 65 | """Convert to dictionary.""" 66 | # Handle exception serialization 67 | result_value = self.result 68 | if isinstance(self.result, Exception): 69 | result_value = { 70 | 'error': type(self.result).__name__, 71 | 'message': str(self.result) 72 | } 73 | 74 | return { 75 | 'string': self.string, 76 | 'declarative': self.declarative, 77 | 'result': result_value, 78 | 'time': self.time, 79 | 'date': self.date.isoformat() if isinstance(self.date, datetime) else self.date, 80 | 'error': self.error, 81 | 'events': self.events, 82 | } 83 | 84 | 85 | DEFAULT_OPTIONS = Options() 86 | 87 | 88 | class Runtime: 89 | """Runtime processor for code execution.""" 90 | 91 | def process(self, string: str, options: Optional[Dict[str, Any]] = None) -> Any: 92 | """ 93 | Process code string. 94 | 95 | Args: 96 | string: Code to execute 97 | options: Execution options 98 | 99 | Returns: 100 | Execution result or detailed data 101 | """ 102 | # Lazy imports to avoid circular dependencies 103 | from . import config 104 | from . import event 105 | from . import datastore 106 | from .lib.statement import statement_instance 107 | from . import transaction 108 | from . import stack 109 | 110 | # Merge options 111 | opts_dict = { 112 | 'declarative': DEFAULT_OPTIONS.declarative, 113 | 'details': DEFAULT_OPTIONS.details, 114 | } 115 | 116 | # Add config options 117 | config_opts = config.config_instance.options 118 | if config_opts: 119 | opts_dict.update(config_opts) 120 | 121 | # Add provided options 122 | if options: 123 | opts_dict.update(options) 124 | 125 | opts = Options(**opts_dict) 126 | 127 | before = time.time() 128 | result: Any = None 129 | error = False 130 | 131 | try: 132 | statements = statement_instance.compile(string) 133 | 134 | if not statements: 135 | return None 136 | 137 | transaction.start() 138 | result = stack.stack_instance.process(statements, None, opts) 139 | transaction.end() 140 | 141 | except Exception as err: 142 | transaction.rollback() 143 | error = True 144 | result = err 145 | 146 | events = event.event_instance.list() 147 | date = datetime.now() 148 | elapsed = (time.time() - before) * 1000 # Convert to milliseconds 149 | 150 | data = Data( 151 | string=string, 152 | declarative=opts.declarative, 153 | result=result, 154 | time=elapsed, 155 | date=date, 156 | error=error, 157 | events=events, 158 | ) 159 | 160 | datastore.datastore_instance.write(data.to_dict()) 161 | event.event_instance.clear() 162 | 163 | if opts.details: 164 | return data.to_dict() 165 | else: 166 | if error: 167 | raise result 168 | 169 | # Return result value if it has a value attribute 170 | if hasattr(result, 'value'): 171 | return result.value 172 | return result 173 | 174 | 175 | # Create singleton instance 176 | runtime_instance = Runtime() 177 | -------------------------------------------------------------------------------- /tests/test___nuc__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for $nuc statement storage and restoration. 3 | 4 | This test suite corresponds to the TypeScript test file: 5 | typescript/src/test/$nuc.spec.ts 6 | 7 | NOTE: In Python, we use __nuc__ instead of $nuc to follow Python naming conventions. 8 | """ 9 | 10 | import pytest 11 | from nucleoid import nucleoid 12 | from nucleoid.lib.test import clear 13 | from nucleoid.stack import process 14 | 15 | 16 | class TestNucStorage: 17 | """ 18 | Test suite for $nuc statement storage and datastore functionality. 19 | 20 | This class contains the test from the '$nuc' describe block 21 | in the TypeScript test suite. 22 | """ 23 | 24 | @classmethod 25 | def setup_class(cls): 26 | """Setup class - start nucleoid with test mode and declarative mode.""" 27 | nucleoid.start({'test': True, 'options': {'declarative': True}}) 28 | 29 | def setup_method(self): 30 | """Setup method - clear state before each test.""" 31 | clear() 32 | 33 | def test_stores_nuc(self): 34 | """ 35 | Test that $nuc statements are stored and can be restored from datastore. 36 | 37 | Original TypeScript (lines 16-55): 38 | ```typescript 39 | it("stores $nuc", () => { 40 | nucleoid.run("a = 1"); 41 | nucleoid.run("b = a + 2"); 42 | nucleoid.run("a = 2"); 43 | 44 | nucleoid.run("arr = [ 1, 2, 3 ]"); 45 | nucleoid.run("arr.push ( 4 )"); 46 | 47 | nucleoid.run( 48 | "class User { constructor ( name, createdAt ) { this.name = name; this.createdAt = createdAt } }" 49 | ); 50 | nucleoid.run("$User.active = true"); 51 | nucleoid.run("if ( $User.name === 'Test' ) { $User.mode = 'TEST' }"); 52 | nucleoid.run("new User ( 'Test', Date.now() )"); 53 | 54 | const expectedUserList = nucleoid.run("User"); 55 | 56 | const statements = nucleoid.datastore 57 | .read() 58 | .flatMap((stmt: any) => stmt.$) 59 | .filter(Boolean); 60 | 61 | test.clear(); 62 | 63 | process(statements, null, { declarative: true }); 64 | 65 | equal(nucleoid.run("a"), 2); 66 | equal(nucleoid.run("b"), 4); 67 | 68 | nucleoid.run("c = b + 3"); 69 | nucleoid.run("a = 3"); 70 | 71 | equal(nucleoid.run("b"), 5); 72 | equal(nucleoid.run("c"), 8); 73 | 74 | deepEqual(nucleoid.run("arr"), [1, 2, 3, 4]); 75 | 76 | const actualUserList = nucleoid.run("User"); 77 | deepEqual(actualUserList, expectedUserList); 78 | }); 79 | ``` 80 | 81 | EXPECTED BEHAVIOR: 82 | 1. Create variables with dependencies (a, b) 83 | 2. Create array and modify it 84 | 3. Create class with $Class properties and rules 85 | 4. Read all $nuc statements from datastore 86 | 5. Clear state and replay statements 87 | 6. Verify state is restored correctly 88 | 7. Verify dependency tracking still works after restoration 89 | """ 90 | # Step 1: Create variable dependencies 91 | nucleoid.run("a = 1") 92 | nucleoid.run("b = a + 2") 93 | nucleoid.run("a = 2") 94 | 95 | # Step 2: Create and modify array 96 | nucleoid.run("arr = [1, 2, 3]") 97 | nucleoid.run("arr.push(4)") 98 | 99 | # Step 3: Create class with $Class properties 100 | nucleoid.run( 101 | "class User { constructor(name, createdAt) { this.name = name; this.createdAt = createdAt } }" 102 | ) 103 | nucleoid.run("$User.active = True") 104 | nucleoid.run("if ($User.name == 'Test') { $User.mode = 'TEST' }") 105 | 106 | # Note: Using a fixed timestamp for testing instead of Date.now() 107 | nucleoid.run("new User('Test', 1234567890)") 108 | 109 | # Step 4: Store expected User list 110 | expected_user_list = nucleoid.run("User") 111 | 112 | # Step 5: Read statements from datastore 113 | datastore_data = nucleoid.datastore.read() 114 | statements = [] 115 | for stmt in datastore_data: 116 | if hasattr(stmt, '$') and stmt['$'] is not None: 117 | statements.extend(stmt['$'] if isinstance(stmt['$'], list) else [stmt['$']]) 118 | 119 | # Filter out None/null values 120 | statements = [s for s in statements if s is not None] 121 | 122 | # Step 6: Clear state 123 | clear() 124 | 125 | # Step 7: Replay statements to restore state 126 | process(statements, None, {'declarative': True}) 127 | 128 | # Step 8: Verify state is restored 129 | assert nucleoid.run("a") == 2 130 | assert nucleoid.run("b") == 4 131 | 132 | # Step 9: Create new variables to test dependency tracking 133 | nucleoid.run("c = b + 3") 134 | nucleoid.run("a = 3") 135 | 136 | # Step 10: Verify dependency tracking works after restoration 137 | assert nucleoid.run("b") == 5 # b should recalculate to a + 2 = 5 138 | assert nucleoid.run("c") == 8 # c should recalculate to b + 3 = 8 139 | 140 | # Step 11: Verify array is restored 141 | assert nucleoid.run("arr") == [1, 2, 3, 4] 142 | 143 | # Step 12: Verify User class and instances are restored 144 | actual_user_list = nucleoid.run("User") 145 | assert actual_user_list == expected_user_list 146 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | canmingir@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /src/nucleoid/process.py: -------------------------------------------------------------------------------- 1 | """ 2 | Process module for initializing the Nucleoid runtime. 3 | """ 4 | import os 5 | import json 6 | from typing import Any, Dict, Optional 7 | 8 | 9 | initialized = False 10 | 11 | 12 | def init() -> None: 13 | """ 14 | Initialize the Nucleoid runtime process. 15 | 16 | This function: 17 | 1. Initializes the datastore 18 | 2. Loads context from datastore 19 | 3. Loads configuration files 20 | 4. Sets up routes and extensions 21 | 5. Starts the terminal server 22 | """ 23 | global initialized 24 | 25 | if initialized: 26 | return 27 | 28 | # Lazy imports to avoid circular dependencies 29 | from . import datastore 30 | from . import config 31 | from . import stack 32 | from . import context 33 | from .lib import openapi 34 | from .routes import terminal 35 | 36 | print("[✓] Data Store is initiated") 37 | 38 | _config = config.config_instance 39 | 40 | datastore.init(_config.to_dict()) 41 | 42 | # Load context from datastore 43 | def load_context() -> None: 44 | """Load and process stored data.""" 45 | data_list = datastore.read() 46 | 47 | for data in data_list: 48 | dollar = data.get('$') 49 | c = data.get('c') 50 | e = data.get('e') 51 | 52 | if not e and dollar: 53 | stack.stack_instance.process( 54 | dollar, 55 | None, 56 | type('Options', (), {'declarative': c})() 57 | ) 58 | 59 | print("[✓] Context is loaded") 60 | 61 | # Load nucleoid.js if it exists 62 | nucleoid_path = os.path.join(_config.path, 'nucleoid.py') 63 | if os.path.exists(nucleoid_path): 64 | try: 65 | import importlib.util 66 | spec = importlib.util.spec_from_file_location("nucleoid_config", nucleoid_path) 67 | if spec and spec.loader: 68 | module = importlib.util.module_from_spec(spec) 69 | spec.loader.exec_module(module) 70 | if hasattr(module, 'init'): 71 | from . import nucleoid as nuc_module 72 | module.init(nuc_module) 73 | except Exception as err: 74 | print(f"Warning: Failed to load nucleoid.py: {err}") 75 | 76 | # Try to load event extension 77 | event_path = os.path.join(_config.path, 'extensions', 'event.py') 78 | if os.path.exists(event_path): 79 | try: 80 | import importlib.util 81 | spec = importlib.util.spec_from_file_location("event_ext", event_path) 82 | if spec and spec.loader: 83 | module = importlib.util.module_from_spec(spec) 84 | spec.loader.exec_module(module) 85 | if hasattr(module, 'init'): 86 | module.init() 87 | except Exception: 88 | pass # Silently ignore if event extension doesn't exist 89 | 90 | # Load native routes if configured 91 | native = _config.options.get('native') 92 | if native and 'routes' in native: 93 | try: 94 | for route in native['routes']: 95 | route_path = os.path.join(_config.path, 'native', f"{route}.py") 96 | if os.path.exists(route_path): 97 | import importlib.util 98 | spec = importlib.util.spec_from_file_location(f"native_{route}", route_path) 99 | if spec and spec.loader: 100 | module = importlib.util.module_from_spec(spec) 101 | spec.loader.exec_module(module) 102 | # Register the blueprint if it exists 103 | if hasattr(module, 'bp'): 104 | terminal.terminal.register_blueprint(module.bp) 105 | except Exception as err: 106 | print(f"Failed to load native routes: {err}") 107 | raise 108 | 109 | # Try to load OpenAPI configuration 110 | openapi_path = os.path.join(_config.path, 'openapi.json') 111 | if os.path.exists(openapi_path): 112 | try: 113 | with open(openapi_path, 'r') as f: 114 | openapi_config = json.load(f) 115 | 116 | functions = openapi_config.get('functions') 117 | if functions: 118 | context.run(functions) 119 | 120 | openapi.openapi_instance.init() 121 | openapi.openapi_instance.load({ 122 | 'api': openapi_config.get('api'), 123 | 'types': openapi_config.get('types'), 124 | 'prefix': openapi_config.get('prefix'), 125 | 'events': openapi_config.get('events'), 126 | }) 127 | 128 | port = openapi_config.get('port', _config.port.get('openapi', 3000)) 129 | openapi.openapi_instance.start(port) 130 | 131 | except FileNotFoundError: 132 | pass # OpenAPI config is optional 133 | except Exception as err: 134 | print(f"Error loading OpenAPI: {err}") 135 | import sys 136 | sys.exit(1) 137 | 138 | print("[✓] Process is running") 139 | 140 | # Start terminal server if not in test mode 141 | test_mode = _config.options.get('test', False) 142 | if not test_mode: 143 | # Add 404 handler 144 | @terminal.terminal.route('*') 145 | def catch_all(): 146 | from flask import make_response 147 | return make_response('', 404) 148 | 149 | # Start the Flask server 150 | port = _config.port.get('terminal', 8448) 151 | terminal.terminal.run(host='0.0.0.0', port=port) 152 | print("[✓] Terminal is ready") 153 | 154 | # Schedule context loading (Python equivalent of setImmediate) 155 | import threading 156 | thread = threading.Thread(target=load_context) 157 | thread.daemon = True 158 | thread.start() 159 | 160 | initialized = True 161 | --------------------------------------------------------------------------------