Chraki as a programming language is a peculiar beast. It is based on tried and true computer science theories and techniques, but at the same time, it isn’t afraid to step “out of line” and do things a little different, like for example have multi-value logic.

You might notice that there is no post dedicated to Chraki as an actual syntactic and grammatical language yet. We currently go straight from the (proposed) writing system to programming. That’s not very logical, however, because without a specification of syntax or grammar, any kind of mechanical processing over a language is impossible.

That is why this post, for now, talks about the foundational concepts that are to help shape the future of the Chraki language as a technical/programming language.

Programming: A Formal Technical Language

That being said, some general ideas and projections have been made that are being explored, as well as some foundational concepts to guide development. These include multi-value logic (and virtual machine), ultimate-stack development, ubiquitous abstraction, and meta-augmentation.

Ultimate-Stack Development And Ubiquitous Abstraction

Most programming languages out there serve a particular function/niche (even when they are ultimately “complete” in the sense that you can use them for general purposes). Their design choices (syntax, instructions, capabilities, abstraction) are determined by their role in a given context that defines this function/niche.

Generations Of Programming Languages

For example, PHP is meant to be executed on a (web) server offering up files pertinent to the web (HTML documents). For this reason, it’s relatively easy to use PHP to query a database and use that information to construct an HTML document with the result. It becomes much more tricky to use PHP as its own socket server run as a daemon on the command line or to manipulate large amounts of binary data on a bit by bit level. In other words, you would most likely encounter difficulties trying to create an operating system with it as opposed to a language like C.

So you can then see the evolution and progress of programming languages: we go from machine code (specific processor instructions) to assembly, and from assembly to something like C, and even further from C to something like PHP or Python. You’d be astute to notice that we advance from fine exacting hardware details to higher levels of abstraction and expressive power as we progress. This is often referred to as a programming language’s “level of abstraction” or “generation” (i.e. first-generation language as opposed to fourth-generation language.)

An Esoteric Pain

When you combine various computational resources that are each devoted to various levels of abstraction, you form what is often referred to as a “stack.” It’s called such because each component stacks on the others. For instance, the LAMP Stack is composed of Linux as an operating system, upon which Apache runs to serve web pages, which invokes PHP to process data, which uses MySQL to store and collate data. There are multitudinous stacks, even in programming (from above): machine-code to assembly to C to PHP as an example.

In my view, this introduces unnecessary components. Each layer of the stack is ordered and maintained in a particular domain and with a particular syntax. Composing in C is entirely different in many respects than constructing in Assembly, and writing Python or PHP is quite different in many respects from creating in C. Doing things in MySQL requires a very different syntax than C, and shares nothing functional in common.

That’s not necessarily bad, as these domain-specific languages (assembly, C++, Python, SQL, etc.) are engineered in such a way as to be efficient and useful for what they accomplish. What does C really have in common with an SQL query after all?

However, as a programmer, I now run into the issue that for every piece of differing technology I want to use (SQL, C, R, Prolog, Lisp, and so on) I have to essentially (re-)learn a whole new environment, syntax, grammar, and set of models/design patterns in order to use it. Just to author a website from the ground up I must be fluent enough in an Operating System (OS), Apache/HTTP (webserver), HTML, CSS, JavaScript (browser-side), and a language like PHP or Python (server-side). Sometimes we can bring over concepts we’ve learned before (object-orientation, if-clauses, for loops, etc.), but arbitrarily, sometimes we can’t. What an esoteric pain!

This phenomenon also leads to programmers having to re-invent the wheel often for each various niche or technology.

The Ultimate Stack

In light of this intellectual pain, I’ve asked, “What if I could just learn one basic foundation, and then build up from there. That way everything would be connected and consistent?” Thus, the first idea for Chraki as a programming language was born.

The idea is generally: create a basic complete operational foundation that can theoretically compute anything (simplistically known as Turing complete) and then use those blocks to create the next layer of abstraction in such a way that they are not wholly disconnected, but instead complementary; then continue to do this over and over again maintaining those connections. In this way, the knowledge of how the system works at its lowest levels informs the engineer as to how to use the higher levels (and is still accessible); on top of that, the engineer can use the lower levels to implement and construct new interconnected higher levels.

