[QW] "Quick Write" The Most Succinct Programming Language

 

Introduction

I am really annoyed about using unnecessary keywords in many languages, so I created this one. Editing commas on array or method changing, adding [;], typing [var] takes too much time in total. Maybe, it is impossible to get rid of this. But I wrote the compiler and this article to prove it is possible. Also, I wrote a source editor (IDE) for this language to prove the code can be easily readable.

QW is my own created language for a fast coding. This language is not for beginners, language does not provide an easy start. The main goal is to minimize programmer work by using the least amount key presses as it is possible. Language is fully compliable in C language for now; strictly typed; syntax is C-like. (Compiling into JS or into machine code is possible in future.)

Code must be succinct and agile for all incoming changes. QW does not have special statement terminators like [;] or [\n], most keywords replaced with symbols, like [\] or [,], [.] and other.

I replaced almost all keywords with a single key press, if it is possible - without using SHIFT key. This is crucial for a frequently using commands. Because of lack of special symbols on keyboard - some symbols are reused in different situations. Some commands may be unaccustomed, but it is because there are not a lot of symbols on keyboard.

QW can detect some special situations from the context, so a programmer doesn't need to write useless code. I want to get rid of artificial restraints, because making readable code is a programmer's work or IDE, not a language.

I want the language to be agile; so I don't want to keep compatibility between major versions. This can be a problem for a long term language using, but this keeps language free from a historical restrictions and unnecessary hacks. Potentially, a code migrator can solve compatibility problem.

The language updates supports semver.ver2 [v.[major].[minor].[patch]]. The "0" major version of QW does not supports previous versions, only patches. So, v.0.1.5 will support v.0.1.1, but does not support v.0.0.1. Current version is "0" (zero), this is version for tests. This version is not stable, it can be changed at any time.

Current version: ildarin-qw-v.0.0.1

Using the Code

Types

All common types are shortened to a single word.

[type]:  
[i] - integer, default is [0]
[d] - double, [0..[5.*10^325 .. 1.*10^308]], default is [0]

(... other types can be added later, like float or long)  

