Skip to content

Zerynth Builtins

This module contains builtins functions and constants. It is automatically loaded and it's not needed to prefix the module name to call its functions. For example it is not necessary to write __builtins__.print() but only print() will suffice.

Builtins Constants

Zerynth OS defines the following Python builtin constants:

  • False: the false value of the boolean type. Assignments to False are illegal and raise a SyntaxError.
  • True: the true value of the boolean type. Assignments to True are illegal and raise a SyntaxError.
  • None: The sole value of the type NoneType. None is frequently used to indicate represent the absence of a value, as when default arguments are not passed to a function. Assignments to None are illegal and raise a SyntaxError.

Zerynth OS recognizes a set of pre-defined uppercase names representing constants:

  • GPIO Names:

  • D0 to D256 representing the names of gpios.

  • LED0 to LED32 representing the names of the board leds.
  • BTN0 to BTN32 representing the names of the board buttons.

  • GPIO Modes and Values:

  • INPUT, OUTPUT, INPUT_PULLUP, INPUT_PULLDOWN, OUTPUT_PUSHPULL, OUTPUT_OPENDRAIN, INPUT_ANALOG representing gpio modes.

  • LOW, HIGH representing digital gpio states.

  • Time Units:

  • MICROS to select microseconds

  • MILLIS to select milliseconds
  • SECONDS to select seconds

  • Peripherals Names:

  • SERIAL0 to SERIAL7 representing the name of the nth serial port of a board.

  • I2C0 to I2C7 representing the name of the nth I2C bus

Additional names are defined depending on the selected board support package

Builtin Exceptions

Zerynth OS exceptions are different from Python exceptions. In Python, exceptions are very powerful because they are implemented as classes, contain error messages, and one can examine the full execution stack when an exception is raised. However, in the embedded world, resources are precious and keeping class definition in memory, creating a class instance every time an exception is raised, can be very resource-consuming.

Zerynth OS exceptions are therefore implemented as error codes with optional error messages organized as a tree::

Exception
  +-- StopIteration
  +-- ArithmeticError
  |    +-- FloatingPointError
  |    +-- OverflowError
  |    +-- ZeroDivisionError
  +-- AttributeError
  +-- LookupError
  |    +-- IndexError
  |    +-- KeyError
  +-- MemoryError
  +-- NameError
  +-- PeripheralError
  |    +-- InvalidPinError
  |    +-- InvalidHardwareStatusError
  |    +-- HardwareInitializationError
  +-- IOError
  |    +-- ConnectionError
  |    |    +-- ConnectionAbortedError
  |    |    +-- ConnectionRefusedError
  |    |    +-- ConnectionResetError
  |    +-- TimeoutError
  +-- RuntimeError
  |    +-- NotImplementedError
  |    +-- UnsupportedError
  +-- TypeError
  +-- ValueError

This way, the inheritance mechanism of classes is maintained and transposed to the exception matching mechanism transparently. The following is valid Zerynth code:

try:
    # raise ZeroDivisionError
    x = 1/0
except ArithmeticError as e:
    print(e)

The main difference between Zerynth exceptions and Python exceptions is in the way new exceptions are created and used. To create a user defined exception in Zerynth you need to use the following code:

new_exception(MyExceptionName, MyExceptionParent, MyErrorMessage)

The builtin function new_exception always needs 2 arguments and an optional message:

  • the first one is the user defined exception name
  • the second is the name of the parent exception in the exception tree
  • the third one is a static error message, where static in this context means that it is not stored in ram as a Python string.

Behind the scenes MyExceptionName is created and placed under MyExceptionParent in the exception tree. An exception object is returned. The exception object can only be compared to other exceptions, printed or raised again.

When an exception is printed, the error message and the error type are printed.

Zerynth exceptions are not garbage collected. They also are not scoped: this means that an exception defined in a module is not contained in that module, but it is moved at builtin scope, so that it can be accessible by all other modules simply by name. This feature has a drawback: two modules defining an exception with the same name, can't be compiled in the same program. Exception names must be manually scoped by correctly choosing them (i.e. preprending the module name to the actual name).

Exceptions can be thrown by C code. Any custom defined exception is exposed as a C macro named as the Python exception and prefixed with ZEXC_ (i.e. ZEXC_MyExceptionName).

Builtin Functions

function int

int(x=0, base=10)

Return an integer object constructed from a number or string x, or return 0 if no arguments are given. If x is a floating point number, it is truncated towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an :integer in radix base. Optionally, the literal can be preceded by + or - (with no space in between) and surrounded by whitespace. A base-n literal consists of the digits 0 to n-1, with a to z (or A to Z) having values 10 to 35. The default base is 10. The allowed values are 0 and 2-36. Base-2, -8, and -16 literals can be optionally prefixed with 0b/0B, 0o/0O, or 0x/0X, as with integer literals in code. Base 0 means to interpret exactly as a code literal, so that the actual base is 2, 8, 10, or 16, and so that int('010', 0) is not legal, while int('010') is, as well as int('010', 8).

