diff --git a/python/__init__.py b/python/__init__.py new file mode 100644 index 00000000..296f660f --- /dev/null +++ b/python/__init__.py @@ -0,0 +1,3 @@ +""" +python version of nucleoid +""" diff --git a/python/lang/handlers/assignment_handler.py b/python/lang/handlers/assignment_handler.py new file mode 100644 index 00000000..194d48a3 --- /dev/null +++ b/python/lang/handlers/assignment_handler.py @@ -0,0 +1,21 @@ +from ...nucleoid.state import variable_state +from ...nucleoid.graph import maingraph +import ast + +def assignment_handler(node): + # Extract the variable name from the target + target = node.targets[0] + if isinstance(target, ast.Name): + var_name = target.id + # Extract the value + if isinstance(node.value, ast.Constant): + var_value = node.value.value + #THIS NEXT LINE IS FOR DEPENDENCY HANDLING + #elif isinstance(node.value, ast.Name): + # var_value = variable_state.get(node.value.id, None) + else: + var_value = None # Handle other types if necessary + # Store the variable and its value in the dictionary + variable_state[var_name] = var_value + # Add the variable as a node in the graph + maingraph.add_node(var_name) diff --git a/python/lang/handlers/expression_handler.py b/python/lang/handlers/expression_handler.py new file mode 100644 index 00000000..3345654a --- /dev/null +++ b/python/lang/handlers/expression_handler.py @@ -0,0 +1,59 @@ +import ast +from ...nucleoid.state import variable_state + +def expression_handler(node): + """ + Evaluates an AST node and returns its value based on the variable_state dictionary. + + Args: + node (ast.Node): The AST node to evaluate. + variable_state (dict): A dictionary containing variable names and their values. + + Returns: + The evaluated value of the node. + + Raises: + NameError: If a variable is not defined in variable_state. + NotImplementedError: If the node type or operation is not supported. + """ + if isinstance(node, ast.Name): + if node.id in variable_state: + return variable_state[node.id] + else: + raise NameError(f"Variable {node.id} is not defined") + elif isinstance(node, ast.Constant): + return node.value + elif isinstance(node, ast.BinOp): + left = expression_handler(node.left) + right = expression_handler(node.right) + if isinstance(node.op, ast.Add): + return left + right + elif isinstance(node.op, ast.Sub): + return left - right + elif isinstance(node.op, ast.Mult): + return left * right + elif isinstance(node.op, ast.Div): + return left / right + # Add more operators as needed + else: + raise NotImplementedError(f"Operator {node.op} not supported") + elif isinstance(node, ast.Compare): + left = expression_handler(node.left) + right = expression_handler(node.comparators[0]) + if isinstance(node.ops[0], ast.Eq): + return left == right + elif isinstance(node.ops[0], ast.NotEq): + return left != right + elif isinstance(node.ops[0], ast.Lt): + return left < right + elif isinstance(node.ops[0], ast.LtE): + return left <= right + elif isinstance(node.ops[0], ast.Gt): + return left > right + elif isinstance(node.ops[0], ast.GtE): + return left >= right + # Add more comparison operators as needed + else: + raise NotImplementedError(f"Comparison operator {node.ops[0]} not supported") + else: + raise NotImplementedError(f"Node type {type(node)} not supported") diff --git a/python/nucleoid/Calculator.py b/python/nucleoid/Calculator.py deleted file mode 100644 index 0d354ee3..00000000 --- a/python/nucleoid/Calculator.py +++ /dev/null @@ -1,35 +0,0 @@ -from .logger import setup_logger - - -class Calculator: - def __init__(self): - self.result = 0 - self.logger = setup_logger(__name__) - self.logger.info("Calculator initialized") - - def add(self, x, y): - self.logger.debug(f"Adding numbers: {x} + {y}") - self.result = x + y - self.logger.info(f"Addition result: {self.result}") - return self.result - - def subtract(self, x, y): - self.logger.debug(f"Subtracting numbers: {x} - {y}") - self.result = x - y - self.logger.info(f"Subtraction result: {self.result}") - return self.result - - def multiply(self, x, y): - self.logger.debug(f"Multiplying numbers: {x} * {y}") - self.result = x * y - self.logger.info(f"Multiplication result: {self.result}") - return self.result - - def divide(self, x, y): - self.logger.debug(f"Dividing numbers: {x} / {y}") - if y == 0: - self.logger.error("Division by zero attempted") - raise ValueError("Division by zero is not allowed") - self.result = x / y - self.logger.info(f"Division result: {self.result}") - return self.result diff --git a/python/nucleoid/graph.py b/python/nucleoid/graph.py new file mode 100644 index 00000000..222f456c --- /dev/null +++ b/python/nucleoid/graph.py @@ -0,0 +1,3 @@ +import networkx as nx + +maingraph = nx.MultiDiGraph() diff --git a/python/nucleoid/logger.py b/python/nucleoid/logger.py deleted file mode 100644 index 93b59a0a..00000000 --- a/python/nucleoid/logger.py +++ /dev/null @@ -1,28 +0,0 @@ -import logging - - -def setup_logger(name: str) -> logging.Logger: - """ - Set up a logger with console handler only - - Args: - name: The name of the logger - - Returns: - logging.Logger: Configured logger instance - """ - logger = logging.getLogger(name) - logger.setLevel(logging.DEBUG) - - if logger.handlers: - return logger - - console_formatter = logging.Formatter("%(levelname)s - %(message)s") - - console_handler = logging.StreamHandler() - console_handler.setLevel(logging.INFO) - console_handler.setFormatter(console_formatter) - - logger.addHandler(console_handler) - - return logger diff --git a/python/nucleoid/main.py b/python/nucleoid/main.py deleted file mode 100644 index 754c1941..00000000 --- a/python/nucleoid/main.py +++ /dev/null @@ -1,6 +0,0 @@ -def main(): - print("Welcome to Nucleoid!") - - -if __name__ == "__main__": - main() diff --git a/python/nucleoid/nucleoid.py b/python/nucleoid/nucleoid.py new file mode 100644 index 00000000..9a9dffe8 --- /dev/null +++ b/python/nucleoid/nucleoid.py @@ -0,0 +1,16 @@ +from .parse import parse +from .process import process + +class Nucleoid: + def __init__(self): + print("Nucleoid object created") + + #clear all the graph and state etc(for later) + + + def run(self, statement): + if isinstance(statement, str): + print("Running statement: ", statement) + parsed_tree = parse(statement) + out = process(parsed_tree) + return out diff --git a/python/nucleoid/parse.py b/python/nucleoid/parse.py new file mode 100644 index 00000000..c762495f --- /dev/null +++ b/python/nucleoid/parse.py @@ -0,0 +1,6 @@ +import ast + +def parse(statement): + print("Parsing statement: ", statement) + tree = ast.parse(statement) + return tree diff --git a/python/nucleoid/process.py b/python/nucleoid/process.py new file mode 100644 index 00000000..475c86c6 --- /dev/null +++ b/python/nucleoid/process.py @@ -0,0 +1,15 @@ +import ast +from ..lang.handlers.assignment_handler import assignment_handler +from ..lang.handlers.expression_handler import expression_handler + +def process(parsed_tree): + + """ast.walk(node) + Recursively yield all descendant nodes in the tree starting at node (including node itself), in no specified order. + This is useful if you only want to modify nodes in place and don’t care about the context.""" + if isinstance(parsed_tree.body[0], ast.Expr): + return expression_handler(parsed_tree.body[0].value) + + + if isinstance(parsed_tree.body[0], ast.Assign): + assignment_handler(parsed_tree.body[0]) diff --git a/python/nucleoid/state.py b/python/nucleoid/state.py new file mode 100644 index 00000000..78ec839b --- /dev/null +++ b/python/nucleoid/state.py @@ -0,0 +1 @@ +variable_state = {} diff --git a/python/tests/test_calculator.py b/python/tests/test_calculator.py deleted file mode 100644 index e06df011..00000000 --- a/python/tests/test_calculator.py +++ /dev/null @@ -1,65 +0,0 @@ -import pytest -from centaur.Calculator import Calculator - - -@pytest.fixture -def calc(): - """Fixture to initialize a Calculator instance for testing.""" - return Calculator() - - -def test_add(calc): - """Tests addition functionality of the Calculator.""" - assert calc.add(2, 3) == 5 - assert calc.add(-1, 1) == 0 - assert calc.add(0, 0) == 0 - - -def test_subtract(calc): - """Tests subtraction functionality of the Calculator.""" - assert calc.subtract(5, 3) == 2 - assert calc.subtract(0, 5) == -5 - assert calc.subtract(-5, -5) == 0 - - -def test_multiply(calc): - """Tests multiplication functionality of the Calculator.""" - assert calc.multiply(2, 3) == 6 - assert calc.multiply(-1, 3) == -3 - assert calc.multiply(0, 5) == 0 - - -def test_divide(calc): - """ - Tests division functionality of the Calculator, - including handling division by zero. - """ - assert calc.divide(10, 2) == 5 - assert calc.divide(-9, 3) == -3 - assert calc.divide(5, 2) == 2.5 - - with pytest.raises(ValueError, match="Division by zero is not allowed"): - calc.divide(5, 0) - - -def test_logger_initialization(calc): - """Verifies that the logger is properly initialized in the Calculator.""" - assert calc.logger is not None - assert calc.logger.name == "centaur.Calculator" - - -def test_result_property(calc): - """ - Ensures the `result` attribute updates correctly after each operation. - """ - calc.add(2, 3) - assert calc.result == 5 - - calc.subtract(5, 3) - assert calc.result == 2 - - calc.multiply(2, 3) - assert calc.result == 6 - - calc.divide(6, 3) - assert calc.result == 2.0 diff --git a/python/tests/test_nucleoid.py b/python/tests/test_nucleoid.py new file mode 100644 index 00000000..df901e0c --- /dev/null +++ b/python/tests/test_nucleoid.py @@ -0,0 +1,13 @@ +import pytest +from ..nucleoid.nucleoid import Nucleoid # Import the Nucleoid class from the nucleoid module + +@pytest.fixture +def setup(): + # Initialize the Nucleoid class + return Nucleoid() + +def test_give_variable_value(setup): + # Use the initialized Nucleoid instance + nucleoid = setup + nucleoid.run("i = 1") + assert nucleoid.run("i == 1") is True diff --git a/src/lang/$nuc/$INSTANCE.js b/src/lang/$nuc/$INSTANCE.js index 0608ba29..8c494ac4 100644 --- a/src/lang/$nuc/$INSTANCE.js +++ b/src/lang/$nuc/$INSTANCE.js @@ -12,6 +12,7 @@ function build(cls, object, name, args = []) { statement.obj = object; statement.nme = name; statement.args = args; + return statement; }