public static function EmitExpression($expr) { if ($expr === NULL || $expr === FALSE || is_array($expr) && empty($expr)) { return 'NULL'; } if ($expr === TRUE) { return 'true'; } if (is_int($expr) || is_double($expr)) { return (string) $expr; } if (is_string($expr)) { return "'" . addslashes($expr) . "'"; } if (is_array($expr)) { $out = array(); foreach ($expr as $e) { $out[] = self::EmitExpression($e); } return 'array(' . implode(', ', $out) . ')'; } if ($expr instanceof Tilde) { return 'new Tilde()'; } if ($expr instanceof AtSign) { return 'new AtSign()'; } if ($expr instanceof Symbol) { return "Symbol::Make('{$expr->name}')"; } if ($expr instanceof Lambda) { return '<lambda:' . Expression::Render($expr->arguments) . '>'; } if ($expr instanceof Macro) { return '<macro:' . Expression::Render($expr->arguments) . '>'; } return '<' . get_class($expr) . '>'; }
public function Evaluate($sexp) { //echo "EVAL: " . Expression::Render($sexp) . "\n"; if ($sexp instanceof Symbol) { if (($r = @$this->environment[$sexp->name]) !== NULL) { return $r === FALSE ? NULL : $r; } var_dump($sexp); throw new Exception("Unknown identifier: " . $sexp->name); } elseif (!is_array($sexp)) { return $sexp; } if (empty($sexp)) { return NULL; } $lambda = $sexp[0]; $args = array_slice($sexp, 1); if (is_array($lambda)) { $evald = $this->Evaluate($lambda); //echo Expression::Render($lambda) . " ~~> " . Expression::Render($evald) . "\n"; $lambda = $evald; } if ($lambda instanceof Symbol && ($val = @$this->environment[$lambda->name]) !== NULL) { $lambda = $val; } $phpName = NULL; if ($lambda instanceof Symbol) { $phpName = ($in = @self::$_internalNames[$lambda->name]) === NULL ? str_replace('-', '_', $lambda->name) : $in; } if ($lambda instanceof Macro) { $list = NULL; foreach ($lambda->expressions as $e) { // macro-expansion-time $applied = $lambda->arguments === NULL ? $e : $this->Apply($e, $lambda->arguments, $args); //echo Expression::Render($e) . " =APPLY=> " . Expression::Render($applied) . "\n"; $expanded = $this->Evaluate($applied); //echo Expression::Render($applied) . " =MACROEXPAND=> " . Expression::Render($expanded) . "\n"; } return $this->Evaluate($expanded); } if ($lambda instanceof Symbol) { // special forms (non-evaluated parameters) $specialForm = "lizp_special_form_{$phpName}"; if (function_exists($specialForm)) { return call_user_func($specialForm, $this, $args); } } // We evaluate the parameters $params = array(); $expandNext = FALSE; foreach ($args as $v) { if ($v instanceof AtSign) { $expandNext = TRUE; continue; } $r = $this->Evaluate($v); if ($expandNext && is_array($r)) { $params = array_merge($params, $r); } else { $params[] = $r; } $expandNext = FALSE; } if ($lambda instanceof Lambda) { $r = NULL; foreach ($lambda->expressions as $e) { $args = array(); foreach ($params as $i) { if (is_array($i)) { $i = array(Symbol::Make('quote'), $i); } $args[] = $i; } //$params = $args; $applied = $lambda->arguments === NULL ? $e : $this->Apply($e, $lambda->arguments, $params); //echo Expression::Render($e) . " -APPLY-> " . Expression::Render($applied) . "\n"; $r = $this->Evaluate($applied); //echo Expression::Render($applied) . " -EVAL-> " . Expression::Render($r) . "\n"; } return $r; } if ($lambda instanceof Symbol) { // internal functions / php functions $internalFn = "lizp_internal_fn_{$phpName}"; if (($isInternal = function_exists($internalFn)) || function_exists($phpName)) { if ($isInternal) { return call_user_func($internalFn, $this, $params); } $r = call_user_func_array($phpName, $params); if ($r === FALSE || is_array($r) && empty($r)) { $r = NULL; } return $r; } } throw new Exception("Unable to evaluate Expression: " . Expression::Render($sexp) . " because function name evaluates to " . Expression::Render($lambda)); }
function lizp_special_form_dump($env, $args) { foreach ($args as $arg) { echo Expression::Render($arg) . "\n"; } return NULL; }
function lizp_internal_fn_parse($env, $args) { if (!is_string(@$args[0])) { throw new Exception("Syntax Error: (PARSE <string>)"); } $expr = Expression::NewParse($args[0]); if (count($expr) > 1) { throw new Exception("Error: Multiple expressions given in " . Expression::Render($arg[0])); } return @$expr[0]; }