None
Programmierung

Combining Programming with Ontologies

by Viktor Garske on Oct. 10, 2020, 10 p.m.
Today I'll present my newest project to you: a programming langauge which incorporates the imperative programming paradigm but extends it aspects of the logic programming paradigm.
Language icon Language: this article is available in: de

→ Quick access: working paper (PDF), GitHub repository

Programming is a very important tool today. During the last decades the focus has been changed: C started as a „portable assembler“ to abstract different target platforms. That was back the 1970s. Today is about combining different components to compose applications fulfilling requirements. But one thing remains until today: the imperative approach. In this paradigm, the programmer specifies every step to reach a desired state or result.

A look at the history

However, there are some problems that didn't need more attention in the past, but which make work much more difficult today: for example, in the 1980s, people could afford to develop the whole codebase themselves. Ken Thompson puts it in a nutshell: “You can't trust code that you did not totally create yourself.” This sentence is still valid today because imported code executes on the same level as your own one.

There are different programming languages that also serve different purposes: while the previously mentioned C works on the low level, there are languages like Python that abstract further and further.

This abstraction does not end here and this makes it particularly interesting. Actually, we are at level 3 of 5 for the imperative or procedural languages. Level 1 and 2 are machine code or assembly languages. The higher levels 4 and 5 contain SQL, the Unix shell and R (4GL) as well as Mercury and OPS5 (5GL). While most people are still familiar with some of the 4th generation languages, very few will have heard of Mercury or similar.

By the way, the goal of this abstraction is to describe only the problem to the computer and to let it find the solution itself.

When I heard about it a few years ago, it did keep preying on my mind. I started thinking about a solution located between system programming langauges like C, C++ or Rust and dynamic scripting langauges like Python. A solution where you can specify an abstract program with the support of high-quality components from a standard library which can be linked together. Just like the classic Unix philosophy, just on code-level.

Classification

A few months ago it became apparent that the idea could best be implemented in a (experimental) programming language.

XKCD 2309: X, License: CC BY-NC 2.5

xkcd 2309: X, License: CC BY-NC 2.5

But what is the special feature of language? The fifth generation of programming languages was very functional, declarative - and that might be unfamiliar for many developers. What about not replacing but extending imperative programming style with logical programming?

What is the project about?

I've started to develop a grammar for the Ontology-assisted Experimental Programming Language (OXPL).

The OXPL dives into the world of ontologies: roughly speaking, ontologies are about making knowledge accessible to the computer so that it can process it. This type of knowledge representation is present today already: Java class structures are a good example.

Java class hierarchy

Let me just briefly outline the key aspects: let's start with the "Hello world".

fn main() {
    println("hello, world");
}

As we can see, we are in the field of imperative programming - and this is a crucial aspect: you can use it as a fallback at any time. But now let's take the plunge: the following code block implements an addition: two summands are can be input and the result is output.

instance Summand1: integer {
    std::fetchesFrom <std::io::stdin>.
    <std::io::stdin> std::io::prompts "Summand 1: ".
}

instance Summand2: integer {
    std::fetchesFrom <std::io::stdin>.
    <std::io::stdin> std::io::prompts "Summand 2: ".
}

instance Sum: std::math::sum {
    std::math::sum::hasSummand <Summand1>.
    std::math::sum::hasSummand <Summand2>.
}

fn main() {
    println("The sum is " + string::from(Sum));
}

Here we see the most important feature of the language: the program is, except for the main function, only a description of two summands and a sum. The triples (subject - predicate - object - period) explicitly state the relations and requirements among each other. In the next step the interpreter or compiler is supposed to derive rules and a lot of information in order to create the executable. Even if Python would be able to solve this task in one line, the above example would already recognize the summands as integers by-design, so that bugs like a sum "11" of the summands 1 and 1 can be avoided.

The program creates this universe of discourse and states the following relations:

Visualization of the example program

Instances (singletons) are blue, classes are red, special built-in resources like the stdin are green.

Using logical rules, the interpreter and reasoner can now infer additional facts and relations. Thus, it automatically concludes that it needs to create two input procedures to calculate the sum which is queried in the main function.

Another aspect: security. Malicious side effects are a serious problem when importing third-party libraries. But what if all communication to the outside world has to be permitted by the developer? A calculation library requiring hard disk and network access will propably attract attention by the programmer. For the "hello world" example it would look like this (if enforced):

allows(this, std::io::print, main).        

fn main() {
    println("hello, world!");
}

The first line means that the program (root) allows the main resource/function to use the std::io::print permission which is needed in order to write to the stdout. You don't need to write this every time for the built-in printing features as they are trusted specially but you will be able to disable this behavior so that every communication of the program with the outside world has to be permitted.

OXPL will implement this permission system from the beginning, so that later improvements like with libseccomp are no longer necessary.

What is already done

I have already started to develop the ontology toolchain (ontc) as a sideproject. This will be the reference implementation. It is written in C and is already available on GitHub. ontc will contain an interpreter (later perhaps a LLVM compiler), a debugger and an analyzer which accelerates programming as it support developers with the ontology while writing the code. The ontc binary will be licensed under the GNU GPLv3, the underlying libraries for the execution and compilation of ontc programs (i.e. libontg and liboxpl, also included in the repository) will be licensed under the GNU LGPL v2.1.

You can build the application using:

sudo apt install build-essential git bison flex
git clone https://github.com/v-gar/ontc.git
make

The executable ontc is then located in the build directory. Now you can create a file called helloworld (I haven't defined a file extension yet) which contains the hello world program from above. You can execute it by running ./build/ontc run helloworld. To test the ontology there is the following example you can use:

fn hey() {
    println("Hey!");
}

fn main() {
    println("Hello world!");
}

<main> isPreceededBy <hey>.

This example shows, that these triples can be used to influence the program flow, if (like in the example) the interpreter considers certain predicates.

A starting point

These two examples are part of the proof of concept of this project. This is a starting point. Two things are crucial for the language: good development tools and a high-quality standard library covering many application fields. The standard library gives, similar to schema.org, the framework and defines how predicates are usually constructed, how to interact with the compiler, etc. The ontc should serve as a toolchain with a common codebase and contains an interpreter, debugger and analyzer to write good programs quickly.

If you like to read more about my project, you can have a look at my working paper (PDF).

Since this project is impossible to realize alone in the foreseeable future, I am looking for people who want to participate in this project. You can contact me via email!

Tags:
Author image
Viktor Garske

Viktor Garske ist der Hauptautor des Blogs und schreibt gerne über Technologie, Panorama sowie Tipps & Tricks.

Comments (0)

Comments are not enabled for this entry.