Skip to content

Instantly share code, notes, and snippets.

@igorw
Last active August 29, 2015 14:01
Show Gist options
  • Save igorw/8a170a98b4c737317b35 to your computer and use it in GitHub Desktop.
Save igorw/8a170a98b4c737317b35 to your computer and use it in GitHub Desktop.
Playing with concatenative programming.
<?hh
// concatenative programming
// based on this paper:
// http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/ICSOFT.2009.pdf
namespace igorw\concat;
class OpenQuotation {
var $words;
function __construct($words = []) {
$this->words = $words;
}
function push($word) {
$words = $this->words;
array_push($words, $word);
return new OpenQuotation($words);
}
function close() {
return new Quotation($this->words);
}
}
class Quotation {
var $words;
function __construct($words = []) {
$this->words = $words;
}
function unquote() {
return $this->words;
}
}
function word($word, array $stack) {
$top = end($stack);
if ($top instanceof OpenQuotation && !in_array($word, ['[', ']'])) {
$s = quote($word, $stack);
return $s;
}
if (is_numeric($word)) {
return number($word, $stack);
}
$fns = [
'dup' => $stack ==> {
$val = array_pop($stack);
array_push($stack, $val);
array_push($stack, $val);
return $stack;
},
'[' => $stack ==> {
array_push($stack, new OpenQuotation());
return $stack;
},
']' => $stack ==> {
$quot = array_pop($stack);
array_push($stack, $quot->close());
return $stack;
},
'>' => $stack ==> {
$b = array_pop($stack);
$a = array_pop($stack);
array_push($stack, $a > $b);
return $stack;
},
'call' => $stack ==> {
$quot = array_pop($stack);
return call($quot, $stack);
},
'if' => $stack ==> {
$quot_false = array_pop($stack);
$quot_true = array_pop($stack);
$val = array_pop($stack);
$quot = $val ? $quot_true : $quot_false;
return call($quot, $stack);
},
'+' => $stack ==> {
$b = array_pop($stack);
$a = array_pop($stack);
array_push($stack, $a + $b);
return $stack;
},
];
if (isset($fns[$word])) {
return $fns[$word]($stack);
}
throw new \InvalidArgumentException("Unknown word $word");
}
function quote($word, array $stack) {
$quot = array_pop($stack);
array_push($stack, $quot->push($word));
return $stack;
}
function number($word, array $stack) {
array_push($stack, (int) $word);
return $stack;
}
function call(Quotation $quot, array $stack) {
$words = $quot->unquote();
return evaluate($words, $stack);
}
function evaluate(array $words, array $stack = []) {
foreach ($words as $word) {
var_dump($stack);
$stack = word($word, $stack);
}
return $stack;
}
$code = '6 5 dup [ 3 > ] call [ + ] [ * ] if';
$words = explode(' ', $code);
var_dump(evaluate($words));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment