CX basics native functions - SkycoinWikis/CX GitHub Wiki

CX HOME » CX BASICS » NATIVE FUNCTIONS

Native Functions

Table of Contents

Type-inferenced Functions

CX has a small set of functions that are not associated to a single type signature. For example, instead of using i32.add to add two 32-bit integers, you can use the generalized add function. Furthermore, whenever you use arithmetic operators, such as +, - or %, these are translated to their corresponding "type-inferenced" function, e.g. num = 5 + 5 is translated to num = i32.add(5, 5). These native functions still follow CX's philosophy of having a strict typing system, as the types of the arguments sent to these native functions must be the same.

Note that after listing a group of similar "type-inferenced" functions below, we list the compatible types for the corresponding functions.

eq

uneq

Note: the preceding functions only work with arguments of type bool, byte, str, i32, i64, f32 or f64.

Example

package main

func main () {
	bool.print(eq(5, 5))
	bool.print(5 == 5) // alternative
	
	bool.print(uneq("hihi", "byebye"))
	bool.print("hihi" != "byebye") // alternative
}

lt

gt

lteq

gteq

Note: the preceding function only works with arguments of type byte, bool, str, i32, i64, f32 or f64.

Example

package main

func main () {
	bool.print(lt(3B, 4B))
	bool.print(3B < 4B) // alternative

	bool.print(gt("hello", "hi!"))
	bool.print("hello" > "hi!") // alternative

	bool.print(lteq(5.3D, 5.3D))
	bool.print(5.3D <= 5.3D) // alternative

	bool.print(gteq(10L, 3L))
	bool.print(10L >= 3L) // alternative
}

bitand

bitor

bitxor

bitclear

bitshl

bitshr

Note: the preceding functions only work with arguments of type i32 or i64.

Example

package main

func main () {
	i32.print(bitand(5, 1))
	i32.print(5 & 1) // alternative

	i64.print(bitor(3L, 2L))
	i64.print(3L | 2L) // alternative

	i32.print(bitxor(10, 2))
	i32.print(10 ^ 2) // alternative

	i64.print(bitclear(5L, 2L))
	i64.print(5L &^ 2L) // alternative

	i32.print(bitshl(2, 3))
	i32.print(2 << 3) // alternative

	i32.print(bitshr(16, 3))
	i32.print(16 >> 3) // alternative
}

add

sub

mul

div

Note: the preceding functions only work with arguments of type byte, i32, i64, f32 or f64.

Example

package main

func main () {
	byte.print(add(5B, 10B))
	byte.print(5B + 10B) // alternative

	i32.print(sub(3, 7))
	i32.print(3 - 7) // alternative

	i64.print(mul(4L, 5L))
	i64.print(4L * 5L) // alternative

	f32.print(div(4.3, 2.1))
	f32.print(4.3 / 2.1) // alternative
}

mod

Note: the preceding function only works with arguments of type byte, i32 or i64.

Example

package main

func main () {
	byte.print(mod(5B, 3B))
	byte.print(5B % 3B) // alternative
}

len

Note: the preceding function only works with arguments of type str, arrays or slices.

Example

package main

func main () {
	var string str
	var array [5]i32
	var slice []i32

	string = "this should print 20"
	array = [5]i32{1, 2, 3, 4, 5}
	slice = []i32{10, 20, 30}
	
	i32.print(len(string)) // prints 20
	i32.print(len(array)) // prints 5
	i32.print(len(slice)) // prints 3
}

printf

Note: the preceding function requires a format str as its first argument, followed by any number of arguments of type str, i32, i64, f32 or f64. The format string recognizes the following directives: %s for strings, %d for integers and %f for floating point numbers.

Example

package main

func main () {
	var name str
	var age i32
	var wrongPI f32
	var error f64

	name = "Richard"
	age = 14
	wrongPI = 3.16
	error = 0.0000000000000001D

	printf("Hello, %s. My name is %s. I see that you calculated the value of PI wrong (%f). I think this is not so bad, considering your young age of %d. When I was %d years old, I remember I miscalculated it, too (I got %f as a result, using a numerical method). If you are using a numerical method, please consider reaching an error lower than %f to get an acceptable result, and not a ridiculous value such as %f. \n\nBest regards!\n", name, "Edward", wrongPI, age, 25, 3.1417, error, 0.1)
}

sprintf

Note: the preceding function requires a format str as its first argument, followed by any number of arguments of type str, i32, i64, f32 or f64. The format string recognizes the following directives: %s for strings, %d for integers and %f for floating point numbers.

package main

func main () {
	var reply str
	var name str
	var title str

	name = "Edward"
	title = "Richard 8 PI"

	reply = sprintf("Thank you for contacting our technical support, %s. We see that you are having trouble with our video game titled '%s', targetted to kids under age %d. If you provide us with your parents e-mail address, we'll be glad to help you!", name, title, 14)

	str.print(reply)
}

Slice Functions

append

Example

package main

func main () {
	var slc1 []i32
	slc1 = append(slc1, 1)
	slc1 = append(slc1, 2)

	var slc2 []i32
	slc2 = append(slc1, 3)
	slc2 = append(slc2, 4)

	i32.print(len(slc1)) // prints 2
	i32.print(len(slc2)) // prints 4
}

Input/Output Functions

The following functions are used to handle input from the user and to print output to a terminal.

read

Example

package main

func main () {
	var password str

	for true {
		printf("What's the password, kid? ")
		password = read()

		if password == "123" {
			str.print("Welcome back.")
			return
		} else {
			str.print("Wrong, but you'll get another chance.")
		}
	}
}

byte.print

bool.print

str.print

i32.print

i64.print

f32.print

f64.print

printf

Example

package main

func main () {
    byte.print(5B)
    bool.print(true)
    str.print("Hello!")
    i32.print(5)
    i64.print(5L)
    f32.print(5.0)
    f64.print(5.0D)
    printf("For a better example, check section Type-inferenced Functions'")
}

Parse Functions

All parse functions follow the same pattern: XXX.YYY where XXX is the receiving type and YYY is the target type. You can read these functions as "parse XXX to YYY".

byte.str

byte.i32

byte.i64

byte.f32

byte.f64

Example

package main

func main () {
	var b byte
	b = 30B

	str.print(str.concat("Hello, ", byte.str(b)))
	i32.print(5 + byte.i32(b))
	i64.print(10L + byte.i64(b))
	f32.print(33.3 + byte.f32(b))
	f64.print(50.111D + byte.f64(b))
}

i32.byte

i32.str

i32.i64

i32.f32

i32.f64

Example

package main

func main () {
	var num i32
	num = 43

	str.print(str.concat("Hello, ", i32.str(num)))
	byte.print(5B + i32.byte(num))
	i64.print(10L + i32.i64(num))
	f32.print(33.3 + i32.f32(num))
	f64.print(50.111D + i32.f64(num))
}

i64.byte

i64.str

i64.i32

i64.f32

i64.f64

Example

package main

func main () {
	var num i64
	num = 43L

	str.print(str.concat("Hello, ", i64.str(num)))
	byte.print(5B + i64.byte(num))
	i64.print(10L + i64.i64(num))
	f32.print(33.3 + i64.f32(num))
	f64.print(50.111D + i64.f64(num))
}

f32.byte

f32.str

f32.i32

f32.i64

f32.f64

Example

package main

func main () {
	var num f32
	num = 43.33

	str.print(str.concat("Hello, ", f32.str(num)))
	byte.print(5B + f32.byte(num))
	i32.print(33 + f32.f32(num))
	i64.print(10L + f32.i64(num))
	f64.print(50.111D + f32.f64(num))
}

f64.byte

f64.str

f64.i32

f64.i64

f64.f32

Example

package main

func main () {
	var num f64
	num = 43.33D

	str.print(str.concat("Hello, ", f64.str(num)))
	byte.print(5B + f64.byte(num))
	i32.print(33 + f64.f32(num))
	i64.print(10L + f64.i64(num))
	f32.print(50.111 + f64.f32(num))
}

str.byte

str.i32

str.i64

str.f32

str.f64

Example

package main

func main () {
	var num str
	num = "33"

	byte.print(5B + str.byte(num))
	i32.print(33 + str.f32(num))
	i64.print(10L + str.i64(num))
	f32.print(50.111 + str.f32(num))
	f64.print(50.111D + str.f32(num))
}

