📜 ⬆️ ⬇️

I write in pseudocode, it works in PHP

I can write pseudocode programs and turn them into PHP code. Or in portable C. Or something else. The list will be updated.

The part of the project that is “turn into PHP” is not fully ready. But I am writing an article now to:


An example and technical details under a habrokat.
')
Sample program:

( display "Hello, world!\n")

Or more difficult:

( define (- -)
( lambda () ( display -)))
( define - ( - "!\n"))
( - )


In this example, the function returns a function. In PHP, the code would look like this (does not work):

function _($_) {
return function () {
print $_;
}
}
$_ = _ ("!\n");
$ _ ();


You can look at other examples on github or in the archive . Tests check what works

* at least something (example “Hello, world”)
* recursion (factorial, fibonacci, accermann)
* circuit
* continue

All important things work. Until the full implementation of the standard R5RS, it remains only to make primitives. Oh yeah, quite by chance my pseudocode is the same as Scheme R5RS.

For my project I use the Gambit Schema compiler. Inside it is a register-stack GVM virtual machine ( A Parallel Virtual Machine for Efficient Scheme Compilation ). This is what our example turns into when it turns into GVM:

; +N: N
; -N: N
; : +1, +2 ..
; +1
; continuation-passing style, - +0
; , escape sequences
;
; #1

#1 0 entry-point 0 ()
; "-"
|~#-| = '#<procedure |~#-|>
-1 = +0
+1 = '"!\n"
+0 = #3
; #2
jump* 4 #2
#2 4
; . +0 #3, , +1 ()
jump$ 4 |~#-| 1
#3 4 return-point
|~#-| = +1
+0 = -1
jump* 4 #4
#4 4
jump$ 0 |~#-| 0

**** #<procedure |~#-|> =
#1 0 entry-point 1 ()
; --
close -1 = (#2 +1)
+1 = -1
jump 0 +0
;
#2 0 closure-entry-point 0 ()
; +4 , +4(1) --
+1 = +4(1)
jump* 0 #3
#3 0
jump$ 0 display 1


The result of the GVM translation in PHP:

function glo_x20hellowr () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$ GLOBALS['glo_-'] = 'glo__';
$ stack[$fp+1] = $reg0;
$ reg1 = "!\n";
$ reg0 = 'lbl_x20hellowr_3';
$ pc = 'lbl_x20hellowr_2';
$ fp = $fp+4;
}
function lbl_x20hellowr_2 () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$nargs = 1;
$ pc = $GLOBALS['glo_-'];
}
function lbl_x20hellowr_3 () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$ GLOBALS['glo_-'] = $reg1;
$ reg0 = $stack[$fp-3];
$ pc = 'lbl_x20hellowr_4';
}
function lbl_x20hellowr_4 () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$nargs = 0;
$ pc = $GLOBALS['glo_-'];
$ fp = $fp-4;
}
// procedure - =
function glo__ () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$ stack[$fp+1] = array('lbl___2', $reg1);
$ reg1 = $stack[$fp+1];
$ pc = $reg0;
}
function lbl___2 () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$ reg1 = $reg4[1];
$ pc = 'lbl___3';
}
function lbl___3 () {
global $reg0, $reg1, $reg2, $reg3, $reg4, $pc, $fp, $stack, $nargs;
$nargs = 1;
$ pc = $GLOBALS['glo_display'];
}
exec_scheme_code(' glo_x20hellowr ');


1) How to implement goto?


Each GVM block (from label to transition) becomes a PHP function that returns where to goto. The executor of the exec_scheme_code ($ pc) program looks like this:

$ reg0 = 'glo_exit';
while (1) {
$ pc = $ pc ()
}

Instead of a compiler, the interpreter is here. Performance suffers.

Alternatives?

2) Superglobals


Each function has to list the same global variables. Maybe there is a way to tell PHP that they are global by default?

3) Stack


Instead of a hardware stack, you should use a software one. Naturally, I took an array. And did not guess a little. It turns out that they are always associative, with a bunch of curious side effects, which also slows down the work.

How to make a quick stack?

4) Performance


Naturally, such a PHP code slows down. For example, compared with the manual implementation of the Ackermann function, it is 30 times slower. I suspect why (under-goto and stack), but I want to make sure.

What tools to measure that slows down?

Source: https://habr.com/ru/post/113763/


All Articles