Internals: Reformat with new settings (last commit). No functional change.

This commit is contained in:
Wilson Snyder
2024-08-26 21:53:36 -04:00
parent bde4097df2
commit ae35be9102
23 changed files with 433 additions and 816 deletions
+121 -230
View File
@@ -89,8 +89,7 @@ class Node:
assert not self.isCompleted
# Sort sub-classes and convert to tuple, which marks completion
self._subClasses = tuple(
sorted(self._subClasses,
key=lambda _: (bool(_._subClasses), _.name))) # pylint: disable=protected-access
sorted(self._subClasses, key=lambda _: (bool(_._subClasses), _.name))) # pylint: disable=protected-access
self._ordIdx = ordIdx
ordIdx = ordIdx + 1
@@ -128,8 +127,7 @@ class Node:
if self.superClass is None:
self._allSuperClasses = ()
else:
self._allSuperClasses = self.superClass.allSuperClasses + (
self.superClass, )
self._allSuperClasses = self.superClass.allSuperClasses + (self.superClass, )
return self._allSuperClasses
@property
@@ -139,9 +137,8 @@ class Node:
if self.isLeaf:
self._allSubClasses = ()
else:
self._allSubClasses = self.subClasses + tuple(
_ for subClass in self.subClasses
for _ in subClass.allSubClasses)
self._allSubClasses = self.subClasses + tuple(_ for subClass in self.subClasses
for _ in subClass.allSubClasses)
return self._allSubClasses
@property
@@ -210,8 +207,7 @@ class Cpt:
self._exec_syms = {}
def error(self, txt):
sys.exit("%%Error: %s:%d: %s" %
(self.in_filename, self.in_linenum, txt))
sys.exit("%%Error: %s:%d: %s" % (self.in_filename, self.in_linenum, txt))
def print(self, txt):
self.out_lines.append(txt)
@@ -220,8 +216,7 @@ class Cpt:
self.out_lines.append(func)
def _output_line(self):
self.print("#line " + str(self.out_linenum + 2) + " \"" +
self.out_filename + "\"\n")
self.print("#line " + str(self.out_linenum + 2) + " \"" + self.out_filename + "\"\n")
def process(self, in_filename, out_filename):
self.in_filename = in_filename
@@ -234,8 +229,7 @@ class Cpt:
for line in fhi:
ln += 1
if not didln:
self.print("#line " + str(ln) + " \"" + self.in_filename +
"\"\n")
self.print("#line " + str(ln) + " \"" + self.in_filename + "\"\n")
didln = True
match = re.match(r'^\s+(TREE.*)$', line)
if match:
@@ -245,8 +239,8 @@ class Cpt:
self.output_func(lambda self: self._output_line())
self.tree_line(func)
didln = False
elif not re.match(r'^\s*(#define|/[/\*])\s*TREE',
line) and re.search(r'\s+TREE', line):
elif not re.match(r'^\s*(#define|/[/\*])\s*TREE', line) and re.search(
r'\s+TREE', line):
self.error("Unknown astgen line: " + line)
else:
self.print(line)
@@ -275,8 +269,7 @@ class Cpt:
# 1 2 3 4
r'TREEOP(1?)([ACSV]?)\s*\(\s*\"([^\"]*)\"\s*,\s*\"([^\"]*)\"\s*\)',
func)
match_skip = re.search(r'TREE_SKIP_VISIT\s*\(\s*\"([^\"]*)\"\s*\)',
func)
match_skip = re.search(r'TREE_SKIP_VISIT\s*\(\s*\"([^\"]*)\"\s*\)', func)
if match:
order = match.group(1)
@@ -314,20 +307,18 @@ class Cpt:
if re.match(r'^\$([a-zA-Z0-9]+)$', subnode):
continue # "$lhs" is just a comment that this op has a lhs
subnodeif = subnode
subnodeif = re.sub(
r'\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$',
r'VN_IS(nodep->\1(),\2)', subnodeif)
subnodeif = re.sub(r'\$([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$',
r'nodep->\1()->\2()', subnodeif)
subnodeif = re.sub(r'\$([a-zA-Z0-9]+)\.cast([A-Z][A-Za-z0-9]+)$',
r'VN_IS(nodep->\1(),\2)', subnodeif)
subnodeif = re.sub(r'\$([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)$', r'nodep->\1()->\2()',
subnodeif)
subnodeif = self.add_nodep(subnodeif)
if mif != "" and subnodeif != "":
mif += " && "
mif += subnodeif
exec_func = self.treeop_exec_func(to)
exec_func = re.sub(
r'([-()a-zA-Z0-9_>]+)->cast([A-Z][A-Za-z0-9]+)\(\)',
r'VN_CAST(\1,\2)', exec_func)
exec_func = re.sub(r'([-()a-zA-Z0-9_>]+)->cast([A-Z][A-Za-z0-9]+)\(\)',
r'VN_CAST(\1,\2)', exec_func)
if typen not in self.treeop:
self.treeop[typen] = []
@@ -431,14 +422,12 @@ class Cpt:
self._exec_nsyms = 0
self._exec_syms_recurse(aref)
for sym in sorted(self._exec_syms.keys(),
key=lambda val: self._exec_syms[val]):
for sym in sorted(self._exec_syms.keys(), key=lambda val: self._exec_syms[val]):
argnp = self._exec_syms[sym]
arg = self.add_nodep(sym)
out += "AstNodeExpr* " + argnp + " = " + arg + "->unlinkFrBack();\n"
out += "AstNodeExpr* newp = " + self._exec_new_recurse(
aref) + ";\n"
out += "AstNodeExpr* newp = " + self._exec_new_recurse(aref) + ";\n"
out += "nodep->replaceWith(newp);"
out += "VL_DO_DANGLING(nodep->deleteTree(), nodep);"
elif func == "NEVER":
@@ -454,19 +443,15 @@ class Cpt:
self.tree_base()
def tree_match(self):
self.print(
" // TREEOP functions, each return true if they matched & transformed\n"
)
self.print(" // TREEOP functions, each return true if they matched & transformed\n")
for base in sorted(self.treeop.keys()):
for typefunc in self.treeop[base]:
self.print(" // Generated by astgen\n")
self.print(" bool " + typefunc['match_func'] + "(Ast" +
base + "* nodep) {\n")
self.print(" bool " + typefunc['match_func'] + "(Ast" + base + "* nodep) {\n")
self.print("\t// " + typefunc['comment'] + "\n")
self.print("\tif (" + typefunc['match_if'] + ") {\n")
self.print("\t UINFO(" + str(typefunc['uinfo_level']) +
", cvtToHex(nodep)" + " << \" " +
typefunc['uinfo'] + "\\n\");\n")
self.print("\t UINFO(" + str(typefunc['uinfo_level']) + ", cvtToHex(nodep)" +
" << \" " + typefunc['uinfo'] + "\\n\");\n")
self.print("\t " + typefunc['exec_func'] + "\n")
self.print("\t return true;\n")
self.print("\t}\n")
@@ -475,9 +460,7 @@ class Cpt:
def tree_base(self):
self.print(" // TREEOP visitors, call each base type's match\n")
self.print(
" // Bottom class up, as more simple transforms are generally better\n"
)
self.print(" // Bottom class up, as more simple transforms are generally better\n")
for node in AstNodeList:
out_for_type_sc = []
out_for_type = []
@@ -488,15 +471,11 @@ class Cpt:
if base not in self.treeop:
continue
for typefunc in self.treeop[base]:
lines = [
" if (" + typefunc['match_func'] +
"(nodep)) return;\n"
]
lines = [" if (" + typefunc['match_func'] + "(nodep)) return;\n"]
if typefunc['short_circuit']: # short-circuit match fn
out_for_type_sc.extend(lines)
else: # Standard match fn
if typefunc[
'order']: # TREEOP1's go in front of others
if typefunc['order']: # TREEOP1's go in front of others
out_for_type = lines + out_for_type
else:
out_for_type.extend(lines)
@@ -509,32 +488,26 @@ class Cpt:
# For types without short-circuits, we just use iterateChildren, which
# saves one comparison.
if len(out_for_type_sc) > 0: # Short-circuited types
self.print(
" // Generated by astgen with short-circuiting\n" +
" void visit(Ast" + node.name +
"* nodep) override {\n" +
" iterateAndNextNull(nodep->{op1}());\n".format(
op1=node.getOp(1)[0]) + "".join(out_for_type_sc))
self.print(" // Generated by astgen with short-circuiting\n" +
" void visit(Ast" + node.name + "* nodep) override {\n" +
" iterateAndNextNull(nodep->{op1}());\n".format(
op1=node.getOp(1)[0]) + "".join(out_for_type_sc))
if out_for_type[0]:
self.print(
" iterateAndNextNull(nodep->{op2}());\n".format(
op2=node.getOp(2)[0]))
" iterateAndNextNull(nodep->{op2}());\n".format(op2=node.getOp(2)[0]))
if node.isSubClassOf(AstNodes["NodeTriop"]):
self.print(
" iterateAndNextNull(nodep->{op3}());\n".
format(op3=node.getOp(3)[0]))
self.print(" iterateAndNextNull(nodep->{op3}());\n".format(
op3=node.getOp(3)[0]))
self.print("".join(out_for_type) + " }\n")
elif len(out_for_type) > 0: # Other types with something to print
skip = node.name in self.tree_skip_visit
gen = "Gen" if skip else ""
virtual = "virtual " if skip else ""
override = "" if skip else " override"
self.print(
" // Generated by astgen\n" + " " + virtual +
"void visit" + gen + "(Ast" + node.name + "* nodep)" +
override + " {\n" +
("" if skip else " iterateChildren(nodep);\n") +
''.join(out_for_type) + " }\n")
self.print(" // Generated by astgen\n" + " " + virtual + "void visit" + gen +
"(Ast" + node.name + "* nodep)" + override + " {\n" +
("" if skip else " iterateChildren(nodep);\n") +
''.join(out_for_type) + " }\n")
######################################################################
@@ -565,8 +538,7 @@ def read_types(filename, Nodes, prefix):
def error(lineno, message):
nonlocal hasErrors
print(filename + ":" + str(lineno) + ": %Error: " + message,
file=sys.stderr)
print(filename + ":" + str(lineno) + ": %Error: " + message, file=sys.stderr)
hasErrors = True
node = None
@@ -579,8 +551,7 @@ def read_types(filename, Nodes, prefix):
if not hasAstgenMembers:
error(
node.lineno,
"'{p}{n}' does not contain 'ASTGEN_MEMBERS_{p}{n};'".format(
p=prefix, n=node.name))
"'{p}{n}' does not contain 'ASTGEN_MEMBERS_{p}{n};'".format(p=prefix, n=node.name))
hasAstgenMembers = False
with open(filename, "r", encoding="utf8") as fh:
@@ -598,8 +569,7 @@ def read_types(filename, Nodes, prefix):
classn = re.sub(r'^' + prefix, '', classn)
supern = re.sub(r'^' + prefix, '', supern)
if not supern:
sys.exit("%Error: '{p}{c}' has no super-class".format(
p=prefix, c=classn))
sys.exit("%Error: '{p}{c}' has no super-class".format(p=prefix, c=classn))
checkFinishedNode(node)
superClass = Nodes[supern]
node = Node(classn, superClass, filename, lineno)
@@ -608,8 +578,7 @@ def read_types(filename, Nodes, prefix):
if not node:
continue
if re.match(r'^\s*ASTGEN_MEMBERS_' + prefix + node.name + ';',
line):
if re.match(r'^\s*ASTGEN_MEMBERS_' + prefix + node.name + ';', line):
hasAstgenMembers = True
if prefix != "Ast":
@@ -631,36 +600,29 @@ def read_types(filename, Nodes, prefix):
ident = ident.strip()
if not sep or not re.match(r'^\w+$', ident):
error(
lineno, "Malformed '@astgen " + what +
"' directive (expecting '" + what +
" := <identifier> : <type>': " + decl)
lineno, "Malformed '@astgen " + what + "' directive (expecting '" +
what + " := <identifier> : <type>': " + decl)
else:
kind = parseOpType(kind)
if not kind:
error(
lineno, "Bad type for '@astgen " + what +
"' (expecting Ast*, Optional[Ast*], or List[Ast*]):"
+ decl)
"' (expecting Ast*, Optional[Ast*], or List[Ast*]):" + decl)
elif node.getOp(n) is not None:
error(
lineno, "Already defined " + what + " for " +
node.name)
error(lineno, "Already defined " + what + " for " + node.name)
else:
node.addOp(n, ident, *kind)
elif what in ("alias op1", "alias op2", "alias op3",
"alias op4"):
elif what in ("alias op1", "alias op2", "alias op3", "alias op4"):
n = int(what[-1])
ident = rest.strip()
if not re.match(r'^\w+$', ident):
error(
lineno, "Malformed '@astgen " + what +
"' directive (expecting '" + what +
" := <identifier>': " + decl)
lineno, "Malformed '@astgen " + what + "' directive (expecting '" +
what + " := <identifier>': " + decl)
else:
op = node.getOp(n)
if op is None:
error(lineno,
"Aliased op" + str(n) + " is not defined")
error(lineno, "Aliased op" + str(n) + " is not defined")
else:
node.addOp(n, ident, *op[1:])
elif what == "ptr":
@@ -670,8 +632,7 @@ def read_types(filename, Nodes, prefix):
if not kind:
error(
lineno, "Bad type for '@astgen " + what +
"' (expecting Ast*, Optional[Ast*], or List[Ast*]):"
+ decl)
"' (expecting Ast*, Optional[Ast*], or List[Ast*]):" + decl)
if not re.match(r'^m_(\w+)$', ident):
error(
lineno, "Malformed '@astgen ptr'"
@@ -680,20 +641,15 @@ def read_types(filename, Nodes, prefix):
node.addPtr(ident, *kind)
else:
error(
lineno,
"Malformed @astgen what (expecting 'op1'..'op4'," +
lineno, "Malformed @astgen what (expecting 'op1'..'op4'," +
" 'alias op1'.., 'ptr'): " + what)
else:
line = re.sub(r'//.*$', '', line)
if re.match(r'.*[Oo]p[1-9].*', line):
error(lineno,
"Use generated accessors to access op<N> operands")
error(lineno, "Use generated accessors to access op<N> operands")
if re.match(
r'^\s*Ast[A-Z][A-Za-z0-9_]+\s*\*(\s*const)?\s+m_[A-Za-z0-9_]+\s*;',
line):
error(lineno,
"Use '@astgen ptr' for Ast pointer members: " + line)
if re.match(r'^\s*Ast[A-Z][A-Za-z0-9_]+\s*\*(\s*const)?\s+m_[A-Za-z0-9_]+\s*;', line):
error(lineno, "Use '@astgen ptr' for Ast pointer members: " + line)
checkFinishedNode(node)
if hasErrors:
@@ -707,33 +663,24 @@ def check_types(sortedTypes, prefix, abstractPrefix):
for node in sortedTypes:
if re.match(r'^' + abstractPrefix, node.name):
if node.isLeaf:
sys.exit(
"%Error: Final {b} subclasses must not be named {b}*: {p}{n}"
.format(b=baseClass, p=prefix, n=node.name))
sys.exit("%Error: Final {b} subclasses must not be named {b}*: {p}{n}".format(
b=baseClass, p=prefix, n=node.name))
else:
if not node.isLeaf:
sys.exit(
"%Error: Non-final {b} subclasses must be named {b}*: {p}{n}"
.format(b=baseClass, p=prefix, n=node.name))
sys.exit("%Error: Non-final {b} subclasses must be named {b}*: {p}{n}".format(
b=baseClass, p=prefix, n=node.name))
# Check ordering of node definitions
hasOrderingError = False
files = tuple(
sorted(set(_.file for _ in sortedTypes if _.file is not None)))
files = tuple(sorted(set(_.file for _ in sortedTypes if _.file is not None)))
for file in files:
nodes = tuple(filter(lambda _, f=file: _.file == f, sortedTypes))
expectOrder = tuple(sorted(nodes, key=lambda _: (_.isLeaf, _.ordIdx)))
actualOrder = tuple(sorted(nodes, key=lambda _: _.lineno))
expect = {
node: pred
for pred, node in zip((None, ) + expectOrder[:-1], expectOrder)
}
actual = {
node: pred
for pred, node in zip((None, ) + actualOrder[:-1], actualOrder)
}
expect = {node: pred for pred, node in zip((None, ) + expectOrder[:-1], expectOrder)}
actual = {node: pred for pred, node in zip((None, ) + actualOrder[:-1], actualOrder)}
for node in nodes:
if expect[node] != actual[node]:
hasOrderingError = True
@@ -749,8 +696,7 @@ def check_types(sortedTypes, prefix, abstractPrefix):
file=sys.stderr)
if hasOrderingError:
sys.exit(
"%Error: Stopping due to out of order definitions listed above")
sys.exit("%Error: Stopping due to out of order definitions listed above")
def read_stages(filename):
@@ -783,8 +729,7 @@ def read_refs(filename):
if ref not in ClassRefs:
ClassRefs[ref] = {'newed': {}, 'used': {}}
ClassRefs[ref]['used'][basename] = 1
for match in re.finditer(
r'(VN_IS|VN_AS|VN_CAST)\([^.]+, ([A-Za-z0-9_]+)', line):
for match in re.finditer(r'(VN_IS|VN_AS|VN_CAST)\([^.]+, ([A-Za-z0-9_]+)', line):
ref = "Ast" + match.group(2)
if ref not in ClassRefs:
ClassRefs[ref] = {'newed': {}, 'used': {}}
@@ -796,9 +741,7 @@ def open_file(filename):
if re.search(r'\.txt$', filename):
fh.write("// Generated by astgen\n")
else:
fh.write(
'// Generated by astgen // -*- mode: C++; c-file-style: "cc-mode" -*-'
+ "\n")
fh.write('// Generated by astgen // -*- mode: C++; c-file-style: "cc-mode" -*-' + "\n")
return fh
@@ -808,9 +751,7 @@ def open_file(filename):
def write_report(filename):
with open_file(filename) as fh:
fh.write(
"Processing stages (approximate, based on order in Verilator.cpp):\n"
)
fh.write("Processing stages (approximate, based on order in Verilator.cpp):\n")
for classn in sorted(Stages.keys(), key=lambda val: Stages[val]):
fh.write(" " + classn + "\n")
@@ -831,14 +772,12 @@ def write_report(filename):
refs = ClassRefs["Ast" + node.name]
fh.write(" newed: ")
for stage in sorted(refs['newed'].keys(),
key=lambda val: Stages[val]
if (val in Stages) else -1):
key=lambda val: Stages[val] if (val in Stages) else -1):
fh.write(stage + " ")
fh.write("\n")
fh.write(" used: ")
for stage in sorted(refs['used'].keys(),
key=lambda val: Stages[val]
if (val in Stages) else -1):
key=lambda val: Stages[val] if (val in Stages) else -1):
fh.write(stage + " ")
fh.write("\n")
fh.write("\n")
@@ -852,8 +791,7 @@ def write_report(filename):
def write_forward_class_decls(prefix, nodeList):
with open_file("V3{p}__gen_forward_class_decls.h".format(p=prefix)) as fh:
for node in nodeList:
fh.write("class {p}{n:<17} // ".format(p=prefix,
n=node.name + ";"))
fh.write("class {p}{n:<17} // ".format(p=prefix, n=node.name + ";"))
for superClass in node.allSuperClasses:
fh.write("{p}{n:<12} ".format(p=prefix, n=superClass.name))
fh.write("\n")
@@ -863,8 +801,7 @@ def write_visitor_decls(prefix, nodeList):
with open_file("V3{p}__gen_visitor_decls.h".format(p=prefix)) as fh:
for node in nodeList:
if not node.isRoot:
fh.write("virtual void visit({p}{n}*);\n".format(p=prefix,
n=node.name))
fh.write("virtual void visit({p}{n}*);\n".format(p=prefix, n=node.name))
def write_visitor_defns(prefix, nodeList, visitor):
@@ -873,13 +810,8 @@ def write_visitor_defns(prefix, nodeList, visitor):
for node in nodeList:
base = node.superClass
if base is not None:
fh.write(
"void {c}::visit({p}{n}* {v}) {{ visit(static_cast<{p}{b}*>({v})); }}\n"
.format(c=visitor,
p=prefix,
n=node.name,
b=base.name,
v=variable))
fh.write("void {c}::visit({p}{n}* {v}) {{ visit(static_cast<{p}{b}*>({v})); }}\n".
format(c=visitor, p=prefix, n=node.name, b=base.name, v=variable))
def write_type_enum(prefix, nodeList):
@@ -887,27 +819,21 @@ def write_type_enum(prefix, nodeList):
with open_file("V3{p}__gen_type_enum.h".format(p=prefix)) as fh:
fh.write(" enum en : uint16_t {\n")
for node in sorted(filter(lambda _: _.isLeaf, nodeList),
key=lambda _: _.typeId):
fh.write(" at{t} = {n},\n".format(t=node.name,
n=node.typeId))
for node in sorted(filter(lambda _: _.isLeaf, nodeList), key=lambda _: _.typeId):
fh.write(" at{t} = {n},\n".format(t=node.name, n=node.typeId))
fh.write(" _ENUM_END = {n}\n".format(n=root.typeIdMax + 1))
fh.write(" };\n")
fh.write(" enum bounds : uint16_t {\n")
for node in sorted(filter(lambda _: not _.isLeaf, nodeList),
key=lambda _: _.typeIdMin):
fh.write(" first{t} = {n},\n".format(t=node.name,
n=node.typeIdMin))
fh.write(" last{t} = {n},\n".format(t=node.name,
n=node.typeIdMax))
for node in sorted(filter(lambda _: not _.isLeaf, nodeList), key=lambda _: _.typeIdMin):
fh.write(" first{t} = {n},\n".format(t=node.name, n=node.typeIdMin))
fh.write(" last{t} = {n},\n".format(t=node.name, n=node.typeIdMax))
fh.write(" _BOUNDS_END\n")
fh.write(" };\n")
fh.write(" const char* ascii() const VL_MT_SAFE {\n")
fh.write(" static const char* const names[_ENUM_END + 1] = {\n")
for node in sorted(filter(lambda _: _.isLeaf, nodeList),
key=lambda _: _.typeId):
for node in sorted(filter(lambda _: _.isLeaf, nodeList), key=lambda _: _.typeId):
fh.write(' "{T}",\n'.format(T=node.name.upper()))
fh.write(" \"_ENUM_END\"\n")
fh.write(" };\n")
@@ -928,8 +854,8 @@ def write_type_tests(prefix, nodeList):
enum = "VDfgType"
for node in nodeList:
fh.write(
"template<> inline bool {b}::privateTypeTest<{p}{n}>(const {b}* {v}) {{ "
.format(b=base, p=prefix, n=node.name, v=variable))
"template<> inline bool {b}::privateTypeTest<{p}{n}>(const {b}* {v}) {{ ".format(
b=base, p=prefix, n=node.name, v=variable))
if node.isRoot:
fh.write("return true;")
elif not node.isLeaf:
@@ -937,8 +863,9 @@ def write_type_tests(prefix, nodeList):
"return static_cast<int>({v}->type()) >= static_cast<int>({e}::first{t}) && static_cast<int>({v}->type()) <= static_cast<int>({e}::last{t});"
.format(v=variable, e=enum, t=node.name))
else:
fh.write("return {v}->type() == {e}::at{t};".format(
v=variable, e=enum, t=node.name))
fh.write("return {v}->type() == {e}::at{t};".format(v=variable,
e=enum,
t=node.name))
fh.write(" }\n")
@@ -949,8 +876,7 @@ def write_type_tests(prefix, nodeList):
def write_ast_type_info(filename):
with open_file(filename) as fh:
for node in sorted(filter(lambda _: _.isLeaf, AstNodeList),
key=lambda _: _.typeId):
for node in sorted(filter(lambda _: _.isLeaf, AstNodeList), key=lambda _: _.typeId):
opTypeList = []
opNameList = []
for n in range(1, 5):
@@ -968,12 +894,11 @@ def write_ast_type_info(filename):
opTypeList.append('OP_LIST')
opNameList.append(name)
# opTypeStr = ', '.join(opTypeList)
opTypeStr = ', '.join(
['VNTypeInfo::{0}'.format(s) for s in opTypeList])
opTypeStr = ', '.join(['VNTypeInfo::{0}'.format(s) for s in opTypeList])
opNameStr = ', '.join(['"{0}"'.format(s) for s in opNameList])
fh.write(
' {{ "Ast{name}", {{{opTypeStr}}}, {{{opNameStr}}}, sizeof(Ast{name}) }},\n'
.format(
' {{ "Ast{name}", {{{opTypeStr}}}, {{{opNameStr}}}, sizeof(Ast{name}) }},\n'.
format(
name=node.name,
opTypeStr=opTypeStr,
opNameStr=opNameStr,
@@ -984,23 +909,19 @@ def write_ast_impl(filename):
with open_file(filename) as fh:
def emitBlock(pattern, **fmt):
fh.write(
textwrap.indent(textwrap.dedent(pattern),
" ").format(**fmt))
fh.write(textwrap.indent(textwrap.dedent(pattern), " ").format(**fmt))
for node in AstNodeList:
if node.name == "Node":
continue
emitBlock("const char* Ast{t}::brokenGen() const {{\n",
t=node.name)
emitBlock("const char* Ast{t}::brokenGen() const {{\n", t=node.name)
if node.superClass.name != 'Node':
emitBlock(" BROKEN_BASE_RTN(Ast{base}::brokenGen());\n",
base=node.superClass.name)
for ptr in node.ptrs:
if ptr['monad'] == 'Optional':
emitBlock(
" BROKEN_RTN(m_{name} && !m_{name}->brokeExists());\n",
name=ptr['name'])
emitBlock(" BROKEN_RTN(m_{name} && !m_{name}->brokeExists());\n",
name=ptr['name'])
else:
emitBlock(" BROKEN_RTN(!m_{name});\n" +
" BROKEN_RTN(!m_{name}->brokeExists());\n",
@@ -1010,8 +931,7 @@ def write_ast_impl(filename):
emitBlock("void Ast{t}::cloneRelinkGen() {{\n", t=node.name)
if node.superClass.name != 'Node':
emitBlock(" Ast{base}::cloneRelinkGen();\n",
base=node.superClass.name)
emitBlock(" Ast{base}::cloneRelinkGen();\n", base=node.superClass.name)
for ptr in node.ptrs:
emitBlock(
" if (m_{name} && m_{name}->clonep()) m_{name} = m_{name}->clonep();\n",
@@ -1020,14 +940,11 @@ def write_ast_impl(filename):
emitBlock("}}\n")
emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n",
t=node.name)
emitBlock("void Ast{t}::dumpJsonGen(std::ostream& str) const {{\n", t=node.name)
if node.superClass.name != 'Node':
emitBlock(" Ast{base}::dumpJson(str);\n",
base=node.superClass.name)
emitBlock(" Ast{base}::dumpJson(str);\n", base=node.superClass.name)
for ptr in node.ptrs:
emitBlock(" dumpJsonPtr(str, \"{name}\", m_{name});\n",
name=ptr['name'])
emitBlock(" dumpJsonPtr(str, \"{name}\", m_{name});\n", name=ptr['name'])
emitBlock("}}\n")
emitBlock(
@@ -1038,9 +955,7 @@ def write_ast_impl(filename):
if op is None:
continue
name, _, _ = op
emitBlock(
" dumpNodeListJson(str, {name}(), \"{name}\", indent);\n",
name=name)
emitBlock(" dumpNodeListJson(str, {name}(), \"{name}\", indent);\n", name=name)
emitBlock("}}\n")
@@ -1059,9 +974,7 @@ def write_ast_macros(filename):
if not any_ptr:
fh.write("private: \\\n")
any_ptr = True
emitBlock("Ast{kind}* m_{name} = nullptr;",
name=ptr['name'],
kind=ptr['kind'])
emitBlock("Ast{kind}* m_{name} = nullptr;", name=ptr['name'], kind=ptr['kind'])
if any_ptr:
fh.write("public: \\\n")
# TODO pointer accessors
@@ -1108,8 +1021,8 @@ def write_ast_macros(filename):
if not op:
continue
name, monad, kind = op
retrieve = ("VN_DBG_AS(op{n}p(), {kind})" if kind != "Node"
else "op{n}p()").format(n=n, kind=kind)
retrieve = ("VN_DBG_AS(op{n}p(), {kind})"
if kind != "Node" else "op{n}p()").format(n=n, kind=kind)
superOp = node.superClass.getOp(n)
superName = None
if superOp:
@@ -1126,8 +1039,7 @@ def write_ast_macros(filename):
n=n,
retrieve=retrieve)
if superOp:
hiddenMethods.append("add" + superName[0].upper() +
superName[1:])
hiddenMethods.append("add" + superName[0].upper() + superName[1:])
elif monad == "Optional":
emitBlock('''\
Ast{kind}* {name}() const VL_MT_STABLE {{ return {retrieve}; }}
@@ -1150,27 +1062,24 @@ def write_ast_macros(filename):
if hiddenMethods:
fh.write("private: \\\n")
for method in hiddenMethods:
fh.write(" using Ast{sup}::{method}; \\\n".format(
sup=node.superClass.name, method=method))
fh.write(" using Ast{sup}::{method}; \\\n".format(sup=node.superClass.name,
method=method))
fh.write("public: \\\n")
fh.write(
" static_assert(true, \"\")\n") # Swallowing the semicolon
fh.write(" static_assert(true, \"\")\n") # Swallowing the semicolon
# Only care about leaf classes for the rest
if node.isLeaf:
fh.write(
"#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n"
.format(t=node.name, b=node.superClass.name))
"#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n".format(
t=node.name, b=node.superClass.name))
fh.write("\n")
def write_ast_yystype(filename):
with open_file(filename) as fh:
for node in AstNodeList:
fh.write("Ast{t}* {m}p;\n".format(t=node.name,
m=node.name[0].lower() +
node.name[1:]))
fh.write("Ast{t}* {m}p;\n".format(t=node.name, m=node.name[0].lower() + node.name[1:]))
################################################################################
@@ -1207,8 +1116,7 @@ def write_dfg_macros(filename):
name=name,
n=n - 1)
operandNames = tuple(
node.getOp(n)[0] for n in range(1, node.arity + 1))
operandNames = tuple(node.getOp(n)[0] for n in range(1, node.arity + 1))
if operandNames:
emitBlock('''\
const std::string srcName(size_t idx) const override {{
@@ -1217,10 +1125,8 @@ def write_dfg_macros(filename):
}}
''',
a=node.arity,
ns=", ".join(
map(lambda _: '"' + _ + '"', operandNames)))
fh.write(
" static_assert(true, \"\")\n") # Swallowing the semicolon
ns=", ".join(map(lambda _: '"' + _ + '"', operandNames)))
fh.write(" static_assert(true, \"\")\n") # Swallowing the semicolon
def write_dfg_auto_classes(filename):
@@ -1254,11 +1160,8 @@ def write_dfg_ast_to_dfg(filename):
if (node.file is not None) or (not node.isLeaf):
continue
fh.write(
"void visit(Ast{t}* nodep) override {{\n".format(t=node.name))
fh.write(
' UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex");\n\n'
)
fh.write("void visit(Ast{t}* nodep) override {{\n".format(t=node.name))
fh.write(' UASSERT_OBJ(!nodep->user1p(), nodep, "Already has Dfg vertex");\n\n')
fh.write(" if (unhandled(nodep)) return;\n\n")
for i in range(node.arity):
fh.write(" iterate(nodep->op{j}p());\n".format(j=i + 1))
@@ -1267,9 +1170,8 @@ def write_dfg_ast_to_dfg(filename):
' UASSERT_OBJ(nodep->op{j}p()->user1p(), nodep, "Child {j} missing Dfg vertex");\n'
.format(j=i + 1))
fh.write("\n")
fh.write(
" Dfg{t}* const vtxp = makeVertex<Dfg{t}>(nodep, *m_dfgp);\n"
.format(t=node.name))
fh.write(" Dfg{t}* const vtxp = makeVertex<Dfg{t}>(nodep, *m_dfgp);\n".format(
t=node.name))
fh.write(" if (!vtxp) {\n")
fh.write(" m_foundUnhandled = true;\n")
fh.write(" ++m_ctx.m_nonRepNode;\n")
@@ -1277,8 +1179,8 @@ def write_dfg_ast_to_dfg(filename):
fh.write(" }\n\n")
for i in range(node.arity):
fh.write(
" vtxp->relinkSource<{i}>(nodep->op{j}p()->user1u().to<DfgVertex*>());\n"
.format(i=i, j=i + 1))
" vtxp->relinkSource<{i}>(nodep->op{j}p()->user1u().to<DfgVertex*>());\n".
format(i=i, j=i + 1))
fh.write("\n")
fh.write(" m_uncommittedVertices.push_back(vtxp);\n")
fh.write(" nodep->user1p(vtxp);\n")
@@ -1292,14 +1194,12 @@ def write_dfg_dfg_to_ast(filename):
if (node.file is not None) or (not node.isLeaf):
continue
fh.write(
"void visit(Dfg{t}* vtxp) override {{\n".format(t=node.name))
fh.write("void visit(Dfg{t}* vtxp) override {{\n".format(t=node.name))
for i in range(node.arity):
fh.write(
" AstNodeExpr* const op{j}p = convertDfgVertexToAstNodeExpr(vtxp->source<{i}>());\n"
.format(i=i, j=i + 1))
fh.write(
" m_resultp = makeNode<Ast{t}>(vtxp".format(t=node.name))
fh.write(" m_resultp = makeNode<Ast{t}>(vtxp".format(t=node.name))
for i in range(node.arity):
fh.write(", op{j}p".format(j=i + 1))
fh.write(");\n")
@@ -1313,8 +1213,7 @@ parser = argparse.ArgumentParser(
allow_abbrev=False,
formatter_class=argparse.RawDescriptionHelpFormatter,
description="""Generate V3Ast headers to reduce C++ code duplication.""",
epilog=
"""Copyright 2002-2024 by Wilson Snyder. This program is free software; you
epilog="""Copyright 2002-2024 by Wilson Snyder. This program is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License
Version 2.0.
@@ -1322,15 +1221,9 @@ Version 2.0.
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
parser.add_argument('-I', action='store', help='source code include directory')
parser.add_argument('--astdef',
action='append',
help='add AST definition file (relative to -I)')
parser.add_argument('--dfgdef',
action='append',
help='add DFG definition file (relative to -I)')
parser.add_argument('--classes',
action='store_true',
help='makes class declaration files')
parser.add_argument('--astdef', action='append', help='add AST definition file (relative to -I)')
parser.add_argument('--dfgdef', action='append', help='add DFG definition file (relative to -I)')
parser.add_argument('--classes', action='store_true', help='makes class declaration files')
parser.add_argument('--debug', action='store_true', help='enable debug')
parser.add_argument('infiles', nargs='*', help='list of input .cpp filenames')
@@ -1409,8 +1302,7 @@ for node in AstNodeList:
# Compute derived properties over the whole DfgVertex hierarchy
DfgVertices["Vertex"].complete()
DfgVertexList = tuple(map(lambda _: DfgVertices[_],
sorted(DfgVertices.keys())))
DfgVertexList = tuple(map(lambda _: DfgVertices[_], sorted(DfgVertices.keys())))
check_types(DfgVertexList, "Dfg", "Vertex")
@@ -1457,8 +1349,7 @@ for cpt in Args.infiles:
if not re.search(r'.cpp$', cpt):
sys.exit("%Error: Expected argument to be .cpp file: " + cpt)
cpt = re.sub(r'.cpp$', '', cpt)
Cpt().process(in_filename=Args.I + "/" + cpt + ".cpp",
out_filename=cpt + "__gen.cpp")
Cpt().process(in_filename=Args.I + "/" + cpt + ".cpp", out_filename=cpt + "__gen.cpp")
######################################################################
# Local Variables: