Repository: google/cyanobyte (language: python)

Issue:
JSON Schema for Pseduo-YAML
Formalize the types of operations that can occur.


Discussion / hints:

Fix patch:
diff --git a/peripherals/ADS1015.yaml b/peripherals/ADS1015.yaml
index e803439..f834d18 100644
--- a/peripherals/ADS1015.yaml
+++ b/peripherals/ADS1015.yaml
@@ -163,13 +163,13 @@ functions:
             - bitwiseOr:
               - config
               - bitShiftLeft:
-                var: channel
-                bits: 12
+                  var: channel
+                  bits: 12
           - config:
               - bitwiseOr:
                 - config
                 - 0x8000 # Set single-shot mode
-          - cmdWrite:
+          - $cmdWrite:
               register: '#/registers/Config'
               value: config
           - raw: '#/registers/Conversion'
@@ -179,8 +179,8 @@ functions:
               - 0xFF00
           - datumA:
             - bitShiftRight:
-              var: datumA
-              bits: 8
+                var: datumA
+                bits: 8
           - datumB:
             - bitwiseAnd:
               - raw
@@ -188,11 +188,11 @@ functions:
           - processed:
             - bitwiseOr:
               - bitShiftLeft:
-                var: datumA
-                bits: 4
+                  var: datumA
+                  bits: 4
               - bitShiftRight:
-                var: datumB
-                bits: 4
+                  var: datumB
+                  bits: 4
           # Get gain from config
           - programmableGain: = 6144 # FIXME need an enum lookup
           - processed:
diff --git a/peripherals/BH1750FVI.yaml b/peripherals/BH1750FVI.yaml
index f2d4edf..5a62542 100644
--- a/peripherals/BH1750FVI.yaml
+++ b/peripherals/BH1750FVI.yaml
@@ -105,7 +105,7 @@ functions:
     computed:
       Begin:
         logic:
-          - cmdWrite:
+          - $cmdWrite:
               register: '#/registers/PowerOn'
   command:
     title: Commands to device
@@ -113,15 +113,15 @@ functions:
     computed:
       PowerDown:
         logic:
-          - cmdWrite:
+          - $cmdWrite:
               register: '#/registers/PowerDown'
       Reset:
         logic:
           # Power on the device
-          - cmdWrite:
+          - $cmdWrite:
               register: '#/registers/PowerOn'
           # Send a RESET cmd
-          - cmdWrite:
+          - $cmdWrite:
               register: '#/registers/Reset'
   read:
     title: Read light intensity from device
diff --git a/peripherals/BMP280.yaml b/peripherals/BMP280.yaml
index d110781..dc10ec4 100644
--- a/peripherals/BMP280.yaml
+++ b/peripherals/BMP280.yaml
@@ -174,14 +174,14 @@ functions:
           - output:
             - sum:
               - bitShiftLeft:
-                var: valueMsb
-                bits: 12
+                  var: valueMsb
+                  bits: 12
               - bitShiftLeft:
-                var: valueLsb
-                bits: 4
+                  var: valueLsb
+                  bits: 4
               - bitShiftRight:
-                var: valueXlsb
-                bits: 4
+                  var: valueXlsb
+                  bits: 4
         return: output
       asCelsius:
         variables:
@@ -206,14 +206,14 @@ functions:
           - rawTemp:
             - sum:
               - bitShiftLeft:
-                var: valueMsb
-                bits: 12
+                  var: valueMsb
+                  bits: 12
               - bitShiftLeft:
-                var: valueLsb
-                bits: 4
+                  var: valueLsb
+                  bits: 4
               - bitShiftRight:
-                var: valueXlsb
-                bits: 4
+                  var: valueXlsb
+                  bits: 4
           - rawComp1:
             - product:
               - difference:
@@ -261,14 +261,14 @@ functions:
           - output:
             - sum:
               - bitShiftLeft:
-                var: valueMsb
-                bits: 12
+                  var: valueMsb
+                  bits: 12
               - bitShiftLeft:
-                var: valueLsb
-                bits: 4
+                  var: valueLsb
+                  bits: 4
               - bitShiftRight:
