mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-21 17:56:31 +00:00
Add Berry language reference in Markdown for AI (#23647)
This commit is contained in:
parent
850fd07d3a
commit
19c212f261
976
.doc_for_ai/BERRY_LANGUAGE_REFERENCE.md
Normal file
976
.doc_for_ai/BERRY_LANGUAGE_REFERENCE.md
Normal file
@ -0,0 +1,976 @@
|
|||||||
|
# Berry Language Reference
|
||||||
|
|
||||||
|
Note: this file is supposed to use as a reference manual for Generative AI in a compact form. For Claude AI it costs ~6000 tokens.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Berry is an ultra-lightweight, dynamically typed embedded scripting language designed for resource-constrained environments. The language primarily supports procedural programming, with additional support for object-oriented and functional programming paradigms. Berry's key design goal is to run efficiently on embedded devices with very limited memory, making the language highly streamlined while maintaining rich scripting capabilities.
|
||||||
|
|
||||||
|
## Basic Information
|
||||||
|
|
||||||
|
### Comments
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# This is a line comment
|
||||||
|
#- This is a
|
||||||
|
block comment
|
||||||
|
-#
|
||||||
|
```
|
||||||
|
|
||||||
|
### Literals
|
||||||
|
|
||||||
|
#### Numerical Literals
|
||||||
|
```berry
|
||||||
|
40 # Integer literal
|
||||||
|
0x80 # Hexadecimal literal (integer)
|
||||||
|
3.14 # Real literal
|
||||||
|
1.1e-6 # Real literal with scientific notation
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Boolean Literals
|
||||||
|
```berry
|
||||||
|
true # Boolean true
|
||||||
|
false # Boolean false
|
||||||
|
```
|
||||||
|
|
||||||
|
#### String Literals
|
||||||
|
```berry
|
||||||
|
'this is a string'
|
||||||
|
"this is a string"
|
||||||
|
```
|
||||||
|
|
||||||
|
String literals can be concatenated without operators:
|
||||||
|
```berry
|
||||||
|
s = "a" "b" "c" # s == "abc"
|
||||||
|
s = "a" # Multi-line strings
|
||||||
|
"b"
|
||||||
|
"c" # s == "abc"
|
||||||
|
```
|
||||||
|
|
||||||
|
Escape sequences:
|
||||||
|
- `\a` - Bell
|
||||||
|
- `\b` - Backspace
|
||||||
|
- `\f` - Form feed
|
||||||
|
- `\n` - Newline
|
||||||
|
- `\r` - Carriage return
|
||||||
|
- `\t` - Horizontal tab
|
||||||
|
- `\v` - Vertical tab
|
||||||
|
- `\\` - Backslash
|
||||||
|
- `\'` - Single quote
|
||||||
|
- `\"` - Double quote
|
||||||
|
- `\?` - Question mark
|
||||||
|
- `\0` - Null character
|
||||||
|
- `\ooo` - Character represented by octal number
|
||||||
|
- `\xhh` - Character represented by hexadecimal number
|
||||||
|
- `\uXXXX` - Unicode character (UTF-8 encoded)
|
||||||
|
|
||||||
|
#### Nil Literal
|
||||||
|
```berry
|
||||||
|
nil # Represents no value
|
||||||
|
```
|
||||||
|
|
||||||
|
### Identifiers
|
||||||
|
|
||||||
|
An identifier starts with an underscore or letter, followed by any combination of underscores, letters, or numbers. Berry is case-sensitive.
|
||||||
|
|
||||||
|
```berry
|
||||||
|
a
|
||||||
|
TestVariable
|
||||||
|
Test_Var
|
||||||
|
_init
|
||||||
|
baseClass
|
||||||
|
_
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keywords
|
||||||
|
|
||||||
|
```
|
||||||
|
if elif else while for def
|
||||||
|
end class break continue return true
|
||||||
|
false nil var do import as
|
||||||
|
try except raise static
|
||||||
|
```
|
||||||
|
|
||||||
|
## Types and Variables
|
||||||
|
|
||||||
|
### Built-in Types
|
||||||
|
|
||||||
|
#### Simple Types
|
||||||
|
|
||||||
|
- **nil**: Represents no value
|
||||||
|
- **Integer**: Signed integer (typically 32-bit)
|
||||||
|
- **Real**: Floating-point number (typically 32-bit)
|
||||||
|
- **Boolean**: `true` or `false`
|
||||||
|
- **String**: Sequence of characters
|
||||||
|
- **Function**: First-class value that can be called
|
||||||
|
- **Class**: Template for instances
|
||||||
|
- **Instance**: Object constructed from a class
|
||||||
|
|
||||||
|
#### Class Types
|
||||||
|
|
||||||
|
- **list**: Ordered collection of elements
|
||||||
|
- **map**: Key-value pairs collection
|
||||||
|
- **range**: Integer range
|
||||||
|
- **bytes**: Byte buffer
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
|
||||||
|
Variables are dynamically typed in Berry. They can be defined in two ways:
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Direct assignment (creates variable if it doesn't exist)
|
||||||
|
a = 1
|
||||||
|
|
||||||
|
# Using the var keyword
|
||||||
|
var a # Defines a with nil value
|
||||||
|
var a = 1 # Defines a with value 1
|
||||||
|
var a, b # Defines multiple variables
|
||||||
|
var a = 1, b = 2 # Defines multiple variables with values
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scope and Lifecycle
|
||||||
|
|
||||||
|
Variables defined in the outermost block have global scope. Variables defined in inner blocks have local scope.
|
||||||
|
|
||||||
|
```berry
|
||||||
|
var i = 0 # Global scope
|
||||||
|
do
|
||||||
|
var j = 'str' # Local scope
|
||||||
|
print(i, j) # Both i and j are accessible
|
||||||
|
end
|
||||||
|
print(i) # Only i is accessible here
|
||||||
|
```
|
||||||
|
|
||||||
|
## Expressions
|
||||||
|
|
||||||
|
### Operators
|
||||||
|
|
||||||
|
#### Arithmetic Operators
|
||||||
|
- `-` (unary): Negation
|
||||||
|
- `+`: Addition or string concatenation
|
||||||
|
- `-`: Subtraction
|
||||||
|
- `*`: Multiplication
|
||||||
|
- `/`: Division
|
||||||
|
- `%`: Modulo (remainder)
|
||||||
|
|
||||||
|
#### Relational Operators
|
||||||
|
- `<`: Less than
|
||||||
|
- `<=`: Less than or equal to
|
||||||
|
- `==`: Equal to
|
||||||
|
- `!=`: Not equal to
|
||||||
|
- `>=`: Greater than or equal to
|
||||||
|
- `>`: Greater than
|
||||||
|
|
||||||
|
#### Logical Operators
|
||||||
|
- `&&`: Logical AND (short-circuit)
|
||||||
|
- `||`: Logical OR (short-circuit)
|
||||||
|
- `!`: Logical NOT
|
||||||
|
|
||||||
|
#### Bitwise Operators
|
||||||
|
- `~`: Bitwise NOT
|
||||||
|
- `&`: Bitwise AND
|
||||||
|
- `|`: Bitwise OR
|
||||||
|
- `^`: Bitwise XOR
|
||||||
|
- `<<`: Left shift
|
||||||
|
- `>>`: Right shift
|
||||||
|
|
||||||
|
#### Assignment Operators
|
||||||
|
- `=`: Simple assignment
|
||||||
|
- `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`: Compound assignment
|
||||||
|
- `:=`: Walrus assignment (assigns and returns value)
|
||||||
|
|
||||||
|
#### Domain and Subscript Operators
|
||||||
|
- `.`: Member access
|
||||||
|
- `[]`: Subscript access
|
||||||
|
|
||||||
|
#### Conditional Operator
|
||||||
|
- `? :`: Ternary conditional
|
||||||
|
|
||||||
|
#### Concatenation Operators
|
||||||
|
- `+`: String or list concatenation
|
||||||
|
- `..`: String concatenation or range creation
|
||||||
|
|
||||||
|
### Operator Precedence (highest to lowest)
|
||||||
|
|
||||||
|
1. `()` (grouping)
|
||||||
|
2. `()` (function call), `[]` (subscript), `.` (member access)
|
||||||
|
3. `-` (unary), `!`, `~`
|
||||||
|
4. `*`, `/`, `%`
|
||||||
|
5. `+`, `-`
|
||||||
|
6. `<<`, `>>`
|
||||||
|
7. `&`
|
||||||
|
8. `^`
|
||||||
|
9. `|`
|
||||||
|
10. `..`
|
||||||
|
11. `<`, `<=`, `>`, `>=`
|
||||||
|
12. `==`, `!=`
|
||||||
|
13. `&&`
|
||||||
|
14. `||`
|
||||||
|
15. `? :`
|
||||||
|
16. `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`, `^=`, `<<=`, `>>=`
|
||||||
|
17. `:=`
|
||||||
|
|
||||||
|
## Statements
|
||||||
|
|
||||||
|
### Expression Statements
|
||||||
|
|
||||||
|
```berry
|
||||||
|
a = 1 # Assignment statement
|
||||||
|
print(a) # Function call statement
|
||||||
|
```
|
||||||
|
|
||||||
|
### Block
|
||||||
|
|
||||||
|
A block is a collection of statements. It defines a scope.
|
||||||
|
|
||||||
|
```berry
|
||||||
|
do
|
||||||
|
# This is a block
|
||||||
|
var a = 1
|
||||||
|
print(a)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional Statements
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Simple if
|
||||||
|
if condition
|
||||||
|
# code executed if condition is true
|
||||||
|
end
|
||||||
|
|
||||||
|
# if-else
|
||||||
|
if condition
|
||||||
|
# code executed if condition is true
|
||||||
|
else
|
||||||
|
# code executed if condition is false
|
||||||
|
end
|
||||||
|
|
||||||
|
# if-elif-else
|
||||||
|
if condition1
|
||||||
|
# code executed if condition1 is true
|
||||||
|
elif condition2
|
||||||
|
# code executed if condition1 is false and condition2 is true
|
||||||
|
else
|
||||||
|
# code executed if both condition1 and condition2 are false
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Iteration Statements
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# while loop
|
||||||
|
while condition
|
||||||
|
# code executed repeatedly while condition is true
|
||||||
|
end
|
||||||
|
|
||||||
|
# for loop (iterating over a container)
|
||||||
|
for variable: expression
|
||||||
|
# code executed for each element in the container
|
||||||
|
end
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
for i: 0..5
|
||||||
|
print(i) # Prints 0, 1, 2, 3, 4, 5
|
||||||
|
end
|
||||||
|
|
||||||
|
for item: ['a', 'b', 'c']
|
||||||
|
print(item) # Prints a, b, c
|
||||||
|
end
|
||||||
|
|
||||||
|
for key: map.keys()
|
||||||
|
print(key, map[key]) # Iterates over map keys
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Jump Statements
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# break - exits the loop
|
||||||
|
while true
|
||||||
|
if condition
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# continue - skips to the next iteration
|
||||||
|
for i: 0..5
|
||||||
|
if i == 3
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
print(i) # Prints 0, 1, 2, 4, 5
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import Statement
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import math # Import math module
|
||||||
|
import hardware as hw # Import hardware module as hw
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exception Handling
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Raising exceptions
|
||||||
|
raise 'my_error' # Raise an exception
|
||||||
|
raise 'my_error', 'error message' # Raise with message
|
||||||
|
|
||||||
|
# Catching exceptions
|
||||||
|
try
|
||||||
|
# code that might raise an exception
|
||||||
|
except 'my_error'
|
||||||
|
# code executed if 'my_error' is raised
|
||||||
|
end
|
||||||
|
|
||||||
|
# Catching with exception variable
|
||||||
|
try
|
||||||
|
# code that might raise an exception
|
||||||
|
except 'my_error' as e
|
||||||
|
# e contains the exception value
|
||||||
|
end
|
||||||
|
|
||||||
|
# Catching with exception and message variables
|
||||||
|
try
|
||||||
|
# code that might raise an exception
|
||||||
|
except 'my_error' as e, msg
|
||||||
|
# e contains the exception value, msg contains the message
|
||||||
|
end
|
||||||
|
|
||||||
|
# Catching any exception
|
||||||
|
try
|
||||||
|
# code that might raise an exception
|
||||||
|
except ..
|
||||||
|
# code executed for any exception
|
||||||
|
end
|
||||||
|
|
||||||
|
# Catching multiple exception types
|
||||||
|
try
|
||||||
|
# code that might raise an exception
|
||||||
|
except 'error1', 'error2' as e, msg
|
||||||
|
# code executed if either 'error1' or 'error2' is raised
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### Function Definition
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Named function
|
||||||
|
def add(a, b)
|
||||||
|
return a + b
|
||||||
|
end
|
||||||
|
|
||||||
|
# Anonymous function
|
||||||
|
add = def (a, b)
|
||||||
|
return a + b
|
||||||
|
end
|
||||||
|
|
||||||
|
# Lambda expression (compact form)
|
||||||
|
add = / a, b -> a + b
|
||||||
|
```
|
||||||
|
|
||||||
|
### Function with Variable Arguments
|
||||||
|
|
||||||
|
```berry
|
||||||
|
def print_all(a, b, *args)
|
||||||
|
print(a, b)
|
||||||
|
for arg: args
|
||||||
|
print(arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print_all(1, 2, 3, 4, 5) # args will be [3, 4, 5]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Calling Functions with Dynamic Arguments
|
||||||
|
|
||||||
|
```berry
|
||||||
|
def sum(a, b, c)
|
||||||
|
return a + b + c
|
||||||
|
end
|
||||||
|
|
||||||
|
call(sum, 1, 2, 3) # Calls sum(1, 2, 3)
|
||||||
|
call(sum, 1, [2, 3]) # Calls sum(1, 2, 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Closures
|
||||||
|
|
||||||
|
```berry
|
||||||
|
def counter(start)
|
||||||
|
var count = start
|
||||||
|
return def()
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
c = counter(0)
|
||||||
|
print(c()) # 1
|
||||||
|
print(c()) # 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Object-Oriented Programming
|
||||||
|
|
||||||
|
### Class Declaration
|
||||||
|
|
||||||
|
```berry
|
||||||
|
class Person
|
||||||
|
var name, age
|
||||||
|
|
||||||
|
def init(name, age)
|
||||||
|
self.name = name
|
||||||
|
self.age = age
|
||||||
|
end
|
||||||
|
|
||||||
|
def greet()
|
||||||
|
print("Hello, my name is", self.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Static Members
|
||||||
|
|
||||||
|
```berry
|
||||||
|
class MathUtils
|
||||||
|
static var PI = 3.14159
|
||||||
|
|
||||||
|
static def square(x)
|
||||||
|
return x * x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
print(MathUtils.PI) # Access static variable
|
||||||
|
print(MathUtils.square(5)) # Call static method
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inheritance
|
||||||
|
|
||||||
|
```berry
|
||||||
|
class Student : Person
|
||||||
|
var school
|
||||||
|
|
||||||
|
def init(name, age, school)
|
||||||
|
super(self).init(name, age) # Call parent constructor
|
||||||
|
self.school = school
|
||||||
|
end
|
||||||
|
|
||||||
|
def greet()
|
||||||
|
super(self).greet() # Call parent method
|
||||||
|
print("I study at", self.school)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Instantiation and Method Calls
|
||||||
|
|
||||||
|
```berry
|
||||||
|
person = Person("John", 30)
|
||||||
|
person.greet() # Hello, my name is John
|
||||||
|
|
||||||
|
student = Student("Alice", 20, "University")
|
||||||
|
student.greet() # Hello, my name is Alice
|
||||||
|
# I study at University
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operator Overloading
|
||||||
|
|
||||||
|
```berry
|
||||||
|
class Vector
|
||||||
|
var x, y
|
||||||
|
|
||||||
|
def init(x, y)
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
end
|
||||||
|
|
||||||
|
def +(other)
|
||||||
|
return Vector(self.x + other.x, self.y + other.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
def tostring()
|
||||||
|
return "Vector(" + str(self.x) + ", " + str(self.y) + ")"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
v1 = Vector(1, 2)
|
||||||
|
v2 = Vector(3, 4)
|
||||||
|
v3 = v1 + v2
|
||||||
|
print(v3) # Vector(4, 6)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Built-in Classes
|
||||||
|
|
||||||
|
### List
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Creating lists
|
||||||
|
l1 = [] # Empty list
|
||||||
|
l2 = [1, 2, 3] # List with elements
|
||||||
|
l3 = list() # Empty list using constructor
|
||||||
|
l4 = list(1, 2, 3) # List with elements using constructor
|
||||||
|
|
||||||
|
# Accessing elements
|
||||||
|
l2[0] # First element (1)
|
||||||
|
l2[-1] # Last element (3)
|
||||||
|
|
||||||
|
# Range-based access (slicing)
|
||||||
|
l2[1..3] # Elements from index 1 to 3 inclusive [2, 3]
|
||||||
|
l2[1..] # Elements from index 1 to end [2, 3]
|
||||||
|
l2[1..-1] # Elements from index 1 to last element [2, 3]
|
||||||
|
l2[0..-2] # All elements except the last one [1, 2]
|
||||||
|
l2[-2..-1] # Last two elements [2, 3]
|
||||||
|
|
||||||
|
# Modifying lists
|
||||||
|
l2.push(4) # Add element to end
|
||||||
|
l2.pop() # Remove and return last element
|
||||||
|
l2.pop(1) # Remove and return element at index 1
|
||||||
|
l2.insert(1, 5) # Insert 5 at index 1
|
||||||
|
l2.remove(1) # Remove element at index 1
|
||||||
|
l2.resize(5) # Resize list to 5 elements (fills with nil)
|
||||||
|
l2.clear() # Remove all elements
|
||||||
|
|
||||||
|
# Negative indices for modification
|
||||||
|
l2[-1] = 10 # Set last element to 10
|
||||||
|
l2[-2] += 5 # Add 5 to second-to-last element
|
||||||
|
|
||||||
|
# Other operations
|
||||||
|
l2.size() # Number of elements
|
||||||
|
l2.concat() # Join elements as string (no separator)
|
||||||
|
l2.concat(", ") # Join elements with separator
|
||||||
|
l2.reverse() # Reverse the list
|
||||||
|
l2.copy() # Create a shallow copy
|
||||||
|
l2 + [4, 5] # Concatenate lists (new list)
|
||||||
|
l2 .. 4 # Append element (modifies list)
|
||||||
|
|
||||||
|
# Finding elements
|
||||||
|
l2.find(3) # Returns index of first occurrence or nil if not found
|
||||||
|
|
||||||
|
# Iterating over indices
|
||||||
|
for i: l2.keys() # Iterate over list indices
|
||||||
|
print(i, l2[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Comparing lists
|
||||||
|
[1, 2] == [1, 2] # true
|
||||||
|
[1, 2] != [1, 3] # true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Map
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Creating maps
|
||||||
|
m1 = {} # Empty map
|
||||||
|
m2 = {"key": "value"} # Map with key-value pair
|
||||||
|
m3 = map() # Empty map using constructor
|
||||||
|
|
||||||
|
# Accessing elements
|
||||||
|
m2["key"] # Get value by key
|
||||||
|
m2.find("key") # Get value by key (returns nil if not found)
|
||||||
|
m2.find("key", "default") # Get value with default if not found
|
||||||
|
|
||||||
|
# Modifying maps
|
||||||
|
m2["new_key"] = "new_value" # Add or update key-value pair
|
||||||
|
m2.insert("key", "value") # Insert key-value pair (returns true if inserted, false if key exists)
|
||||||
|
m2.remove("key") # Remove key-value pair
|
||||||
|
|
||||||
|
# Other operations
|
||||||
|
m2.size() # Number of key-value pairs
|
||||||
|
m2.contains("key") # Check if key exists
|
||||||
|
for k: m2.keys() # Iterate over keys
|
||||||
|
print(k, m2[k])
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Range
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Creating ranges
|
||||||
|
r1 = 0..5 # Range from 0 to 5 (inclusive)
|
||||||
|
r2 = range(0, 5) # Same using constructor
|
||||||
|
r3 = 10.. # Range from 10 to MAXINT
|
||||||
|
|
||||||
|
# Accessing properties
|
||||||
|
r1.lower() # Lower bound (0)
|
||||||
|
r1.upper() # Upper bound (5)
|
||||||
|
r1.incr() # Increment (default 1)
|
||||||
|
|
||||||
|
# Modifying ranges
|
||||||
|
r1.setrange(1, 6) # Change range bounds
|
||||||
|
r1.setrange(1, 10, 2) # Change range bounds and increment
|
||||||
|
|
||||||
|
# Using in for loops
|
||||||
|
for i: 0..5
|
||||||
|
print(i) # Prints 0, 1, 2, 3, 4, 5
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### String Operations
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# String indexing and slicing
|
||||||
|
s = "hello"
|
||||||
|
s[0] # "h"
|
||||||
|
s[1] # "e"
|
||||||
|
s[-1] # "o" (last character)
|
||||||
|
s[1..3] # "ell" (characters from index 1 to 3)
|
||||||
|
s[1..] # "ello" (characters from index 1 to end)
|
||||||
|
s[1..-1] # "ello" (characters from index 1 to last)
|
||||||
|
s[0..-2] # "hell" (all characters except the last one)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bytes
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Creating bytes objects
|
||||||
|
b1 = bytes() # Empty bytes
|
||||||
|
b2 = bytes("1122AA") # From hex string
|
||||||
|
b3 = bytes(10) # Pre-allocated 10 bytes
|
||||||
|
b4 = bytes(-8) # Fixed size 8 bytes
|
||||||
|
|
||||||
|
# Accessing bytes
|
||||||
|
b2[0] # First byte (0x11)
|
||||||
|
b2[1..2] # Bytes from index 1 to 2
|
||||||
|
|
||||||
|
# Modifying bytes
|
||||||
|
b2[0] = 0xFF # Set byte at index 0
|
||||||
|
b2.resize(10) # Resize buffer
|
||||||
|
b2.clear() # Clear all bytes
|
||||||
|
|
||||||
|
# Reading/writing structured data
|
||||||
|
b2.get(0, 2) # Read 2 bytes as unsigned int (little endian)
|
||||||
|
b2.get(0, -2) # Read 2 bytes as unsigned int (big endian)
|
||||||
|
b2.geti(0, 2) # Read 2 bytes as signed int
|
||||||
|
b2.set(0, 0x1234, 2) # Write 2-byte value
|
||||||
|
b2.add(0x1234, 2) # Append 2-byte value
|
||||||
|
|
||||||
|
# Conversion
|
||||||
|
b2.tohex() # Convert to hex string
|
||||||
|
b2.asstring() # Convert to raw string
|
||||||
|
b2.tob64() # Convert to base64 string
|
||||||
|
b2.fromhex("AABBCC") # Load from hex string
|
||||||
|
b2.fromstring("Hello") # Load from raw string
|
||||||
|
b2.fromb64("SGVsbG8=") # Load from base64 string
|
||||||
|
```
|
||||||
|
|
||||||
|
### File
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# Opening files
|
||||||
|
f = open("test.txt", "w") # Open for writing
|
||||||
|
f = open("test.txt", "r") # Open for reading
|
||||||
|
|
||||||
|
# Writing to files
|
||||||
|
f.write("Hello, world!") # Write string
|
||||||
|
f.write(bytes("AABBCC")) # Write bytes
|
||||||
|
|
||||||
|
# Reading from files
|
||||||
|
content = f.read() # Read entire file
|
||||||
|
line = f.readline() # Read one line
|
||||||
|
raw_data = f.readbytes() # Read as bytes
|
||||||
|
|
||||||
|
# File positioning
|
||||||
|
f.seek(10) # Move to position 10
|
||||||
|
pos = f.tell() # Get current position
|
||||||
|
size = f.size() # Get file size
|
||||||
|
|
||||||
|
# Closing files
|
||||||
|
f.flush() # Flush buffers
|
||||||
|
f.close() # Close file
|
||||||
|
```
|
||||||
|
|
||||||
|
## Standard Libraries
|
||||||
|
|
||||||
|
### String Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import string
|
||||||
|
|
||||||
|
# String operations
|
||||||
|
string.count("hello", "l") # Count occurrences (2)
|
||||||
|
string.find("hello", "lo") # Find substring (3), returns -1 if not found
|
||||||
|
string.split("a,b,c", ",") # Split by separator (["a", "b", "c"])
|
||||||
|
string.split("hello", 2) # Split at position (["he", "llo"])
|
||||||
|
|
||||||
|
# Character operations
|
||||||
|
string.byte("A") # Get byte value (65)
|
||||||
|
string.char(65) # Get character from byte ('A')
|
||||||
|
|
||||||
|
# Case conversion
|
||||||
|
string.toupper("hello") # Convert to uppercase ("HELLO")
|
||||||
|
string.tolower("HELLO") # Convert to lowercase ("hello")
|
||||||
|
|
||||||
|
# String transformation
|
||||||
|
string.tr("hello", "el", "ip") # Replace characters ("hippo")
|
||||||
|
string.replace("hello", "ll", "xx") # Replace substring ("hexxo")
|
||||||
|
string.escape("hello\n") # Escape for C strings
|
||||||
|
|
||||||
|
# Checking
|
||||||
|
string.startswith("hello", "he") # Check prefix (true)
|
||||||
|
string.startswith("hello", "HE", true) # Case-insensitive check (true)
|
||||||
|
string.endswith("hello", "lo") # Check suffix (true)
|
||||||
|
string.endswith("hello", "LO", true) # Case-insensitive check (true)
|
||||||
|
|
||||||
|
# Formatting
|
||||||
|
string.format("Value: %d", 42) # Format string
|
||||||
|
format("Value: %.2f", 3.14159) # Format (global function)
|
||||||
|
f"Value: {x}" # f-string format
|
||||||
|
f"Value: {x:.2f}" # f-string with format specifier
|
||||||
|
f"{x=}" # f-string debug format
|
||||||
|
```
|
||||||
|
|
||||||
|
### Math Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import math
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
math.pi # Pi (3.14159...)
|
||||||
|
math.inf # Infinity
|
||||||
|
math.nan # Not a Number
|
||||||
|
math.imin # Smallest possible integer
|
||||||
|
math.imax # Largest possible integer
|
||||||
|
|
||||||
|
# Basic functions
|
||||||
|
math.abs(-5) # Absolute value (5)
|
||||||
|
math.floor(3.7) # Round down (3)
|
||||||
|
math.ceil(3.2) # Round up (4)
|
||||||
|
math.round(3.5) # Round to nearest (4)
|
||||||
|
math.min(1, 2, 3) # Minimum value (1)
|
||||||
|
math.max(1, 2, 3) # Maximum value (3)
|
||||||
|
|
||||||
|
# Exponential and logarithmic
|
||||||
|
math.sqrt(16) # Square root (4)
|
||||||
|
math.pow(2, 3) # Power (8)
|
||||||
|
math.exp(1) # e^x (2.71828...)
|
||||||
|
math.log(2.71828) # Natural logarithm (1)
|
||||||
|
math.log10(100) # Base-10 logarithm (2)
|
||||||
|
|
||||||
|
# Trigonometric
|
||||||
|
math.sin(math.pi/2) # Sine (1)
|
||||||
|
math.cos(0) # Cosine (1)
|
||||||
|
math.tan(math.pi/4) # Tangent (1)
|
||||||
|
math.asin(1) # Arc sine (pi/2)
|
||||||
|
math.acos(1) # Arc cosine (0)
|
||||||
|
math.atan(1) # Arc tangent (pi/4)
|
||||||
|
math.atan2(1, 1) # Arc tangent of y/x (pi/4)
|
||||||
|
|
||||||
|
# Angle conversion
|
||||||
|
math.deg(math.pi) # Radians to degrees (180)
|
||||||
|
math.rad(180) # Degrees to radians (pi)
|
||||||
|
|
||||||
|
# Random numbers
|
||||||
|
math.srand(42) # Seed random generator
|
||||||
|
math.rand() # Random integer
|
||||||
|
|
||||||
|
# Special checks
|
||||||
|
math.isinf(math.inf) # Check if value is infinity (true)
|
||||||
|
math.isnan(math.nan) # Check if value is NaN (true)
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Parsing JSON
|
||||||
|
data = json.load('{"name": "John", "age": 30}')
|
||||||
|
print(data.name) # John
|
||||||
|
|
||||||
|
# Error handling with json.load
|
||||||
|
data = json.load('{"invalid": }') # Returns nil on parsing error
|
||||||
|
if data == nil
|
||||||
|
print("Invalid JSON")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generating JSON
|
||||||
|
person = {
|
||||||
|
"name": "Alice",
|
||||||
|
"age": 25,
|
||||||
|
"hobbies": ["reading", "swimming"]
|
||||||
|
}
|
||||||
|
json_str = json.dump(person) # Compact JSON
|
||||||
|
json_formatted = json.dump(person, "format") # Formatted JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
### OS Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Directory operations
|
||||||
|
os.getcwd() # Get current directory
|
||||||
|
os.chdir("/path/to/dir") # Change directory
|
||||||
|
os.mkdir("/path/to/new/dir") # Create directory
|
||||||
|
os.remove("/path/to/file") # Delete file or directory
|
||||||
|
os.listdir() # List current directory
|
||||||
|
os.listdir("/path") # List specific directory
|
||||||
|
|
||||||
|
# Path operations
|
||||||
|
os.path.isdir("/path") # Check if path is directory
|
||||||
|
os.path.isfile("/path/file.txt") # Check if path is file
|
||||||
|
os.path.exists("/path") # Check if path exists
|
||||||
|
os.path.split("/path/file.txt") # Split into ["/path", "file.txt"]
|
||||||
|
os.path.splitext("file.txt") # Split into ["file", ".txt"]
|
||||||
|
os.path.join("path", "file.txt") # Join into "path/file.txt"
|
||||||
|
|
||||||
|
# System operations
|
||||||
|
os.system("command") # Execute system command
|
||||||
|
os.exit() # Exit interpreter
|
||||||
|
```
|
||||||
|
|
||||||
|
### Global Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import global
|
||||||
|
|
||||||
|
# Accessing globals
|
||||||
|
global_vars = global() # List of all global variables
|
||||||
|
global.contains("var_name") # Check if global exists
|
||||||
|
value = global.var_name # Get global value
|
||||||
|
global.var_name = 42 # Set global value
|
||||||
|
value = global.("dynamic_name") # Dynamic access by name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Introspect Module
|
||||||
|
|
||||||
|
```berry
|
||||||
|
import introspect
|
||||||
|
|
||||||
|
# Inspecting objects
|
||||||
|
members = introspect.members(obj) # List of object members
|
||||||
|
value = introspect.get(obj, "attr") # Get attribute value
|
||||||
|
introspect.set(obj, "attr", value) # Set attribute value
|
||||||
|
name = introspect.name(obj) # Get object name
|
||||||
|
is_method = introspect.ismethod(fn) # Check if function is method
|
||||||
|
|
||||||
|
# Module operations
|
||||||
|
mod = introspect.module("math") # Import module dynamically
|
||||||
|
|
||||||
|
# Pointer operations (advanced)
|
||||||
|
ptr = introspect.toptr(addr) # Convert int to pointer
|
||||||
|
addr = introspect.fromptr(ptr) # Convert pointer to int
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Standard Exceptions
|
||||||
|
|
||||||
|
- `assert_failed`: Assertion failed
|
||||||
|
- `index_error`: Index out of bounds
|
||||||
|
- `io_error`: IO malfunction
|
||||||
|
- `key_error`: Key error
|
||||||
|
- `runtime_error`: VM runtime exception
|
||||||
|
- `stop_iteration`: End of iterator
|
||||||
|
- `syntax_error`: Syntax error
|
||||||
|
- `unrealized_error`: Unrealized function
|
||||||
|
- `type_error`: Type error
|
||||||
|
|
||||||
|
### Raising Exceptions
|
||||||
|
|
||||||
|
```berry
|
||||||
|
raise "my_error" # Raise exception
|
||||||
|
raise "my_error", "message" # Raise with message
|
||||||
|
```
|
||||||
|
|
||||||
|
### Catching Exceptions
|
||||||
|
|
||||||
|
```berry
|
||||||
|
try
|
||||||
|
# Code that might raise an exception
|
||||||
|
except "my_error"
|
||||||
|
# Handle specific exception
|
||||||
|
end
|
||||||
|
|
||||||
|
try
|
||||||
|
# Code that might raise an exception
|
||||||
|
except "error1", "error2"
|
||||||
|
# Handle multiple exceptions
|
||||||
|
end
|
||||||
|
|
||||||
|
try
|
||||||
|
# Code that might raise an exception
|
||||||
|
except "my_error" as e
|
||||||
|
# e contains the exception value
|
||||||
|
end
|
||||||
|
|
||||||
|
try
|
||||||
|
# Code that might raise an exception
|
||||||
|
except "my_error" as e, msg
|
||||||
|
# e contains exception, msg contains message
|
||||||
|
end
|
||||||
|
|
||||||
|
try
|
||||||
|
# Code that might raise an exception
|
||||||
|
except ..
|
||||||
|
# Catch all exceptions
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling Patterns
|
||||||
|
|
||||||
|
Many functions in Berry return `nil` to indicate errors rather than raising exceptions. This is common in functions that parse data or perform operations that might fail:
|
||||||
|
|
||||||
|
```berry
|
||||||
|
# JSON parsing
|
||||||
|
data = json.load('{"invalid": }') # Returns nil on parsing error
|
||||||
|
if data == nil
|
||||||
|
print("Invalid JSON")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Map access
|
||||||
|
value = map.find("key") # Returns nil if key doesn't exist
|
||||||
|
if value == nil
|
||||||
|
print("Key not found")
|
||||||
|
end
|
||||||
|
|
||||||
|
# String operations
|
||||||
|
index = string.find("hello", "z") # Returns -1 if substring not found
|
||||||
|
if index == -1
|
||||||
|
print("Substring not found")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Assertions
|
||||||
|
|
||||||
|
```berry
|
||||||
|
assert(condition) # Raises assert_failed if condition is false
|
||||||
|
assert(condition, "message") # Raises with custom message
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Variable Naming
|
||||||
|
|
||||||
|
- Use descriptive names for variables and functions
|
||||||
|
- Use camelCase or snake_case consistently
|
||||||
|
- Prefix private members with underscore (convention only)
|
||||||
|
|
||||||
|
### Code Organization
|
||||||
|
|
||||||
|
- Group related functions and classes
|
||||||
|
- Use modules for logical separation
|
||||||
|
- Keep functions small and focused
|
||||||
|
|
||||||
|
### Memory Management
|
||||||
|
|
||||||
|
- Be mindful of memory usage on embedded systems
|
||||||
|
- Release resources when no longer needed
|
||||||
|
- Use fixed-size buffers when appropriate
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
- Use exceptions for exceptional conditions
|
||||||
|
- Check return values for expected errors
|
||||||
|
- Provide meaningful error messages
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
- Avoid creating unnecessary objects
|
||||||
|
- Reuse buffers when processing large data
|
||||||
|
- Use native functions for performance-critical code
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Berry is a powerful yet lightweight scripting language designed for embedded systems. It combines the flexibility of dynamic typing with the efficiency needed for resource-constrained environments. With its support for procedural, object-oriented, and functional programming paradigms, Berry provides a versatile toolset for embedded development while maintaining a small memory footprint.
|
Loading…
x
Reference in New Issue
Block a user