Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

actions.py: Create enums for type and emit_type #326

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 61 additions & 28 deletions pysrc/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
# limitations under the License.
#
#END_LEGAL
from enum import Enum, auto
from typing import Optional

from verbosity import *
import patterns
import genutil
Expand All @@ -35,7 +38,7 @@ def dummy_emit(act_in,name):
dummy emit type and name as the field name'''

action = copy.deepcopy(act_in)
action.emit_type = 'dummy'
action.emit_type = ActionEmitType.DUMMY
action.field_name = name
return action

Expand All @@ -58,36 +61,66 @@ def gen_nt_action(nt):
action = action_t(str)
return action


class ActionType(Enum):
FIELD_BINDING = auto()
EMIT = auto()
NONTERMINAL = auto()
NONTERMINAL_LOOKUP_FN = auto()
ERROR = auto()
NOTHING = auto()
RETURN = auto()

def __str__(self):
if self == ActionType.FIELD_BINDING:
return "FB"
if self == ActionType.NONTERMINAL:
return "nt"
if self == ActionType.NONTERMINAL_LOOKUP_FN:
return "ntluf"
return self.name.lower()


class ActionEmitType(Enum):
NUMERIC = auto()
LETTERS = auto()
REG = auto()
DUMMY = auto()

def __str__(self):
return self.name.lower()


class action_t(object):
"""This is the right hand side of the rule_t. It can be a (1)
field binding (2) a byte encoding, (3) 'error' or (4) 'nothing'."""


def __init__(self, arg_action):
# field bindings (FB) are OD=value
self.type = None # 'FB', 'emit', 'nt', 'error', 'nothing', 'return'
self.type: Optional[ActionType] = None
self.field_name = None
self.value = None
self.nt = None
self.ntluf = None
self.int_value = None
self.emit_type = None # 'numeric', 'letters', 'reg'
self.emit_type: Optional[ActionEmitType] = None
self.nbits = 0
if vaction():
msgb("ARGACTION", arg_action)
if arg_action in ['nothing', "NOTHING"]:
self.type = 'nothing'
self.type = ActionType.NOTHING
return

b = patterns.return_pattern.search(arg_action)
if b:
self.type = 'return'
self.type = ActionType.RETURN
self.value = b.group('retval')
return

# in the inputs, "error" gets expanded to "ERROR=1" via the statebits.
if arg_action == 'error' or arg_action == "ERROR" or arg_action == 'ERROR=1':
self.type = 'error'
self.type = ActionType.ERROR
return

b = patterns.bit_expand_pattern.search(arg_action)
Expand All @@ -114,33 +147,33 @@ def __init__(self, arg_action):
else:
self.value = rhs

self.type = 'FB'
self.type = ActionType.FIELD_BINDING
return

nt = patterns.nt_name_pattern.match(action)
if nt:
# NTLUF or NT. Only shows up on decode-oriented rules
self.nt = nt.group('ntname')
self.type = 'nt'
self.type = ActionType.NONTERMINAL
return
ntluf = patterns.ntluf_name_pattern.match(action)
if ntluf:
# NTLUF or NT. Only shows up on decode-oriented rules
self.ntluf = ntluf.group('ntname')
self.type = 'ntluf'
self.type = ActionType.NONTERMINAL_LOOKUP_FN
return

cp = patterns.lhs_capture_pattern_end.match(action)
if cp:
self.type = 'emit'
self.type = ActionType.EMIT
self.value = cp.group('bits')
self.field_name = cp.group('name').lower()
#msgerr("EMIT ACTION %s" % action)
self.classify()
return

# simple byte encoding
self.type = 'emit'
self.type = ActionType.EMIT
self.field_name = None
#msgerr("EMIT ACTION %s" % action)
self.value = action
Expand All @@ -149,7 +182,7 @@ def __init__(self, arg_action):

def classify(self):
if patterns.decimal_pattern.match(self.value):
self.emit_type = 'numeric'
self.emit_type = ActionEmitType.NUMERIC
self.int_value = int(self.value)
t = hex(self.int_value)
self.nbits = 4*len(t[2:])
Expand All @@ -158,14 +191,14 @@ def classify(self):
return

if patterns.hex_pattern.match(self.value):
self.emit_type = 'numeric'
self.emit_type = ActionEmitType.NUMERIC
self.int_value = int(self.value,16)
self.nbits = 4*(len(self.value)-2) # drop the 0x, convert nibbles to bits
if vclassify():
msgb("CLASSIFY", "%s as hex" % (self.value))
return
if patterns.letter_and_underscore_pattern.match(self.value):
self.emit_type = 'letters'
self.emit_type = ActionEmitType.LETTERS
t = self.value
t = genutil.no_underscores(t)
self.nbits = len(t)
Expand All @@ -174,7 +207,7 @@ def classify(self):
return
b = patterns.binary_pattern.match(self.value) # leading "0b"
if b:
self.emit_type = 'numeric'
self.emit_type = ActionEmitType.NUMERIC
t = '0b' + b.group('bits') # pattern match strips out 0b
self.int_value = genutil.make_numeric(t)
bits_str = genutil.make_binary(t)
Expand All @@ -183,7 +216,7 @@ def classify(self):
msgb("CLASSIFY", "%s as explicit-binary -> int = %d nbits=%d [%s,%s]" % (self.value,self.int_value,self.nbits,t,bits_str))
return
if patterns.bits_and_letters_underscore_pattern.match(self.value):
self.emit_type = 'letters'
self.emit_type = ActionEmitType.LETTERS
v = genutil.no_underscores(self.value)
self.nbits = len(v)
if vclassify():
Expand All @@ -192,7 +225,7 @@ def classify(self):


if patterns.simple_number_pattern.match(self.value):
self.emit_type = 'numeric'
self.emit_type = ActionEmitType.NUMERIC
self.int_value = genutil.make_numeric(self.value)
t = hex(self.int_value)
self.nbits = 4*len(t[2:])
Expand All @@ -204,16 +237,16 @@ def classify(self):

def naked_bits(self):
''' returns True if the type is emit but there is no field name. '''
if self.type == 'emit' and self.field_name == None:
if self.type == ActionType.EMIT and self.field_name == None:
return True
return False

def is_nothing(self):
return self.type == 'nothing'
return self.type == ActionType.NOTHING
def is_error(self):
return self.type == 'error'
return self.type == ActionType.ERROR
def is_return(self):
return self.type == 'return'
return self.type == ActionType.RETURN

def is_nonterminal(self):
if self.nt:
Expand All @@ -226,13 +259,13 @@ def is_ntluf(self):

def is_field_binding(self):
"""Return True if this action is a field binding."""
if self.type == 'FB':
if self.type == ActionType.FIELD_BINDING:
return True
return False

def is_emit_action(self):
"""Return True if this action is an emit action."""
if self.type == 'emit':
if self.type == ActionType.EMIT:
return True
return False

Expand All @@ -248,7 +281,7 @@ def __str__(self):
s.append(" ")
s.append(self.value)
if self.emit_type:
s.append(" emit_type=%s" % self.emit_type)
s.append(" emit_type=%s" % str(self.emit_type))
if self.int_value != None:
s.append(" value=0x%x" % self.int_value)
if self.nbits != 0:
Expand Down Expand Up @@ -304,9 +337,9 @@ def _generate_code_for_field_binding(self, bind_or_emit):
def _generate_code_for_emit_action(self,bind_or_emit):
"""Emit code for emit action """
if bind_or_emit == 'BIND':
if self.emit_type == 'letters' or self.field_name == None:
if self.emit_type == ActionEmitType.LETTERS or self.field_name == None:
return ''
elif self.emit_type == 'numeric':
elif self.emit_type == ActionEmitType.NUMERIC:
op_accessor = encutil.enc_strings['op_accessor']
operand_setter = "%s_set_%s" % (op_accessor,
self.field_name.lower())
Expand All @@ -315,14 +348,14 @@ def _generate_code_for_emit_action(self,bind_or_emit):
code = "%s(%s, %s);" % (operand_setter, obj_name, hex_val)
return [' ' + code]
else:
genutil.die("Unknown emit_type %s" % self.emit_type)
genutil.die("Unknown emit_type %s" % str(self.emit_type))
else: # EMIT
emit_util_function = encutil.enc_strings['emit_util_function']
obj_name = encutil.enc_strings['obj_str']
nbits = self.nbits
code = ''
if self.field_name == None:
if self.emit_type == 'numeric':
if self.emit_type == ActionEmitType.NUMERIC:
hex_val = hex(self.int_value)
code = "%s(%s, %d, %s);" % (emit_util_function,obj_name,
nbits,hex_val)
Expand Down
19 changes: 10 additions & 9 deletions pysrc/ins_emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import encutil
import genutil
import actions
from actions import ActionType, ActionEmitType
import verbosity

max_in_byte = 256 #max unsigned int per byte
Expand Down Expand Up @@ -727,12 +728,12 @@ def _make_field_bindings_pattern(self,iform):

bind_actions = []
for action in iform.rule.actions:
if action.type == 'nt':
if action.type == ActionType.NONTERMINAL:
pass
elif action.type == 'FB':
elif action.type == ActionType.FIELD_BINDING:
bind_actions.append(action.field_name)
elif action.type == 'emit':
if action.emit_type == 'numeric' and action.field_name:
elif action.type == ActionType.EMIT:
if action.emit_type == ActionEmitType.NUMERIC and action.field_name:
bind_actions.append(action.field_name)
else:
pass
Expand All @@ -754,7 +755,7 @@ def _make_emit_pattern(self,iform):
def _make_emit_pattern_low(self,iform):
emit_pattern = []
for action in iform.rule.actions:
if action.type == 'emit':
if action.type == ActionType.EMIT:
# if no field_name, then we must differentiate the
# emit patterns using the value to avoid collisions.
if action.field_name == None:
Expand All @@ -767,14 +768,14 @@ def _make_emit_pattern_low(self,iform):
action.field_name,
action.nbits))

elif action.type == 'nt':
elif action.type == ActionType.NONTERMINAL:
emit_pattern.append(str(action))
elif action.type == 'FB':
elif action.type == ActionType.FIELD_BINDING:
# FB are not used in emit phase so we do not factor them
# in to the string that represents the pattern
pass
else:
genutil.die("unexpected action type: %s" % action.type)
genutil.die("unexpected action type: %s" % str(action.type))
emit_actions_str = ', '.join(emit_pattern)
return emit_actions_str

Expand All @@ -783,7 +784,7 @@ def _make_bind_pattern(self,iform):

bind_ptrn = [ str(iform.rule.conditions) ]
for action in iform.rule.actions:
if action.type == 'nt':
if action.type == ActionType.NONTERMINAL:
bind_ptrn.append(str(action))

iform.bind_ptrn = ''
Expand Down
13 changes: 7 additions & 6 deletions pysrc/read-encfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def find_dir(d):
sys.exit(1)

import actions
from actions import ActionEmitType, ActionType
import ins_emit
import encutil
from patterns import *
Expand Down Expand Up @@ -721,7 +722,7 @@ def compute_field_capture_list(self):

def prepare_value_for_emit(self, a):
"""@return: (length-in-bits, value-as-hex)"""
if a.emit_type == 'numeric':
if a.emit_type == ActionEmitType.NUMERIC:
v = hex(a.int_value)
return (a.nbits, v) # return v with the leading 0x
s = a.value
Expand Down Expand Up @@ -996,7 +997,7 @@ def emit_rule_emit(self, ith_rule_arg, nt_name, captures):

if vtuples():
msgb("TUPLES", (" ,".join( [str(x) for x in list_of_tuples] )))
if len(list_of_tuples) == 0 or a.emit_type == 'numeric':
if len(list_of_tuples) == 0 or a.emit_type == ActionEmitType.NUMERIC:
# no substitutions required
(length, s) = self.prepare_value_for_emit(a)
if veemit():
Expand Down Expand Up @@ -1045,7 +1046,7 @@ def get_all_fbs(self):
fbs.append(action)
if action.field_name == 'MAP':
found_map_fb = True
if action.is_emit_action() and action.emit_type == 'numeric':
if action.is_emit_action() and action.emit_type == ActionEmitType.NUMERIC:
if action.field_name:
fbs.append(action)

Expand Down Expand Up @@ -1321,15 +1322,15 @@ def _remove_overlapping_actions(self, action_list):
modifying to input action_list
'''

emit_actions = list(filter(lambda x: x.type == 'emit', action_list))
fb_actions = list(filter(lambda x: x.type == 'FB', action_list))
emit_actions = list(filter(lambda x: x.type == ActionType.EMIT, action_list))
fb_actions = list(filter(lambda x: x.type == ActionType.FIELD_BINDING, action_list))

#iterate to find overlapping actions
action_to_remove = []
for fb in fb_actions:
for emit in emit_actions:
if fb.field_name.lower() == emit.field_name and \
emit.emit_type == 'numeric':
emit.emit_type == ActionEmitType.NUMERIC:
if fb.int_value == emit.int_value:
# overlapping actions, recored this action
# and remove later
Expand Down