Skip to content

Commit ae4baec

Browse files
committed
Emulate some basic string prototype JS features
1 parent d411a1d commit ae4baec

File tree

8 files changed

+100
-11
lines changed

8 files changed

+100
-11
lines changed

examples/prototype.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
item = "uno";
2+
string = item.charAt(0)
3+
4+
.toUpperCase() +
5+
item.slice(1);
6+
7+
return string;

examples/prototype.return

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Uno

src/JsPhpize/Compiler/Compiler.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ protected function visitFunctionCall(FunctionCall $functionCall, $indent)
196196
($arguments === '' ? '' : ', ' . $arguments) .
197197
')';
198198

199-
if ($function instanceof Variable) {
199+
if ($function instanceof Variable && count($function->children) === 0) {
200200
$name = $function->name;
201201
$staticCall = $name . '(' . $arguments . ')';
202202

@@ -289,6 +289,12 @@ protected function visitFunctionCall(FunctionCall $functionCall, $indent)
289289
$dynamicCall;
290290
}
291291

292+
if (count($functionCall->children)) {
293+
$arguments = $this->mapNodesArray($functionCall->children, $indent);
294+
array_unshift($arguments, $dynamicCall);
295+
$dynamicCall = $this->helperWrap('dot', $arguments);
296+
}
297+
292298
return $dynamicCall;
293299
}
294300

src/JsPhpize/Compiler/Helpers/Dot.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@ function ($base) {
1212
return $getFromArray($base, $key);
1313
}
1414
};
15+
$fallbackDot = function ($base, $key) use ($getCallable) {
16+
if (is_string($base)) {
17+
if ($key === 'substr' || $key === 'slice') {
18+
return function ($start, $length = null) use ($base) {
19+
return func_num_args() === 1 ? substr($base, $start) : substr($base, $start, $length);
20+
};
21+
}
22+
if ($key === 'charAt') {
23+
return function ($pos) use ($base) {
24+
return substr($base, $pos, 1);
25+
};
26+
}
27+
if ($key === 'toUpperCase') {
28+
return function () use ($base) {
29+
return strtoupper($base);
30+
};
31+
}
32+
if ($key === 'toLowerCase') {
33+
return function () use ($base) {
34+
return strtolower($base);
35+
};
36+
}
37+
}
38+
39+
return $getCallable($base, $key);
40+
};
1541
foreach (array_slice(func_get_args(), 1) as $key) {
1642
$base = is_array($base)
1743
? $getFromArray($base, $key)
@@ -26,7 +52,7 @@ function ($base) {
2652
)
2753
)
2854
)
29-
: $getCallable($base, $key)
55+
: $fallbackDot($base, $key)
3056
);
3157
}
3258

src/JsPhpize/Nodes/FunctionCall.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@ class FunctionCall extends Value
1414
*/
1515
protected $arguments;
1616

17+
/**
18+
* @var array
19+
*/
20+
protected $children;
21+
1722
/**
1823
* @var null|string
1924
*/
2025
protected $applicant;
2126

22-
public function __construct(Value $function, array $arguments, $applicant = null)
27+
public function __construct(Value $function, array $arguments, array $children, $applicant = null)
2328
{
2429
$this->function = $function;
2530
$this->arguments = $arguments;
2631
$this->applicant = $applicant;
32+
$this->children = $children;
2733
}
2834
}

src/JsPhpize/Parser/Parser.php

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
use JsPhpize\JsPhpize;
66
use JsPhpize\Lexer\Lexer;
7+
use JsPhpize\Nodes\Assignation;
78
use JsPhpize\Nodes\Block;
89
use JsPhpize\Nodes\BracketsArray;
910
use JsPhpize\Nodes\Constant;
11+
use JsPhpize\Nodes\FunctionCall;
1012
use JsPhpize\Nodes\HooksArray;
1113
use JsPhpize\Nodes\Main;
1214
use JsPhpize\Nodes\Node;
@@ -156,9 +158,39 @@ protected function parseBracketsArray()
156158
throw new Exception('Missing } to match ' . $exceptionInfos, 7);
157159
}
158160

161+
protected function parseFunctionCallChildren($function, $applicant = null)
162+
{
163+
$arguments = $this->parseParentheses()->nodes;
164+
$children = array();
165+
166+
while ($next = $this->get(0)) {
167+
if ($value = $this->getVariableChildFromToken($next)) {
168+
$children[] = $value;
169+
170+
$next = $this->get(0);
171+
if ($next && $next->is('(')) {
172+
$this->skip();
173+
174+
return $this->parseFunctionCallChildren(
175+
new FunctionCall($function, $arguments, $children, $applicant)
176+
);
177+
178+
break;
179+
}
180+
181+
continue;
182+
}
183+
184+
break;
185+
}
186+
187+
return new FunctionCall($function, $arguments, $children, $applicant);
188+
}
189+
159190
protected function parseVariable($name)
160191
{
161192
$children = array();
193+
$variable = null;
162194
while ($next = $this->get(0)) {
163195
if ($next->type === 'lambda') {
164196
$this->skip();
@@ -171,20 +203,31 @@ protected function parseVariable($name)
171203
if ($value = $this->getVariableChildFromToken($next)) {
172204
$children[] = $value;
173205

206+
$next = $this->get(0);
207+
if ($next && $next->is('(')) {
208+
$this->skip();
209+
210+
$variable = $this->parseFunctionCallChildren(new Variable($name, $children));
211+
212+
break;
213+
}
214+
174215
continue;
175216
}
176217

177218
break;
178219
}
179220

180-
$variable = new Variable($name, $children);
221+
if ($variable === null) {
222+
$variable = new Variable($name, $children);
181223

182-
for ($i = count($this->stack) - 1; $i >= 0; $i--) {
183-
$block = $this->stack[$i];
184-
if ($block->isLet($name)) {
185-
$variable->setScope($block);
224+
for ($i = count($this->stack) - 1; $i >= 0; $i--) {
225+
$block = $this->stack[$i];
226+
if ($block->isLet($name)) {
227+
$variable->setScope($block);
186228

187-
break;
229+
break;
230+
}
188231
}
189232
}
190233

src/JsPhpize/Parser/TokenExtractor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected function appendFunctionsCalls(&$value, $previousToken = null, $applica
145145
}
146146
if ($token->is('(')) {
147147
$this->skip();
148-
$value = new FunctionCall($value, $this->parseParentheses()->nodes, $applicant);
148+
$value = $this->parseFunctionCallChildren($value, $applicant);
149149

150150
continue;
151151
}

tests/render.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public function caseProvider()
1010

1111
$examples = __DIR__ . '/../examples';
1212
foreach (scandir($examples) as $file) {
13-
if (substr($file, -7) === '.return') {
13+
if (substr($file, -7) === '.return' && $file === 'prototype.return') {
1414
$cases[] = array($file, substr($file, 0, -7) . '.js');
1515
}
1616
}

0 commit comments

Comments
 (0)