# The Volang Language
Welcome to the documentation for Volang, Voldeno's proprietary programming language. It serves as the core tool for implementing logic across blocks in our smart home ecosystem.
# Introduction
Volang is a specialized programming language developed by Voldeno, specifically designed to implement the logic of blocks within our smart home ecosystem. It bridges the gap between hardware capabilities and high-level automation, allowing developers to create advanced control scenarios efficiently and securely.
The primary purpose of Volang is to define the behavior of Blocks. In the Voldeno system, a block represents an autonomous functional unit (e.g., a roller shutter controller, a thermostat, or an energy meter). Volang allows developers to define how these blocks react to input signals, process internal state, and trigger actions based on events.
# Architecture: The Compiled Model
Unlike simple scripting languages that are interpreted directly from text, Volang utilizes a Virtual Machine (VM) architecture. The execution process consists of two distinct stages:
- Compilation: The source code written by the developer is processed by the Volang Compiler. This step verifies syntax, data types, and logical integrity, transforming the code into an optimized binary format known as bytecode.
- Execution: The resulting bytecode is loaded into the Volang Virtual Machine (Volang VM)—a dedicated runtime environment operating on Voldeno controllers. The VM is responsible for interpreting the bytecode instructions and executing them safely on the physical hardware.
# Why Volang VM?
Adopting a virtual machine architecture offers significant advantages for smart home environments, unifies the development workflow and extends the capabilities of the hardware:
- Safety (Sandboxing): User code runs in an isolated environment, separated from the core operating system. A runtime error (e.g., division by zero) will only stop the specific script within the VM, ensuring the overall stability of the controller remains uncompromised.
- Performance: Executing compact binary bytecode is significantly faster and more resource-efficient than parsing text files at runtime, which is crucial for embedded systems and microcontrollers.
- Portability: Logic written in Volang is hardware-agnostic. It can be executed on any device capable of running the Volang VM, regardless of the underlying processor architecture.
- Identical Simulation: Since the Volang VM runs consistently across platforms, the exact same block logic can be executed within Voldeno Studio. This allows developers to test and debug their code in a desktop environment with the guarantee that the behavior will be identical to the actual production system.
- Distributed Execution: The efficiency of the VM allows it to run not only on the central Voldeno Hub but also on peripheral extension modules. This capability enables true distributed logic, where complex processing can occur locally on the device (at the edge) without being limited to basic event reporting.
# Lexical Conventions
# Keywords
The following words are reserved in Volang and cannot be used as variable or function names. They form the structural foundation of the language.
and break else
extern false fn
if or shl
shr return true
while xor
# Literals
In Volang, a literal is a notation for representing a fixed value directly within the source code. These are the raw data values that you assign to variables or pass to functions. Volang supports specific formats for boolean, strings, integer, and floating-point literals.
# Boolean Literals
Used to represent logical states. There are exactly two boolean literals:
true: Represents a positive or active state (On).false: Represents a negative or inactive state (Off).
# Integer Literals
Integer literals represent whole numbers. Volang supports two notations:
- Decimal (Base-10): Standard numeric representation using digits
0-9. Negative numbers are prefixed with a minus sign-. - Hexadecimal (Base-16): Often used for color codes, bitmasks, or hardware addresses. These literals must start with the prefix
0xfollowed by digits0-9and lettersA-F(case-insensitive).
# Floating-Point Literals
Floating-point literals represent numbers with fractional parts.
- Syntax: They are written using decimal notation with a dot
.acting as the decimal separator. - Requirement: A valid float literal typically requires at least one digit before or after the decimal point (e.g.,
0.5,10.0,23.34).
# Text Literals (Strings)
Text literals represent sequences of characters and are used for messages, identifiers, or labels.
- Syntax: Text must be enclosed in double quotes
". - Multi-line Support: A string literal in Volang can span multiple lines. The newline characters within the quotes are preserved, making it easy to format text for display panels or logs without using special escape codes like
\n.
# Raw Strings
Raw strings are used to represent text exactly as written, ignoring special characters or formatting that might otherwise be interpreted by the compiler.
- Syntax: Raw strings must be enclosed in triple double quotes
""". - Usage: Everything inside the triple quotes is treated as literal text. This is particularly useful for storing blocks of code, complex regex patterns, or pre-formatted documentation.
- Preservation: Like standard multi-line strings, all indentation and line breaks are maintained exactly as they appear between the
"""delimiters.
Examples:
// --- Boolean Literals ---
is_light_on = true
is_door_locked = false
// --- Integer Literals (Decimal) ---
counter = 10
negative_offset = -5
// --- Integer Literals (Hexadecimal) ---
status_mask = 0xFF // Decimal 255
color_red = 0xFF0000 // Color code
// --- Floating-Point Literals ---
temperature = 23.34
calibration_factor = 0.95
voltage = 12.0 // .0 indicates this is a Float, not an Integer
// --- String Literals ---
device_name = "Living Room Thermostat"
// Multi-line string (preserves formatting)
notification_msg = "
Warning: High Temperature!
Action: Cooling Activated
Time: 12:00
"
// --- Raw String Literal ---
configJson = """
{
"status": "success",
"directory": "C:\users\volang\app",
"pattern": "\b[A-Z0-9._%+-]+",
"description": "No need to escape backslashes or "quotes" here!"
}
"""
# Values and Types
Volang operates on a dynamic type system, offering a flexible approach to data management. In Volang, variables function as generic containers rather than strictly typed storage. Consequently, there is no need to explicitly declare types (such as int or float) within the code. The type information is intrinsic to the value itself, not the variable assigned to hold it.
# First-Class Values
All values in Volang are first-class values. This implies that every value, regardless of its type, can be:
- Stored in variables.
- Passed as arguments to functions.
- Returned as results from functions.
# Type Consistency (Strict Typing)
While Volang does not require type declarations, it enforces type stability. Once a variable is assigned a value of a specific type (e.g., an Integer), it becomes bound to that type. You cannot subsequently assign a value of a different type (e.g., a String) to that same variable. This mechanism prevents common runtime errors and ensures predictable controller behavior.
# Value Categories
Volang distinguishes between four primary kinds of values:
# 1. Numeric (Integer & Float)
Used for mathematical calculations, sensor readings, and counters.
- Integer: Whole numbers without a fractional component (e.g.,
0,42,-15). - Float: Floating-point numbers representing fractional values (e.g.,
3.14,21.5,-0.001).
# 2. Textual (String)
Used for status messages, logs, names, and text processing. Strings are sequences of characters enclosed in double quotes ".
- Multi-line Support: Volang supports multi-line strings. You can press Enter within the quotes to create a text block that spans several lines.
# 3. Logical (Boolean)
Booleans represent truth values and are crucial for decision-making logic (if, while).
- Values:
trueorfalse.
# 4. Opaque
Opaque values represent complex data structures whose internal implementation is managed by the Volang VM. The user interacts with them through dedicated Standard Library functions rather than direct syntax operators. Examples of opaque types include:
- Array: An ordered, indexed collection of values.
- Map: A collection of key-value pairs, where each key is unique.
These are just some of the opaque types available — the Standard Library may provide additional ones. Opaque values follow the same first-class rules as other types — they can be stored in variables, passed as arguments, and returned from functions. However, they cannot be used with standard arithmetic or logical operators.
Example:
// 1. Dynamic Typing
status = 25.5
// 2. Multi-line Strings
config_info = "Device: Thermostat
Location: Living Room
Firmware: v1.2"
// 3. Passing values
fn logStatus(message) {
print(message)
}
logStatus(config_info)
# Variables
Volang employs a streamlined approach to variable management. There are no declaration keywords (such as var, let, or int). A variable is created the moment you assign a value to a name. The location where you define the variable determines its scope (visibility) throughout the script.
# Creating Variables
To define a variable, simply use the assignment operator =. The variable's data type is inferred from the assigned value and becomes fixed for the lifetime of that variable.
Syntax:
variable_name = value
# Variable Scope
Scope defines where a variable can be accessed within your code. Volang distinguishes between two types of scope:
# Global Variables
Variables defined at the top level of the script (outside of any function or control block) are Global.
- Visibility: They are accessible from anywhere in the script, but not inside functions. To use a global value inside a function, pass it as an argument.
- Use Case: Ideal for storing the overall state of the device, such as
target_temperature,system_mode, oralarm_status.
# Local Variables
Variables defined inside a function (fn) or a control block are Local.
- Visibility: They exist only within the block where they were created. They are destroyed as soon as the execution leaves that block.
- Use Case: Used for temporary calculations, loop counters, or intermediate logic steps.
Example:
// --- Global Variables ---
system_status = "IDLE"
setpoint = 21.5
// Global variables are NOT accessible inside functions.
// Pass them as arguments instead:
fn checkTemperature(current_temp, target) {
// --- Local Variable ---
// 'diff' exists only inside this function
diff = current_temp - target
if diff > 1.0 {
return "Cooling Needed"
}
return "Stable"
}
// Pass the global 'setpoint' as an argument
result = checkTemperature(22.8, setpoint)
// 'diff' is not accessible here
# Comments
Comments are fragments of code that are ignored by the Volang compiler. They are used to explain the logic, leave notes for other developers, or temporarily disable specific parts of the code during testing.
# Single-line Comments
Single-line comments start with two forward slashes //. Any text following these characters up to the end of the line is treated as a comment.
# Multi-line Comments
Multi-line (block) comments start with /* and end with */. Everything between these markers is ignored, regardless of how many lines it spans.
Example:
// This is a single-line comment
targetTemp = 21.5 // Comment at the end of a line
/*
This is a multi-line comment.
It is useful for describing complex logic
or block headers.
*/
/* oldLogic = 10
if (oldLogic > 5) {
// This code is disabled
}
*/
# Statements
Volang is designed to minimize visual noise and maximize readability. Unlike languages such as C++ or Java, Volang does not use semicolons (;) to mark the end of an instruction.
The newline character (pressing Enter) serves as the definitive statement terminator. The compiler interprets the end of a line as the completion of the current command.
# Assignments
Assignment operators are used to store a value in a variable. Volang supports the standard basic assignment operator as well as compound assignment operators.
# Basic Assignment
The = operator assigns the value on the right-hand side to the variable on the left-hand side.
target_temp = 21.0
event_counter = 0
# Compound Assignment Operators
Compound operators perform an operation on the current value of the variable and then update it with the new result.
| Operator | Description |
|---|---|
+= | Add and assign |
-= | Subtract and assign |
*= | Multiply and assign |
/= | Divide and assign |
Key Behaviors:
- Initialization Requirement: For compound operators, the variable on the left side must already exist.
- Type Promotion: Compound assignment follows the same type promotion rules as standard arithmetic.
Examples:
// Increment counter
event_counter += 1
// Decrease setpoint
target_temp -= 0.5
// Scale brightness to 80%
brightness = 100
brightness *= 0.8 // Result: 80.0
// Energy accumulation
total_energy_kwh = 0.0
current_usage = 1.5
total_energy_kwh += current_usage
# Control Flow
The if statement is the fundamental decision-making structure in Volang. The condition expression must evaluate to a Boolean value (true or false). Non-boolean values (such as integers, floats, or strings) are not implicitly converted — using them as a condition will result in a compilation error.
# Basic if
if (condition) {
// Code to run if condition is true
}
# if with else
if (condition) {
// Code to run if condition is true
} else {
// Code to run if condition is false
}
# Chained Conditions (else if)
if (condition_1) {
// Runs if condition_1 is true
} else if (condition_2) {
// Runs if condition_1 is false AND condition_2 is true
} else {
// Runs if all above conditions are false
}
Example - Thermostat Logic:
current_temp = 19.0
target_temp = 21.0
hysteresis = 0.5
if (current_temp < (target_temp - hysteresis)) {
// Too cold -> Start Heating
setHeating(true)
} else if (current_temp > (target_temp + hysteresis)) {
// Too hot -> Start Cooling
setCooling(true)
} else {
// Temperature is within the optimal range
setHeating(false)
setCooling(false)
}
# Loops
Volang supports a single loop construct: the while loop. There are no for or do-while loops in the language. As with if, the condition expression must evaluate to a Boolean value (true or false).
Syntax:
while (condition) {
// Code to execute repeatedly
}
Volang supports the break keyword within loops. When break is encountered, the loop is immediately terminated.
In embedded systems and smart home controllers, infinite loops can be dangerous. The Volang VM monitors execution time, but it is your responsibility to ensure that the loop condition eventually becomes false or that a break statement is reached.
Examples:
// Basic Counter
counter = 5
while (counter > 0) {
logValue(counter)
counter -= 1
}
// Waiting with Timeout (Using break)
attempts = 0
max_retries = 10
success = false
while (attempts < max_retries) {
if (checkConnection()) {
success = true
break
}
attempts += 1
}
if (success) {
startProcess()
}
# Functions
Functions are reusable blocks of code designed to perform a specific task. In Volang, functions are defined using the fn keyword.
Syntax:
fn functionName(argument1, argument2) {
// Code to be executed
}
Key Rules:
- Arguments: A function can accept multiple arguments (separated by commas) or no arguments at all.
- Return Values: Use
returnto send a value back. If omitted, the function returns nothing (void). - Naming Constraints: Function names must be different from Standard Library function names.
- Scope: Variables defined inside a function are local to that function.
- No global access: Global variables are not accessible inside functions. Any external data the function needs must be passed as an argument.
Example:
fn calculateAverage(a, b, c) {
total = a + b + c
return total / 3
}
avg = calculateAverage(20.5, 21.0, 19.5)
# Expressions
# Binary Arithmetic Operators
| Operator | Description |
|---|---|
+ | Addition |
- | Subtraction |
* | Multiplication |
/ | Division |
% | Modulo |
Precedence: Multiplication, Division, and Modulo are evaluated before Addition and Subtraction.
Examples:
// Sensor Calibration
raw_value = 50
scale_factor = 1.2
offset = 5.0
calibrated_value = raw_value * scale_factor + offset // 65.0
// Average with parentheses
average_temp = (temp_1 + temp_2 + temp_3) / 3
// Modulo for cyclical events
remainder = loop_counter % 10
# Binary Logical Operators
| Operator | Description |
|---|---|
and | Logical AND - Returns true only if both operands are true |
or | Logical OR - Returns true if at least one operand is true. Both operands are always evaluated (no short-circuit evaluation). |
Examples:
// Conditional Lighting (AND)
if (motion_active and brightness_level < threshold) {
setLight(true)
}
// Redundant Triggering (OR)
if (door_open or window_vibration) {
triggerAlarm()
}
// Complex Logic (Grouping)
heating_on = manual_override or (is_weekend and user_home)
# Binary Bitwise Operations
Bitwise operations allow direct manipulation of individual bits within integer values.
| Operator | Description |
|---|---|
& | Bitwise AND |
| | Bitwise OR |
xor | Bitwise XOR |
shl | Shift Left |
shr | Shift Right |
Example - Bitwise AND for masking:
sensor_value = 0xA7 // Binary: 1010 0111
mask = 0x0F // Binary: 0000 1111
// Extract only the lower 4 bits
lower_nibble = sensor_value & mask
// Result: 0x07 (Binary: 0000 0111)
