Completed
Branch master (5720e6)
by Scott
05:47 queued 02:57
created

Evaluator::specialFunctionList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 12
nc 1
nop 1
crap 1
1
<?php
2
namespace Desmond;
3
use Desmond\functions\EnvLoader;
4
use Desmond\data_types\ListType;
5
use Desmond\data_types\VectorType;
6
use Desmond\data_types\HashType;
7
use Desmond\data_types\SymbolType;
8
use Desmond\data_types\LambdaType;
9
use Exception;
10
11
class Evaluator
12
{
13
    private $coreEnv;
14
    public $currentEnv;
15
16 154
    public function __construct()
17
    {
18 154
        $this->coreEnv = new Environment();
19 154
        $this->currentEnv = $this->coreEnv;
20 154
        EnvLoader::loadInto($this->coreEnv, 'core');
21 154
    }
22
23 152
    public function getReturn($ast)
24
    {
25 152
        if ($ast instanceof ListType) {
26 149
            return $this->evalForm($ast);
27 152
        } else if ($ast instanceof VectorType || $ast instanceof HashType) {
28 25
            return $this->evalCollection($ast);
29
        } else {
30 152
            return $this->evalAtom($ast);
31
        }
32
    }
33
34 149
    private function evalForm($form)
35
    {
36 149
        if ($form->get(0) instanceof ListType || $this->getReturn($form->get(0)) instanceof LambdaType) {
37 5
            $function = $this->getReturn($form->get(0));
38
        } else {
39 149
            $function = $form->getFunction()->value();
40
        }
41 149
        return $this->doSpecialForm($function, $form->getArgs());
42
    }
43
44 25
    public function evalCollection($ast)
45
    {
46 25
        $collection = $ast;
47 25
        foreach ($collection->value() as $key => $value) {
48 21
            $collection->set($this->getReturn($value), $key);
49
        }
50 25
        return $collection;
51
    }
52
53 149
    private function doSpecialForm($function, $args)
54
    {
55 149
        $possibilities = $this->specialFunctionList($function);
56 149
        $functionName = null;
57 149
        foreach ($possibilities as $possibility) {
58 149
            if ($possibility[0]) {
59 46
                $functionName = $possibility[1];
60 149
                break;
61
            }
62
        }
63 149
        $functionName = $functionName ? $functionName : 'EnvironmentFunction';
64 149
        return call_user_func_array(
65 149
            "Desmond\\functions\\special\\{$functionName}::run",
66 149
            [$args, $function, &$this->currentEnv, $this]);
67
    }
68
69 149
    private function specialFunctionList($function)
70
    {
71
        return [
72 149
            [$function == 'quote', 'Quote'],
73 149
            [$function == 'quasiquote', 'Quasiquote'],
74 149
            [$function == 'define', 'DefineSymbol'],
75 149
            [$function == 'let', 'Let'],
76 149
            [$function == 'do', 'DoBlock'],
77 149
            [$function == 'if', 'Conditional'],
78 149
            [$function == 'lambda', 'CreateLambda'],
79 149
            [($function instanceof LambdaType), 'RunLambda'],
80 149
            [$function == 'load-file', 'LoadFile'],
81 149
            [$function == 'eval', 'EvalBlock']
82
        ];
83
    }
84
85 152
    private function evalAtom($atom)
86
    {
87 152
        if (!($atom instanceof SymbolType)) {
88 102
            return $atom;
89
        }
90
        try {
91 149
            $value = $this->currentEnv->get($atom->value());
92 135
            return $value;
93 67
        } catch (Exception $exeption) {
94 67
            return $atom;
95
        }
96
    }
97
}
98