Passed
Push — master ( 079f1e...99c93a )
by Observer
01:36
created

Translator::formatLine()   B

Complexity

Conditions 8
Paths 2

Size

Total Lines 50
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 27
c 1
b 0
f 0
dl 0
loc 50
rs 8.4444
cc 8
nc 2
nop 2
1
<?php
2
3
namespace VLF;
4
5
class Translator
6
{
7
    public static function translate (AST $tree): string
8
    {
9
        $code = "<?php\n\nnamespace VoidEngine;\n\n";
10
        $definedObjects = [];
11
12
        foreach ($tree->getNodes () as $node)
13
            $code .= self::translateNode ($node, null, $definedObjects) ."\n";
14
15
        return $code;
16
    }
17
18
    protected static function translateNode (Node $node, Node $owner = null, array &$definedObjects = []): string
19
    {
20
        $code = '';
21
22
        switch ($node->type)
23
        {
24
            case RUNTIME_EXECUTION:
25
                $code .= self::formatLine ($node->args['code'], $definedObjects) ."\n\n";
26
27
                break;
28
29
            case OBJECT_DEFINITION:
30
                if (isset ($definedObjects[$node->args['name']]))
31
                    break;
32
                
33
                $code .= '$'. $node->args['name'] .' = new '. $node->args['class'] .' ('. implode (', ', self::processArgs ($node->args['args'], $definedObjects)) .');' ."\n". '$'. $node->args['name'] .'->name = \''. $node->args['name'] .'\';' ."\n";
34
35
                $definedObjects[$node->args['name']] = $node->args['name'];
36
37
                break;
38
39
            case PROPERTY_SET:
40
                $preset = '';
41
42
                if (preg_match ('/function \((.*)\) use \((.*)\)/', $node->args['property_value']))
43
                {
44
                    $use = substr ($node->args['property_value'], strpos ($node->args['property_value'], 'use'));
45
                    $use = $ouse = substr ($use, ($pos = strpos ($use, '(') + 1), strpos ($use, ')') - $pos);
46
                    $use = explode (' ', $use);
47
48
                    foreach ($use as $id => $useParam)  
49
                        if (isset ($definedObjects[$useParam]) && $use[$id + 1][0] == '$')
50
                        {
51
                            $fname = $use[$id + 1];
52
53
                            if (substr ($fname, strlen ($fname) - 1) == ',')
54
                                $fname = substr ($fname, 0, -1);
55
56
                            $preset .= "$fname = $useParam; ";
57
58
                            unset ($use[$id]);
59
                        }
60
61
                    $preset = self::formatLine ($preset, $definedObjects) ."\n";
62
63
                    $node->args['property_value'] = self::formatLine (str_replace ($ouse, join (' ', $use), $node->args['property_value']), $definedObjects);
64
                }
65
                
66
                $code .= $preset .'$'. $owner->args['name'] .'->'. $node->args['property_name'] .' = '. self::formatLine ($node->args['property_value'], $definedObjects) .';' ."\n";
67
68
                break;
69
70
            case METHOD_CALL:
71
                $code .= '$'. $owner->args['name'] .'->'. $node->args['method_name'] .' ('. implode (', ', self::processArgs ($node->args['method_args'], $definedObjects)) .');' ."\n";
72
73
                break;
74
        }
75
76
        foreach ($node->getNodes () as $subnode)
77
            $code .= self::translateNode ($subnode, $node, $definedObjects);
78
79
        return $code;
80
    }
81
82
    protected static function processArgs (array $args, array $definedObjects = []): array
83
    {
84
        $newArgs = [];
85
86
        foreach ($args as $arg)
87
            $newArgs[] = self::formatLine ($arg, $definedObjects);
88
89
        return $newArgs;
90
    }
91
92
    protected static function formatLine (string $line, array $objects = []): string
93
    {
94
        if (sizeof ($objects) > 0)
95
        {
96
            $len     = strlen ($line);
97
            $newLine = '';
98
99
            $replacement = array_map (function ($object)
100
            {
101
                return '$'. $object;
102
            }, $objects);
103
104
            $replacement = array_map (function ($name)
105
            {
106
                return strlen ($name = trim ($name)) + substr_count ($name, '_');
107
            }, $omap = array_flip ($replacement));
0 ignored issues
show
Bug introduced by
It seems like $omap = array_flip($replacement) can also be of type null; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

107
            }, /** @scrutinizer ignore-type */ $omap = array_flip ($replacement));
Loading history...
108
109
            arsort ($replacement);
110
111
            $nReplacement = [];
112
113
            foreach ($replacement as $replaceTo => $nLn)
114
                $nReplacement[$omap[$replaceTo]] = $replaceTo;
115
116
            $replacement = $nReplacement;
117
            $blacklist   = array_flip (['\'', '"', '$']);
118
119
            for ($i = 0; $i < $len; ++$i)
120
            {
121
                $replaced = false;
122
123
                foreach ($replacement as $name => $replaceAt)
124
                    if (substr ($line, $i, ($l = strlen ($name))) == $name && !isset ($blacklist[$line[$i - 1]]))
125
                    {
126
                        $newLine .= $replaceAt;
127
128
                        $i += $l - 1;
129
                        $replaced = true;
130
131
                        break;
132
                    }
133
134
                if (!$replaced)
135
                    $newLine .= $line[$i];
136
            }
137
138
            $line = $newLine;
139
        }
140
141
        return $line;
142
    }
143
}
144