A rewrite is currently in progress which you can check out here
Adept is designed for performace and simplicity.
Generally it runs as fast or faster than C code.
Download Adept 1.1 Installer 64-bit
public def main() int {
customer_age int = 36
total_amount int = 10 + 3
return 0
}
private import "adept/terminal.adept"
public def main() int {
println(integer_sum(13, 8))
return 0
}
private def integer_sum(a int, b int) int {
return a + b
}
private import "adept/terminal.adept"
private constant $MESSAGE "Hello World"
private constant $AN_EXPRESSION 10 * 5 - (3 + 81) / 2
public def main() int {
println($MESSAGE)
println($AN_EXPRESSION)
return 0
}
private import "adept/string.adept"
private import "adept/terminal.adept"
public def main() int {
// Allocate 12 bytes (one extra for null termination)
hello *ubyte = new ubyte * 12
defer delete hello
// Set the byte array
copy(hello, "Hello World")
// Print the string
println(hello)
return 0
}
private import "adept/terminal.adept"
public def main() int {
// Create an array
integer_array [] int = new [3] int
defer delete integer_array
// Set some elements of the array
integer_array[0] = 10
integer_array[1] = 11
integer_array[2] = 12
// Print the length of the array
println(integer_array.length)
// Print some elements of the array
println(integer_array[0])
println(integer_array[1])
println(integer_array[2])
return 0
}
private import "adept/terminal.adept"
public def main() int {
// Allocate 10 ints
an_array *int = new int * 10
defer delete an_array
// Using low-level arrays with basic pointer arithmetic
*an_array = 10
an_array[3] = 42
an_array[7] = an_array[0] + 3
// Print some of the values we set
println(*an_array)
println(an_array[3])
println(an_array[7])
return 0
}
NOTE: I did not come up with this concept myself, I got it from Johnathan Blow's programming language Jai.
build.adept
private import "adept/terminal.adept"
private def build() int {
config AdeptConfig
// Initialize and defer freeing the configuration
config.create()
defer config.free()
// Set configuration options
config.setTiming(true)
config.setOptimization(3ui)
// Compile the program using the configuration
if config.compile("main.adept") != 0 {
println("Failed to compile main.adept")
return 1
}
// Return success
println("Build Complete!")
return 0
}
main.adept
public def main() int {
some_variable int = 10
another_variable int = 13
some_function(some_variable, another_variable)
return 0
}
Adept treats any file named build.adept
as a just-in-time build script. When Adept invokes a build script, it uses the 'build' function as an entry point instead of 'main'. So to use build.adept
to compile main.adept
you run the command adept build.adept
or just adept
NOTE: I did not come up with this concept myself, I got it from Johnathan Blow's programming language Jai.
private import "adept/terminal.adept"
public def main() int {
result int = 13 sum 8 sum 100
println(result)
return 0
}
private def sum(a int, b int) int {
return a + b
}
public def main() int {
int_sum int = sum(8, 13)
long_sum long = sum(8sl, 13sl)
println(int_sum)
println(long_sum)
return 0
}
private def sum(a int, b int) int {
return a + b
}
private def sum(a long, b long) long {
return a + b
}
private import "adept/terminal.adept"
private class Vector3f {
public x float
public y float
public z float
public def set(x float, y float, z float) void {
this.x = x
this.y = y
this.z = z
}
public def println() void {
println(this.x)
println(this.y)
println(this.z)
}
}
public def main() int {
vector Vector3f
vector.set(10.0f, 9.0f, 8.0f)
vector.println()
return 0
}
private import "adept/terminal.adept"
public def add(a int, b int) int {
// Basic function to add 2 integers
return a + b
}
public def mul(a int, b int) int {
// Basic function to multiply 2 integers
return a * b
}
public def printcalc(calc def(int, int) int, a int, b int) void {
// A simple function that preforms a calculation on 2 integers and prints the result
println(calc(a, b))
}
public def main() int {
// Declare a function pointer that points to 'add'
sum def(int, int) int = funcptr add(int, int)
// Call the function pointed to by 'sum'
println(8 sum 13)
// Pass it to a function and have the function call it
println("--------------------------")
printcalc(funcptr add(int,int), 8, 13)
printcalc(funcptr mul(int,int), 8, 13)
return 0
}
private import "system/system.adept"
private import "adept/terminal.adept"
private type SmallType {
length usize
data ptr
}
private type BigType {
a int
b int
c int
d long
e SmallType
}
public def main() int {
// Get the size of the type 'BigType' and print it
// NOTE: This will be different depending on the alignment of the type and
// depending on what the target system is. You can ensure a type is aligned to
// one byte by specifing the 'packed' attribute like: "private packed type BigType { ... }"
length usize = sizeof BigType
println(cast int length)
// Use 'new' operator to allocate an object of type 'BigType' on the heap
data *BigType = new BigType
// Use the allocated object
data.c = 12345
println(data.c)
// Use the 'delete' statement to free the object
delete data
return 0
}
private import "adept/terminal.adept"
public def main() int {
integer_list *int = {
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
}
for i usize = 0ui, i != 11ui, i += 1ui {
println(integer_list[i])
}
// Don't delete the data pointed to by
// 'integer_list' because it is constant
return 0
}
private import "adept/terminal.adept"
private type s64 = long
public def main() int {
a_big_number s64 = twice(12345678sl)
println(a_big_number)
return 0
}
private def twice(number s64) s64 {
return number * number
}
private import "adept/terminal.adept"
enum Fruit {
APPLE, BANANA, ORANGE
}
public def main() int {
fruit Fruit = Fruit::ORANGE
println(fruit)
println(Fruit::APPLE)
println(Fruit::BANANA)
return 0
}
private def println(fruit Fruit) void {
switch fruit {
case Fruit::APPLE
println("Apple")
case Fruit::BANANA
println("Banana")
case Fruit::ORANGE
println("Orange")
default
println("Unknown Fruit")
}
}
private import "adept/string.adept"
private import "adept/terminal.adept"
public def main() int {
firstname ! *ubyte = clone("Steve")
lastname ! *ubyte = clone("Johnson")
fullname ! *ubyte = new ubyte * 512
copy(fullname, firstname)
append(fullname, " ")
append(fullname, lastname)
greeting ! *ubyte = new ubyte * 768
copy(greeting, "Welcome ")
append(greeting, fullname)
println(greeting)
// NOTICE: We don't have to manually delete any of those strings
// that we created because they will automatically be deleted when
// we exit this function. This is because of the '!' operator signifying defered deletion.
return 0
}
NOTE: Try to avoid variable argument functions if and when performance matters.
Currently the implementation of calling them isn't the fastest :\
NOTE: Variable argument functions can also be called by passing an []
type containing the extra arguments.
private import "adept/terminal.adept"
public def main() int {
// Call the function with a different amount of integers each time
printIntegers(10, 20, 30, 40)
printIntegers(11, 12, 13, 14, 15, 16, 17)
// You can also pass an array containing the integers instead
integer_array [] int
integer_array.data = {1, 2, 3}
integer_array.length = 3ui
printIntegers(integer_array)
return 0
}
private def printIntegers(integers ... int) void {
for i usize = 0ui, i != integers.length, i += 1ui {
println(integers[i])
}
}
The Adept library adept/string.adept
contains lots of useful functions for manipulating strings.
NOTE: This example uses null-terminated '*ubyte
' strings, but all the functions in adept/string.adept
also have a variant that takes a 'string
' instead of a '*ubyte
' where it's applicable.
private import "adept/string.adept"
private import "adept/terminal.adept"
public def main() int {
// Request a string from the terminal
name *ubyte = new ubyte * 256
print("Enter your name: ")
input(name)
// Print a greeting
greeting ! *ubyte = join("Welcome ", name)
println(greeting)
// Create another greeting and print it
cloned_greeting ! *ubyte = clone(greeting)
new_greeting ! *ubyte = join(cloned_greeting, "!!!")
println(new_greeting)
// Copy a string into a buffer
buffer ! *ubyte = new ubyte * 1024
copy(buffer, "This is the string that will be copied into the buffer")
print("The length of the string in the buffer is: ")
println(length(buffer))
return 0
}
The 'string
' type is literally just an alias for the type '[]ubyte
'
String literals that are of the type 'string
' use single quotes!
(Instead of double quotes which are used for '*ubyte
' string literals)
All the functions defined in 'adept/string.adept
' used for string manipulation also have a variant that takes a 'string
' instead of a '*ubyte
'.
private import "adept/string.adept"
private import "adept/terminal.adept"
public def main() int {
hello_world string = 'Hello World'
println(hello_world)
name ! string = new [256] ubyte
input(name)
greeting ! string = join('Welcome ', name, '!')
println(greeting)
return 0
}