This means essentially that you can use one, and just one, programming language (environment/methodology/meta-paradigm) for any level of abstraction without having to add/substitute in random disconnected arbitrary components for new functionality. This is what I call “the Ultimate Stack,” or “Ubiquitous Abstraction.”

Language On Language: Meta-Augmentation

So, how would one accomplish something like this? Don’t new functionalities/paradigms need new syntactic and grammatical structures quite particular to their purposes? How would one paradigm co-exist with another? How would one even “build” a computational paradigm?

These are very heady questions, but ones for which I do ultimately have answers.

The first thing we have to do is realize that if we’re going to have a programming language or foundation that can be “turned into anything,” without supporting (random) technologies then we’re going to have to have some way of doing the ultimate bootstrap. Bootstrapping is typically when a programmer implements a compiler/interpreter (for more info on compilers see the next section, “A Virtual Machine.”) for a language in that very language, thus enabling him to augment or edit the mechanics of that language using itself.

If we’re going to do what I’m proposing though, we need something more than just a self-modifiable compiler. Using only that approach I can see the project quickly becoming a monolithic construction akin to a swiss army knife, with so much inorganic complexity and toggle switches that it’s unusable. Every new “feature” or “addendum” would be glued on to the amorphous mass in some official way, which gets in the way of a programmer just doing it themselves. I only foresee organizational nightmares, and I don’t want to do that.

Self-Modifying Language = Architecture = Language

What I’m looking for instead is a construction that can modify itself while it executes, that is, in run-time. This means that it would be an interpretive system that, while interpreting various structures can alter how it understands or interprets those structures. In theory, it could then be extended with new functionality, models, and grammars on the fly using basic foundational (axiomatic) instructions/structures.

To this end, I’m interested in developing an architecture that very much can do the same thing from the ground up. An architecture that can augment itself at run-time is the perfect bed for a language that can modify itself. Imagine, if you would, what could be possible if you could actually alter/augment the very mechanics of the machine you’re executing on? All of this, while still only using one fundamental programming language, instead of seven.

This may sound scary, or even horrific, at first, but… if you think about it, isn’t that essentially what we’re always doing as programmers? We’re constantly using a foundation (the programming language/processor) to create new functionality, new verbs, new actions, new models in our programs all the time. We just don’t necessarily always think of them as a “new language feature,” but instead simply as “functions,” “methods,” or “data structures.” In reality, however, we are constantly constructing a “new programming language/environment” to some degree just by creating a new program.

This notion of architecture does bring us to our next topic though, which is the question of what something like this would run on? Well, the answer is…

A Virtual Machine

Right off the bat, I propose that Chraki is designed for a virtual machine. For those unfamiliar with the term, I shall explain the concept of the virtual machine from the beginning.

The Traditional Programming Model

All modern computational machines are operated by specifying an exact sequence of instructions from a specific finite set. Each machine, or processor, will have its own specific set of instructions (even if it is similar to others or a standard.) This is often referred to as a (or part of a) architecture. Traditionally, computer programming is done in the following way: write a program (in a language), compile that program (using a program that translates it into instructions known as machine code), execute those specific instructions on the hardware (processor).

This process makes it possible to write a program (in a programming language) in such a way that it can be compiled down to multiple different architectures. However, the reverse does not hold: we can’t take the compiled instructions from one machine and expect them to run on any other arbitrary machine, since their instruction sets may not match. Likewise, for each new architecture to compile for, the original program may have to be slightly modified to make sure it “fits” (or written in such a way that it only uses a subset of all available instructions.)

Abstracting That Model For Increased Flexibility

This has been mitigated in the past by employing “interpreters” and “virtual machines.” An interpreter is like a compiler, however, instead of producing exact machine code it simply instructs the computer to immediately execute the instructions. In this way, we can write one program to a specific standard, and have it be able to be processed on any machine to which we’ve ported an interpreter.

