Features

Take a look at the most amazing features in Quail!

#:alias "set\\s*(?<id>[a-zA-Z0-9.]*)\\s*to\\s*(?<value>.*)" $1 = $2

set a to 2
set c to 455.3
          

Preprocessor

Simple regex-based preprocessor opens possibilities to widely customize the syntax

while true {
    for i in 1:10 do
        if i % 2 == 0:
            print(i)
    end
}
          

Flexible syntax

One of the many examples of Quail's flexible syntax is this. You can define code blocks as you wish: with curly braces, do-end's or even like in Python. Quail does not limit you

a = 10
a = "abc"
print(a)
          

Dynamic typing

Dynamic typing opens wide possibilities when writing code

a = 10
a = "Hello"
a = [1, 2, 3]

num b = 10
b = "Hello" # causes an error

num | string c = 10
c = "Hello" # Ok
c = [1, 2, 3] # causes an error
          

A little bit of static typing

While Quail is conceptually a dynamic typed language, it also can do static typing. By default, all variables are dynamic, but you can clarify the type and the variable becomes statically typed

class Person {
  name = ""
  method hello(this)
    out("Hello from " + this.name)
}

# Add methods to class on the way
Person.someMethod = (this, args...) -> {}
          

Prototype-based OOP

Prototype-oriented programming is the best in scripting, especially dynamic typed languages. You can add methods and fields to the class at the runtime or modify existing, easily inherit via standard tools or make your own inheritance system

Number.sum = (this, a) -> {
  return this + a
}

print(15.sum(37))
          

Everything is an object

You can use every value in Quail as an object, add, remove, change fields and methods, invoke them.

a = [1, 2, 3]
b = [4, 5, 6]
print(a + b)    # [1, 2, 3, 4, 5, 6]
print(a [+] b)  # [5, 7, 9]

c = [[1, -1], [-1, 1]]
d = [[1, 2], [3, 4]]
print(c {*} d)  # [[1, -2], [-3, 4]]
          

Rich tools for list manipulation

Alongside with very useful map and filter functions, Quail also provides so-called matrix and array operators which "unfold" lists and perform operations element-by-element

n = num(input())
f = [((i) -> {
        if i < 2 return i
        else return _this[-2] + _this[-1]
    })(i) through 0:n as i]
print(f)
          

Richer generators

Alongside with array and matrix operators, Quail's list and dict generators have a richer functionality by providing a special variable _this which contains currently generated list or dict. So it is now possible to generate basing on last-generated content. For example, this could be used for calculating Fibonacci numbers.

through 0:10 as x {
  through 0:10 as y {
    through 0:10 as z {
      if z == 5
        strike 2
      print(x, y, z)
    }
  }
}
          

strike syntax

strike works pretty much same as break, but with nested loops. In this example, when z reaches 5, not only z's loop will be broken, but also the one that corresponds to y, because 2 is specified in the strike instruction. But x's loop will remain untouched

use "lang/ji" = ji

JFrame = ji.getClass("javax.swing.JFrame")

win = JFrame("My window")
win.setSize(640, 480)
win.setDefaultCloseOperation(3)
win.setVisible(true)

while win.isVisible() {}

          

Deep Java integration

The JI (Java Integration) library allows you to create a bridge between Java and Quail, so you can grab a class from Java and it will act almost like native Quail class: you can call methods with native Quail values - they will be automatically converted to Java values, you can construct objects and access fields

class Queue {
    #? Implementation of a single-ended queue.

    num size(this) {}
    void add(this, object obj) {
        #? Add object to back of queue
    }
    object pop(this) {
        #? Pop object from front.
        #? If queue is empty, null is returned
    }
    void clear(this) {}
    object peek(this) {
        #? Get object from front without popping it.
        #? If queue is empty, null is returned
    }
}
          

Inbuilt documentation language

You can create documentation right in your source code using comments that start with #?. Then you can export that documentation to HTML to serve on your documentation portal.

btw, this is exactly how all Quail Library Docs are created

public class QuailTestAddon extends QuailAddon {
    public List<BuiltinLibrary> providedLibraries() {
        return Arrays.asList(
                new MyTestLibrary()
        );
    }
}
public class MyTestLibrary implements BuiltinLibrary {
    public String id() { return "test/mytestlib"; }
    public QObject constructLibrary(Runtime runtime) {
        ...
        contents.put("test", new MyTestFuncTest(runtime));
        ...
    }
}
public class MyTestFuncTest extends QBuiltinFunc {
    public QObject action(...) {
        return Val("Test library works!");
    }
}
          
use "test/mytestlib" = testlib
print(testlib.test())
          

Quail Addons

And if even all these features weren't enough for you, Quail allows you to create "addons" that can add new preprocessor directives, parser annotations and libraries all in pure Java. Then you just package your addon into .jar and add a little -G.addons=myaddon.jar flag when starting Quail