Vely logo what is  |  why  |  install  |  tutorials  |  examples  |  documentation  |  license  |  about
Current release 10.4.36 (Beta). This page last updated on Jul 01 2022

Language constructs



DESCRIPTION:


Vely construct (such as write-file or run-query etc.) is a declarative programming statement that can be written within C code in a file with .v extension and which is pre-processed by vv into C code, and then compiled into a native executable.

Vely constructs are the core of the language functionality. They are easy to follow and intuitive. Here's a formal description of what they are.

What are constructs


Vely constructs generally have three components separated by whitespace:

A construct starts with a name, which designates its main purpose. A subject argument denotes the subject of the purpose stated in the name. Each clause consist of a clause name, which specifies some aspect of the construct's purpose and it may be followed by no additional data, or it may be accompanied with one or more data arguments. A clause may have subclauses, which follow the same structure and are associated with the clause by appearing immediately after it.

A subject argument must immediately follow the construct's name, while clauses may be specified in any order, unless stated otherwise.

For example, in the following Vely code:

encrypt-data orig_data input-length 6 output-length define encrypted_len password "mypass" salt newsalt to define res binary

encrypt-data is the construct's name, and "orig_data" is its subject argument. The clauses are:

The clauses can be in any order (unless otherwise stated on rare occasions), so the above can be restated as:

encrypt-data orig_data to define res password "mypass" salt newsalt output-length define encrypted_len binary input-length 6

Vely documentation provides a concise BNF-like notation of how each construct works, which in case of encrypt-data is:

encrypt-data <data to encrypt> [input-length <input length>] password <password> [salt <salt>] [output-length [define] <output length>] [binary] to [define] <result>

Optional clauses are enclosed with angle brackets (i.e between "[" and "]"), and data arguments (in general C expressions) are stated between "<" and ">". If only one of a number of clauses may appear, such clauses are separated by "|", and each clause possibly enclosed with "(" and ")" if it consists of more than one keywords or arguments. Generally a clause continues until the next clause, which means until all subclauses and arguments are exhausted.

The most common subclause is an optional "define", which always precedes an output variable, i.e. a variable that stores (one of) the results of the constructs. If used, it creates such variable within the construct. It is commonly used to shorten the code written.

Keywords (other than construct names such as encrypt-data above) are generally specific to each construct (or a group of constructs in which they are used). So, keyword "salt", for example, has meaning only within encrypt-data construct, where it is used to specify the data for the "salt" clause. In order to have the complete freedom to choose your variable names so they don't clash with keywords, you can simply surround them (or the expressions in which they appear) in parenthesis (i.e. "(" and ")") and use any names you want, without worrying about keywords, for example:

const char *password = "some password";
const char *salt = "0123456789012345";
encrypt-data "some data" password (password) salt (salt) to define (define)
p-out define

In this example, keywords "password", "salt" and "define" are used as variable names as well; and in p-out construct, variable named "define" is used freely, even if it is a keyword for other constructs - but it is not for the p-out construct.

It is recommended to use supplied Vely constructs over your C code for the same functionality.

Note that while you can use tab characters at the beginning of the line (such as for indentation), as well as in string literals, do not use tabs in Vely code as they are not supported for lack of readability - use plain spaces.

Look and feel


Vely constructs have decidedly non-C look and feel, unlike what's common with typical API interface. This is by design. They stand out when reading code in a way that clearly communicates their purpose, with the intent of increased readability and more expressive and condensed functionality. On the other hand, Vely constructs are decidedly C, as they are completely integrated with C code and translate to pure C in the end.

Constructs in code blocks


Note that, Vely constructs, after translated into C code by vv, are generally made of multiple statements, hence Vely constructs can never be treated as single-line statements. Thus, for example, never write:

if (some condition) vely-construct

if (some condition)
    vely-construct

but rather, write:

if (some condition) {
    vely-construct
}

Vely will generally emit an error if you attempt to write constructs incorrectly.

Splitting construct into multiple lines


To split a construct into multiple lines (including string continuations), use a backslash (\), for instance:

encrypt-data orig_data input-length 6 \
    output-length define encrypted_len \
    password "my\
    pass" salt \
    newsalt to define res binary

Note that all constructs are always left-trimmed for whitespace. Thus the resulting string literal in the above example is "mypass", and not "my   pass", as the whitespaces prior to line starting with "pass" are trimmed first. Also, all construct are right-trimmed for white space, except if backslash is used at the end, in which case any spaces prior to backslash are conserved. For that reason, in the above example there is a space prior to a backslash where clauses need to be separated.

Code processing, error reporting, debugging


A construct is pre-processed into C code, which is then compiled into a native executable using gcc compiler. The final C code is a mix of your own code and generated Vely code. Error reporting by default shows line numbers in your .v source code files, which generally makes it easy to pinpoint an error. If you want to see generated C code and make error reporting refer to it, use "--c-lines" option of vv utility; this is useful if the error refers to details of generated code. You can also obtain the line number from .v source file, and then examine generated source code file by looking for #line directives. Generated final C file is located in:

/var/lib/vv/bld/<app name>/__<source file base name>.o.c

For instance if application name is "myapp" and source file is "mycode.v", then generated code is in file:

/var/lib/vv/bld/myapp/__mycode.o.c

If an error is reported as being on line 43 of file "mycode.v", then look for lines in the above .c file that look like:

#line 43 "mycode.v"

The code adjacent to those lines is the generated code for the Vely construct at line 43 in "mycode.v".

Vely will perform many sanity checks when possible while preprocessing your .v files, such as enforce the presence and count of required arguments in clauses, check if conflicting clauses are used, report imbalance of opening/closing clauses in statement that use them (such as for example write-string, read-line or with database_queries), reject unknown constructs, report incorrect usage of constructs and similar. However, most of the checking of your code is ultimately done by gcc (Linux C compiler), such as typing, expression syntax, C language correctness, linkage issues and others; in doing so, gcc will report the correct line number, as stated above (either a line number in your .v source file, or a generated C code file).

When debugging (such as with using gdb), stepping through your code is similar to error reporting: by default gdb will treat Vely construct as a "single-statement" and step over it as such. If you use "--c-lines" option, then you will be able to step through final C code.

This approach for error reporting and debugging provides an overall ease of finding errors in your code along with greater transparency into the final C code.

SEE ALSO:


Language ( dot   syntax_highlighting   inline_code   language_constructs   unused-var  )  SEE ALL (documentation)



Copyright (c) 2017-2022 DaSoftver LLC. Vely is a trademark of Dasoftver LLC. The software and information herein are provided "AS IS" and without any warranties or guarantees of any kind. This web page is licensed under CC-BY-SA-4.0.