A virtual machine takes it one step further, and instead of defining an abstract (away from the specifics of the hardware) language, it defines an abstract (as in no hardware) computational machine with its own instruction set. This abstract machine may exist in reality, in which case we will be emulating that machine on another, or it may be purely imaginary (like the Java Virtual Machine.) We then write an interpreter that translates sets of instructions for this abstract machine into “real” instructions for the given processor.

A virtual machine moves the abstraction from a specific language definition to a whole machine definition. This allows us to theoretically have even more freedom than a language interpreter: we can write multiple different programming languages for this hypothetical machine, and as long as our interpreter runs on a particular architecture, it’ll run those programs too.

The Meta-Virtual Machine

Going back to what I was speaking about before, we are presented with not only the idea of a self-modifying language but of a complete self-modifying architecture! We march forward with little regard here for physical capability (we’re not as concerned about that here, but it could be possible with Field-Programmable Gate Array-like technology) precisely because we’re designing a virtual machine. It only has to exist in our minds, and in our software, and because of this, it is possible.

It’s not necessarily as difficult as one might presume off hand. This is because, in one form or another, we must compose the software that implements this virtual machine for some architecture at some point. If we can construct it in such a way that its operation can be modified by the code it’s running (through extension like architectures, plugins, hooks, meta-languages) then we’re good to go!

Before we get too gung-ho though, we should take a step back. My focus here is on implementing a programming language, and not necessarily a fancy hardware doo-dad. Wouldn’t it somewhat break the idea of being able to use one language at every level of abstraction if we had to specify the virtual machine’s operation in a different language?

Yes, it would.

Thus, we enter into the twilight frontier of Chraki as a programming language: the process of defining a language that not only follows the organizational guidelines of its natural counterpart but is also able to specify computations (and their models) from the ground up extensively. This is not an easy or light task as we might have painted three paragraphs ago, but this is what I’m intending to do. If this task interests you in any way please take a moment to register an account, join us on the Forum, and even perhaps contribute to the Encyclopaedia.

Multi-Valued Logic, Particularly Ternary

Traditionally, electrically-based computational machines have operated on a system known as binary. It’s definition, from Wikipedia, is:

In mathematics and digital electronics, a binary number is a number expressed in the base-2 numeral system or binary numeral system, which uses only two symbols: typically “0” (zero) and “1” (one).

The base-2 numeral system is a positional notation with a radix of 2. Each digit is referred to as a bit. Because of its straightforward implementation in digital electronic circuitry using logic gates, the binary system is used by almost all modern computers and computer-based devices.

A Physical-Mathematical Tradition

This adherence to binary has been due to a number of factors. The largest factor has been the laws of physics and the available hardware, while tradition garners a close second. In electrically-based computational machines, we use electricity to represent values/symbols. Electricity essentially has two major states corresponding to its nature: a positive state (or charge), and a negative state (or charge). The most basic stripped-down method for representing values with electricity then is to distinguish between an “on” state (one charge) and an “off” state (the opposite charge.)

You can’t only have abstract states to store values, one must be able to do something with them predictably. Computers these days often used what is known as a field-effect transistor (or FET) to actually “process” these values. The idea is that an FET only allows current to pass through it (go from the source to the drain) if there is a current on it. This allows us to construct what is known as a binary switch. Using combinations of various types of these switches we can build an entire microprocessor capable of “switching” around binary with incredible speed and power.

The trouble is that, currently, differentiating any more than between two states (on and off) is difficult. You’d think that one might be able to assign various values to say various voltages or something, but that has proved unstable. Even modern central processing units (or CPUs) can have difficulty differentiating between only two states.

But, Is It Arbitrary?

There are some who seem to operate under the impression that binary is the best and most efficient way to represent values and computations, but I believe they have been unduly influenced by the prevalence of binary and the ease of its representation. Granted, it is much easier to distinguish between two states (on and off) in any system, but simply because something is easiest doesn’t make it the best.

There are new technologies coming out these days that suggest that binary doesn’t HAVE to be the only system. Photonic processors and quantum processors (or perhaps even biological processors) may very well have the ability in the future to store three or even more states reliably. As these technologies become more stable and viable, the choice to use binary becomes more and more a matter of simple tradition.

I believe there are benefits to using a multi-valued logic (particularly a ternary or even one with a radix of four) in a computational system. It has been shown that if we were to use a radix of three we would be able to store information in perhaps the most efficient manner (this is known as radix economy). It has also been proposed that a ternary logic system could achieve mathematical operation processing more efficiently than with our current binary system (see below.)

Is It Really Better?

Would using ternary, or even a radix of four (quadenary?), actually be theoretically better than using binary?

I believe the answer to this is a definite yes. Let’s examine two examples of advantages that cop up immediately: radix economy, and arithmetic calculations.

Radix Economy

When I consult Wikipedia, it gives me the following formula for radix economy with the explanation: The radix economy E(b,N) for any particular number N in a given base b is defined as:

E(b,N)=b\lfloor \log _{b}(N)+1\rfloor

The above was generated using the LaTeX code: E(b,N)=b\lfloor \log _{b}(N)+1\rfloor

For those who may be a little less mathematically inclined, I shall explain. First, you must understand that a base is the maximum value we can “count up to” for a given value placement in a number. For example, base 10 (otherwise known as decimal, which is what we’re used to) allows me to count from the number zero (0) to the number nine (9) for any given digit/value placement. Binary (as above) on the other hand, being base 2, only allows me to count from the number zero (0) to the number one (1). Thus, a decimal number like 123 in binary would be 1111011.

A logarithm done to a particular base (known as logbase) handily gives us about the number of digits or places required to represent a number. This is because, technically, a logarithm is the exponent to which the base must be raised to produce a given number. Thus, log2 will give the required exponent of two, which is also approximately the required number of digits. You can see: log2(5) = 2.321928 (1013 digits), and inside the equation above floor(log2(5)+1) = 3.

The key here is multiplying the number of digits we get by the base itself. The idea is that each digit “costs” a certain amount to record, and that cost is the number of values that digit could be (being more information.) If we multiply the number of required digits by the radix b we get that ultimate cost and are thus able to measure efficiency (lower cost versus higher cost.)

Exploring Radix Economy Further

So let’s play around with that a little bit. Let’s take the decimal number 123 again. That has a radix economy [ E(10,123) ] of 30 (10 x 3), whereas in binary [ 1111011 ] it has a cost of 14 (2 x 7), and in ternary [ 11120 ] it has a cost of 15 (3 x 5).

You might notice that in that specific case the ternary base is actually not as efficient as the binary base. This example is somewhat counterintuitive, but it forces me to show the math (as taken from Wikipedia) that is involved in determining that, overall, a ternary value system (base three) is more efficient. First, we must observe the asymptotic behavior of the above radix economy equation:

{\displaystyle E(b,N)=b\lfloor \log _{b}(N)+1\rfloor \approx b\ \log _{b}(N)={b \over \ln(b)}\ln(N)}

{\displaystyle {E(b,N) \over \ln(N)}\approx {b \over \ln(b)}}

The code for the above is: {\displaystyle E(b,N)=b\lfloor \log {b}(N)+1\rfloor \approx b\ \log {b}(N)={b \over \ln(b)}\ln(N)} and {\displaystyle {E(b,N) \over \ln(N)}\approx {b \over \ln(b)}}

Thus, if we consider that in the following equation, the minimum for x > 1 is e:

y={\frac {x}{\ln(x)}}

The code for the above is: y={\frac {x}{\ln(x)}}

We can then consider:

{\displaystyle {E(b,N)}\approx {b\ {\log _{b}(N)}}={b{\ln(N) \over \ln(b)}}}

The code for the above is: {\displaystyle {E(b,N)}\approx {b\ {\log _{b}(N)}}={b{\ln(N) \over \ln(b)}}}

I did not come up with these equations, I am reproducing them from Wikipedia, which at the end of this process states:

