Last active
December 31, 2015 11:08
-
-
Save KaeruCT/7977254 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
class Gasm { private $code = []; private $pc = 0; private $code_start = 0; private $code_len = 0; private $vars = []; private $labels = []; private $stack = []; private $comparison = false; private function line_number() { return 1 + $this->code_start + $this->pc; } private function strip_comments($line) { return trim(preg_replace('%;(.*)$%m', '', $line)); } private function is_label ($line) { return substr($line, -1) === ':'; } private function parse_line($line) { return array_map('trim', preg_split('%\s%', $line, 2)); } private function parse_args($args) { return array_map('trim', preg_split('%,%', $args)); } private function eval_expression($exp) { $matches = []; $ops = [ '+' => function ($a, $b) {return $a + $b;}, '-' => function ($a, $b) {return $a - $b;}, '*' => function ($a, $b) {return $a * $b;}, '/' => function ($a, $b) {return $a / $b;}, '%' => function ($a, $b) {return $a % $b;}, ]; $literals = [ '\n' => "\n", '\t' => "\t" ]; $ifx = '/(\w+)\s*(['.preg_quote(implode('', array_keys($ops)), '/').'])\s*(\w+)/'; if (preg_match('%^".*"$%', $exp)) { $val = str_replace(array_keys($literals), $literals, substr($exp, 1, -1)); } else if (preg_match($ifx, $exp, $matches)) { list($_, $a, $op, $b) = $matches; if (array_key_exists($a, $this->vars)) $a = $this->vars[$a]; if (array_key_exists($b, $this->vars)) $b = $this->vars[$b]; $val = $ops[$op]((double)$a, (double)$b); } else if (array_key_exists($exp, $this->vars)) { $val = $this->vars[$exp]; } else if (is_numeric($exp)) { $val = (double)$exp; } else { $val = $exp; } return $val; } public function load($handle) { $parse_data = true; for ($i = 0; false !== ($line = fgets($handle)); $i += 1) { $line = $this->strip_comments($line); if ($line === 'CODE') { $parse_data = false; $this->code_start = $i + 1; continue; } if ($parse_data) { if ($line === 'DATA') continue; @list($name, $value) = $this->parse_line($line); if (!empty($name)) $this->vars[$name] = $this->eval_expression($value); } else { if ($this->is_label($line)) { $lname = substr($line, 0, -1); $this->labels[$lname] = $i - $this->code_start; } $this->code[] = $line; } } $this->code_len = sizeof($this->code); } public function execute_line($line) { if ($this->is_label($line)) return; if ($line = $this->parse_line($line)) @list($op, $args) = $line; if (empty($op)) return; $op = strtolower($op); if (!empty($args)) $args = $this->parse_args($args); switch($op) { case 'println': case 'print': $val = $this->eval_expression($args[0]); if ($op === 'println') $val .= "\n"; echo $val; break; case 'inc': $this->vars[$args[0]] += 1; break; case 'dec': $this->vars[$args[0]] -= 1; break; case 'push': $this->stack[] = $this->eval_expression($args[0]); break; case 'pop': $val = array_pop($this->stack); if (!empty($args[0])) $this->vars[$args[0]] = $val; break; case 'mov': $val = $this->eval_expression($args[0]); $this->vars[$args[1]] = $val; break; case 'cmp': $a = $this->eval_expression($args[0]); $b = $this->eval_expression($args[1]); $this->comparison = ($a == $b); break; case 'jne': case 'je': $eq = $this->comparison; if ($op === 'jne') $eq = !$eq; if ($eq) { $this->pc = $this->labels[$args[0]]; } else if (!empty($args[1])) { $this->pc = $this->labels[$args[1]]; } break; case 'jmp': $this->pc = $this->labels[$args[0]]; break; case 'nop': break; default: $line = $this->line_number(); throw new Exception("INSTRUCTION NOT RECOGNIZED: {$op}, at line {$line}\n"); break; } } public function execute() { for ($this->pc = 0; $this->pc < $this->code_len; $this->pc += 1) { $this->execute_line($this->code[$this->pc]); } } } ;$gasm = unserialize('O:4:"Gasm":8:{s:10:"Gasmcode";a:23:{i:0;s:40:"println "here\'s a multiplication table:"";i:1;s:0:"";i:2;s:6:"start:";i:3;s:17:"mov w * h, number";i:4;s:0:"";i:5;s:16:"cmp w, w_max + 1";i:6;s:5:"inc w";i:7;s:19:"je end_row, print_n";i:8;s:0:"";i:9;s:8:"print_n:";i:10;s:12:"print number";i:11;s:10:"print "\t"";i:12;s:9:"jmp start";i:13;s:0:"";i:14;s:8:"end_row:";i:15;s:8:"mov 1, w";i:16;s:10:"print "\n"";i:17;s:12:"cmp h, h_max";i:18;s:5:"inc h";i:19;s:13:"je end, start";i:20;s:0:"";i:21;s:4:"end:";i:22;s:0:"";}s:8:"Gasmpc";i:0;s:16:"Gasmcode_start";i:7;s:14:"Gasmcode_len";i:23;s:10:"Gasmvars";a:4:{s:1:"w";d:1;s:1:"h";d:1;s:5:"w_max";d:12;s:5:"h_max";d:12;}s:12:"Gasmlabels";a:4:{s:5:"start";i:2;s:7:"print_n";i:9;s:7:"end_row";i:14;s:3:"end";i:21;}s:11:"Gasmstack";a:0:{}s:16:"Gasmcomparison";b:0;}');$gasm->execute(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment