Skip to content

Commit

Permalink
Feat: better error handling and better SPL traces
Browse files Browse the repository at this point in the history
This commit started as an attempt to fix a few bugs with SPL chords. It
ended up making error tracing and error logging better for SPL. Errors
are bubbling up and the trace from a failed parse can be inspected.
  • Loading branch information
Bubobubobubobubo committed Jun 26, 2024
1 parent fca4921 commit 63c745e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
2 changes: 1 addition & 1 deletion sardine_core/handlers/sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def pattern_element(
if length > 0:
i = floor(iterator * rate / divisor) % length
return val[i]
raise ValueError(f"Cannot pattern an empty sequence: {val!r}")
raise ValueError(f"Cannot pattern an empty sequence: {val}")

def pattern_reduce(
self,
Expand Down
4 changes: 0 additions & 4 deletions sardine_core/sequences/sardine_parser/funclib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
from random import shuffle
from time import time
from typing import Optional

from sardine_core.sequences.sequence import euclid

from .chord import Chord
from .utils import map_unary_function

# Type declarations


class FunctionLibrary:
qualifiers = {
Expand Down
11 changes: 6 additions & 5 deletions sardine_core/sequences/sardine_parser/list_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from pathlib import Path

from lark import Lark, Tree
from lark.exceptions import LarkError, UnexpectedCharacters, UnexpectedToken

from sardine_core.base import BaseParser
from sardine_core.logger import print

Expand Down Expand Up @@ -55,15 +53,15 @@ def setup(self):
parsers = {
"sardine": {
"raw": Lark.open(
grammar,
str(grammar),
rel_to=__file__,
parser="lalr",
start="start",
cache=True,
lexer="contextual",
),
"full": Lark.open(
grammar,
str(grammar),
rel_to=__file__,
parser="lalr",
start="start",
Expand Down Expand Up @@ -151,7 +149,10 @@ def parse(self, *args):
try:
final_pattern = self._result_parser.parse(pattern)
except Exception as e:
print(f"[red][Pattern Language Error][/red]")
tb = traceback.format_exc()
raise ParserError(
f"Error parsing pattern {pattern}: {e.__class__.__name__} {e}\nTraceback: {tb}"
)

if self.debug:
print(f"Pat: {self._flatten_result(final_pattern)}")
Expand Down
41 changes: 31 additions & 10 deletions sardine_core/sequences/sardine_parser/tree_calc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import random
from itertools import chain, count, takewhile
from types import SimpleNamespace
from functools import wraps

from lark import Transformer, v_args
from lark.lexer import Token
Expand All @@ -13,6 +14,26 @@
from .utils import CyclicalList, map_binary_function, map_unary_function, zip_cycle


class ParseError(Exception):
pass


class FunctionError(Exception):
pass


def log_on_error(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Error in {func.__name__} with args: {args}, kwargs: {kwargs}")
raise e

return wrapper


@v_args(inline=True)
class CalculateTree(Transformer):
def __init__(self, clock, variables: SimpleNamespace, global_scale: str):
Expand Down Expand Up @@ -131,8 +152,11 @@ def get_slice(self, content: list, list_slice: list) -> list:
content = CyclicalList(content)
return content[list_slice[0] : list_slice[1]]

@log_on_error
def make_chord(self, *args: list):
"""Turn a list into a chord"""
# NOTE: this is a possible bugfix
args = [x if isinstance(x, list) else [x] for x in args]
return [self.library.chordify(*sum(args, start=[]))]

def chord_reverse(self, notes: list, inversion: list) -> list:
Expand Down Expand Up @@ -546,7 +570,6 @@ def function_call(self, func_name, *args):
"while": self.library.unary_condition,
"nwhile": self.library.negative_unary_condition,
# Boolean functions
"phase": self.library.phase,
"beat": self.library.beat,
"obar": self.library.oddbar,
"modbar": self.library.modbar,
Expand Down Expand Up @@ -624,21 +647,19 @@ def function_call(self, func_name, *args):
"bl": self.library.binary_list,
"rot": self.library.rotate,
}
except Exception as e:
print(e)
try:
if kwarguments.get("cond", [1]) >= [1] or not "cond" in kwarguments.keys():
if kwarguments.get("cond", [1]) >= [1] or "cond" not in kwarguments.keys():
return modifiers_list[func_name](
*list(chain(arguments)), **(kwarguments)
)
else:
return list(arguments)
except Exception as e:
# Fail safe
except KeyError as e:
print(
Panel.fit(
f"[red]/!\\\\[/red] [bold]Unknown or malformed function [/bold][bold yellow]{func_name}[/bold yellow] [red]/!\\\\[/red]\n\n[reverse gold1]{e}\n[/reverse gold1]\n[bold]Possible functions are:[/bold] \n\n"
+ "".join(f"{name} " for name in modifiers_list.keys())
f"[red]/!\\\\[/red] [bold]Unknown SPL function [/bold][bold yellow]{func_name}[/bold yellow] [red]/!\\\\[/red]\n[bold yellow]> {e}[/bold yellow]"
)
)
return args[0]
except Exception as e:
raise FunctionError(
f"Unknown SPL function {func_name} with args {args} and kwargs {kwarguments}: {e}"
)
14 changes: 12 additions & 2 deletions sardine_core/sequences/sardine_parser/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from itertools import count, cycle, dropwhile, islice, takewhile
from typing import Iterable, Tuple


from .chord import Chord

Expand Down Expand Up @@ -57,8 +59,16 @@ def map_unary_function(func, value):
return [allow_silence_1(func)(x) for x in value]


def zip_cycle(left, right):
"""Zip two lists, cycling the shortest one"""
def zip_cycle(left: Iterable, right: Iterable) -> Iterable[Tuple]:
"""Zip two iterables, cycling the shortest one"""

def ensure_iterable(obj):
"""Ensure obj is iterable."""
return obj if isinstance(obj, Iterable) else [obj]

left = ensure_iterable(left)
right = ensure_iterable(right)

if len(left) < len(right):
return zip(cycle(left), right)
else:
Expand Down

0 comments on commit 63c745e

Please sign in to comment.