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

Feature/generator typing #216

Merged
merged 4 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 37 additions & 35 deletions hvcc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (C) 2014-2018 Enzien Audio, Ltd.
# Copyright (C) 2021-2023 Wasted Audio
# Copyright (C) 2021-2024 Wasted Audio
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -35,6 +35,7 @@
from hvcc.generators.c2wwise import c2wwise
from hvcc.generators.c2unity import c2unity
from hvcc.generators.types.meta import Meta
from hvcc.types.compiler import CompilerResp, CompilerNotif, CompilerMsg


class Colours:
Expand All @@ -50,19 +51,18 @@ class Colours:
end = "\033[0m"


def add_error(results: OrderedDict, error: str) -> OrderedDict:
def add_error(
results: Dict[str, CompilerResp],
error: str
) -> Dict[str, CompilerResp]:
if "hvcc" in results:
results["hvcc"]["notifs"]["errors"].append({"message": error})
results["hvcc"].notifs.errors.append(CompilerMsg(message=error))
else:
results["hvcc"] = {
"stage": "hvcc",
"notifs": {
"has_error": True,
"exception": None,
"errors": [{"message": error}],
"warnings": []
}
}
results["hvcc"] = CompilerResp(stage="hvcc",
notifs=CompilerNotif(
has_error=True,
errors=[CompilerMsg(message=error)],
))
return results


Expand Down Expand Up @@ -212,9 +212,9 @@ def compile_dataflow(
verbose: bool = False,
copyright: Optional[str] = None,
nodsp: Optional[bool] = False
) -> OrderedDict:
) -> Dict[str, CompilerResp]:

results: OrderedDict = OrderedDict() # default value, empty dictionary
results: OrderedDict[str, CompilerResp] = OrderedDict() # default value, empty dictionary
patch_meta = Meta()

# basic error checking on input
Expand Down Expand Up @@ -250,23 +250,26 @@ def compile_dataflow(
verbose=verbose)

# check for errors
if list(results.values())[0]["notifs"].get("has_error", False):

response: CompilerResp = list(results.values())[0]

if response.notifs.has_error:
return results

subst_name = re.sub(r'\W', '_', patch_name)
results["hv2ir"] = hv2ir.hv2ir.compile(
hv_file=os.path.join(list(results.values())[0]["out_dir"], list(results.values())[0]["out_file"]),
hv_file=os.path.join(response.out_dir, response.out_file),
# ensure that the ir filename has no funky characters in it
ir_file=os.path.join(out_dir, "ir", f"{subst_name}.heavy.ir.json"),
patch_name=patch_name,
verbose=verbose)

# check for errors
if results["hv2ir"]["notifs"].get("has_error", False):
if results["hv2ir"].notifs.has_error:
return results

# get the hvir data
hvir = results["hv2ir"]["ir"]
hvir = results["hv2ir"].ir
patch_name = hvir["name"]["escaped"]
externs = generate_extern_info(hvir, results)

Expand All @@ -278,25 +281,24 @@ def compile_dataflow(

c_src_dir = os.path.join(out_dir, "c")
results["ir2c"] = ir2c.ir2c.compile(
hv_ir_path=os.path.join(results["hv2ir"]["out_dir"], results["hv2ir"]["out_file"]),
hv_ir_path=os.path.join(results["hv2ir"].out_dir, results["hv2ir"].out_file),
static_dir=os.path.join(application_path, "generators/ir2c/static"),
output_dir=c_src_dir,
externs=externs,
copyright=copyright,
nodsp=nodsp)

# check for errors
if results["ir2c"]["notifs"].get("has_error", False):
if results["ir2c"].notifs.has_error:
return results

# ir2c_perf
results["ir2c_perf"] = {
"stage": "ir2c_perf",
"obj_counter": ir2c_perf.ir2c_perf.perf(results["hv2ir"]["ir"], verbose=verbose),
"in_dir": results["hv2ir"]["out_dir"],
"in_file": results["hv2ir"]["out_file"],
"notifs": {}
}
results["ir2c_perf"] = CompilerResp(
stage="ir2c_perf",
obj_perf=ir2c_perf.ir2c_perf.perf(results["hv2ir"].ir, verbose=verbose),
in_dir=results["hv2ir"].out_dir,
in_file=results["hv2ir"].out_file,
)

# reconfigure such that next stage is triggered
in_path = c_src_dir
Expand Down Expand Up @@ -442,25 +444,25 @@ def main() -> bool:
errorCount = 0
for r in list(results.values()):
# print any errors
if r["notifs"].get("has_error", False):
for i, error in enumerate(r["notifs"].get("errors", [])):
if r.notifs.has_error:
for i, error in enumerate(r.notifs.errors):
errorCount += 1
print("{4:3d}) {2}Error{3} {0}: {1}".format(
r["stage"], error["message"], Colours.red, Colours.end, i + 1))
r.stage, error.message, Colours.red, Colours.end, i + 1))