function type

type(x)
Returns an integer representing the type of x. The following are the builtin constants returned by type():

PSMALLINT, PINTEGER, PFLOAT, PBOOL, PSTRING, PBYTES, PBYTEARRAY, PSHORTS, PSHORTARRAY, PLIST, PTUPLE, PRANGE, PFROZENSET, PSET, PDICT, PFUNCTION, PMETHOD, PCLASS, PINSTANCE, PMODULE, PITERATOR, PNONE, PEXCEPTION, PNATIVE, PSYSOBJ, PDRIVER, PTHREAD

function thread

thread(fun, *args, prio=PRIO_NORMAL, size=-1)
Function fun is launched in a new thread using args as its parameters. fun must be a normal function or a methods, other callables are not supported yet.

prio sets the thread priority and accepts one of PRIO_LOWEST, PRIO_LOWER, PRIO_LOW, PRIO_NORMAL, PRIO_HIGH, PRIO_HIGHER, PRIO_HIGHEST. size is the memory in bytes , reserved for the thread inner workings. Negative values select the VM default size.

Returns the created thread, already started. Raises RuntimeError if no more threads can be created.

function sleep

sleep(time, time_unit=MILLIS)
Suspend the current thread for time expressed in time_units. All the other threads are free to continue their execution. If time_unit is MICROS, sleep does not suspend the current thread, but starts polling the cycles counter in a loop.

For high precision sleep refer to hwtimers

function random

random()
random(a,b)

Returns a random integer. If a and b are given, the random integer is contained in the range [a,b]. If the board has a builtin Random Number Generator, it is used.

function range

range(stop)
range(start, stop[, step])

Creates a range object.

function bytearray

bytearray([source])

Return a new array of bytes. A bytearray is a mutable sequence of integers in the range 0 <= x < 256. It has most of the usual methods of mutable sequences, described in typesseq-mutable, as well as most methods that the bytes type has, see bytes-methods.

The optional source parameter can be used to initialize the array in a few different ways:

  • If it is a string, bytearray then converts the string to bytes.
  • If it is an integer, the array will have that size and will be initialized with null bytes.

Without an argument, an array of size 0 is created.

function bytes

bytes([source])

Return a new "bytes" object, which is an immutable sequence of integers in the range 0 <= x < 256. bytes is an immutable version of bytearray -- it has the same non-mutating methods and the same indexing and slicing behavior.

Accordingly, constructor arguments are interpreted as for bytearray.

function shortarray

shortarray([source])

Return a new array of shorts. A shortarray is a mutable sequence of integers in the range 0 <= x < 65536. It has most of the usual methods of mutable sequences, described in typesseq-mutable, as well as most methods that the shorts type has, see shorts-methods.

The optional source parameter can be used to initialize the array in a few different ways:

  • If it is an integer, the array will have that size and will be initialized with zeros.
  • If it is a sequence, the array will be a copy of source with its elements converted into shorts. If the conversion is not possible, an exception is raised.

Without an argument, an array of size 0 is created.

function shorts

shorts([source])
Return a new shorts object, which is an immutable sequence of integers in the range 0 <= x < 65536. shorts is an immutable version of shortarray -- it has the same non-mutating methods and the same indexing and slicing behavior.

Accordingly, constructor arguments are interpreted as for shortarray.

function enumerate

enumerate(iterable, start=0)
Return an enumerate object. iterable must be a sequence, an iterator, or some other object which supports iteration. The ~iterator.__next__ method of the iterator returned by enumerate returns a tuple containing a count (from start which defaults to 0) and the values obtained from iterating over iterable.

It is normally used in for loops: ::

    ints = [10,20,30]
    for idx, val in enumerate(ints):
        print(idx, val)
    # prints out the following:
    >>> 0 10
    >>> 1 20
    >>> 2 30

In this version of the VM, enumerate works only for primitive iterable types, not yet for instances with __next__ and __iter__ methods.

function reversed

reversed(seq)
Return a reverse iterator. seq must be an object which has a __reversed__ method or supports the sequence protocol (the __len__ method and the __getitem__ method with integer arguments starting at 0).

In this version of the VM, reversed works only for primitive iterable types, not yet for instances with __next__ and __iter__ methods.

function ord

ord(c)
Given a string representing one character, return an integer representing that character. For example, ord('a') returns the integer 97. This is the inverse of chr.

When c is a literal string, the compiler macro __ORD© can be used to reduce code size. For example:

x = ord(":")

is valid Zerynth code. During its execution a string must be created containing ":" and ord must be called on it. After ord is executed the created string is probably immediately garbage collected. In the embedded world, this is time and resource consuming. The operation ord(":") can be executed during compilation because the result is known before the execution of the Zerynth program. To enable this feature use the following code:

x = __ORD(":")

Now, no string is created and no function is called, because the compiler knows that you want to assign to x the result of ord(":") (which is 58). The compiler transforms our program to a faster and equivalent version: ::

x = 58

function chr

chr(i)

Return the string representing a character whose byte representation is the integer i. For example, chr(97) returns the string 'a'. This is the inverse of ord. ValueError will be raised if i is outside the valid range.

function isinstance

isinstance(object, class)

Return true if the object argument is an instance of the class argument, or of a (direct, indirect) subclass thereof. If object is not an object of the given type, the function always returns false. If class is not a class, a TypeError exception is raised.

In this version of the VM, isinstance is still not compliant with the Python one. It is suggested to use isinstance to determine the hierarchy of instances and to use type for primitive types.

function thread

thread(fn,*args, prio = PRIO_NORMAL, size=-1)
TBD

function print

print(*args,sep=" ",end="\\n", stream=None)
Print objects to the stream stream, separated by sep and followed by end. sep, end and stream, if present, must be given as keyword arguments.

All non-keyword arguments are converted to strings like str does and written to the stream, separated by sep and followed by end. Both sep and end must be strings. If no objects are given, print will just write end.

The stream argument must be an object with a write(string) method; if it is not present or None, __default_stream will be used.

Whether output is buffered is usually determined by stream.

function abs

abs(x)
Return the absolute value of a number. The argument may be an integer or a floating point number.

function all

all(iterable)
Return True if all elements of the iterable are true (or if the iterable is empty). Equivalent to::

  def all(iterable):
      for element in iterable:
          if not element:
              return False
      return True

function any

any(iterable)

Return True if any element of the iterable is true. If the iterable is empty, return False. Equivalent to::

  def any(iterable):
      for element in iterable:
          if element:
              return True
      return False

function sum

sum(iterable[, start])
Sums start and the items of an iterable from left to right and returns the total. start defaults to 0.

function divmod

divmod(a, b)
Take two (non complex) numbers as arguments and return a pair of numbers consisting of their quotient and remainder when using integer division. When a and b are integers, the result is the same as (a // b, a % b). For floating point numbers the result is (q, a % b), where q is float(int(a / b)).
### function `max`
```python
max(*args)
````
   Return the largest item in args.

### function `min`
```python
min(*args)
Return the smallest item in args.

function round

round(number[, ndigits])
Return number rounded to ndigits precision after the decimal point. If ndigits is omitted or is None, it returns the nearest integer to its input.

For the built-in types supporting round, values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(-1.5) and round(-0.5) are 0, and round(1.5) is 2). Any integer value is valid for ndigits (positive, zero, or negative). The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as number.

The behavior of round for floats can be surprising: for example, round(1.125, 2) gives 1.1200000000000001 instead of the expected 1.12. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float (e.g., print(2.675) gives 2.6749999999999998 in Zerynth).

For a general Python object number, round is not implemented.

function len

len(s)
Return the length (the number of items) of an object. The argument may be a sequence (such as a string, bytes, tuple, list, or range) or a collection (such as a dictionary, set, or frozen set), or any instance defining the method __len__.

function hex

hex(x,prefix="0x")
Convert an integer number to a lowercase hexadecimal string prefixed with prefix (if not given "0x" is used), for example:

  >>> hex(255)
  '0xff'
  >>> hex(-42)
  '-0x2a'

See also int for converting a hexadecimal string to an integer using a base of 16.

function str

str(x="")
Return a string version of x. If x is not provided, returns the empty string. Returns the "informal" or nicely printable string representation of object. For string objects, this is the string itself. For primitive types like list, tuples, dicts a standard representation is returned. For all other types, the method str is called.

function dict

dict(*args)
Return a new dictionary initialized from an optional *args.

If no *args is given, an empty dictionary is created. If a single positional argument is given and it is a mapping object, a dictionary is created with the same key-value pairs as the mapping object. Otherwise, if more than a positional argument is given, each pair of arguments is inserted in the dictionary with the first argument of the pair being the key and the second argument the value. If a key occurs more than once, the last value for that key becomes the corresponding value in the new dictionary. If the number of positional arguments is odd, the value for the last key is None.

function set

set(*args)
Return a new set initialized from an optional *args.

If no *args is given, an empty set is created. If a single positional argument is given and it is an iterable object, a set is created and filled with the values of the iterable. Otherwise, if more than a positional argument is given, each argument is inserted in the set.

function frozenset

frozenset(*args)
Return a new frozenset initialized from an optional *args.

If no *args is given, an empty frozenset is created. If a single positional argument is given and it is an iterable object, a frozenset is created and filled with the values of the iterable. Otherwise, if more than a positional argument is given, each argument is inserted in the frozenset.