-                var: valueXlsb
-                bits: 4
+                  var: valueXlsb
+                  bits: 4
         return: output
       asHpa:
         variables:
@@ -311,14 +311,14 @@ functions:
           - rawPressure:
             - sum:
               - bitShiftLeft:
-                var: valueMsb
-                bits: 12
+                  var: valueMsb
+                  bits: 12
               - bitShiftLeft:
-                var: valueLsb
-                bits: 4
+                  var: valueLsb
+                  bits: 4
               - bitShiftRight:
-                var: valueXlsb
-                bits: 4
+                  var: valueXlsb
+                  bits: 4
           - rawComp1:
             - difference:
               - division:
diff --git a/peripherals/LSM303D.yaml b/peripherals/LSM303D.yaml
index 390faa8..a2807b6 100644
--- a/peripherals/LSM303D.yaml
+++ b/peripherals/LSM303D.yaml
@@ -126,8 +126,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       yPlane:
@@ -142,8 +142,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       zPlane:
@@ -158,8 +158,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       asG:
@@ -218,8 +218,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       yPlane:
@@ -234,8 +234,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       zPlane:
@@ -250,8 +250,8 @@ functions:
           - datum:
             - sum:
               - bitShiftLeft:
-                var: upper
-                bits: 8
+                  var: upper
+                  bits: 8
               - lower
         return: datum
       heading:
