Skip to content

Commit

Permalink
Feat: simplify internal variable mechanism
Browse files Browse the repository at this point in the history
This commit:
- deprecates amphibian variables in favor of `get` and `set`
- removes any mention of it from the documentation
- removes the `Variables` class in favor of Python's `SimpleNamespace`
- adapts SPL to use the SimpleNamespace designated by the `V` alias

For the longest time, there was many different variable systems used
internally by SPL. It was getting pretty ugly, this commit tries to go
back to something that feels a bit more manageable. You can manipulate
variables through the `V` namespace, and grab them using `set` and `get`
in SPL expressions.
  • Loading branch information
Bubobubobubobubo committed Jun 25, 2024
1 parent 816a726 commit fca4921
Show file tree
Hide file tree
Showing 12 changed files with 21 additions and 188 deletions.
1 change: 0 additions & 1 deletion docs/sardine_doc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
- [High-level patterns](diving_deeper/high_level_patterns.md)
- [Sleeping / oversleeping](diving_deeper/sleeping.md)
- [Pattern object](diving_deeper/pattern_object.md)
- [Amphibian Variables](diving_deeper/amphibian_variables.md)
- [Using python](diving_deeper/python.md)
- [Advanced: Sample Slicer](diving_deeper/python-sampleslicer.md)
- [External to Sardine](diving_deeper/externals.md)
Expand Down
44 changes: 0 additions & 44 deletions docs/sardine_doc/src/diving_deeper/amphibian_variables.md

This file was deleted.

2 changes: 2 additions & 0 deletions docs/sardine_doc/src/diving_deeper/python-sampleslicer.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Advanced Python - Sample Slicer

**NOTE:** this article was using _amphibian variables_, a deprecated feature. Rely on the `set` and `get` functions for a similar behavior.

**Using custom python functions to multiple amphibian variables**

This example uses custom functions to generate 4 amphibian variables at once. It also uses presets, initialized values, and sample lists. The Sample Slicer is a complete livecoding program, ready to use. You can also extend it, add more samples to slice, add more amphibian variables, add more parameters, etc.
Expand Down
24 changes: 1 addition & 23 deletions docs/sardine_doc/src/diving_deeper/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,6 @@ def melody(p=1, i=0):
again(melody, p=1, i=i+1)
```

### Setting amphibian variables
A similar results can be achieved using Amphibian Variables.

Amphibian variables can have their values set outside of @swim with a python assignment/expression, or with a custom function.

The custom function below returns a list of midi note value with an argument that sets the number of notes in the list.

```python
def randNotes(listLen):
notes = []
i = 0
while i < listLen:
notes.append(randint(30,80))
i += 1
return notes

V.n = randNotes(5) # Execute again to change notes
Pa * d('supersaw', n='(v n)', p=1 )
```

For more info see [Amphibian Variables](./amphibian_variables.md).

### Conditional logic
This example uses python `if/elif/else` conditional logic to switch between sample sets and change the tempo. Notice the use of the iterator and how resetting it to 0 at the end resets the conditional logic.

Expand All @@ -113,4 +91,4 @@ def demo(p=1, i=0):
again(demo, p=0.5, i=i+1)
```
### Going even deeper
See the next section - [Advanced python: Sample Slicer](./python-sampleslicer.md), where custom functions generate 4 Amphibian Variables at once.
See the next section - [Advanced python: Sample Slicer](./python-sampleslicer.md), where custom functions generate 4 Amphibian Variables at once.
2 changes: 1 addition & 1 deletion docs/sardine_doc/src/pattern_languages/sardine/names.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The **Sardine Pattern Language** is using names for multiple things:
- audio sample and synthesizer names like `kick` or `sawsynth`.
- variable naming in the context of **amphibian variables** or **internal variables**.
- variable naming in the context of or **internal global variables**.
- addresses, a special type of composed name used for OSC addressing.

```python
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,6 @@ Get a variable associated to a name. This function is the second part of the *ge
Pz * d('clap', room='(get roomy)', crush='(get globalcrush)')
```

# setA (sa)

This function is part of the [amphibian variables](../../diving_deeper/amphibian_variables.html) mechanism. In a similar fashion to **set**, this function can be used to set the value of the associated amphibian variable. There is currently 26 amphibian variables you can use, one for each letter of the latin alphabet in lowercase. Just like **set**, you can set a value and still return its value for later usage.

**Arguments:**
- **variable name:** name of the amphibian variable to get.

**Example:**
```python
(setA b 20)
(sa b 20)
```

# getA (ga)

- **variable name:** name of the amphibian variable to set.
**Arguments:**

**Example:**
```python
V.n = [52, randint(40, 60), 72, 35]
Pa * d('supersaw', n='(ga n)', p=0.75 )
```

# setscl

The **Sardine Pattern Language** always remember the name of a global scale that the user can set. It defaults to `major`, taken from the [list of possible qualifiers](../sardine/notes.md). You can choose any scale from that list as the default scale for all patterns using **scl**, thus the name of this very function.
Expand Down
11 changes: 7 additions & 4 deletions sardine_core/fish_bowl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from .clock import InternalClock, Time
from .handlers import SleepHandler
from .scheduler import Scheduler
from .sequences import Iterator, ListParser, Variables
from .sequences import Iterator, ListParser
from types import SimpleNamespace

__all__ = ("FishBowl",)