# only print exception if no errors are indicated
if len(r["notifs"].get("errors", [])) == 0 and r["notifs"].get("exception", None) is not None:
if len(r.notifs.errors) == 0 and r.notifs.exception is not None:
errorCount += 1
print("{2}Error{3} {0} exception: {1}".format(
r["stage"], r["notifs"]["exception"], Colours.red, Colours.end))
r.stage, r.notifs.exception, Colours.red, Colours.end))

# clear any exceptions such that results can be JSONified if necessary
r["notifs"]["exception"] = []
r.notifs.exception = None

# print any warnings
for i, warning in enumerate(r["notifs"].get("warnings", [])):
for i, warning in enumerate(r.notifs.warnings):
print("{4:3d}) {2}Warning{3} {0}: {1}".format(
r["stage"], warning["message"], Colours.yellow, Colours.end, i + 1))
r.stage, warning.message, Colours.yellow, Colours.end, i + 1))

if args.results_path:
results_path = os.path.realpath(os.path.abspath(args.results_path))
Expand Down
89 changes: 45 additions & 44 deletions hvcc/core/hv2ir/hv2ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
import os
import time

from typing import Optional, Dict
from typing import Optional

from .HeavyException import HeavyException
from .HeavyParser import HeavyParser

from hvcc.types.compiler import CompilerResp, CompilerNotif, CompilerMsg


class hv2ir:

