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

WIP: Feature/expr sig #104

Draft
wants to merge 42 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
067ade7
started working on expr prototype. added alt tox config file, tox.dev…
dgbillotte Sep 5, 2022
80b3ee7
tweaks
dgbillotte Sep 5, 2022
c4987df
added script file for project aliases
dgbillotte Sep 5, 2022
2efed77
getting a test harness together
dgbillotte Sep 5, 2022
6cee0ad
got the pieces together enough to compile. Next: make a static expres…
dgbillotte Sep 6, 2022
042396f
just poked a hole through to the other side
dgbillotte Sep 13, 2022
6c70386
fair to call it a "basically working" prototype?
dgbillotte Sep 13, 2022
096b642
added args param to get_C_impl method
dgbillotte Sep 13, 2022
789cc44
cleaned out crud
dgbillotte Sep 13, 2022
f2f5cc0
it works!
dgbillotte Sep 14, 2022
2217862
fixed the "unused variable" bug and a python 2->3 bug
dgbillotte Sep 15, 2022
a49848d
added the rag-tag files
dgbillotte Sep 15, 2022
4a3e303
added almost working test for expr
dgbillotte Sep 15, 2022
9e7fdbc
Merge branch 'develop' into feature/expr
dgbillotte Sep 16, 2022
806fb43
getting signalExpr prototyped inside of SignalMath at the moment
dgbillotte Sep 17, 2022
72aa3de
added some generic generation methods to HeavyObject and have basic c…
dgbillotte Sep 17, 2022
e0bb20e
plowing through on expr~. break to fix some heavy stuff
dgbillotte Sep 18, 2022
b6c1539
added some base method implementations and changed get_C_process sign…
dgbillotte Sep 18, 2022
d14665b
added exceptions into 2 of the base methods
dgbillotte Sep 18, 2022
7fe888e
merged in fix to ir2c/HeavyObject.py
dgbillotte Sep 18, 2022
a6a43cb
fixed flake8 stuff
dgbillotte Sep 18, 2022
eff8128
nit
dgbillotte Sep 18, 2022
6bea875
removed an unintended addition
dgbillotte Sep 18, 2022
6cea7ac
fixed merge
dgbillotte Sep 18, 2022
b087a2c
cleaned stuff up, ready to start integrating the expression parser/wr…
dgbillotte Sep 23, 2022
3ae6a64
updated test patch
dgbillotte Oct 8, 2022
c90323c
Merge branch 'develop' into feature/expr
dgbillotte Oct 8, 2022
ae15adf
fixed merge conflict
dgbillotte Oct 8, 2022
d2dc269
Merge branch 'develop' into feature/expr
dgbillotte Oct 8, 2022
4b658cb
Merge branch 'develop' into feature/expr-sig
dgbillotte Oct 8, 2022
00b5dcf
expr~ is barely working :-)
dgbillotte Oct 10, 2022
be3c1e9
updated requirements so that it automatically pulls the libs
dgbillotte Oct 11, 2022
98b5df9
added comment
dgbillotte Oct 11, 2022
698f3aa
Merge branch 'develop' into feature/expr-sig
dgbillotte Oct 11, 2022
7878028
Merge branch 'develop' into feature/expr
dgbillotte Oct 11, 2022
5cb18f0
deleted old files, one of which was breaking the build
dgbillotte Oct 11, 2022
6dd0cd9
merge conflicts
Mar 16, 2023
d8e2ac2
merge conflicts
Mar 16, 2023
5b9b1b1
typing and style tweaks
Mar 16, 2023
4609bff
Merge branch 'develop' into feature/expr-sig
dromer Jul 19, 2023
9ff861f
start adding expr tests
dromer Jul 19, 2023
5f696c2
Merge branch 'develop' into feature/expr-sig
dromer Jul 31, 2024
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,7 @@ DerivedData
generators/vs2015/Heavy/generated
generators/c2js/emsdk_portable/
generators/c2js/emsdk/

