Next | Previous

Quick Language Overview

For those with good programming experience, reading through tons of pages of documentation may look like a waste of time since they'll already be equipped enough to pick off new stuff fast. If you are one of them — this is for you!

Click the REPL box to toggle the REPL mode on and off.

Reference

Start in REPL mode

Simple type blade in your terminal to launch REPL mode

$ blade
Blade 0.0.86 (running on BladeVM 0.1.1), REPL/Interactive mode = ON
Clang 13.0.0, (Build time = Feb  8 2022, 02:47:36)
Type ".exit" to quit or ".credits" for more information
%> 

Running a script

Type blade followed by the path to the file in the terminal.
Blade scripts use the .b extension.

$ blade /path/to/file.b

You can use the echo keyword to print any object to standard output or use the print() function to print one or more objects to standard output.

%> echo 'Hello, World'     # using echo keyword
'Hello, World'
%> print('Hello,', 'World\n')   # using the print function
Hello, World

@note: Statements are terminated by newlines, but they can also be separated by semicolons ;
@convention: use newlines

Variables

Use the var keyword to declare variables.

%> var a = 10
%> a    # in the REPL mode, you can omit `echo` to do a quick print
10
%> var b = 'Hello, World'
%> b
'Hello, World'
%> a = 25
%> b = 33
%> a; b     # printing a and b to screen at the same time
25
33

Operators such as +=, -=, ++, -- are all supported.

%> a++
%> b--
%> a; b
26
32
%> a += 10
%> b *= 5
%> a; b
36
160

More

Comments

Single line comments begin with an #, multiline comments are wrapped in /* and */ and they can be nested.

# a single line comment

/*
 Multiline comments
  /*
    can be nested...
  */
*/

More

String interpolation

Blade strings allow you to evaluate expressions within strings using the interpolation syntax ${expression...}.

@note: Blade strings always support interpolation and can span multiple lines whether wrapped in '' or ""

%> var a = 93
%> 'a is ${a}'
'a is 93'
%> var b = 'a is ${a}'
%> b
'a is 93'
%> a = 107
%> '${b.replace("is", "was")}, but is now ${a}'
'a was 93, but is now 107'

The arguments to replace could have used '' pairs too. We only used "" for clarity.
More

if...else... statements

Blade has the standard if... else... you'll find in most C-like languages except that it doesn't require the parenthesis.

%> var a = 20
%> if a > 20 {
..   echo 'a is greater than 20'
.. } else {
..   echo 'a is less than or equal to 20'
.. }
'a is less than or equal to 20'

It can be inlined if only one statement follows

if a == 20 echo 'a is 20'
else echo 'a is not 20'

/**
 * Output:
 * a is 20
 */

More

Ternary operators ?:

Simple expression time decisions are supported via ternary operators

%> var a = 10
%> echo a < 10 ? 'Failed.' : 'Congrats!'
'Congrats!'

More

using statements

This statement takes a value and matches it against a set of constants to run the piece of code associated with it.

%> var name = 'james'
%> 
%> using name {
..   when 10 echo 'My name is 10'
..   when true {
..     echo 'My name is true'
..     echo 'Yes, true is a constant!'
..   }
..   when 'james' echo 'My name is James'
..   default echo "I don't know my name"
.. }
'My name is James'

More

while loop

%> var items = ['Apple', 'Mango', 'Banana', 'Peach']
%> var index = 0
%> 
%> while index < items.length() {
..   echo 'Item at ${index} is ${items[index]}'
..   index++
.. }
'Item at 0 is Apple'
'Item at 1 is Mango'
'Item at 2 is Banana
'Item at 3 is Peach'

More

do...while loop

%> var i = 5
%> do {
..   echo i
..   i--
.. } while i > 0
5
4
3
2
1

More

iter loop

Blade's version of C/JavaScript's for loops. See here for why we didn't call it a for loop.

%> iter var i = 0; i < 5; i++ {
..   echo 'Iteration ${i}'
.. }
'Iteration 0'
'Iteration 1'
'Iteration 2'
'Iteration 3'
'Iteration 4'

More

Ranges

You can define numbers over a range using Blade's range operator .. and they can be used with loops very easily.

%> 0..5
<range 0-5>
%> 1..10
<range 1-10>
%> 21..3
<range 21-3>

More

for loop

%> var items = ['Nigeria', 'Ghanan', 'Senegal', 'Mali']
%> for item in items {
..   echo '${item} is a country'
.. }
'Nigeria is a country'
'Ghanan is a country'
'Senegal is a country'
'Mali is a country'
%> 
%> var details = {name: 'Blade', version: 0.5, website: 'https://bladelang.org'} 
%> for key, value in details {
..   echo '${key} -> ${value}'
.. }
'name -> Blade'
'version -> 0.5'
'website -> https://bladelang.org'