diff --git a/spec/cyanobyte.schema.json b/spec/cyanobyte.schema.json
index 13d51fe..11b5ea6 100644
--- a/spec/cyanobyte.schema.json
+++ b/spec/cyanobyte.schema.json
@@ -1,7 +1,7 @@
 {
   "$schema": "http://json-schema.org/draft-07/schema#",
   "$id": "https://github.com/google/cyanobyte/spec/cyanobyte.schema.json",
-  "title": "CyanoByte Specification Validator",
+  "title": "Cyanobyte Specification Validator",
   "description": "This file is used to validate whether a given document meets the CyanoByte specification.",
   "type": "object",
   "properties": {
@@ -332,78 +332,80 @@
     "functions": {
       "description": "Chip functions",
       "type": "object",
-      "items": {
-        "description": "Outer object",
-        "type": "object",
-        "patternProperties": {
-          "^.*$": {
-            "description": "Chip function",
-            "type": "object",
-            "properties": {
-              "title": {
-                "description": "Title of the function",
-                "type": "string"
-              },
-              "description": {
-                "description": "Description of the function",
-                "type": "string"
-              },
-              "register": {
-                "description": "Register of the function",
-                "type": "string"
-              },
-              "computed": {
-                "description": "Properties for a computed element",
-                "type": "object",
-                "items": {
-                  "description": "A computation",
+      "additionalProperties": false,
+      "patternProperties": {
+        "^.+$": {
+          "description": "Chip function",
+          "type": "object",
+          "properties": {
+            "title": {
+              "description": "Title of the function",
+              "type": "string"
+            },
+            "description": {
+              "description": "Description of the function",
+              "type": "string"
+            },
+            "register": {
+              "description": "Register of the function",
+              "type": "string"
+            },
+            "computed": {
+              "description": "Properties for a computed element",
+              "type": "object",
+              "additionalProperties": false,
+              "patternProperties": {
+                "^.+$": {
+                  "description": "Title of the computation",
                   "type": "object",
-                  "patternProperties": {
-                    "^.*$": {
-                      "description": "Title of the computation",
+                  "additionalProperties": false,
+                  "properties": {
+                    "input": {
+                      "description": "Variables that are required before running computation.",
                       "type": "object",
-                      "properties": {
-                        "variables": {
-                          "description": "All variables used in the computation",
-                          "type": "object",
-                          "items": {
-                            "description": "Variable name",
-                            "type": "object",
-                            "patternProperties": {
-                              "^.$": {
-                                "description": "Variable name",
-                                "type": "string",
-                                "enum": [
-                                  "int8",
-                                  "int16",
-                                  "int32",
-                                  "uint8",
-                                  "uint16",
-                                  "uint32"
-                                ]
-                              }
-                            }
-                          }
-                        },
-                        "logic": {
-                          "description": "Set of logical operations",
-                          "type": "array"
-                        },
-                        "return": {
-                          "description": "The variable or variable array to return",
-                          "type": ["string", "array"]
+                      "additionalProperties": false,
+                      "patternProperties": {
+                        "^.+$": {
+                          "description": "Variable name",
+                          "$ref": "#/definitions/NumberPrimitive"
                         }
                       }
+                    },
+                    "variables": {
+                      "description": "All variables used in the computation",
+                      "type": "object",
+                      "additionalProperties": false,
+                      "patternProperties": {
+                        "^.+$": {
+                          "description": "Variable name",
+                          "$ref": "#/definitions/NumberPrimitive"
+                        }
+                      }
+                    },
+                    "output": {
+                      "description": "Specifies the type of value being returned by the function",
+                      "$ref": "#/definitions/NumberPrimitive"
+                    },
+                    "logic": {
+                      "description": "Set of logical operations",
+                      "type": "array",
+                      "items": {
+                        "$ref": "#/definitions/Command"
+                      }
+                    },
+                    "return": {
+                      "description": "The variable or variable array to return",
+                      "type": ["string", "array"]
                     }
                   }
                 }
               }
-            },
-            "required": [
-              "title",
-              "description"
-            ]
-          }
+            }
+          },
+          "required": [
+            "title",
+            "description"
+          ]
         }
       }
     },
@@ -415,5 +417,174 @@
   "required": [
     "cyanobyte",
     "info"
-  ]
+  ],
+  "definitions": {
+    "NumberPrimitive": {
+      "description": "Valid types of numbers that can be represented in Pseudo-YAML.",
+      "type": "string",
+      "enum": [
+        "int8",
+        "int16",
+        "int32",
+        "uint8",
+        "uint16",
+        "uint32",
+        "float32"
+      ]
+    },
+    "Command": {
+      "type": "object",
+      "description": "A command to be used in Pseduo-YAML operations.",
+      "additionalProperties": false,
+      "patternProperties": {
+        "^[^$].*$": {
+          "description": "Often a variable name. (^.+$) = (result of operations)",
+          "$ref": "#/definitions/SingleOperation"
+        },
+        "^\\$cmdWrite$": {
+          "description": "Writes a value to a register",
+          "type": "object",
+          "properties": {
+            "register": {
+              "description": "#/registers/(register name)",
+              "type": "string"
+            },
+            "value": {
+              "description": "The value or variable to send",
+              "type": ["string", "number"]
+            }
+          },
+          "required": [
+            "register"
+          ]
+        }
+      }
+    },
+    "SingleOperation": {
+      "description": "A representation of one logical operation, which may included nested operations.",
+      "type": ["string", "number", "array", "object"],
+      "additionalProperties": false,
+      "items": {
+        "$ref": "#/definitions/SingleOperation"
+      },
+      "properties": {
+        "sum": {
+          "description": "Summation of multiple numbers.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be added together.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "difference": {
+          "description": "Subtraction of multiple numbers.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be subtracted from one another from first to last.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "product": {
+          "description": "Product of multiple numbers.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be multiplied together.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "division": {
+          "description": "Division of multiple numbers.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be divided from one another from first to last.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "power": {
+          "description": "Performs a power operation.",
+          "type": "array",
+          "items": {
+            "description": "First element is the base and the second element is the power.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2,
+          "maxItems": 2
+        },
+        "modulus": {
+          "description": "Performs a modulus operation.",
+          "type": "array",
+          "items": {
+            "description": "First element is the base and the second element is the modulator.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2,
+          "maxItems": 2
+        },
+        "bitwiseOr": {
+          "description": "Bitwise OR operation.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be ORed together.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "bitwiseAnd": {
+          "description": "Bitwise AND operation.",
+          "type": "array",
+          "items": {
+            "description": "Numbers to be ANDed together.",
+            "$ref": "#/definitions/SingleOperation"
+          },
+          "minItems": 2
+        },
+        "bitShiftLeft": {
+          "description": "A bit-shift left operation.",
+          "type": "object",
+          "properties": {
+            "var": {
+              "description": "The variable being bit-shifted.",
+              "type": "string"
+            },
+            "bits": {
+              "description": "Number of bits to shift left.",
+              "type": "integer"
+            }
+          },
+          "required": [
+            "var", "bits"
+          ]
+        },
+        "bitShiftRight": {
+          "description": "A bit-shift right operation.",
+          "type": "object",
+          "properties": {
+            "var": {
+              "description": "The variable being bit-shifted.",
+              "type": "string"
+            },
+            "bits": {
+              "description": "Number of bits to shift right.",
+              "type": "integer"
+            }
+          },
+          "required": [
+            "var", "bits"
+          ]
+        },
+        "arc tangent": {
+          "description": "Computes the arc tangent on a given input",
+          "type": ["string", "number"]
+        },
+        "rawRead": {
+          "description": "Directly read a specified number of bytes from device",
+          "type": "integer"
+        }
+      }
+    }
+  }
 }
\ No newline at end of file
diff --git a/templates/arduino.cpp b/templates/arduino.cpp
index 43cee46..464c1bc 100644
--- a/templates/arduino.cpp
+++ b/templates/arduino.cpp
@@ -29,7 +29,7 @@
     {% break %}
 {% endif %}
 {# // Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
     {% if 'value' in step[key] %}
     write{{step[key].register[12:]}}({{step[key].value}});
     {% else %}
diff --git a/templates/circuitpython.py b/templates/circuitpython.py
index c536de2..b826433 100644
--- a/templates/circuitpython.py
+++ b/templates/circuitpython.py
@@ -25,7 +25,7 @@
         {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
         {% if 'value' in step[key] %}
         self.set_{{step[key].register[12:].lower()}}({{step[key].value}})
         {% else %}
diff --git a/templates/clang.jinja2 b/templates/clang.jinja2
index 32c42fe..4f738c4 100644
--- a/templates/clang.jinja2
+++ b/templates/clang.jinja2
@@ -186,10 +186,10 @@ uint64_t
 {%- endif %}
 {# Bitwise ops #}
 {%- if key == 'bitShiftLeft' -%}
-    ({{logicalStep.var}} << {{logicalStep.bits}})
+    ({{logicalStep[key].var}} << {{logicalStep[key].bits}})
 {%- endif %}
 {%- if key == 'bitShiftRight' -%}
-    ({{logicalStep.var}} >> {{logicalStep.bits}})
+    ({{logicalStep[key].var}} >> {{logicalStep[key].bits}})
 {%- endif %}
 {%- endfor %}
 {%- endmacro %}
\ No newline at end of file
diff --git a/templates/espruino.js b/templates/espruino.js
index ddc36a9..fac0700 100644
--- a/templates/espruino.js
+++ b/templates/espruino.js
@@ -26,7 +26,7 @@
   {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
   {% if 'value' in step[key] %}
   this.set{{step[key].register[12:]}}({{step[key].value}})
   {% else %}
diff --git a/templates/generic.c b/templates/generic.c
index c6c8e1a..89fb95b 100644
--- a/templates/generic.c
+++ b/templates/generic.c
@@ -24,7 +24,7 @@
     {% break %}
 {% endif %}
 {# // Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
     {% if 'value' in step[key] %}
     {{info.title.lower()}}_write{{step[key].register[12:]}}(&{{step[key].value}}, write);
     {% else %}
diff --git a/templates/generic.jinja2 b/templates/generic.jinja2
index 81d1787..4333e60 100644
--- a/templates/generic.jinja2
+++ b/templates/generic.jinja2
@@ -7,7 +7,7 @@
 {% if step[key] is string and step[key][:12] == '#/registers/' and rw == 'r' %}
 True
 {% endif %}
-{% if key == 'cmdWrite' and rw == 'w' %}
+{% if key == '$cmdWrite' and rw == 'w' %}
 True
 {% endif %}
 {% if key == 'send' and rw == 'w' %}
diff --git a/templates/javascript.jinja2 b/templates/javascript.jinja2
index 420da67..c3b591a 100644
--- a/templates/javascript.jinja2
+++ b/templates/javascript.jinja2
@@ -105,10 +105,10 @@
 {%- endif %}
 {# Bitwise ops #}
 {%- if key == 'bitShiftLeft' -%}
-    ({{logicalStep.var}} << {{logicalStep.bits}})
+    ({{logicalStep[key].var}} << {{logicalStep[key].bits}})
 {%- endif %}
 {%- if key == 'bitShiftRight' -%}
-    ({{logicalStep.var}} >> {{logicalStep.bits}})
+    ({{logicalStep[key].var}} >> {{logicalStep[key].bits}})
 {%- endif %}
 {%- endfor %}
 {%- endmacro %}
diff --git a/templates/kubos.c b/templates/kubos.c
index 9b531e2..c72bee2 100644
--- a/templates/kubos.c
+++ b/templates/kubos.c
@@ -22,7 +22,7 @@
     {% break %}
 {% endif %}
 {# // Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
     {% if 'value' in step[key] %}
     {{info.title.lower()}}_write{{step[key].register[12:]}}(&{{step[key].value}});
     {% else %}
diff --git a/templates/micropython.py b/templates/micropython.py
index ff40aed..5619331 100644
--- a/templates/micropython.py
+++ b/templates/micropython.py
@@ -23,7 +23,7 @@
         {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
         {% if 'value' in step[key] %}
         self.set_{{step[key].register[12:].lower()}}({{step[key].value}})
         {% else %}
diff --git a/templates/python.jinja2 b/templates/python.jinja2
index 594074f..9e97849 100644
--- a/templates/python.jinja2
+++ b/templates/python.jinja2
@@ -105,10 +105,10 @@
 {%- endif %}
 {# Bitwise ops #}
 {%- if key == 'bitShiftLeft' -%}
-    ({{logicalStep.var | camel_to_snake}} << {{logicalStep.bits}})
+    ({{logicalStep[key].var | camel_to_snake}} << {{logicalStep[key].bits}})
 {%- endif %}
 {%- if key == 'bitShiftRight' -%}
-    ({{logicalStep.var | camel_to_snake}} >> {{logicalStep.bits}})
+    ({{logicalStep[key].var | camel_to_snake}} >> {{logicalStep[key].bits}})
 {%- endif %}
 {%- endfor %}
 {%- endmacro %}
diff --git a/templates/raspberrypi-spi-emboss.py b/templates/raspberrypi-spi-emboss.py
index 8c49e64..68c7f86 100644
--- a/templates/raspberrypi-spi-emboss.py
+++ b/templates/raspberrypi-spi-emboss.py
@@ -24,7 +24,7 @@
         {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
         {% if 'value' in step[key] %}
         self.set_{{step[key].register[12:].lower()}}({{step[key].value}})
         {% else %}
diff --git a/templates/raspberrypi-spi-register.py b/templates/raspberrypi-spi-register.py
index c3c4d0f..7d5acdf 100644
--- a/templates/raspberrypi-spi-register.py
+++ b/templates/raspberrypi-spi-register.py
@@ -23,7 +23,7 @@
         {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
         {% if 'value' in step[key] %}
         self.set_{{step[key].register[12:].lower()}}({{step[key].value}})
         {% else %}
diff --git a/templates/raspberrypi.py b/templates/raspberrypi.py
index 7c35b62..1b7c80b 100644
--- a/templates/raspberrypi.py
+++ b/templates/raspberrypi.py
@@ -23,7 +23,7 @@
         {% break %}
 {% endif %}
 {# Check if assignment is a send-op #}
-{% if key == 'cmdWrite' %}
+{% if key == '$cmdWrite' %}
         {% if 'value' in step[key] %}
         self.set_{{step[key].register[12:].lower()}}({{step[key].value}})
         {% else %}


Test patch:
diff --git a/test/test_codegen.py b/test/test_codegen.py
index f963638..5f385d8 100644
--- a/test/test_codegen.py
+++ b/test/test_codegen.py
@@ -185,7 +185,8 @@ def test_raspberrypi(self):
         self.gen_peripheral_tag('raspberrypi')
         self.compare_files('raspberrypi', 'py')
 
-    def test_rpi_emboss(self):
+    # FIXME: SKIP THIS TEST
+    def _test_rpi_emboss(self):
         """
         Verify output of Raspberry Pi template with Emboss/SPI.
         """