Modified: 05th Jun 16 |

QHA Interpreter

Version:
0.1.230, October 8th, 2008
License:
Copyright © 2008 Daniel Korsgaard, Freeware
Download:
qha-0.1.230.zip

The scripting language QHA, was originally intended for frontend scripting of IRC bots. The name is based on syntactical elements form the language, namely a Question mark, a Hash, and an At-sign.

QHA draws on numerous concepts in the world of programming languages, but was not specifically inspired by any particular language. It was designed to be very flexible and highlevel, not to mention very compact.

Some of the language constructs have not been implemented in this preview.

The .zip file includes a win32 executable that interprets QHA source code, and a plain text file containing a partial description of the language and how to use the interpreter.

QHA Specification

Basics:

  • QHA is a dynamically typed language.
  • Variables need not be declared before use. In fact, they cannot possibly be declared.
  • A variable will be defined at first use of the variable.
  • Variables dissapear when the function, in which it was first used, ends. (unless a closure inherits these)
  • All assignments are making copies.
  • everything is first class values.

The dynamic types and the data they can store:

The nine datatypes of QHA
Type Data
Unset The initial type of all variables
Integer A 64 bit signed integer
Float A 64 bit float (not yet supported)
String An UTF-8 string
Aggregate Variable with members
Array Variable containing an ordered list of values
Map Variable that maps one value to another
Function Code that can be executed
Closure Code that can be executed, and at the same time keeps it's initial context accessible

The arithmetic and logical operators in QHA:

++ -- !
+ - ~ * / % | ^ & || && << >>
== < > <= >= <> <>= != !< !> !<= !>= !<> !<>=
= += -= ~= *= /= %= |= &= <<= >>=

some of these operators might not work.

QHA syntax:

A program in QHA is composed of a sequence of statements. There are 6 built in control flow statements, 4 of which doesnt work yet.

The if statement:

QHA-if C-if
? (condition) {
    foo();
}{
    bar();
}
if (condition) {
    foo();
} else {
    bar();
}

 

The for-loop:

QHA-for C-for
# (init; cond; incr) {
    foo();
}
for (init; cond; incr) {
    foo();
}

 

The not-yet completely implemented statements are:

foreach statement:

QHA-foreach D-foreach
@ (ident, ident2; expr) {
    bar();
}
foreach (ident, ident2; expr) {
    bar();
}

 

continue statement:

QHA-for C-for
#>; continue;

This continue statement also accepts an integer to specify the depth of the loop from which it will continue. For instance:

QHA-continue PHP-continue
#> 3; continue 3;

break statement:

QHA-break C-break
#!; break;

This break statement also accepts an integer to specify the depth of the loop from which it will break. For instance:

QHA-break PHP-break
#! 3; break 3;

return statement;

QHA-for C-for
#< expr; return expr;

 

Basic literals and identifiers:

Identifiers are alphanumeric + underscore, but cannot start with a number.

[_a-zA-Z][_a-zA-Z0-9]*

Integers is any sequence of decimal digits

[0-9]+

Floats are not implemented yet.

Strings are any sequence of characters starting with a double quote, and extending up untill the next double quote.

"[^"]*"

An array is a sequence of comma separated expressions, enclosed in square brackets. For instance:

[1, 2, "three"]

The array accepts any kind and any number of expressions.

A map is an associative array, and consists of pairs of expressions. The first expression in a pair, is the key, and the second is the value. An example of a map:

[: key_a: value_a, key_b: value_b, "some key": "some value"]

Aggregates consists of identifier-expression pairs. For instance:

{: some_arbitrary_identifier: "some expression", a: "property a", b: "property b", c: 1}

Function literals are used to express computation. For instance:

{(param_a, param_b) list(); of[statements] += here; }

Closures are similar, just with another set of curly brackets, like this:

{{(param_a, param_b) list(); of[statements] += here; }}

 

Basic expressions

Array and map lookup, just as in C:

result = array_or_map[any_expression];

Accessing members, just as in C:

value = some_aggregate.any_member;

Calling functions or closures, just as in C:

return_value = any_function_or_closure(any_expression, more_expressions);

 

General example:

silly_function = {{ (a_single_arg)
    result = "";   
   
    ? (a_single_arg == 3)
    {
        # (i = 0; i < 7; i++)
        {
            ? (i & 1)
            {
                result = result ~ i;
            }{}
        }
    }{
        result = "Boring :(";
    }
   
    result; // will be returned because it's the last expression
}};

Pasteable version:

silly_function = {{ (a_single_arg) result = ""; ? (a_single_arg == 3) { # (i = 0; i < 7; i++) { ? (i & 1) { result = result ~ i; }{} } }{ result = "Boring :("; } result; }};

Try paste the code into QHA, and then call the function like this:

silly_function(3);

Example of how closures work:

gen_multiplier = {{ (mul_by)
    closure = { (value)
        value * mul_by;
    };
}};

A pasteable version;

gen_multiplier = {{ (mul_by) closure = { (value) value * mul_by; }; }};

Now try calling the function:

multiply_by_four = gen_multiplier(4);
multiply_by_four(6);

The all time fibonacci example
Fib = { (n)
    ? (n == 0 || n == 1)
    {
        1;
    }{
        this(n-1) + this(n-2)
    }
}

A note:
The qha-0.1.230.exe program keeps the previously defined identifiers from earlier executed statements.
So it is possible to define a number of functions, and then use them afterwards for instance.

Also, there are lots of unimplemented combinations of variable types and operators. For instance, the following expression ("foo" & 4),
which is a binary AND of the string "foo" and the integer 5 is not implemented, and the idea is that it will give a warning, but result
in an undefined value.


Previous page: Regex Programming Language
Next page: Explophilia Game