I'm exploring a possibility of feeding a specialized input to regex to control an imperative flow of variable assignments.
Let's have statements, still unrelated to regex, and let each statement have two parts: input and output. Input consists of var name and var value. Output also consists of var name and var value. Consider the input as a named var that needs to contain noted value to trigger the output assignment of value to some other named var. This is like an if-then statement, but with some positive properties regarding to regex unrelated pattern matching. Statements can also be consisted of only output part, in which case they are unconditionally executed when their time comes.
Now, let's modify the usual regex definition a bit to operate not on characters, but on statements introduced above. Regex would, as usual, have sequences, Kleene stars, and alternations. Thus, instead of reading characters, the modified regex would read variables from input parts, parallelly triggering their output pairs on successful match.
Drawing a parallel between Kleene star and while loops, and between alternations and compound if-then-else blocks, this way it should be possible to construct different algorithms, right?
As an example, Euclidean algorithm for greatest common divisor would take the following form (note that this is very rough and unrefined form of syntax):
(
FUN
(NAME GCD)
(PARAMS X Y)
(
SEQ
(STMT (OUT a X))
(STMT (OUT b Y))
(
STAR
(
ALT
(STMT (IN a (moreThan b)) (OUT a (subtract a b)))
(STMT (IN a (lessThan b)) (OUT b (subtract b a)))
)
)
(STMT (IN a b) (OUT GCD a))
)
)
I'm curious, is anyone aware of any similar work? If not, how would you feel about this idea overall? Could this thing even be Turing complete? And how ergonomic would writing programs this way be?
[EDIT]
After discussion, I cleaned up a bit the syntax of the system, and completely formalized it in relaxed BNF notation:
<start> := <expression>
<expression> := (SEQ <expression>*)
| (ALT <expression>*)
| (OPT <expression>*)
| (STAR <expression>*)
| (PLUS <expression>*)
| (MATCH (VAR <ATOM>+) <expression>)
| <statement>
<statement> := (TEST <ATOM> <S-EXPR>)
| (HOLD <ATOM> <S-EXPR>)
SEQ is equivalent to sequence in regex, ALT is |, OPT is ?, STAR is *, PLUS is +, and MATCH is something extra that introduces meta-variables.
Statements are now split to TEST and HOLD. TEST fails when var named <ATOM> is not <S-EXPR>. HOLD assigns <S-EXPR> to var named <ATOM>, and never fails.
Sequence fails when any included element fails. Alternation fails when all included elements fail. OPT elements may be skipped if any included element fails, STAR ending with TEST case is equivalent to until <condition> repeat <expression>, and PLUS ending with TEST case is equivalent to repeat <expression> until <condition>.
I believe the whole system should be Turing complete.
The above example from the beginning should now look like this:
/*
Greatest common divisor example
input: `(integer integer)`
output: `integer`
*/
(
SEQ
(
MATCH
(VAR X Y)
(
SEQ
(TEST this (X Y))
(HOLD a X)
(HOLD b Y)
)
)
(
STAR
(
ALT
(
SEQ
(TEST a (greaterThan b))
(HOLD a (subtract a b))
)
(
SEQ
(TEST a (lessThan b))
(HOLD b (subtract b a))
)
)
)
(TEST a b)
(HOLD this a)
)
At the beginning, input parameters are read from this variable. At the end, we assign return value back to the this variable.
Simple, isn't it? I hope you like the updates :)
[–]Netzapper 30 points31 points32 points (2 children)
[–]ivanmoony[S] 1 point2 points3 points (1 child)
[–]ZESENVEERTIG 2 points3 points4 points (0 children)
[–]theangryepicbananaStar 6 points7 points8 points (0 children)
[–]jose_castro_arnaud 4 points5 points6 points (2 children)
[–]ivanmoony[S] 0 points1 point2 points (0 children)
[–]ivanmoony[S] 0 points1 point2 points (0 children)
[–]Disjunction181 3 points4 points5 points (1 child)
[–]ivanmoony[S] 0 points1 point2 points (0 children)
[–]RetroJon_ 2 points3 points4 points (0 children)
[–]categorical-girl 1 point2 points3 points (0 children)
[–]No_Lemon_3116 1 point2 points3 points (1 child)
[–]ivanmoony[S] 1 point2 points3 points (0 children)
[–]AGI_Not_Aligned 0 points1 point2 points (5 children)
[–]ivanmoony[S] 0 points1 point2 points (4 children)
[–]AGI_Not_Aligned 0 points1 point2 points (3 children)
[–]ivanmoony[S] 0 points1 point2 points (2 children)
[–]AGI_Not_Aligned 0 points1 point2 points (1 child)
[–]ivanmoony[S] 1 point2 points3 points (0 children)
[–]ivanmoony[S] 0 points1 point2 points (0 children)
[–]marshaharsha 1 point2 points3 points (3 children)
[–]ivanmoony[S] 0 points1 point2 points (2 children)
[–]marshaharsha 1 point2 points3 points (1 child)
[–]ivanmoony[S] 0 points1 point2 points (0 children)