-
Notifications
You must be signed in to change notification settings - Fork 0
Builtins
Builtins are divided into two categories:
- Builtin functions, which are globally available functions.
- Builtin methods, which are methods callable on instances of the harlock types.
The following is a list of the builtin function available within the harlock language, alongside with their signatures.
hex(int|array) -> string
Converts an integer or a byte array to a hex-string. When using byte arrays, the hex-string will not have the '0x' prefix.
Usage:
>>> hex(255)
0xff
>>> hex(12000)
0x2ee0
>>> hex([0xca, 0xfe, 0x01, 0x02])
cafe0102
from_hex(string) -> array
Converts a hex-string '0x' to an array of bytes
Usage:
>>> from_hex("beefcafe")
[190, 239, 202, 254]
>>> from_hex("0xbeefcafe")
>>> from_hex("0XBEEFCAFE")
[190, 239, 202, 254]
>>> from_hex(hex([0xbe, 0xef, 0xca, 0xfe]))
[190, 239, 202, 254]
len(string|array|map|set) -> int
Returns the length of the passed collection type.
Usage:
>>> [len("test"), len([1,2]), len({"a": 1, "b": 2, "c": 3}), len(set(1, 2, 3))]
[4, 2, 3, 3]
set(...hashable|iterable) -> set
Builds a set starting from the passed elements.
If one of the elements is iterable, its elements are iterated instead of adding the iterable itself.
Usage:
>>> set(3, 4, [5, 7, "test"], {"c": 0})
set(test, c, 3, 4, 5, 7)
type(any) -> string
Returns the type of the object as a string.
Usage:
>>> [type(1), type(type), type(fun(x){}), type("test")]
[Int, Builtin Function, Function, String]
open(string, string) -> file
Attempts to open a file with the name of the first argument, with the file type specified by the second argument.
Valid file types are:
- hex, which creates a new instance of
Hex Filetype. - elf, which creates a new instance of
Elf Filetype. - bytes, which creates a new instance of
Bytes Filetype.
Usage:
>>> var h = open("small.hex", "hex")
>>> h
:100000000C9438000C9442000C9442000C94420072
:100010000C9442000C9442000C9442000C94420058
:100020000C9442000C9442000C9442000C94420048
:100030000C9442000C9442000C9442000C94420038
:100040000C9442000C9442000C9442000C94420028
:100050000C9442000C9442000C9442000C94420018
:100060000C9442000C9442000C9442000C94420008
:1000700011241FBECFEFD0E1DEBFCDBF0E944400F0
:0E0080000C9445000C940000FFCFF894FFCFC5
:00000001FF
>>>
>>> var e = open("small.elf", "elf")
>>> e
ElfFile(@small.elf) {
Sections: [ .data .text .comment .note.gnu.avr.deviceinfo .debug_aranges .debug_info .debug_abbrev .debug_line .debug_str .debug_line_str .symtab .strtab .shstrtab ]
}
>>>
>>> var b = open("small.bin", "bytes")
>>> b
12, 148, 56, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 12, 148, 66, 0, 17, 36, 31, 190, 207, 239, 208, 225, 222, 191, 205, 191, 14, 148, 68, 0, 12, 148, 69, 0, 12, 148, 0, 0, 255, 207, 248, 148, 255, 207
>>>
save(hex_file|elf_file|bytes_file) -> no return
Saves a previously opened file's contents unto the original file.
Usage:
>>> var b = open("small.bin", "bytes")
>>> save(b)
print(...) -> no return
Prints every passed object as a string separated by a space, with a newline character at the end.
Usage:
>>> print("Hello world!")
Hello world!
as_bytes(hex_file|elf_file|bytes_file) -> array
Returns an array containing the passed file as a stream of bytes.
Usage:
>>> var h = open("small.hex", "hex")
>>> as_bytes(h)
[58, 49, 48, 48, 48, 48, 48, 48, 48, 48, 67, 57, 52, 51, 56, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 55, 50, 13, 10, 58, 49, 48, 48, 48, 49, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 53, 56, 13, 10, 58, 49, 48, 48, 48, 50, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 52, 56, 13, 10, 58, 49, 48, 48, 48, 51, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 51, 56, 13, 10, 58, 49, 48, 48, 48, 52, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 50, 56, 13, 10, 58, 49, 48, 48, 48, 53, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 49, 56, 13, 10, 58, 49, 48, 48, 48, 54, 48, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 67, 57, 52, 52, 50, 48, 48, 48, 56, 13, 10, 58, 49, 48, 48, 48, 55, 48, 48, 48, 49, 49, 50, 52, 49, 70, 66, 69, 67, 70, 69, 70, 68, 48, 69, 49, 68, 69, 66, 70, 67, 68, 66, 70, 48, 69, 57, 52, 52, 52, 48, 48, 70, 48, 13, 10, 58, 48, 69, 48, 48, 56, 48, 48, 48, 48, 67, 57, 52, 52, 53, 48, 48, 48, 67, 57, 52, 48, 48, 48, 48, 70, 70, 67, 70, 70, 56, 57, 52, 70, 70, 67, 70, 67, 53, 13, 10, 58, 48, 48, 48, 48, 48, 48, 48, 49, 70, 70, 13, 10]
contains(any, array|map|set) -> bool
Returns true if the collection contains the passed object.
Usage:
>>> [contains([1, 2], 1), contains({"k1": 0, "k2": 1}, "k1"), contains(set(4, 5, "t"), "t")]
[true, true, true]
hash(array, string) -> array
Returns an array containing the computed hash of the passed array, using the specified algorithm.
Currently supported algorightms are:
- sha1
- sha256
- md5
Usage:
>>> hash([1, 2, 3], "sha1")
[112, 55, 128, 113, 152, 194, 42, 125, 43, 8, 7, 55, 29, 118, 55, 121, 168, 79, 223, 207]
>>> hash([1, 2, 3], "sha256")
[3, 144, 88, 198, 242, 192, 203, 73, 44, 83, 59, 10, 77, 20, 239, 119, 204, 15, 120, 171, 204, 206, 213, 40, 125, 132, 161, 162, 1, 28, 251, 129]
>>> hash([1, 2, 3], "md5")
[82, 137, 223, 115, 125, 245, 115, 38, 252, 221, 34, 89, 122, 251, 31, 172]
int(string) -> int
Converts a string representing an integer to an actual integer.
Usage:
>>> [int("12"), int("0xca"), int("0XCA")]
[12, 202, 202]
error(...any) -> error
Creates a custom error that can be used in code.
Usage:
>>> error("custom error!")
Runtime Error: custom error! on line 1
as_array(int, int, string) -> array
Converts an integer to its representation as an array of bytes of specific size and endianness.
Usage:
>>> as_array(1234, 4, "little")
[210, 4, 0, 0]
>>> as_array(0xff, 8, "big")
[0, 0, 0, 0, 0, 0, 0, 255]
The following is a list of the builtin methods that can be called on instances of the array builtin type, alongside with their signatures.
A new array instance can be constructed by using the square braces to list a series of elements, like so:
>>> var a = [1, 2, 3, 4]
>>> a
[1, 2, 3, 4]
array.push(any) -> array
Adds an element to the tail of the array and returns the new array. The original array remains unchanged.
Usage:
>>> var arr = [1, 9]
>>> arr.push(12)
[1, 9, 12]
>>> arr
[1, 9]
>>> [1, 9].push(12)
[1, 9, 12]
array.pop() -> array
Removes the last element from the array and returns a copy of the new array.
Usage:
>>> var arr = [10, 2, "test"]
>>> arr.pop()
[10, 2]
>>> arr
[10, 2, test]
>>> [10, 2, "test"].pop()
[10, 2]
array.slice(int, int) -> array
Returns a sub-array slicing the original array in the [args[0]:args[1]) interval. This returns a new array and copies each element in the new array. Lists/Maps/Sets/Files are copied as references.
Usage:
>>> var arr = [1, 2, 3, 4]
>>> arr.slice(0, 2)
[1, 2]
>>> arr
[1, 2, 3, 4]
>>> [1, 2, 3, 4, 5].slice(1, 3)
[2, 3]
array.map(function) -> array
Applies the passed function to each element of the array and returns a new array with the modified values.
I.e.: output[n] = function(input[n])
Usage:
>>> [1, 2, 3, 4].map(fun(x) { ret x*2 })
[2, 4, 6, 8]
array.reduce(function [, any]) -> any
Applies the passed function to each element of the array; the first argument gets used as the result of the previous iteration. An accumulator init value can be passed as an optional final argument.
Usage:
>>> [1, 2, 3, 4].reduce(fun(x, y) { ret x+y })
10
>>> [1, 2, 3, 4].reduce(fun(x, y) { ret x+y }, 5)
15
The following is a list of the builtin methods that can be called on instances of the map builtin type, alongside with their signatures.
A new map instance can be constructed by using the curly braces to list a series of comma-separated key-value pairs, expressed through a colon, like so:
>>> var m = {"key": "value", 2: 3, "test": 14}
>>> m
{2: 3, test: 14, key: value}
map.set(any, any) -> no return
Adds the (arg[0], arg[1]) key value couple to the map. This mutates the map.
Usage:
>>> var m = {"key1": "val1", "key2": 42}
>>> m
{key1: val1, key2: 42}
>>> m.set("key3", 3)
>>> m
{key1: val1, key2: 42, key3: 3}
map.pop(any) -> no return
Removes the passed key from the map if it exists. This mutates the map.
Usage:
>>> var m = {"key1": "val1", "key2": 42}
>>> m
{key1: val1, key2: 42}
>>> m.pop("key2")
>>> m
{key1: val1}
The following is a list of the builtin methods that can be called on instances of the set builtin type, alongside with their signatures.
A new set instance can be constructed by using the builtin set function, like so:
>>> var s = set(1, 2, 3)
>>> s
set(1, 2, 3)
set.add(any) -> no return
Adds the element to the set if it is not already in. This mutates the set.
Usage:
>>> var s = set(1, 2, 3)
>>> s
set(1, 2, 3)
>>> s.add(1)
>>> s
set(1, 2, 3)
>>> s.add(4)
>>> s
set(1, 2, 3, 4)
set.remove(any) -> no return
Removes the passed element from the set if it is there. This mutates the set.
Usage:
>>> var s = set(1, 2, 3)
>>> s.remove(4)
>>> s
set(1, 2, 3)
>>> s.remove(3)
>>> s
set(1, 2)
The following is a list of the builtin methods that can be called on instances of the Hex File builtin type, alongside with their signatures.
All the examples listed in this section are based on the output of the avr-gcc compiler, getting fed the following C program:
int main(void) {
for(;;) {
}
}The complete compilation command is the following:
avr-gcc -o build/small.elf build/src/main.c -std=c11 -Wall -Wextra -Werror -mmcu=atmega644 -DF_CPU=1000000 -Os -DNDEBUG src/main.c
avr-objcopy -j .text -j .data -O ihex build/small.elf build/small.hex
A new Hex File instance can be constructed by using the builtin open function, with the hex modifier.
>>> var h = open("small.hex", "hex")
>>> h
:100000000C9438000C9442000C9442000C94420072
:100010000C9442000C9442000C9442000C94420058
:100020000C9442000C9442000C9442000C94420048
:100030000C9442000C9442000C9442000C94420038
:100040000C9442000C9442000C9442000C94420028
:100050000C9442000C9442000C9442000C94420018
:100060000C9442000C9442000C9442000C94420008
:1000700011241FBECFEFD0E1DEBFCDBF0E944400F0
:0E0080000C9445000C940000FFCFF894FFCFC5
:00000001FF
hex.record(int) -> string
Returns the nth record as a string, if it exists and is a valid index, or an error.
Usage:
>>> var h = open("small.hex", "hex")
>>> var rec = h.record(0)
>>> rec
:100000000C9438000C9442000C9442000C94420072
>>> type(rec)
String
hex.size(int) -> int
Returns the size of the file as a number of records it contains.
Usage:
>>> var h = open("small.hex", "hex")
>>> h.size()
10
hex.read_at(int, int) -> array
Attempts to read arg[1] number of bytes starting from arg[0] position. This returns an array containing the data that would be found in the corresponding .bin file obtained from the hex file as a byte stream.
Usage:
>>> var h = open("small.hex", "hex")
>>> h.read_at(1, 3)
[148, 56, 0]
>>> hex(h.read_at(1, 3))
943800
>>> h.read_at(1, 3).map(fun(x) { ret hex(x) })
[0x94, 0x38, 0x00]
hex.write_at(int, array) -> no return
Attempts to write the contents of the arg[1] byte array to the arg[0] position. This mutates the hex file object but not the copy on disk.
Call the save() function to make the changes persistent.
Usage:
>>> var h = open("small.hex", "hex")
>>> h.read_at(1, 3).map(fun(x) { ret hex(x) })
[0x94, 0x38, 0x00]
>>> h.write_at(1, from_hex("cafe01"))
>>> h.read_at(1, 3).map(fun(x) { ret hex(x) })
[0xca, 0xfe, 0x01]
>>> save(h)
hex.binary_size(int) -> int
Returns the size of the file as the actual number of bytes contained in the data section of the data records found within the hex file.
Usage:
>>> var h = open("small.hex", "hex")
>>> h.binary_size()
142
The following is a list of the builtin methods that can be called on instances of the Elf File builtin type, alongside with their signatures.
All the examples listed in this section are based on the output of the avr-gcc compiler, getting fed the following C program:
int data[32] __attribute__((section(".metadata")));
int main(void) {
for(;;) {
}
}The complete compilation command is the following:
avr-gcc -o build/small.elf build/src/main.o -I ./inc -std=c11 -Wall -Wextra -Werror -mmcu=atmega644 -DF_CPU=1000000 -O0 -DDEBUG
A new Hex File instance can be constructed by using the builtin open function, with the elf modifier.
>>> var e = open("small.elf", "elf")
>>> e
ElfFile(@small.elf) {
Sections: [ .data .metadata .text .comment .note.gnu.avr.deviceinfo .debug_aranges .debug_info .debug_abbrev .debug_line .debug_str .debug_line_str .symtab .strtab .shstrtab ]
}
elf.has_section(string) -> bool
Returns whether the elf file contains a section with the passed name or not.
Usage:
>>> var e = open("small.elf", "elf")
>>> e.has_section(".metadata")
true
>>> e.has_section(".wrong_name")
false
elf.sections() -> array
Returns an array containing the section header names as strings.
Usage:
>>> var e = open("small.elf", "elf")
>>> e.sections()
[, .data, .metadata, .text, .comment, .note.gnu.avr.deviceinfo, .debug_aranges, .debug_info, .debug_abbrev, .debug_line, .debug_str, .debug_line_str, .symtab, .strtab, .shstrtab]
elf.section_address(string) -> int
Returns the address of the specified section, if it exists.
Usage:
>>> var e = open("small.elf", "elf")
>>> var addr = e.section_address(".metadata")
>>> [addr, hex(addr)]
[8388864, 0x800100]
elf.section_size(string) -> int
Returns the size of the specified section, if it exists.
Usage:
>>> // Note that an int is 16-bit wide in this example, size = 32 * sizeof(int)
>>> var e = open("small.elf", "elf")
>>> e.section_size(".metadata")
64
elf.read_section(string) -> array
Attempts to read the contents of the specified section, if it exists, and returns it as a byte array.
Usage:
>>> var e = open("small.elf", "elf")
>>> e.read_section(".metadata")
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
elf.write_section(string, array, int) -> no return
Attempts to write the contents of the arg[1] byte array to the arg[0] section with arg[2] offset. This mutates the elf file object but not the copy on disk.
Call the save() function to make the changes persistent.
Usage:
>>> var e = open("small.elf", "elf")
>>> e.write_section(".metadata", from_hex("cafe01020304"), 0)
>>> e.read_section(".metadata")
[202, 254, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> hex(e.read_section(".metadata"))
cafe0102030400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>> save(e)
The following is a list of the builtin methods that can be called on instances of the Bytes File builtin type, alongside with their signatures.
bytes.read_at(int, int) -> array
Attempts to read arg[1] number of bytes starting from arg[0] position.
This returns an array containing the data that would be found in the corresponding .bin file obtained from the bytes file as a byte stream.
Usage:
>>> var b = open("small.bin", "bytes")
>>> var data = b.read_at(0, 5)
>>> [data, hex(data)]
[[148, 66, 0, 12, 148], 9442000c94]
bytes.write_at(int, array) -> no return
Attempts to write the contents of the arg[1] byte array to the arg[0] position. This mutates the bytes file object but not the copy on disk.
Call the save() function to make the changes persistent.
Usage:
>>> var b = open("small.bin", "bytes")
>>> b.read_at(0, 5)
[12, 148, 56, 0, 12]
>>> b.write_at(0, from_hex("cafe010203"))
>>> b.read_at(0, 5)
[202, 254, 1, 2, 3]
>>> hex(b.read_at(0, 5))
cafe010203