3.18. Complier directives

Quirrel has a way to for flexibly customize language features.

This allows to smoothly change compiler, while keeping backward compatibility if needed.

Example

#default:strict

let function foo() {
  #relaxed-bool
  if (123)
    print("bar")
}

Prefix directive with ‘default:’ to apply it to entire VM, otherwise directive applies to clojure in where it is declared.

3.19. List of Complier directives

3.19.1. Strict booleans

#strict-bool

Force booleans in conditional expressions, raise an error on non-boolean types.

Non-boolean in conditional expressions can lead to errors. Because all programming languages with such feature behave differently, for example Python treats empty arrays and strings as false, but JS doesn’t; PHP convert logical expression to Boolean, etc. Another reason is that due to dynamic nature of Quirrel those who read code can’t know what exactly author meant with it.

if (some_var) //somevar can be null, 0, 0.0 or object

or

local foo = a() || b() && c //what author means? What will be foo?

3.19.2. Implicit bool expressions

#relaxed-bool

Original Squirrel 3.1 behavior (treat boolean false, null, 0 and 0.0 as false, all other values as true)

3.19.3. Disable root fallback

#no-root-fallback

Require :: to access root

print(1) //error
::print(1) //prints 1

Implicit root fallback is error prone and a bit slower due to more lookups.

3.19.4. Enable root fallback

#implicit-root-fallback

Allow to search for variable in root table

3.19.5. Force explicit access to ‘this’

#explicit-this

Require to explicitly specify ‘this’ or :: to access fields of function environment (‘this’) or root table. This behavior is similar to one in Python. Identifiers must be known local variables, free variables or constants. For unknown names a compilation error is thrown.

3.19.6. Allow implicit access to ‘this’

#implicit-this

Original Squirrel 3.1 behavior. For identifiers not known as local or free variables or constants/enums fallback code performing get/set operations in ‘this’ or root table will be generated.

3.19.7. Disable function declaration sugar

#no-func-decl-sugar

Don’t allow to implicitly add functions to ‘this’ as fields. This also error prone (and functions can be unintentionally added to roottable). Root functions can be added explicitely via slot creation

::foo <- function(){}

Local functions can be added as

let function foo(){}

3.19.8. Allow function declaration sugar

#allow-func-decl-sugar

Allow to implicitly add functions to ‘this’

3.19.9. Disable class declaration sugar

#no-class-decl-sugar

The same directive as #no-func-decl-sugar but for classes. Local classes can be added with:

let class Foo{}

3.19.10. Allow class declaration sugar

#allow-class-decl-sugar

Allow implicitly add classes to ‘this’

3.19.11. Disable access to root table via ::

#forbid-root-table

Forbids use of :: operator for the current unit Using root table is dangerous (as all global vairables)

3.19.12. Enable access to root table via ::

#allow-root-table

Allows use of :: operator for the current unit

3.19.13. Disable implicit string concatenation

#no-plus-concat

Throws error on string concatenation with +. It is slower for multple strings, use concat or join instead. It is also not safe and can cause errors, as + is supposed to be at least Associative operation, and usually Commutative too. But + for string concatenation is not associative, e.g.

Example:

let a = 1
let b = 2
let c = "3"
(a + b) + c != a + (b + c) // "33" != "123"

This actually happens especially on reduce of arrays and alike.

3.19.14. Enable plus string concatenation

#allow-plus-concat

Allow using plus operator ‘+’ to concatenate strings.

3.19.15. #strict

#strict

Enable all extra checks/restrictions

3.19.16. #relaxed

#relaxed

Disable all extra checks/restrictions