More

Iterables

Blade comes with built-in support for strings, ranges, bytes, lists, and dictionaries as its primary iterables and they support all common operations such as indexing and slicing. The concepts shown below apply to all iterables with the exception that strings are immutable.

%> var list = [1, 'game', false]  # any data type can fit in...
%> var dictionary = {name: 'Blade', version: '0.0.86'}
%> var byte_array = bytes([104, 101, 108, 108, 111])  # hello
%> var sized_bytes = bytes(10)   # a byte array of size 10 with all entries as 0x0
%> 
%> echo list.length()
3
%> echo byte_array[2]
108
%> echo list[1,-1]
[game]
%> 
%> # update value(string values cannot be updated as they are immutable)
%> dictionary['version'] = 'version 0.0.86'
%> list[0]++
%> 
%> echo dictionary
{name: Blade, version: version 0.0.86}
%> echo list
[2, game, false]
%> 
%> for _, value in byte_array {
..   echo chr(value)
.. }
'h'
'e'
'l'
'l'
'o'

More

Functions

Use the def keyword to define a function.

@note: The default value of a parameter is nil. For this reason, parameters can be omitted when calling functions.

%> # define function name that takes one argument - name.
%> def say_hello(name) {
..   echo 'Hi, ' + name
.. }
%> 
%> say_hello('Parker')
'Hi, Parker'
%> say_hello() # name will default to nil
'Hi, '
%> 
%> def add(a, b) {
..   return a + b
.. }
%> 
%> add(30, 45)
75
%> 
%> # Functions can be nested into closures as they are first class objects...
%> def outer_function() {
..   def inner_function() {
..     return 20
..   }
..   return inner_function
.. }
%> 
%> outer_function()()
20

Blade also has support for Anonymous function. Click more for information. More

Type check and conversions

You can check if a value is a type by calling the related built-in function all named as is_... or convert to that type by calling the built-in to_... functions. E.g.

%> is_string('hello')
true
%> to_list('hello')
[h, e, l, l, o]

@note: They type of a dictionary is shortened to dict for builtin functions. i.e. we have to_dict() and is_dict().

More

Class

%> class Person { /* class content goes here... */ }
%> 
%> # creating instance of a class...
%> var person = Person()

More

Class methods

%> class Person {
..   say_hello(name) {
..     return 'Hello, ${name}'
..   }
.. }
%> 
%> var person = Person()
%> person.say_hello('Hank')
'Hello, Hank'

More

Class constructors

Constructors are simply class methods bearing the same name as the class.

%> class Person {
.. 
..   Person(name) {
..     self.name = name
..   }
.. 
..   say_hello() {
..     return 'Hello, ${self.name}'
..   }
.. }
%> 
%> var person = Person('Stark')
%> person.say_hello()
'Hello, Stark'

More

Class fields

%> class Point {
..   var x = 2.143
..   var y = 7.941
.. }
%> 
%> var point = Point()
%> '${point.x}, ${point.y}'
'2.143, 7.941'

More

Static class fields and methods

%> class Math {
..   static var PI = 3.142
.. 
..   static abs(x) {
..     return x >= 0 ? x : -x
..   }
.. }
%> 
%> Math.PI
3.142
%> Math.abs(-91)
91

More

Private class fields and methods

Class fields or methods whose name starts with an underscore (_) are private and only accessible from the current class.

%> class Class {
..   var _number_of_desks = 10
.. 
..   _get_desks() {
..     return self._number_of_desks
..   }
.. 
..   get_desks() {
..     return self._get_desks()
..   }
.. }
%> 
%> var cls = Class()
%> cls.get_desks()
10
%> cls._number_of_desks   # this will cause an exception
Unhandled Exception: cannot call private property '_number_of_desks' from instance of Class
  StackTrace:
    <repl>:1 -> @.script()

More

Inheritance

%> class Animal {
..   Animal(name) {
..     self.name = name
..   }
.. 
..   greet() {
..     echo 'Hello ${self.name}'
..   }
.. 
..   call() {
..     echo 'Come here ${self.name}'
..   }
.. }
%> 
%> class Dog < Animal {
..   Dog(name) {
..     parent(name)
..   }
.. 
..   call() {
..     parent.call()
..     echo 'Whats up?'
..   }
.. }
%> 
%> var dog = Dog('Bingo')
%> dog.greet()
'Hello Bingo'
%> dog.call()
'Come here Bingo'
'Whats up?'