## added by dgbillotte to ignore my dev stuff, feel free to remove
test/pd/*/dgb*

34 changes: 34 additions & 0 deletions hvcc/core/hv2ir/HIrExpr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (C) 2014-2018 Enzien Audio, Ltd.
#
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from .HeavyIrObject import HeavyIrObject
from .HeavyException import HeavyException


class HIrExpr(HeavyIrObject):
"""Just a stub to get it going..."""

def __init__(self, obj_type, args=None, graph=None, annotations=None):
HeavyIrObject.__init__(self, obj_type, args=args, graph=graph,
num_inlets=args["num_inlets"],
num_outlets=1,
annotations=annotations)

def inlet_requires_signal(self, inlet_index=0):
""" Overriding HeavyIrObject to deal with variable number of inlets
"""
if inlet_index >= self.num_inlets:
raise HeavyException(f"inlet_index: {inlet_index} is greater than number of inlets")
return True
3 changes: 3 additions & 0 deletions hvcc/core/hv2ir/HeavyLangObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def __init__(

# the list of connections at each inlet
num_inlets = num_inlets if num_inlets >= 0 else len(self._obj_desc["inlets"])
# print("=-=-=-=- HeavyLangObject::__init__", self.type, self._obj_desc)
self.inlet_connections: List = [[] for _ in range(num_inlets)]

# the list of connections at each outlet
Expand Down Expand Up @@ -224,6 +225,8 @@ def add_connection(self, c: Connection) -> None:
"""
try:
if c.to_object is self:
print("-------- c props", c)
print("-------- inlet cons", self.inlet_connections)
self.inlet_connections[c.inlet_index].append(c)
elif c.from_object is self:
self.outlet_connections[c.outlet_index].append(c)
Expand Down
5 changes: 4 additions & 1 deletion hvcc/core/hv2ir/HeavyParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from typing import Any, Dict, Optional

from .HIrConvolution import HIrConvolution
from .HIrExpr import HIrExpr
from .HIrInlet import HIrInlet
from .HIrLorenz import HIrLorenz
from .HIrOutlet import HIrOutlet
Expand Down Expand Up @@ -310,5 +311,7 @@ def reduce(self) -> tuple:
"send": HLangSend,
"__switchcase": HIrSwitchcase,
"switchcase": HIrSwitchcase,
"__pack": HIrPack
"__pack": HIrPack,
"__expr": HIrExpr,
"__expr~": HIrExpr,
}
54 changes: 51 additions & 3 deletions hvcc/core/json/heavy.ir.json
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,56 @@

]
},
"__expr": {
"inlets": [],
"ir": {
"control": true,
"signal": false,
"init": true
},
"outlets": [
"-->"
],
"args": [{
"name": "expressions",
"value_type": "stringarray",
"description": "The expression to evaluate",
"default": "",
"required": true
},
{
"name": "num_inlets",
"value_type": "int",
"description": "Number of inlets for this instance",
"default": "",
"required": true
}]
},
"__expr~": {
"inlets": [],
"ir": {
"control": false,
"signal": true,
"init": false
},
"outlets": [
"~f>"
],
"args": [{
"name": "expressions",
"value_type": "stringarray",
"description": "The expression to evaluate",
"default": "",
"required": true
},
{
"name": "num_inlets",
"value_type": "int",
"description": "Number of inlets for this instance",
"default": "",
"required": true
}]
},
"__floor": {
"inlets": [
"-->"
Expand All @@ -1049,9 +1099,7 @@
"outlets": [
"-->"
],
"args": [

]
"args": []
},
"__floor~f": {
"args": [
Expand Down
3 changes: 2 additions & 1 deletion hvcc/generators/ir2c/ControlDelay.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
send_message_list = [
f"cDelay_{obj_id}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *const m) {{"
Expand Down
127 changes: 127 additions & 0 deletions hvcc/generators/ir2c/ControlExpr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Copyright (C) 2014-2018 Enzien Audio, Ltd.
#
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from .HeavyObject import HeavyObject
import re
from typing import Callable, Dict, List


class ControlExpr(HeavyObject):
"""Just a stub to get the thing working"""

c_struct = "ControlExpr"
preamble = "cExpr"

@classmethod
def get_C_header_set(self) -> set:
return {"HvControlExpr.h"}

@classmethod
def get_C_file_set(self) -> set:
return {"HvControlExpr.h", "HvControlExpr.c"}

@classmethod
def get_C_init(cls, obj_type: str, obj_id: int, args: Dict) -> List[str]:
"""(Per object) code that gets inserted into from the Heavy_heavy ctor.
Only if "ir[init]" == true
"""

eval_f = f"&Heavy_heavy::{cls.preamble}_{obj_id}_evaluate"
return [f"cExpr_init(&cExpr_{obj_id}, {eval_f});"]

@classmethod
def get_C_def(cls, obj_type: str, obj_id: int) -> List[str]:
"""(Per object) code that gets inserted into the header file
Only if "ir[init]" == true
"""

lines = super().get_C_def(obj_type, obj_id)
lines.append("// --------------- big ol' comment ------------")
lines.append(f"static float {cls.preamble}_{obj_id}_evaluate(float* args);")
return lines

@classmethod
def get_C_onMessage(cls, obj_type: str, obj_id: int, inlet_index: int, args: Dict) -> List[str]:
"""
(Per object) code that gets inserted into the c<PREAMBLE>_<OBJID>_sendMessage
method in the .cpp file
"""

return [
"cExpr_onMessage(_c, &Context(_c)->cExpr_{0}, {1}, m, &cExpr_{0}_sendMessage);".format(
obj_id,
inlet_index)
]
"""
The get_C_onMessage method returns the code that will get inserted into
the cReceive_<UID>_sendMessage method
"""

# @classmethod
# def get_C_process(cls, process_dict: Dict, obj_type: str, obj_id: int, args: Dict) -> List[str]:
# return [
# "printf(\"hello world\")"
# ]
"""
The get_C_process method seems to only get called by Signal IR objects, it does
not get called for Control IR objects
"""

@classmethod
def get_C_impl(
cls,
obj_type: str,
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict,
args: Dict
) -> List[str]:
"""
(Per object) this creates the _sendMessage function that other objects use to
send messages to this object.
"""

lines = super().get_C_impl(obj_type, obj_id, on_message_list, get_obj_class, objects, args)
expr = args["expressions"][0]
bound_expr = bind_expr(expr, "args")
lines.extend([
"",
f"float Heavy_heavy::{cls.preamble}_{obj_id}_evaluate(float* args) {{",
f"\treturn {bound_expr};",
"}",
])
return lines


"""
Below is code to rewrite the input expression into one that uses local variables
that have been cast to either float or int
"""


# todo(dgb): need to handle the 's' type
def var_n(a_name, var):
parts = re.match(r"\$([fi])(\d)", var)
type = "float" if parts[1] == "f" else "int"
return f"(({type})({a_name}[{int(parts[2])-1}]))"


def bind_expr(exp="$f1+2", a_name="a"):
vars = re.findall(r"\$[fis]\d", exp)
new_exp = exp
for var in vars:
new_exp = new_exp.replace(var, var_n(a_name, var))
return new_exp
3 changes: 2 additions & 1 deletion hvcc/generators/ir2c/ControlMessage.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
send_message_list = [
f"cMsg_{obj_id}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *const n) {{"
Expand Down
3 changes: 2 additions & 1 deletion hvcc/generators/ir2c/ControlPrint.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
return []
3 changes: 2 additions & 1 deletion hvcc/generators/ir2c/ControlSend.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
# Note(joe): if no corresponding receivers exist and there's no extern indicator
# then there is not much need to generate code stub
Expand Down
3 changes: 2 additions & 1 deletion hvcc/generators/ir2c/ControlSwitchcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
# generate the onMessage implementation
out_list = [
Expand Down
27 changes: 22 additions & 5 deletions hvcc/generators/ir2c/HeavyObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def get_C_header_set(self) -> set:
def get_C_file_set(self) -> set:
return set()

@classmethod
def get_C_init(cls, obj_type: str, obj_id: int, args: Dict) -> List[str]:
return [f"{cls.preamble}_init(&{cls.preamble}_{obj_id})"]

@classmethod
def get_C_def(cls, obj_type: str, obj_id: int) -> List[str]:
return ["{0} {1}_{2};".format(
Expand All @@ -73,7 +77,8 @@ def get_C_impl(
obj_id: int,
on_message_list: List,
get_obj_class: Callable,
objects: Dict
objects: Dict,
args: Dict
) -> List[str]:
send_message_list = [
"{0}_{1}_sendMessage(HeavyContextInterface *_c, int letIn, const HvMessage *m) {{".format(
Expand All @@ -97,12 +102,24 @@ def get_C_impl(
return send_message_list

@classmethod
def get_C_init(cls, obj_type: str, obj_id: int, args: Dict) -> List[str]:
raise NotImplementedError("method get_C_init not implemented")
def get_C_onMessage(cls, obj_type: str, obj_id: int, inlet_index: int, args: Dict) -> List[str]:
raise NotImplementedError("method get_C_onMessage not implemented", cls, obj_type)

@classmethod
def get_C_onMessage(cls, obj_type: str, obj_id: int, inlet_index: int, args: Dict) -> List[str]:
raise NotImplementedError("method get_C_onMessage not implemented")
def get_C_obj_header_code(cls, obj_type: str, obj_id: int, args: Dict) -> List[str]:
return []

@classmethod
def get_C_obj_impl_code(cls, obj_type: str, obj_id: int, args: Dict) -> List[str]:
return []

@classmethod
def get_C_class_header_code(cls, obj_type: str, args: Dict) -> List[str]:
return []

@classmethod
def get_C_class_impl_code(cls, obj_type: str, args: Dict) -> List[str]:
return []

@classmethod
def get_C_process(cls, process_dict: Dict, obj_type: str, obj_id: int, args: Dict) -> List[str]:
Expand Down
Loading
Loading