Optimization: read symbol name to variable in eval

This commit is contained in:
Pekka Laiho 2020-12-03 10:08:11 +07:00
parent d6127e6821
commit a86fd77b45

View File

@ -44,7 +44,9 @@ class Evaller
// Handle special forms // Handle special forms
if ($ast->get(0) instanceof Symbol) { if ($ast->get(0) instanceof Symbol) {
if ($ast->get(0)->getName() == 'and') { $symbolName = $ast->get(0)->getName();
if ($symbolName == 'and') {
if ($ast->count() == 1) { if ($ast->count() == 1) {
return true; return true;
} }
@ -58,7 +60,7 @@ class Evaller
$ast = $ast->get($ast->count() - 1); $ast = $ast->get($ast->count() - 1);
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'case') { } elseif ($symbolName == 'case') {
if ($ast->count() < 2) { if ($ast->count() < 2) {
throw new MadLispException("case requires at least 1 argument"); throw new MadLispException("case requires at least 1 argument");
} }
@ -78,7 +80,7 @@ class Evaller
} else { } else {
return null; return null;
} }
} elseif ($ast->get(0)->getName() == 'def') { } elseif ($symbolName == 'def') {
if ($ast->count() != 3) { if ($ast->count() != 3) {
throw new MadLispException("def requires exactly 2 arguments"); throw new MadLispException("def requires exactly 2 arguments");
} }
@ -97,7 +99,7 @@ class Evaller
$value = $this->eval($ast->get(2), $env); $value = $this->eval($ast->get(2), $env);
return $env->set($name, $value); return $env->set($name, $value);
} elseif ($ast->get(0)->getName() == 'do') { } elseif ($symbolName == 'do') {
if ($ast->count() == 1) { if ($ast->count() == 1) {
return null; return null;
} }
@ -108,7 +110,7 @@ class Evaller
$ast = $ast->get($ast->count() - 1); $ast = $ast->get($ast->count() - 1);
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'env') { } elseif ($symbolName == 'env') {
if ($ast->count() >= 2) { if ($ast->count() >= 2) {
if (!($ast->get(1) instanceof Symbol)) { if (!($ast->get(1) instanceof Symbol)) {
throw new MadLispException("first argument to env is not symbol"); throw new MadLispException("first argument to env is not symbol");
@ -118,14 +120,14 @@ class Evaller
} else { } else {
return $env; return $env;
} }
} elseif ($ast->get(0)->getName() == 'eval') { } elseif ($symbolName == 'eval') {
if ($ast->count() == 1) { if ($ast->count() == 1) {
return null; return null;
} }
$ast = $this->eval($ast->get(1), $env); $ast = $this->eval($ast->get(1), $env);
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'fn') { } elseif ($symbolName == 'fn') {
if ($ast->count() != 3) { if ($ast->count() != 3) {
throw new MadLispException("fn requires exactly 2 arguments"); throw new MadLispException("fn requires exactly 2 arguments");
} }
@ -152,7 +154,7 @@ class Evaller
}; };
return new UserFunc($closure, $ast->get(2), $env, $bindings); return new UserFunc($closure, $ast->get(2), $env, $bindings);
} elseif ($ast->get(0)->getName() == 'if') { } elseif ($symbolName == 'if') {
if ($ast->count() < 3 || $ast->count() > 4) { if ($ast->count() < 3 || $ast->count() > 4) {
throw new MadLispException("if requires 2 or 3 arguments"); throw new MadLispException("if requires 2 or 3 arguments");
} }
@ -168,7 +170,7 @@ class Evaller
} else { } else {
return null; return null;
} }
} elseif ($ast->get(0)->getName() == 'let') { } elseif ($symbolName == 'let') {
if ($ast->count() != 3) { if ($ast->count() != 3) {
throw new MadLispException("let requires exactly 2 arguments"); throw new MadLispException("let requires exactly 2 arguments");
} }
@ -199,7 +201,7 @@ class Evaller
$ast = $ast->get(2); $ast = $ast->get(2);
$env = $newEnv; $env = $newEnv;
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'load') { } elseif ($symbolName == 'load') {
// Load is here because we want to load into // Load is here because we want to load into
// current $env which is hard otherwise. // current $env which is hard otherwise.
@ -244,7 +246,7 @@ class Evaller
$rootEnv->set('__DIR__', $prevDir); $rootEnv->set('__DIR__', $prevDir);
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'or') { } elseif ($symbolName == 'or') {
if ($ast->count() == 1) { if ($ast->count() == 1) {
return false; return false;
} }
@ -258,7 +260,7 @@ class Evaller
$ast = $ast->get($ast->count() - 1); $ast = $ast->get($ast->count() - 1);
continue; // tco continue; // tco
} elseif ($ast->get(0)->getName() == 'quote') { } elseif ($symbolName == 'quote') {
if ($ast->count() != 2) { if ($ast->count() != 2) {
throw new MadLispException("quote requires exactly 1 argument"); throw new MadLispException("quote requires exactly 1 argument");
} }