More

Class decorator

These are methods meant to provide information on how to use the class and they cannot be called directly by instances of the said class.

%> class Class {
..   @decoration() {
..     return 1
..   }
.. }

More

Overriding builtin-methods

Simply create a decorator for the function.

%> class Person {
..   Person(name) {
..     self.name = name
..   }
.. }
%> 
%> class Animal {
..   Animal(name) {
..     self.name = name
..   }
.. 
..   @to_string() {
..     return '<Animal ${self.name}>'
..   }
.. }
%> 
%> var person = Person('James')
%> var animal = Animal('Dog')
%> 
%> to_string(animal)  # using to_string function to convert classes to string
'<Animal Dog>'
%> to_string(person)
Unhandled Exception: undefined method '@to_string' in Person
  StackTrace:
    <repl>:1 -> @.script()

@note: Some builtin functions do not support decoration. e.g. max().

More

Class as iterables

To convert a class into an iterable, simply implement the @iter() and @itern() decoration. @itern() returns the current index and @iter() returns the current value.

%> class Iterable {
..   var items = ['Richard', 'Alex', 'Justina']
.. 
..   @iter(x) {
..     return self.items[x]
..   }
.. 
..   @itern(x) {
..     if x == nil return 0
.. 
..     if x < self.items.length() - 1
..       return x + 1
..     return false
..   }
.. }
%> 
%> for it in Iterable() {
..   echo it
.. }
'Richard'
'Alex'
'Justina'

More

Reading and Writing Files

Writing/Creating a file

%> var f = file('test.txt', 'w')
%> var written = f.write('It works!')
%> f.close()
%> 
%> if written echo 'File created successfully!'
'File created successfully!'

Reading a file

%> file('test.txt').read()
'It works!'

More

Throwing exceptions

Blade comes with the built-in class Exception and all exceptions must derive from this class.

%> raise Exception('I died')
Unhandled Exception: I died
  StackTrace:
    <repl>:1 -> @.script()

More

Handling exceptions

%> catch {
..   echo 'do something'
..   raise Exception('there was an exception here')
..   echo 'do something else'
.. } as error
'do something'
%> 
%> if error {
..   echo error.type
..   echo error.message
..   echo error.stacktrace
.. }
'Exception'
'there was an exception here'
'    <repl>:3 -> @.script()'

More

Custom Exceptions

Simply subclass Exception as follows.

%> class CustomError < Exception {}
%> 
%> raise CustomError('I died too!')
Unhandled CustomError: I died too!
  StackTrace:
    <repl>:1 -> @.script()

More

Asserts

%> assert 10 == 10
%> assert 10 > 11
Illegal State:
  StackTrace:
    <repl>:1 -> @.script()
%> assert 10 > 11, 'Failue!'
Illegal State: Failue!
  StackTrace:
    <repl>:1 -> @.script()

More

Importing packages and modules

Import package/module

%> import http
%> http
<module http at /blade/libs/http/index.b>

Import specific items from package/module

%> import http { HttpClient }
%> HttpClient
<class HttpClient at 0x143f1f060>
%> http
Unhandled Exception: 'http' is undefined in this scope
  StackTrace:
    <repl>:1 -> @.script()

Import all exported values into current namespace

%> import math { * }
%> math
Unhandled Exception: 'math' is undefined in this scope
  StackTrace:
    <repl>:1 -> @.script()
%> product
<function product at 0x133e10180>

Rename package/module on import

%> import os as osystem
%> os
Unhandled Exception: 'os' is undefined in this scope
  StackTrace:
    <repl>:1 -> @.script()
%> osystem
<module osystem at /blade/libs/os.b>

Import module/package in relative path

import .test  # prefix the import path with a dot
import ..test # prefix path with a range(..) for the parent directory.

@note: Every Blade .b script is a module.

More

Creating packages

Create a directory with the name of the package and create an index.b file in the directory. That's all!

my_package
|-- index.b
|...

Import as usual!

Fist-class package management

Blade allows you to download packages and libraries into your source code directory and call it from your code as if it were a standard library. It's simple.

Simply create a directory .blade/libs at the root of your application and download Blade modules and/or packages into the directory into that directory. For example, create the directory .blade/libs in your current directory and create a file test.b in that directory. Paste the following code into it.

var name = 'Paula'

Now create a new file sample.b in your current directory and save the following code in it:

import test
echo test.name

Now run your file using:

$ blade sample.b

You should see Paula printed in the console. Voila!

This features extends to C extensions created for Blade as well.

More