The need to develop a new language, and not to copy the syntax of any of the existing common programming languages, is due to a kind of original concept, which we will talk about today. In our opinion, the process of creating and implementing the concept of a new language is itself a fascinating and informative story for everyone who is interested in the pragmatics of languages.
We assume that in order to understand the presented material, the reader is familiar with the syntax and semantics of several common general-purpose programming languages.
Don't bite my finger, look where I am pointing
Warren S. McCulloch, 1960s
Initial statement of the problem
Initially, we set the task of implementing the technology of autonomous generation of interactive tasks for the development of human intelligence, which will be adaptive to his successes and failures. That is, if a person successfully solves a sequence of puzzles and is effective in playing games, then this technology rebuilds its algorithms so that a person can solve puzzles with new, more complex conditions and unpredictable versions of games that are never exactly repeated. In case of failure, this technology returns a person to already familiar positions in order to restructure the program of his abilities and readiness to carry out a new intellectual ascent. At its core, the adaptive program does the same job here as an experienced personal trainer in sports.
In general, with some restrictions, this task was solved back in 2018 by the Helius' application - full of life , which can be found in the App Store .
In the process of implementing the Helius' concept, we realized that in order to take the next step and implement a fundamentally new class of adaptive application that would be able to completely transform its architecture, adapting to human abilities, we need a built-in algorithmic scripting language, the listing of which can be is equally successfully generated in text form by both the application itself and by a person, or can be modified by a person or another program based on the provided code as an initial prototype.
We formed the main requirements and quickly concluded that a concept focused on expressing the creative needs of a developer is not very well modeled in any of the common languages, because our goal, with some degree of joke, is programming people, not computers.
Since it is equally “convenient” for a well-designed intellectual system to generate the syntax of any consistent language in any form, in order to use the language of communication between “artificial” and “natural” intelligence, it is logical to use the traditional algorithmic code, making it as convenient as possible for human thinking patterns familiar with mainstream languages, whose ancestor was Algol. They are descendants of Pascal (Ada, Modula) and C (C ++, Java, Swift). However, our concept of constructing abstractions and attention to parentheses are close to the spirit of Scheme (Lisp), and the integration of programming environment commands into the expressive means of the language corresponds to the ideas of scripting languages, vintage BASIC for the first microcomputers and the Oberon project - Niklaus Wirth's system.
Our original goal also includes providing a simple and convenient algorithmic language for quickly programming mind games and puzzles with a novice developer learning curve of one to two hours. At the same time, we fundamentally left aside the visual design of application objects in the spirit of Scratch or the prototyping of games in the script and visual editors. In our opinion, this distracts from creativity and expression of one's own ideas, because creative efforts are rather replaced by painstaking study and transformation of [graphic] objects. We propose in the future to provide this work as training for algorithms for intelligent agents.
As a result, we will formulate the purpose of the language asexchange of algorithms between artificial and natural intelligence, joint programming of tasks (games and puzzles) for oneself and others, free exchange of program texts.
Hi world
Before we discuss the main points for constructing the syntax of the language, we present three short code snippets. Let's start with the traditional welcome message program:
PRINT “Hello world!”
We see that our language has a scripting character, assuming fast interpretation; the print command is in uppercase and the builtin function argument is not followed by parentheses here.
Let's present two more interesting examples: finding the greatest common divisor for two integers in the imperative style and using recursion:
FUN gcd
INPUT a: INT
INPUT b: INT
WHILE a ~= b LOOP
IF a > b THEN a -= b ELSE b -= a ENDIF
REPEAT
PRINT “gcd = “, a
RETURN
FUN gcd _ a: INT, _ b: INT -> INT
IF b == 0 THEN RETURN a ENDIF
RETURN gcd b, (a % b)
PRINT gcd 6, 9
# 3
Hi language requirements
Every successful language is designed with a specific purpose, which determines its syntactic features and semantics. For example, ASSEMBLER was designed to directly encode processor instructions in a human-friendly mnemonic form; BASIC (the one with line numbers and a GOTO statement) successfully continued the idea of ​​translating commands directly to a high-level interpreter. Hi programming language is intended to become the language of commands and algorithms for communication between the Human and the abstract intelligence of some designed system.
As a logical consequence, the program code is not the compiled machine code and not the bytecode of the virtual machine, but the source code(listing) including comments. Accordingly, the internal implementation of the code is not standardized in any way and is left to the discretion of the interpreter or compiler implementation.
So our main goal is to exchange thoughts using formal language. Let's introduce three main requirements:
- The language should be easy for a person to learn
- The language must be reliable to use
- The language must be capable of organizing very complex software systems.
Let's explore these basic requirements in more detail.
The language should be easy to learn
1) We will use easy-to-read syntactic writing that is familiar to any modern educated person. We will avoid experimenting with brevity to the detriment of reading, as is done, for example, in the APL language.
Hence, we use constructs of the kind
LOOP…REPEAT
rather than {…}
. As a nice bonus, we will use curly braces like this:
s = {1, 2, 3}
we will denote the assignment of the variable s to a set of three integers.
a = [1, 2, 3]
we will denote the assignment of the variable a to an array of three integers.
The use of well-thought out concise language constructs also allows you to make a more logical connection between the semantics and syntax of the language without using the context of the environment. We will discuss this thesis in more detail later when we consider specific language constructs.
2) For arithmetic expressions, we use a notation of the form:,
a + b + c
and not (+ a b c)
, as in the LISP family.
3) The nature of our scripting language requires a built-in library of all the necessary functions in the language environment without the need for external frameworks.
4) We use native algorithms for thinking patterns: an imperative language with the possibility of recursive functions and elements of functional calculations. As we will further consider using one of the examples, the imperative style is quite convenient for programming applications based on the architecture of event handling in a declarative manner, like SwiftUI. In other words, the terms "imperative" and "declarative" rather reflect the position of the observer than the reality given to us in a sense.
5) We monitor the absence of redundancy of syntactic structures and the ergonomics of entering code characters. We use a newline as a separator. However, as in Swift, you can use ";" on one line as a delimiter for multiple expressions. At the same time, our engineering education strongly protests against giving syntactic significance to indentation in the program text, as it was previously used in Fortran, and now in Python.
Reliable language
A necessary condition for the existence of complex systems in time is the requirement for complete semantic uniqueness and feasibility of each correctly written program without corrections in the event of inevitable evolution and complication of the language in the future. How to solve this problem of program reliability in case of its inevitable development and expansion? In order to avoid the conflict of coincidence of identifiers and reserved words, we use a simple and effective way, as is done, for example, in Oberon. The HI language reserves all identifiers with uppercase letters without numbers and more than one character as service ones . Thus, the following examples are valid identifiers written by hand by a programmer or generated by an intelligent system:
foo, Foo, f_001, F1, F, for
Examples of identifiers that are reserved by the language:
FOO, FOR, HI, YES, EVERYRESTRICTIONMATTER
For the sake of code reliability, we use static typing with the ability to automatically deduce types from declarations of the form:
LET x = 6 # x INT
VAR boolean = TRUE # boolean BOOL
We distinguish between constants and variables not to optimize code execution time, but so that the developer has a good understanding of the purpose of the objects that he controls.
A language for building very complex software systems
The architecture of any universal language should provide for a thoughtful possibility of building complex programs from small autonomous pieces, say, up to 250 LOCs in one source, for, forgive us, dear Reader, only a scanner and a parser can easily work with source texts of any complexity, and a person can even multiply a couple of three-digit whole numbers is hard without a calculator.
For now, we will leave aside the implementation of the architecture of complex systems in the Hi language and will analyze these issues in detail in the future when presenting the concept of organizing classes - protocols, communication between them and methods of constructing their hierarchy. We only note that the architecture of complex applications will be built from small autonomous, easily readable and modifiable fragments, and we drew inspiration here not from the study of computer science, but from the architecture of the interaction of cells and organs of living organisms. The body of an ordinary person is about 50 trillion viable cells that function successfully despite difficult environmental conditions, the presence of many parasites and permanent damage to millions of microcomponents. The creator of a computer system,which completely ceases to function due to a single call to a nonexistent array index, there is a lot to learn here.
Although we start by describing a scripting language that is convenient for quick and pleasant programming of small puzzles, we must give full confidence to developers that on the platform of once developed simple software components without the use of third-party solutions in the future they can build viable systems of unlimited complexity.
Limitations
In practice, whenever we apply any requirements for the design of systems, then we have to either sacrifice something or not pay attention to something. For us, in the construction of the Hi language, it is not of fundamental importance:
- Exact syntax compatibility with other programming languages
- Ability to use existing external code libraries or integrate with other software systems
- c n-
- /
- — ,
In conclusion, let's say about the origin of the friendly name of the programming language HI, Hi or hi. Let it be H elius' i nteractive Programming Language or H uman I ntelligence Programming Language. Unlike all constructions in our language, this is the only meta - identifier that has no unambiguous semantics.
In the next article, we will present the description of Hi Basic Programming Language "on one" page and then analyze the syntax construction logic, following the requirements of the theses presented above.