Unit Testing

The assert function is used to test the value of an expression against another value. This function is useful to test that a package is working as intended.

assert

Example

package main

func foo() (res str) {
    res = "Working well"
}

func main () {
    var results []bool

    results = append(results, assert(5 + 5, 10, "Something went wrong with 5 + 5"))
    results = append(results, assert(foo(), "Working well", "Something went wrong with foo()"))

    var successfulTests i32
	for c := 0; c < len(results); c++ {
		if results[c] {
			successfulTests = successfulTests + 1
		}
	}

    printf("%d tests were performed\n", len(results))
    printf("%d were successful\n", successfulTests)
    printf("%d failed\n", len(results) - successfulTests)
}

bool Type Functions

bool.print

bool.eq

bool.uneq

bool.not

bool.or

bool.and

Example

package main

func main () {
	bool.print(bool.eq(true, true))
	bool.print(bool.uneq(false, true))
	bool.print(bool.not(false))
	bool.print(bool.or(true, false))
	bool.print(bool.and(true, true))
}

Type Functions

str Type Functions

str.print

str.concat

Example

package main

func main () {
	str.print(str.concat("Hello, ", "World!"))
}

i32 Type Functions

The following functions are of general purpose and are restricted to work with data structures of type i32 where it makes sense.

i32.print

i32.add

i32.sub

i32.mul

i32.div

i32.mod

i32.abs

Example

package main

func main () {
	i32.print(i32.add(5, 7))
	i32.print(i32.sub(6, 3))
	i32.print(i32.mul(4, 8))
	i32.print(i32.div(15, 3))
	i32.print(i32.mod(5, 3))
	i32.print(i32.abs(-13))
}

i32.log

i32.log2

i32.log10

i32.pow

i32.sqrt

Example

package main

func main () {
	i32.print(i32.log(13))
	i32.print(i32.log2(3))
	i32.print(i32.log10(12))
	i32.print(i32.pow(4, 4))
	i32.print(i32.sqrt(2))
}

i32.gt

i32.gteq

i32.lt

i32.lteq

i32.eq

i32.uneq

Example

package main

func main () {
	bool.print(i32.gt(5, 3))
	bool.print(i32.gteq(3, 8))
	bool.print(i32.lt(4, 3))
	bool.print(i32.lteq(8, 6))
	bool.print(i32.eq(-9, -9))
	bool.print(i32.uneq(3, 3))
}

i32.bitand

i32.bitor

i32.bitxor

i32.bitclear

i32.bitshl

i32.bitshr

Example

package main

func main () {
	i32.print(i32.bitand(2, 5))
	i32.print(i32.bitor(8, 3))
	i32.print(i32.bitxor(3, 9))
	i32.print(i32.bitclear(4, 4))
	i32.print(i32.bitshl(5, 9))
	i32.print(i32.bitshr(1, 6))
}

i32.max

i32.min

Example

package main

func main () {
	i32.print(i32.max(2, 5))
	i32.print(i32.min(10, 3))
}

i32.rand

Example

package main

func main () {
	i32.print(i32.rand(0, 100))
}

i64 Type Functions

The following functions are of general purpose and are restricted to work with data structures of type i64 where it makes sense.

i64.print

i64.add

i64.sub

i64.mul

i64.div

i64.mod

i64.abs

Example

package main

func main () {
	i64.print(i64.add(5L, 7L))
	i64.print(i64.sub(6L, 3L))
	i64.print(i64.mul(4L, 8L))
	i64.print(i64.div(15L, 3L))
	i64.print(i64.mod(5L, 3L))
	i64.print(i64.abs(-13L))
}

i64.log

i64.log2

i64.log10

i64.pow

i64.sqrt

Example

package main

func main () {
	i64.print(i64.log(13L))
	i64.print(i64.log2(3L))
	i64.print(i64.log10(12L))
	i64.print(i64.pow(4L, 4L))
	i64.print(i64.sqrt(2L))
}

i64.gt

i64.gteq

i64.lt

i64.lteq

i64.eq

i64.uneq

Example

package main

