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