[[type]`[n]] - array of [type] with length [n], where [n] is integer
[[type] [variable]] - declaration of a variable

Example of a variable declaration:

i count
d`15 array
i`count numbers

If a type can be recognized from the code - you don't need to write a type. Default values for [i]nteger - any number without the dot [.], [d]ouble - within the dot [.];

count=15  
size=count  
v1 = 1.  
v2 = 2.5  
v3 = v1+v2 
integers = [1 2 3 count count*2 5 6]

No Separators or Line Endings

This can make your code more complex for understanding, but it is all about this language - it gives you possibilities, not restrictions. If it is possible to recognize without ambiguities what you want from the code - it can be written.

i a1 = 1 
d b1 = 2 
c1 = a1 + b1

The code above can be written in a short way in a single line:

i a2=1 d b2=2 c2=a2+b2  
i a1 = 1 d b1 = 2 c1 = a1 + b1

Math Operators

Common using operators: add [+]; multiply [*]; divide [/]; distinct [-]; pow [^];

Can be used for an [i]nteger; [d]ouble values.

d value = 1+2^3+4*5

Operators order is: [+ -], [* /], [^], [;-] [value].

Values must be declared before using. The code below is incorrect, because of [val2] is used in [val1] assigning before its declaration.

i val = 2 * <error>val2</error>
i val2 = 5

If operation contains various types, result will be converted to a bigger type.

s > d > i > c > q

Math Expression Order

Brackets are used to order an expression. [ and ].

a1=[5+5]*[3+3]

Debug Log

To out in the debug log, there are special command [//]. This code will out [10] in the debug log. For now, it is a printf function in C with the format depends on the value type.

i a = 5+5
//a

Arrays

Array declaration is similar to JS, but without line ending, values separator and, if it possible - without the type definition.

i`3 array
integers  = [3 4 5 6]
doubles   = [4. 5. 6. 7.]

Negative Value

To define a negative value, use operator [;-] before the value. This is necessary because of value separator absence.

integers = [3 ;-4 ;-5 6]
doubles = [4. 5. ;-6. 7.]

Without the negative separator, value will be a math expression.

array4 = [
  1*2
  3 +4
  5 -6
  7-8
]

Iterator and This

Iteration through an array was shorten from for and foreach keywords to a single [\] symbol. Its called for-do. In depends on left part of "fordo" symbol [\] behavior will change. If an array on the left, fordo will iterate all elements in array.

Current iterated value can be accessed by this operator, shorten to single symbol dot [.]

sum=0
integers = [3 4 5 6]
integers\ sum = sum + .
//sum

This

To access the current iteration value, you can use the this command - the dot symbol "." It will return the current iterated value.

For nested iterators, [.] will return the last scope value. In the code below, value [i1] will be [24].

a1=[1 1 1]
a2=[2 2 2]
i1=0
a1\a2\i1=i1+.

Code Block

You can define a block of code using the characters [ and ]. This is necessary to use multiple commands in an iterator.

sum2=0     integers = [1 2 3 4]

integers\[
  sum2=sum2+.*.
  .=sum2
]

Compiler

Compiler is written on C#.NET7. Compiler translates QW code to a C language code. After that - TCC compiles from C code to a Windows executable. TCC is added to a binaries of a compiler.

Compiler consists of multiple components, one of them is the translator. Translator can be changed to any another translator, as JS or Assembler. Internal state machine (like in a C# or Java) also is possible. Nice to have is to fully rewrite compiler on QW.

Binaries.

    To use Linux compiler version, you need to install TCC first:

    sudo apt-get install -y tcc

    Then run the file Qw.CompilerConsole. QW source code in the file source.qw. Result will be in the result folder, containing result.c and binary file result.exe.

    Compiler may be bagged because of small amount of tests I've done for a C translator.

    The goal for the first version is a simple realization of a feed forward neural network.

    bias=15
    inputs = [5. 45 6 24 2]
    weights = [.65 .51 ;-.2 ;-.95 .25]
    d sum
    inputs\[
      in=.
      weights\sum=sum+ in*. +bias
    ]
    e=2.718281828459045
    result = 1/[1+e^[;-sum]]
    //result

    Source Editor (IDE)

    Source editor is a Net7 kestrel server app with HTML JS client. It supports syntax highlighting.

    Screenshot-from-2023-02-17-20-06-02 Screenshot-from-2023-02-17-20-05-32

    Features

    Current version of compiler does not realize all language features. So I separated them from the "Using the Code" part of this article. Because I am not done with these features in compiler - I am not sure whether they are correct.

    Types

    Default types of a C language.

    [q] - bit ([q]uestion), [0..1], default is [0]
    [c] - char or byte, [0..255], default is [0]
    [f] - float
    [l] - long
    [s] - string, array of [c], default is empty 

    Dynamic Array

    If array size is not defined, the value will become a dynamic array. It behaves just like a regular array, but predefined size will be zero or depends on assertion.

    i` integers
    d` doubles

    Array Element Access

    Access to an array element by index is without any special symbols, just an index number after the array variable name.

    i`3 array
    array 2 = 5
    // array 1
    array 0 = array 1 + array 2

    Iteration Return

    Iteration returns an array of its result.

    count = 10
    array = count\.*2
    array2 = array\.*3

    Iteration "THIS" element naming

    To access parent iterated this element - it is possible to name it before the iteration call.

    array = [1 2 3 4]
    array2= [6 7 8 9]
    sum=0
    element array\
       array2\
          sum=sum+element*.
    
    
    

    Multidimensional Array

    Additional [`] symbol can be used for declaring a multidimensional array.

    i``` dem3array
    dem3array=[ 
      [ [1 2 3] [2 3 4] ] 
      [ [4 5 6] ]  
    ]
    dem2array = [ [1 2] [2 3] [3 4] ]

    Array Operations

    Plus [+] is for adding element or concatenate arrays, minus [-] is for distinct array from the source or remove an element.

    In expression, order an array operations comes after the base type operations.

    a1 = [2 6 8]
    a1 = a1 + 3
    a1 = a1 + 5
    a1 = a1 - 8
    a1 = a1 + 5 + 6 * 8
    
    i` a2 = a1 + a1 

    String Format

    String constants can be declared using single quote symbol [']. For escaping - duplicate the symbol.

    To insert some value in the formatted string - used symbol [`]. Expression value in the [`] block will be pasted to the string result.

    For a string concatenation is used operator [+].

    s1 = '''Hello world'''
    s2 = 's1 contains `s1`'
    s3 = 's1 concatenates with s2 will be "`s1+s2`"'
    s4 = '5+5=`5+5`' 
    
    
    

    Conditions

    I replaced if keyword with a symbol ?. else keyword with symbol :. (I not very like this solution, it's just mostly taken from C#.)

    Using ? converts expression right after ? to a [q]uestion value (boolean). If question value result equals to zero ([q]=0), then code after the expression will not executed and it goes to an expression after : execution.

    If question expression result is non [q] type value - then it will convert to a [q]. If the value equals to its default value - then value will be zero (false), else it will be equals to one (true).

    Conditions supports operators ! - not, reverts logical value.

    a1 = 1+5
    ? !a1    a=8
    ? a1=8  a1=3

    Conditions also support expression logical operators "<" ">" "<=" ">=", "=", "!=". Math operators has higher priority on logical operators.

    Operators or and and replaced with symbols | and &. Square brackets is used to order logical operations.

    To call multiple operations after the condition is used square brackets "[" "]" to create a new scope.

    a1=1 a2=2
    ? a2>a1           [a1=5 a2=3]
    ? a1&[a2|a1]      a1=10
    ? a1+a2 & a1-a2   a1=a1+a2 : a1=15 

    If statement can return value.

    a1=15   a2=10
    a3 = ? a1>a2 a1 : a2
    
    arr = [1 2 3 4 5 6 5 4 3]
    i max = arr 0
    arr\max= ?.>max .:max 

    Lambda, Functions and Other Iterators

    Function (lambda) can be declared using symbol [\]. Depends on the command before the symbol - function can have different behaviors.

    Range Iterator

    Range iterator is similar to the command [for] in many languages. If the left part of [\] operator is integer [n] - function will iterate [n] times. [n] can be compile time constant or runtime value.

    i a=0
    10\a=a+1
    
    i range = 100
    range\a=a+2

    If iterator returns value - result will be array of this values.

    i a = 10
    array=10\a*a

    The code below can be read like 'ten times one' and 'ten times two'.

    i`10 array
    array = 10\1
    i` list = 10\2

    Iterator Index

    The command index defined by symbol #. It will return current iteration index, counting from zero.

    a=[1 2 3]
    idxsum=0
    a\ idxsum = idxsum + #

    Named Lambda

    Function can has input or output values, depends on declaration. Function with output must have return type before [\]. But if result can be defined automatically - you don't need to write output type.

    For input values - types and names for every input parameter before output type or [\] if there is no output. Functions must be declared before its calling.

    The code below shows functions [func1] without any parameters; [func2] with input; [func3] with output; [func4] with input and output parameters; [func5] with auto output.

    All variables from the parent function can be accessed from the lambda.

    i a=0
    func1\ a=a+1
    func2 i b1\ a=a+b1
    func3 i\ a+2
    func4 i b1 i b2 i\ b1+b2
    func5 \ 2*a

    Then, you can call this functions. Parameters for a function goes after the name without any separators.

    func1
    func2 5
    i r3= func3
    i r4 = func4 5 5
    i r5 = func5 

    Functions

    To return value from a function, you need to use operator [;].

    To declare complex body for a function - use square brackets '[' ']'. This function has closed scope.

    fun d in1 d in2 d[
    d result = in1 + in2
    ;result
    ]
    //fun 1. 2. 

    To open the scope and get access to a parent scope values - use [\] before '['. Same for a range operators. Range or iterator lambda functions will call immediately. Named [lambda] function calls by name.

    val1=0
    val2=0
    
         lambda\[val1=val1+1    val2=2*val1]
    
    100\[
      val1 = val2 + val1
      val2 = val1 - val2
    ]
    
    lambda 

    Scopes

    Lambda operations execute in the current scope. So, if there is new variable is declared, variable will visible from the parent scope.

    To create new scope without named function, just use square brackets in current scope. This is equal to (()=>{})() in JS. Closed scope can access its parent scope variables, but its own new variables are closed to its parent.

    a1 = [ 1 2 3 ]
    a1\last=.
    //last
    [
       i unique = 5 * last
       a1 = a1 + unique
    ]
    a1\[
      unique = 6 * .
      . = unique
    ]
    d unique = 1.5

    Classes

    Classes in the language is very similar to a functional classes in JS. Every closed function without return can be used as a class through the assign operator "=". Calling this function through assigning will return you object of this function, that can be used as a class object. Using class name as parameter with same required type also will create an object.

    Command do or symbol comma [,] is used to call inner function. (Dot symbol cannot be used because of "this" command makes it ambiguous.)

    engine [ d power=5. ]
    
    car engine` engines [ 
       d speed=0.
       go[
         engines\speed=speed+.,power
       ]
    ]
    
    c1 = car [engine]
    c2 = car [engine]
    c1,go 

    Self

    To access this class object from the iterator or function, here is operator "self" or double dot [..]. Every this points to its current scope, but [..] points to the root scope. To make some scope a root - it is needed to add [.] after the function name.

    car. i speed [
      go[ 
         speed=speed+5
         self = ..
         ;self
      ]
    ]
    c1 = car 10
    c1,go,go,go,go 

    Import

    Import is using to add C code in to the language code or another with symbol @. After the import, file name needs to define the language code for using. Imports are the most uncompleted part of the language.

    @console.c [
       console [
           write s input []
           read s []
       ]
    ]

    Comments

    Popular posts from this blog

    Техно-анархизм