Expand All @@ -30,15 +31,15 @@ def __init__(
scheduler: Optional[Scheduler] = None,
sleeper: Optional[SleepHandler] = None,
time: Optional[Time] = None,
variables: Optional[Variables] = None,
variables: Optional[SimpleNamespace] = None,
):
self.clock = clock or InternalClock()
self.iterators = iterator or Iterator()
self.parser = parser or ListParser()
self.scheduler = scheduler or Scheduler()
self.sleeper = sleeper or SleepHandler()
self.time = time or Time()
self.variables = variables or Variables()
self.variables = variables or SimpleNamespace()

self._handlers: dict[BaseHandler, None] = {}
self._alive = asyncio.Event()
Expand Down Expand Up @@ -77,7 +78,9 @@ def __repr__(self) -> str:
status = (
"playing"
if running and not paused
else "paused" if running and paused else "stopped"
else "paused"
if running and paused
else "stopped"
)

return "<{} {} clock={!r}>".format(
Expand Down
1 change: 0 additions & 1 deletion sardine_core/sequences/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
from .sardine_parser import *
from .sequence import *
from .tidal_parser import *
from .variables import *
from .ziffers_parser import *
36 changes: 6 additions & 30 deletions sardine_core/sequences/sardine_parser/funclib.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import datetime
import random
import statistics
from itertools import chain, cycle, islice, repeat
from math import asin, atan, cos, pi, sin, tan
from itertools import chain, cycle, islice
from math import atan, cos, pi, sin, tan
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_binary_function, map_unary_function
from .utils import map_unary_function

# Type declarations

Expand Down Expand Up @@ -114,9 +114,8 @@ class FunctionLibrary:
"octaves": [0, 12, 24, 36, 48],
}

def __init__(self, clock, amphibian, inner_variables, global_scale):
def __init__(self, clock, inner_variables, global_scale):
self.clock = clock
self.amphibian = amphibian
self.inner_variables = inner_variables
self.global_scale = global_scale

Expand Down Expand Up @@ -267,35 +266,12 @@ def negative_unary_condition(self, condition, pattern=[None], **kwargs):

def set_variable(self, *args, **kwargs):
"""Set an internal variable to the given value and return the same value"""
self.inner_variables[str(args[0][0])] = args[1]
setattr(self.inner_variables, args[0][0], *args[1])
return args[1]

def get_variable(self, *args, **kwargs):
"""Get an internal variable. If it doesn't exist, will return 0"""
return self.inner_variables.get(args[0][0], [0])

def get_amphibian_variable(self, *args, **kwargs):
"""
Return the value of an amphibian variable coming from the Python
side. The result can only be an int, a float or a string. The
final result is always assumed to be a list.
"""
reset = kwargs.get("reset", 0)

if reset == 0:
self.amphibian.reset(str(str(args[0])))
return [getattr(self.amphibian, str(args[0][0]))]
else:
return [getattr(self.amphibian, str(args[0][0]))]

def set_amphibian_variable(self, *args):
"""
Set an amphibian variable to a new value. This value can be of any
type supported internally by the Sardine pattern language. This
function will return the new-set value.
"""
setattr(self.amphibian, str(args[0][0]), args[1])
return [getattr(self.amphibian, str(args[1][0]))]
return getattr(self.inner_variables, args[0][0], [0])

def drunk(self, *args, **kwargs):
"""
Expand Down
4 changes: 0 additions & 4 deletions sardine_core/sequences/sardine_parser/list_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ def __init__(
self.debug = debug
self.parser_type = parser_type

# Variables usable only in the SPL environment
self.inner_variables = {}

# Current Global Scale
self.global_scale: str = "major"

Expand Down Expand Up @@ -75,7 +72,6 @@ def setup(self):
transformer=CalculateTree(
clock=self.env.clock,
variables=self.env.variables,
inner_variables=self.inner_variables,
global_scale=self.global_scale,
),
),
Expand Down
14 changes: 4 additions & 10 deletions sardine_core/sequences/sardine_parser/tree_calc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import random
from itertools import chain, count, takewhile
from time import time
from types import SimpleNamespace

from lark import Transformer, v_args
from lark.lexer import Token
Expand All @@ -15,17 +15,15 @@

@v_args(inline=True)
class CalculateTree(Transformer):
def __init__(self, clock, variables, inner_variables: dict, global_scale: str):
def __init__(self, clock, variables: SimpleNamespace, global_scale: str):
super().__init__()
self.clock = clock
self.variables = variables
self.inner_variables = inner_variables
self.global_scale = global_scale
self.memory = {}
self.library = funclib.FunctionLibrary(
clock=self.clock,
amphibian=self.variables,
inner_variables=self.inner_variables,
inner_variables=self.variables,
global_scale=self.global_scale,
)

Expand Down Expand Up @@ -537,13 +535,9 @@ def function_call(self, func_name, *args):

try:
modifiers_list = {
# Amphibian variables
# Variables
"get": self.library.get_variable,
"set": self.library.set_variable,
"getA": self.library.get_amphibian_variable,
"setA": self.library.set_amphibian_variable,
"ga": self.library.get_amphibian_variable,
"sa": self.library.set_amphibian_variable,
"g": self.library.get_variable,
"s": self.library.set_variable,
# Pure conditions
Expand Down
46 changes: 0 additions & 46 deletions sardine_core/sequences/variables.py

This file was deleted.

0 comments on commit fca4921

Please sign in to comment.