Source code for knitout_interpreter.knitout_language.Knitout_Context

"""Module used to manage the context of a knitout interpreter."""
from __future__ import annotations
from knit_graphs.Knit_Graph import Knit_Graph
from virtual_knitting_machine.Knitting_Machine import Knitting_Machine

from knitout_interpreter.knitout_execution import Knitout_Executer
from knitout_interpreter.knitout_language.Knitout_Parser import parse_knitout
from knitout_interpreter.knitout_operations.Header_Line import Knitout_Header_Line, Knitting_Machine_Header
from knitout_interpreter.knitout_operations.Knitout_Line import Knitout_Line, Knitout_Version_Line, Knitout_Comment_Line
from knitout_interpreter.knitout_operations.knitout_instruction import Knitout_Instruction


[docs] def process_knitout_instructions(codes: list[Knitout_Line]) -> ( tuple)[Knitout_Version_Line, list[Knitout_Header_Line], list[Knitout_Instruction], list[Knitout_Comment_Line]]: """Separate list of knitout codes into components of a program for execution. Args: codes: List of knitout instructions to separate into program components. Returns: A tuple containing: - Version line for the knitout program - List of header lines - List of instruction lines - List of comment lines """ version_line: Knitout_Version_Line = Knitout_Version_Line(-1) # -1 set to undo default if no version line is provided. head: list[Knitout_Header_Line] = [] instructions: list[Knitout_Instruction] = [] comments: list[Knitout_Comment_Line] = [] for code in codes: if isinstance(code, Knitout_Version_Line): assert version_line.version == code.version or version_line.version < 0, f"Cannot have multiple versions of knitout {version_line} and {code}" version_line = code elif isinstance(code, Knitout_Header_Line): head.append(code) elif isinstance(code, Knitout_Instruction): instructions.append(code) elif isinstance(code, Knitout_Comment_Line): comments.append(code) else: assert False, f"Cannot process code {code}" if version_line.version < 0: version_line = Knitout_Version_Line(2, "Version defaulted to 2") return version_line, head, instructions, comments
[docs] class Knitout_Context: """Maintains information about the state of a knitting process as knitout instructions are executed.""" def __init__(self) -> None: self.machine_state: Knitting_Machine = Knitting_Machine() self.executed_knitout: list[Knitout_Line] = [] self.version_line: Knitout_Version_Line | None = None self.executed_header: Knitting_Machine_Header = Knitting_Machine_Header(self.machine_state) self.executed_instructions: list[Knitout_Instruction] = [] @property def version(self) -> int: """Get the knitout version of the current context. Returns: The knitout version number, defaults to 2 if no version is set. """ if self.version_line is not None: return int(self.version_line.version) else: return 2 @version.setter def version(self, version_line: Knitout_Version_Line) -> None: """Set the version line for the current context. This will override any existing version. Args: version_line: The version line to set for this context. """ self.version_line = version_line
[docs] def execute_header(self, header_declarations: list[Knitout_Header_Line], comment_no_op_header: bool = False) -> None: """Update the machine state based on the given header values. Header declarations that do not change the current context can optionally be converted to comments. Args: header_declarations: The header lines to update based on. comment_no_op_header: If True, no-op header declarations will be added to the instructions as comments. Defaults to False. """ for header_line in header_declarations: updated = self.executed_header.update_header(header_line, update_machine=True) # update process will always yield a complete header if not updated and comment_no_op_header: # comment out the no-op header line and add it to the execution. self.executed_knitout.append(Knitout_Comment_Line(header_line))
[docs] def execute_instructions(self, instructions: list[Knitout_Line]) -> None: """Execute the instruction set on the machine state defined by the current header. Args: instructions: Instructions to execute on the knitting machine. """ execution = Knitout_Executer(instructions=instructions, knitting_machine=self.machine_state, knitout_version=self.version) self.executed_instructions = execution.executed_instructions
[docs] def execute_knitout(self, version_line: Knitout_Version_Line, header_declarations: list[Knitout_Header_Line], instructions: list[Knitout_Instruction]) -> tuple[list[Knitout_Line], Knitting_Machine, Knit_Graph]: """Execute the given knitout organized by version, header, and instructions. Args: version_line: The version of knitout to use. header_declarations: The header to define the knitout file. instructions: The instructions to execute on the machine. Returns: A tuple containing: - List of knitout instructions that were executed - Machine state after execution - Knit graph created by execution """ self.version = version_line self.execute_header(header_declarations) self.execute_instructions(instructions) for i, instruction in enumerate(self.executed_instructions): instruction.original_line_number = i return self.executed_instructions, self.machine_state, self.machine_state.knit_graph
[docs] def process_knitout_file(self, knitout_file_name: str) -> tuple[list[Knitout_Line], Knitting_Machine, Knit_Graph]: """Parse and process a file of knitout code. Args: knitout_file_name: File path containing knitout code to process. Returns: A tuple containing: - List of executed knitout lines - Knitting machine state after execution - Knit graph formed by execution """ codes = parse_knitout(knitout_file_name, pattern_is_file=True, debug_parser=False, debug_parser_layout=False) return self.execute_knitout_instructions(codes)
[docs] def execute_knitout_instructions(self, codes: list[Knitout_Line]) -> tuple[list[Knitout_Line], Knitting_Machine, Knit_Graph]: """Execute given knitout instructions. Args: codes: List of knitout lines to execute. Returns: A tuple containing: - List of executed knitout lines - Machine state after execution - Knit graph created by execution """ version, head, instructions, comments = process_knitout_instructions(codes) return self.execute_knitout(version, head, instructions)