Skip to content

Commit

Permalink
Add assignments as part of the instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcere committed Jul 22, 2024
1 parent 1cf341a commit a3dd333
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
3 changes: 3 additions & 0 deletions src/parser/cfg_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ def get_block_id(self) -> str:
def get_instructions(self) -> List[CFGInstruction]:
return self._instructions

def get_instructions_to_compute(self) -> List[CFGInstruction]:
return [instruction for instruction in self._instructions if instruction.must_be_computed()]

def get_source_stack(self) -> int:
return self.source_stack

Expand Down
14 changes: 13 additions & 1 deletion src/parser/cfg_instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,20 @@ def build_custom_function_spec(function_name: str, input_args: List[str], output


class CFGInstruction:
def __init__(self, op : str, in_args: List[str], out_args: List[str]):
def __init__(self, op: str, in_args: List[str], out_args: List[str]):
self.op = op
self.in_args = in_args[::-1]
self.out_args = out_args[::-1]
self.builtin_args = None
self.assignments = None

def must_be_computed(self):
"""
Check whether an instruction must be computed (i.e. added as part of the opertions fed into the greedy
algorithm) or not. Instructions that must not be computed include assignments (as they are propagated directly)
and functionReturns
"""
return self.op != "assignments"

def set_builtin_args(self, builtin: List[str]) -> None:
self.builtin_args = builtin
Expand All @@ -112,6 +121,9 @@ def get_as_json(self):
if self.builtin_args is not None:
instruction["builtinArgs"] = self.builtin_args

if self.assignments is not None:
instruction["assignment"] = self.assignments

return instruction

def build_spec(self, out_idx, instrs_idx, map_instructions, assignments: Dict[str, str]):
Expand Down
30 changes: 23 additions & 7 deletions src/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from parser.cfg_function import CFGFunction
from parser.cfg_block import CFGBlock
from parser.cfg_instruction import CFGInstruction
from parser.utils_parser import check_instruction_validity, check_block_validity
from parser.utils_parser import check_instruction_validity, check_block_validity, check_assignment_validity

block_id_T = str

Expand All @@ -28,10 +28,26 @@ def parse_instruction(ins_json: Dict[str,Any]) -> CFGInstruction:
return instruction


def parse_assignment(assignment: Dict[str, Any], assignment_dict: Dict[str, str]) -> None:
for in_var, out_var in zip(assignment["in"], assignment["out"]):
def parse_assignment(assignment: Dict[str, Any], assignment_dict: Dict[str, str]) -> CFGInstruction:
"""
Assignments are handled differently than other instructions, as they have no op field and (theoretically)
multiple assignments can be made at the same time. An instruction is generated per assignment
"""
in_args = assignment.get("in", -1)
assignment_args = assignment.get("assignment", -1)
out_args = assignment.get("out", -1)

check_assignment_validity(in_args, assignment_args, out_args)

# Assignments are combined into a single instruction, maintaining the original format
instruction = CFGInstruction("assignments", in_args, out_args)

# Extend the assignment dict with the corresponding information
for in_var, out_var in zip(in_args, out_args):
assignment_dict[out_var] = in_var

return instruction


def parse_block(block_json: Dict[str,Any]) -> Tuple[block_id_T, CFGBlock, block_id_T]:
block_id = block_json.get("id", -1)
Expand All @@ -43,11 +59,11 @@ def parse_block(block_json: Dict[str,Any]) -> Tuple[block_id_T, CFGBlock, block_

list_cfg_instructions = []
assignment_dict = dict()
for instructions in block_instructions:
if "assignment" in instructions:
parse_assignment(instructions, assignment_dict)
for instruction in block_instructions:
if "assignment" in instruction:
list_cfg_instructions.append(parse_assignment(instruction, assignment_dict))
else:
cfg_instruction = parse_instruction(instructions) if block_type != "FunctionReturn" else []
cfg_instruction = parse_instruction(instruction) if block_type != "FunctionReturn" else []
list_cfg_instructions.append(cfg_instruction)

block = CFGBlock(block_id, list_cfg_instructions, block_type, assignment_dict)
Expand Down
11 changes: 10 additions & 1 deletion src/parser/utils_parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

from typing import List

def check_block_validity(block_id, block_instructions, block_exit, block_type):
if block_id == -1:
Expand All @@ -25,6 +25,15 @@ def check_instruction_validity(in_args, op, out_args):
if out_args == -1:
raise Exception("[ERROR]: instruction does not contain out argument")


def check_assignment_validity(in_args: List[str], assignments: List[str], out_args: List[str]):
"""
Check that there is the same number of elements in fields in_args, assignments and out_args
"""
if len(in_args) != len(assignments) or len(assignments) != len(out_args):
raise Exception("[ERROR]: Assignment must contain the same number of elements for all its fields")


def process_opcode(result):
op_val = hex(int(result))[2:]

Expand Down

0 comments on commit a3dd333

Please sign in to comment.