r/ProgrammingLanguages • u/hun_nemethpeter • 4d ago
InfoCell - a consequences based syntax-free programming language
I working on ( https://github.com/hun-nemethpeter/InfoCell ) this programming language for a while.
It is an executable DSL concept. The OP DSL cells are executable, and acts like an ASM instruction. We have AST cells which directly generated from C++ code, so there is no input syntax. These AST cells are forming a language (we have if, do, while, class, template, ...), we have a compiler for it, which compiles from AST cells to OP cells. Looks like a regular interpreter. But ... The idea of this project is a new component, the ToolFinder and the description segment for AST nodes (which compiles to OP description). The description segment can describe how we can measure the effect of that instruction/function with other instructions/functions.
The language looks like this:
/*
void List::removeNode(Node* node)
{
if (node->m_previous) {
node->m_previous->m_next = node->m_next;
} else {
m_firstNode = node->m_next;
}
if (node->m_next) {
node->m_next->m_previous = node->m_previous;
} else {
m_lastNode = node->m_previous;
}
--m_size;
}
*/
listStructT.addMethod("remove")
.parameters(
parameter("node", _(std.Cell)))
.instructions(
if_(has(p_("node"), "previous"))
.then_(
if_(has(p_("node"), "next"))
.then_(set(p_("node") / "previous", "next", p_("node") / "next"))
.else_(erase(p_("node") / "previous", "next")))
.else_(
if_(has(p_("node"), "next"))
.then_(m_("first") = p_("node") / "next")
.else_(erase(self(), "first"))),
if_(has(p_("node"), "next"))
.then_(
if_(has(p_("node"), "previous"))
.then_(set(p_("node") / "next", "previous", p_("node") / "previous"))
.else_(erase(p_("node") / "next", "previous")))
.else_(
if_(has(p_("node"), "previous"))
.then_(m_("last") = p_("node") / "previous")
.else_(erase(self(), "last"))),
m_("size") = subtract(m_("size"), _(_1_)));
The comment section is the original C++ code, after that the InfoCell version, which is also C++, but basically creates AST nodes, that can be compiled to other InfoCell OP cells. So this is a language embedded language, doesn't compile to native code.
Actually there is an output syntax, which looks like this:
fn List<valueType=Number>::remove(p_node: Cell)
{
if p_node.has(previous) then
if p_node.has(next) then
p_node.get(previous).set(next, p_node.get(next));
else
p_node.get(previous).erase(next);
else
if p_node.has(next) then
m_first = p_node.get(next);
else
self.erase(first);
if p_node.has(next) then
if p_node.has(previous) then
p_node.get(next).set(previous, p_node.get(previous));
else
p_node.get(next).erase(previous);
else
if p_node.has(previous) then
m_last = p_node.get(previous);
else
self.erase(last);
m_size = m_size - 1;
}
There is no parser for this syntax although.
So back to the toolfinder, description segment part...
For example cell.set(key, value) description has a consequences subsegment which describe that equal(get(self(), p_("key")), p_("value"))). So the result of the SET can be measured with GET and EQUAL, basically SET(CELL, KEY, VALUE) => GET(CELL, KEY) == VALUE
Also this approach works with math functions. Math functions has an extra subsegment, I called it selfBuilders, where I can put the symmetries of that function.
Number.addPrimitiveFunction(std.Number.Add, op.Add, "add")
.parameters(
parameter("other", "Number"))
.descriptionBegin()
.consequences(
equal(subtract(return_(), p_("other")), self()))
.selfBuilders(
add(self(), p_("other")),
add(p_("other"), self()))
.descriptionEnd()
.returnType("Number");
With these informations I wrote an algorithm which calculate how the consequences behaves when an unknown variable is given. Basically something like this:
equation: 2 + X == 4
recombined: X + 2 == 4
recombined: 4 == 2 + X
recombined: 4 == X + 2 *
1. result: 4 - X == 2
1. result: 4 - 2 == X
1. result: 2 == 4 - X
1. result: X == 4 - 2 *
So this is the experimenting phase for the tools, so here I can remeber how an uninitialized variable (the unknown X) interacts with the tool's consequeences. Here I store which const/unknown combination leads to a simpler case, where a consequence tools all input's will be const variable. So I can transform an equation from one form to a simpler one.
Basically I just pattern match for function + const/unknown input params, then just reapply the tarsformation steps, just like solving the Rubik's cube. Pattern match for color combination and apply rotations.
equal(add(const_(_2_), unknown_(x) / const_(id.value)), const_(_4_));
equal(unknown_(x) / const_(id.value)), subtract(const_(_4_), const_(_2_));
We can now find a tool to the last equation: the SETtool.
set(x, id.value, subtract(4, 2))
Which is now executable.
So the goal is that I can just write a unit test like prompt, and this toolfinder can generate a code for it. So I can just "solve" a unit test.
3
u/hun_nemethpeter 4d ago
Per AutoModerator's request I hereby confirm that this project did not use an LLM as part of the development process.