Exemple #1
0
function MAL_EVAL($ast, $env)
{
    #echo "MAL_EVAL: " . _pr_str($ast) . "\n";
    if (!_list_Q($ast)) {
        return eval_ast($ast, $env);
    }
    if ($ast->count() === 0) {
        return $ast;
    }
    // apply list
    $a0 = $ast[0];
    $a0v = _symbol_Q($a0) ? $a0->value : $a0;
    switch ($a0v) {
        case "def!":
            $res = MAL_EVAL($ast[2], $env);
            return $env->set($ast[1], $res);
        case "let*":
            $a1 = $ast[1];
            $let_env = new Env($env);
            for ($i = 0; $i < count($a1); $i += 2) {
                $let_env->set($a1[$i], MAL_EVAL($a1[$i + 1], $let_env));
            }
            return MAL_EVAL($ast[2], $let_env);
        default:
            $el = eval_ast($ast, $env);
            $f = $el[0];
            return call_user_func_array($f, array_slice($el->getArrayCopy(), 1));
    }
}
Exemple #2
0
function MAL_EVAL($ast, $env)
{
    if (!_list_Q($ast)) {
        return eval_ast($ast, $env);
    }
    // apply list
    $el = eval_ast($ast, $env);
    $f = $el[0];
    return call_user_func_array($f, array_slice($el->getArrayCopy(), 1));
}
Exemple #3
0
function MAL_EVAL($ast, $env)
{
    #echo "MAL_EVAL: " . _pr_str($ast) . "\n";
    if (!_list_Q($ast)) {
        return eval_ast($ast, $env);
    }
    if ($ast->count() === 0) {
        return $ast;
    }
    // apply list
    $a0 = $ast[0];
    $a0v = _symbol_Q($a0) ? $a0->value : $a0;
    switch ($a0v) {
        case "def!":
            $res = MAL_EVAL($ast[2], $env);
            return $env->set($ast[1], $res);
        case "let*":
            $a1 = $ast[1];
            $let_env = new Env($env);
            for ($i = 0; $i < count($a1); $i += 2) {
                $let_env->set($a1[$i], MAL_EVAL($a1[$i + 1], $let_env));
            }
            return MAL_EVAL($ast[2], $let_env);
        case "do":
            #$el = eval_ast(array_slice($ast->getArrayCopy(), 1), $env);
            $el = eval_ast($ast->slice(1), $env);
            return $el[count($el) - 1];
        case "if":
            $cond = MAL_EVAL($ast[1], $env);
            if ($cond === NULL || $cond === false) {
                if (count($ast) === 4) {
                    return MAL_EVAL($ast[3], $env);
                } else {
                    return NULL;
                }
            } else {
                return MAL_EVAL($ast[2], $env);
            }
        case "fn*":
            return function () use($env, $ast) {
                $fn_env = new Env($env, $ast[1], func_get_args());
                return MAL_EVAL($ast[2], $fn_env);
            };
        default:
            $el = eval_ast($ast, $env);
            $f = $el[0];
            return call_user_func_array($f, array_slice($el->getArrayCopy(), 1));
    }
}
Exemple #4
0
function MAL_EVAL($ast, $env)
{
    while (true) {
        #echo "MAL_EVAL: " . _pr_str($ast) . "\n";
        if (!_list_Q($ast)) {
            return eval_ast($ast, $env);
        }
        // apply list
        $ast = macroexpand($ast, $env);
        if (!_list_Q($ast)) {
            return eval_ast($ast, $env);
        }
        if ($ast->count() === 0) {
            return $ast;
        }
        $a0 = $ast[0];
        $a0v = _symbol_Q($a0) ? $a0->value : $a0;
        switch ($a0v) {
            case "def!":
                $res = MAL_EVAL($ast[2], $env);
                return $env->set($ast[1], $res);
            case "let*":
                $a1 = $ast[1];
                $let_env = new Env($env);
                for ($i = 0; $i < count($a1); $i += 2) {
                    $let_env->set($a1[$i], MAL_EVAL($a1[$i + 1], $let_env));
                }
                $ast = $ast[2];
                $env = $let_env;
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "quote":
                return $ast[1];
            case "quasiquote":
                $ast = quasiquote($ast[1]);
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "defmacro!":
                $func = MAL_EVAL($ast[2], $env);
                $func->ismacro = true;
                return $env->set($ast[1], $func);
            case "macroexpand":
                return macroexpand($ast[1], $env);
            case "do":
                eval_ast($ast->slice(1, -1), $env);
                $ast = $ast[count($ast) - 1];
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "if":
                $cond = MAL_EVAL($ast[1], $env);
                if ($cond === NULL || $cond === false) {
                    if (count($ast) === 4) {
                        $ast = $ast[3];
                    } else {
                        $ast = NULL;
                    }
                } else {
                    $ast = $ast[2];
                }
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "fn*":
                return _function('MAL_EVAL', 'native', $ast[2], $env, $ast[1]);
            default:
                $el = eval_ast($ast, $env);
                $f = $el[0];
                $args = array_slice($el->getArrayCopy(), 1);
                if ($f->type === 'native') {
                    $ast = $f->ast;
                    $env = $f->gen_env($args);
                    // Continue loop (TCO)
                } else {
                    return $f->apply($args);
                }
        }
    }
}
Exemple #5
0
function MAL_EVAL($ast, $env)
{
    while (true) {
        #echo "MAL_EVAL: " . _pr_str($ast) . "\n";
        if (!_list_Q($ast)) {
            return eval_ast($ast, $env);
        }
        // apply list
        $ast = macroexpand($ast, $env);
        if (!_list_Q($ast)) {
            return eval_ast($ast, $env);
        }
        if ($ast->count() === 0) {
            return $ast;
        }
        $a0 = $ast[0];
        $a0v = _symbol_Q($a0) ? $a0->value : $a0;
        switch ($a0v) {
            case "def!":
                $res = MAL_EVAL($ast[2], $env);
                return $env->set($ast[1], $res);
            case "let*":
                $a1 = $ast[1];
                $let_env = new Env($env);
                for ($i = 0; $i < count($a1); $i += 2) {
                    $let_env->set($a1[$i], MAL_EVAL($a1[$i + 1], $let_env));
                }
                $ast = $ast[2];
                $env = $let_env;
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "quote":
                return $ast[1];
            case "quasiquote":
                $ast = quasiquote($ast[1]);
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "defmacro!":
                $func = MAL_EVAL($ast[2], $env);
                $func->ismacro = true;
                return $env->set($ast[1], $func);
            case "macroexpand":
                return macroexpand($ast[1], $env);
            case "php*":
                $res = eval($ast[1]);
                switch (gettype($res)) {
                    case "array":
                        if ($res !== array_values($res)) {
                            $new_res = _hash_map();
                            $new_res->exchangeArray($res);
                            return $new_res;
                        } else {
                            return call_user_func_array('_list', $res);
                        }
                    default:
                        return $res;
                }
            case "try*":
                $a1 = $ast[1];
                $a2 = $ast[2];
                if ($a2[0]->value === "catch*") {
                    try {
                        return MAL_EVAL($a1, $env);
                    } catch (Error $e) {
                        $catch_env = new Env($env, array($a2[1]), array($e->obj));
                        return MAL_EVAL($a2[2], $catch_env);
                    } catch (Exception $e) {
                        $catch_env = new Env($env, array($a2[1]), array($e->getMessage()));
                        return MAL_EVAL($a2[2], $catch_env);
                    }
                } else {
                    return MAL_EVAL($a1, $env);
                }
            case "do":
                eval_ast($ast->slice(1, -1), $env);
                $ast = $ast[count($ast) - 1];
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "if":
                $cond = MAL_EVAL($ast[1], $env);
                if ($cond === NULL || $cond === false) {
                    if (count($ast) === 4) {
                        $ast = $ast[3];
                    } else {
                        $ast = NULL;
                    }
                } else {
                    $ast = $ast[2];
                }
                break;
                // Continue loop (TCO)
            // Continue loop (TCO)
            case "fn*":
                return _function('MAL_EVAL', 'native', $ast[2], $env, $ast[1]);
            default:
                $el = eval_ast($ast, $env);
                $f = $el[0];
                $args = array_slice($el->getArrayCopy(), 1);
                if ($f->type === 'native') {
                    $ast = $f->ast;
                    $env = $f->gen_env($args);
                    // Continue loop (TCO)
                } else {
                    return $f->apply($args);
                }
        }
    }
}