func main () {
	bool.print(i64.gt(5L, 3L))
	bool.print(i64.gteq(3L, 8L))
	bool.print(i64.lt(4L, 3L))
	bool.print(i64.lteq(8L, 6L))
	bool.print(i64.eq(-9L, -9L))
	bool.print(i64.uneq(3L, 3L))
}

i64.bitand

i64.bitor

i64.bitxor

i64.bitclear

i64.bitshl

i64.bitshr

Example

package main

func main () {
	i64.print(i64.bitand(2L, 5L))
	i64.print(i64.bitor(8L, 3L))
	i64.print(i64.bitxor(3L, 9L))
	i64.print(i64.bitclear(4L, 4L))
	i64.print(i64.bitshl(5L, 9L))
	i64.print(i64.bitshr(1L, 6L))
}

i64.max

i64.min

Example

package main

func main () {
	i64.print(i64.max(2L, 5L))
	i64.print(i64.min(10L, 3L))
}

i64.rand

Example

package main

func main () {
	i64.print(i64.rand(0L, 100L))
}

f32 Type Functions

The following functions are of general purpose and are restricted to work with data structures of type f32 where it makes sense.

f32.print

f32.add

f32.sub

f32.mul

f32.div

f32.abs

Example

package main

func main () {
	f32.print(f32.add(5.3, 10.5))
	f32.print(f32.sub(3.2, 6.7))
	f32.print(f32.mul(-7.9, -7.1))
	f32.print(f32.div(10.3, 2.4))
	f32.print(f32.abs(-3.14159))
}

f32.log

f32.log2

f32.log10

f32.pow

f32.sqrt

Example

package main

func main () {
	f32.print(f32.log(2.3))
	f32.print(f32.log2(3.4))
	f32.print(f32.log10(3.0))
	f32.print(f32.pow(-5.3, 2.0))
	f32.print(f32.sqrt(4.0))
}

f32.sin

f32.cos

Example

package main

func main () {
	f32.print(f32.sin(1.0))
	f32.print(f32.cos(2.0))
}

f32.gt

f32.gteq

f32.lt

f32.lteq

f32.eq

f32.uneq

Example

package main

func main () {
	bool.print(f32.gt(5.3, 3.1))
	bool.print(f32.gteq(3.7, 1.9))
	bool.print(f32.lt(2.4, 5.5))
	bool.print(f32.lteq(8.4, 3.2))
	bool.print(f32.eq(10.3, 10.3))
	bool.print(f32.uneq(8.9, 3.3))
}

f32.max

f32.min

Example

package main

func main () {
	f32.print(f32.max(3.3, 4.2))
	f32.print(f32.min(5.8, 9.9))
}

f64 Type Functions

The following functions are of general purpose and are restricted to work with data structures of type f64 where it makes sense.

f64.print

f64.add

f64.sub

f64.mul

f64.div

f64.abs

Example

package main

func main () {
	f64.print(f64.add(5.3D, 10.5D))
	f64.print(f64.sub(3.2D, 6.7D))
	f64.print(f64.mul(-7.9D, -7.1D))
	f64.print(f64.div(10.3D, 2.4D))
	f64.print(f64.abs(-3.14159D))
}

f64.log

f64.log2

f64.log10

f64.pow

f64.sqrt

Example

package main

func main () {
	f64.print(f64.log(2.3D))
	f64.print(f64.log2(3.4D))
	f64.print(f64.log10(3.0D))
	f64.print(f64.pow(-5.3D, 2.0D))
	f64.print(f64.sqrt(4.0D))
}

f64.sin

f64.cos

Example

package main

func main () {
	f64.print(f64.sin(1.0D))
	f64.print(f64.cos(2.0D))
}

f64.gt

f64.gteq

f64.lt

f64.lteq

f64.eq

f64.uneq

Example

package main

func main () {
	bool.print(f64.gt(5.3D, 3.1D))
	bool.print(f64.gteq(3.7D, 1.9D))
	bool.print(f64.lt(2.4D, 5.5D))
	bool.print(f64.lteq(8.4D, 3.2D))
	bool.print(f64.eq(10.3D, 10.3D))
	bool.print(f64.uneq(8.9D, 3.3D))
}

f64.max

f64.min

Example

package main

func main () {
	f64.print(f64.max(3.3D, 4.2D))
	f64.print(f64.min(5.8D, 9.9D))
}