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

Add fpp-to-json utilities #207

Merged
merged 13 commits into from
Aug 1, 2024
Empty file.
Empty file.
20 changes: 20 additions & 0 deletions src/fprime/fpp/utils/fpp_to_json/example-parse/example.fpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module A {
constant B = 1
constant C = 0x44
constant D = "hello"

instance E: Component.A base id 0x4444
instance F: Component.B base id 0x5555 \
queue size 10

topology G {
import I

instance E
instance F

connections H {
E.pout -> F.pin
}
}
}
426 changes: 426 additions & 0 deletions src/fprime/fpp/utils/fpp_to_json/example-parse/example.fpp.ast.json

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions src/fprime/fpp/utils/fpp_to_json/example-parse/parse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import fprime.fpp.utils.fpp_to_json.fpp_interface as fpp
Fixed Show fixed Hide fixed
import fprime.fpp.utils.fpp_to_json.parser as Parser
from pathlib import Path

def walkModule(data, oldQf):
module = Parser.ModuleParser(data)
module.parse()

if oldQf == "":
qf = module.module_name
else:
qf = oldQf + "." + module.module_name # qualifier

module.qf = qf

for member in module.members():
if "DefComponentInstance" in member[1]:
instance = Parser.InstanceParser(member)
instance.parse()
instance.qf = qf + "." + instance.instance_name

if "DefConstant" in member[1]:
constant = Parser.ConstantParser(member)
constant.parse()
constant.qf = qf + "." + constant.constant_Id

# can be continued for other member types

if "DefTopology" in member[1]:
walkTopology(member, qf)

if "DefModule" in member[1]:
walkModule(member, qf)

return qf


def walkTopology(data, module):
topology = Parser.TopologyParser(data)
topology.parse()

if module == "":
qf = topology.topology_name
else:
qf = module + "." + topology.topology_name # qualifier

topology.qf = qf

for member in topology.members():
if "DefTopology" in member[1]:
walkTopology(member, qf)

if "DefModule" in member[1]:
walkModule(member, qf)

return qf

def parse():
AST = Parser.openFppFile(Path(__file__).parent / "example.fpp")

for i in range(len(AST[0]["members"])):
if "DefModule" in AST[0]["members"][i][1]:
walkModule(AST[0]["members"][i], "")

if "DefTopology" in AST[0]["members"][i][1]:
walkTopology(AST[0]["members"][i], "")

if __name__ == "__main__":
parse()
25 changes: 25 additions & 0 deletions src/fprime/fpp/utils/fpp_to_json/example-write/write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fprime.fpp.utils.fpp_to_json.writer as Writer

def write():
# create a new fpp module
module = Writer.FppModule("ExampleModule")
print(module.open())

# create a new fpp constant
constant = Writer.FppConstant("ExampleConstant", "42")
print(constant.write())

# create a new fpp topology
topology = Writer.FppTopology("ExampleTopology")
print(topology.open())

# create a new fpp instance spec
instanceSpec = Writer.FppInstanceSpec("ExampleInstance")
print(instanceSpec.write())

# close the module and topology
print(topology.close())
print(module.close())

if __name__ == "__main__":
write()
137 changes: 137 additions & 0 deletions src/fprime/fpp/utils/fpp_to_json/fpp_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import subprocess
import os


def fpp_depend(cache_folder, input_file, locs_files) -> str:
Fixed Show fixed Hide fixed
"""
This function calculates the dependencies for an fpp file using fprime-util to get
the location of the build cache fpp-depend.

Args:
input_file: The input fpp file to calculate dependencies for
locs_file: The locs.fpp file to use for dependency calculation

Returns:
A string of dependencies for the input file
"""

print(f"[fpp] Calculating fpp dependencies for {os.path.basename(input_file)}...")

try:
fppDep = subprocess.run(
["fpp-depend", input_file]
+ locs_files
+ [
"-d",
f"{cache_folder}/direct.txt",
"-m",
f"{cache_folder}/missing.txt",
"-f",
f"{cache_folder}/framework.txt",
"-g",
f"{cache_folder}/generated.txt",
"-i",
f"{cache_folder}/include.txt",
"-u",
f"{cache_folder}/unittest.txt",
"-a",
],
check=True,
stdout=subprocess.PIPE,
)

with open(f"{cache_folder}/stdout.txt", "w") as f:
f.write(fppDep.stdout.decode("utf-8"))

except subprocess.CalledProcessError as e:
print(f"[ERR] fpp-depend failed with error: {e}")
return 1


def compute_simple_dependencies(locs_file, input):
print(f"[fpp] Calculating simple fpp dependencies for {os.path.basename(input)}...")

try:
fppDep = subprocess.run(
["fpp-depend", locs_file, input],
check=True,
stdout=subprocess.PIPE,
)

return fppDep.stdout.decode("utf-8")
except subprocess.CalledProcessError as e:
print(f"[ERR] fpp-depend failed with error: {e}")
return 1


def fpp_to_json(input_file):
"""
This function runs fpp-to-json on an fpp file to generate a JSON AST.

Args:
input_file: The input fpp file to run fpp-to-json on

Returns:
None
"""

# run fpp
print(f"[fpp] Running fpp-to-json for {os.path.basename(input_file)}...")

cmdS = ["fpp-to-json", input_file, "-s"]

try:
fppToJSON = subprocess.run(cmdS, check=True, stdout=subprocess.PIPE)
Fixed Show fixed Hide fixed
except subprocess.CalledProcessError as e:
raise Exception(f"[ERR] fpp-to-json pt2 failed with error: {e}")


def fpp_format(input_file):
"""
This function runs fpp-format on an fpp file to format the file.

Args:
input_file: The input fpp file to run fpp-format on

Returns:
None
"""

# run fpp-format
print(f"[fpp] Running fpp-format for {os.path.basename(input_file)}...")

try:
fppFormat = subprocess.run(
["fpp-format", input_file], check=True, stdout=subprocess.PIPE
)
return fppFormat.stdout.decode("utf-8")
except subprocess.CalledProcessError as e:
print(f"[ERR] fpp-format failed with error: {e}")
return 1


def fpp_locate_defs(input_file, locs_file):
"""
This function runs fpp-locate-defs on an fpp file to locate definitions.

Args:
input_file: The input fpp file to run fpp-locate-defs on
locs_file: The locs.fpp file used to find the base directory to base def locations
off of
"""

print(f"[fpp] Running fpp-locate-defs for {os.path.basename(input_file)}...")

locs_file = os.path.abspath(locs_file)
Fixed Show fixed Hide fixed
base_dir = os.path.dirname(input_file)

try:
fppLocateDefs = subprocess.run(
["fpp-locate-defs", input_file, "-d", base_dir],
check=True,
stdout=subprocess.PIPE,
)
return fppLocateDefs.stdout.decode("utf-8")
except subprocess.CalledProcessError as e:
print(f"[ERR] fpp-locate-defs failed with error: {e}")
return 1
Loading
Loading