Then for a constant N, E(b,N) will have a minimum at e for the same reason y does, meaning e is therefore the base with the lowest average radix economy. Since 2 / ln(2) ≈ 2.89 and 3 / ln(3) ≈ 2.73, it follows that 3 is the integer base with the lowest average radix economy.

The math now used to demonstrate this conclusion is unfortunately beyond the initial equation explanation I supplied. I feel at this moment it’s beyond the scope of this article (and besides this is mostly a reproduction of the Wikipedia article.) For more information on how it can be shown that ternary, or base three, is more efficient than binary please refer to the Radix Economy Wikipedia Article from which this information was reproduced.

Ternary Arithmetic Calculations

In 1958 some enterprising individuals in the Soviet Union named Sergei Sobolev and Nikolay Brusentsov built what was to become known as Setun (Сетунь in Russian). It was a computing machine based on the concept known as balanced ternary, which is a non-standard base three numerical system. The idea is that a value in balanced ternary is either +1, 0, or -1, and that you can determine it’s place value by multiplying its value by the appropriate power of three.

This system gave Сетунь some interesting computational advantages over a traditional binary computer. By maintaining the consistency of the positive-negative system, one is able to cut down on the carry rate in multi-digit multiplication as well as other advantages such as cutting down the carry rate in rounding on fractions and incurring no carries in one digit multiplication. Likewise, the representation for integers is self-contained and the arbitrary distinctions between signed and unsigned values (something a programmer traditionally has to keep track of himself) need not be made. This allows us to eliminate the need to duplicate operator sets… (See Balanced Ternary on Wikipedia)

You might note that when a replacement binary computer later took the place of Сетунь it had 2.5 times the cost of operation.

Proposed Chraki Ternary

With these possible advantages in mind, and with the hope they can be employed and even furthered, I propose an interesting system that could be used in a Chraki virtual machine (see above.) The basic idea is that we have four states, so a radix of four, but we only use three of the states for information processing and one of the states as a sort of pseudo-instruction/format. These states would be alpha, beta, gamma, and stop (or omega).

The first three states could then make up a ternary value in any of the possible ternary systems (balanced or not, etc), while the fourth would indicate to the virtual machine a termination of some sort. This could be a termination in instruction, in a file, in a calculation, or whatever the programmer might assign. For example, alpha, beta, and gamma could be mapped to +1, 0, -1 for balanced ternary operations.

I imagine this capability would go down to the hardware level (if the hardware would allow), meaning that the very virtual machine itself would operate under ternary. This allows us to not only have the most possibly efficient storage, but also incredible potential logical expression.

In binary, there are 4 (22) unary (single argument) operators, and 16 (22×2) binary (two arguments) operations. In ternary, there are 27 (33) unary operators and a whopping 19,683 (33×3) possible binary operations. This incredible number of potential ways to process data should be able to afford us incredible logical expressiveness and efficiency if engineered carefully.

Conclusion And Looking Forward

As you can see I may very well have my work cut out for me in the development of Chraki as a programming language. Its design immediately begins to question and rebel against what might be considered the status quo (uniformity for disciplined design, binary, etc.) That is alright with me though, as I hope Chraki as a programming language to possibly breach new frontiers.

It is my hope that I, and hopefully also contributors, can maintain a clarity of vision while designing the very basic core foundations of the system. It may be intellectually difficult as I am proposing a hardware/language link that before now I don’t believe has been properly entertained. In terms of moving forward, I’m hoping that I can arrive at some kind of self-augmenting system that stays true not only to the organization of Chraki as a natural language but is also expressive enough to be able to build further abstractions while still being “physically” viable.

I believe the first/second step is going to be determining what kind of abstract structure the virtual machine will have, informed by research into the current state and practices of virtual machines and by the hardware/language link, and then implement that architecture in a traditional language such as C, or even a scripting language such as Python or JavaScript. This essentially comes down to building an interpreter/compiler for a particular conception of bytecode.

Developing this language/machine/bytecode will be my first project on the programming side. Until then, if you are interested at all in what I’ve laid out here please don’t hesitate to register an account and join us on the Forum, and maybe even contribute to the Encyclopaedia.

Photo by Fabian Grohs on Unsplash