Expand All @@ -34,7 +36,7 @@ def compile(
ir_file: str,
patch_name: Optional[str] = None,
verbose: bool = False
) -> Dict:
) -> CompilerResp:
""" Compiles a HeavyLang file into a HeavyIR file.
Returns a tuple of compile time in seconds, a notification dictionary,
and a heavy object counter.
Expand All @@ -50,21 +52,20 @@ def compile(
# parse heavy file
hv_graph = HeavyParser.graph_from_file(hv_file=hv_file, xname=patch_name)
except HeavyException as e:
return {
"stage": "hv2ir",
"compile_time": time.time() - tick,
"notifs": {
"has_error": True,
"exception": e,
"errors": [{"message": e.message}],
"warnings": []
},
"obj_counter": None,
"in_file": os.path.basename(hv_file),
"in_dir": os.path.dirname(hv_file),
"out_file": os.path.basename(ir_file),
"out_dir": os.path.dirname(ir_file)
}
return CompilerResp(
stage="hv2ir",
compile_time=time.time() - tick,
notifs=CompilerNotif(
has_error=True,
exception=e,
errors=[CompilerMsg(message=e.message)],
warnings=[]
),
in_file=os.path.basename(hv_file),
in_dir=os.path.dirname(hv_file),
out_file=os.path.basename(ir_file),
out_dir=os.path.dirname(ir_file)
)

try:
# get a counter of all heavy objects
Expand All @@ -80,21 +81,21 @@ def compile(
# generate Heavy.IR
ir = hv_graph.to_ir()
except HeavyException as e:
return {
"stage": "hv2ir",
"compile_time": time.time() - tick,
"notifs": {
"has_error": True,
"exception": e,
"errors": [{"message": e.message}],
"warnings": []
},
"obj_counter": hv_counter,
"in_file": os.path.basename(hv_file),
"in_dir": os.path.dirname(hv_file),
"out_file": os.path.basename(ir_file),
"out_dir": os.path.dirname(ir_file)
}
return CompilerResp(
stage="hv2ir",
compile_time=time.time() - tick,
notifs=CompilerNotif(
has_error=True,
exception=e,
errors=[CompilerMsg(message=e.message)],
warnings=[]
),
in_file=os.path.basename(hv_file),
in_dir=os.path.dirname(hv_file),
out_file=os.path.basename(ir_file),
out_dir=os.path.dirname(ir_file),
obj_counter=hv_counter
)

# write the hv.ir file
with open(ir_file, "w") as f:
Expand All @@ -121,17 +122,17 @@ def compile(
else:
print(o["type"])

return {
"stage": "hv2ir",
"compile_time": time.time() - tick, # record the total compile time
"notifs": hv_graph.get_notices(),
"obj_counter": hv_counter,
"in_file": os.path.basename(hv_file),
"in_dir": os.path.dirname(hv_file),
"out_file": os.path.basename(ir_file),
"out_dir": os.path.dirname(ir_file),
"ir": ir
}
return CompilerResp(
stage="hv2ir",
compile_time=time.time() - tick, # record the total compile time
notifs=CompilerNotif(**hv_graph.get_notices()),
in_file=os.path.basename(hv_file),
in_dir=os.path.dirname(hv_file),
out_file=os.path.basename(ir_file),
out_dir=os.path.dirname(ir_file),
obj_counter=hv_counter,
ir=ir
)


def main() -> None:
Expand All @@ -158,7 +159,7 @@ def main() -> None:
verbose=args.verbose)

if args.verbose:
print(f"Total hv2ir time: {(d['compile_time'] * 1000):.2f}ms")
print(f"Total hv2ir time: {(d.compile_time * 1000):.2f}ms")


if __name__ == "__main__":
Expand Down
60 changes: 27 additions & 33 deletions hvcc/generators/c2daisy/c2daisy.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from ..types.meta import Meta, Daisy
from . import parameters

from hvcc.interpreters.pd2hv.NotificationEnum import NotificationEnum
from hvcc.types.compiler import Compiler, CompilerResp, CompilerNotif, CompilerMsg


hv_midi_messages = {
"__hv_noteout",
Expand All @@ -23,7 +26,7 @@
}


class c2daisy:
class c2daisy(Compiler):
""" Generates a Daisy wrapper for a given patch.
"""

Expand All @@ -39,7 +42,7 @@ def compile(
num_output_channels: int = 0,
copyright: Optional[str] = None,
verbose: Optional[bool] = False
) -> Dict:
) -> CompilerResp:

tick = time.time()

Expand Down Expand Up @@ -138,36 +141,27 @@ def compile(

# ======================================================================================

return {
"stage": "c2daisy",
"notifs": {
"has_error": False,
"exception": None,
"warnings": [],
"errors": []
},
"in_dir": c_src_dir,
"in_file": "",
"out_dir": out_dir,
"out_file": os.path.basename(daisy_h_path),
"compile_time": time.time() - tick
}
return CompilerResp(
stage="c2daisy",
in_dir=c_src_dir,
out_dir=out_dir,
out_file=os.path.basename(daisy_h_path),
compile_time=time.time() - tick
)

except Exception as e:
return {
"stage": "c2daisy",
"notifs": {
"has_error": True,
"exception": e,
"warnings": [],
"errors": [{
"enum": -1,
"message": str(e)
}]
},
"in_dir": c_src_dir,
"in_file": "",
"out_dir": out_dir,
"out_file": "",
"compile_time": time.time() - tick
}
return CompilerResp(
stage="c2daisy",
notifs=CompilerNotif(
has_error=True,
exception=e,
warnings=[],
errors=[CompilerMsg(
enum=NotificationEnum.ERROR_EXCEPTION,
message=str(e)
)]
),
in_dir=c_src_dir,
out_dir=out_dir,
compile_time=time.time() - tick
)
Loading
Loading