Skip to content

Commit 60087a5

Browse files
committed
Refactor line handling to lang.ast.emit.Result base class
This prevents a parent::emitOne() call for each node
1 parent 4b5c5d0 commit 60087a5

4 files changed

Lines changed: 29 additions & 43 deletions

File tree

src/main/php/lang/ast/Emitter.class.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ protected function emit() {
108108
/**
109109
* Standalone operators
110110
*
111-
* @param lang.ast.Result $result
111+
* @param lang.ast.emit.Result $result
112112
* @param lang.ast.Token $operator
113113
* @return void
114114
*/
@@ -119,7 +119,7 @@ protected function emitOperator($result, $operator) {
119119
/**
120120
* Emit nodes seperated as statements
121121
*
122-
* @param lang.ast.Result $result
122+
* @param lang.ast.emit.Result $result
123123
* @param iterable $nodes
124124
* @return void
125125
*/
@@ -133,23 +133,21 @@ public function emitAll($result, $nodes) {
133133
/**
134134
* Emit single nodes
135135
*
136-
* @param lang.ast.Result $result
136+
* @param lang.ast.emit.Result $result
137137
* @param lang.ast.Node $node
138138
* @return void
139139
*/
140140
public function emitOne($result, $node) {
141-
142-
// Check for transformations
143-
if (isset($this->transformations[$node->kind])) {
144-
foreach ($this->transformations[$node->kind] as $transformation) {
141+
if ($transformations= $this->transformations[$node->kind] ?? null) {
142+
foreach ($transformations as $transformation) {
145143
$r= $transformation($result->codegen, $node);
146144
if ($r instanceof Node) {
147145
if ($r->kind === $node->kind) continue;
148-
$this->{'emit'.$r->kind}($result, $r);
146+
$this->{'emit'.$r->kind}($result->at($r->line), $r);
149147
return;
150148
} else if ($r) {
151149
foreach ($r as $s => $n) {
152-
$this->{'emit'.$n->kind}($result, $n);
150+
$this->{'emit'.$n->kind}($result->at($n->line), $n);
153151
null === $s || $result->out->write(';');
154152
}
155153
return;
@@ -158,14 +156,14 @@ public function emitOne($result, $node) {
158156
// Fall through, use default
159157
}
160158

161-
$this->{'emit'.$node->kind}($result, $node);
159+
$this->{'emit'.$node->kind}($result->at($node->line), $node);
162160
}
163161

164162
/**
165163
* Creates result
166164
*
167165
* @param io.streams.OutputStream $target
168-
* @return lang.ast.Result
166+
* @return lang.ast.emit.Result
169167
*/
170168
protected abstract function result($target);
171169

src/main/php/lang/ast/emit/GeneratedCode.class.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
class GeneratedCode extends Result {
44
private $prolog, $epilog;
5-
public $line= 1;
65

76
/**
87
* Starts a result stream, including an optional prolog and epilog
@@ -36,20 +35,6 @@ protected function finalize() {
3635
'' === $this->epilog || $this->out->write($this->epilog);
3736
}
3837

39-
/**
40-
* Forwards output line to given line number
41-
*
42-
* @param int $line
43-
* @return self
44-
*/
45-
public function at($line) {
46-
if ($line > $this->line) {
47-
$this->out->write(str_repeat("\n", $line - $this->line));
48-
$this->line= $line;
49-
}
50-
return $this;
51-
}
52-
5338
/**
5439
* Creates a temporary variable and returns its name
5540
*

src/main/php/lang/ast/emit/PHP.class.php

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ abstract class PHP extends Emitter {
3232
* Creates result
3333
*
3434
* @param io.streams.OutputStream $target
35-
* @return lang.ast.Result
35+
* @return lang.ast.emit.Result
3636
*/
3737
protected function result($target) {
3838
return new GeneratedCode($target, '<?php ');
@@ -57,7 +57,7 @@ public function literal($type) {
5757
* - Binary expression where left- and right hand side are literals
5858
*
5959
* @see https://wiki.php.net/rfc/const_scalar_exprs
60-
* @param lang.ast.Result $result
60+
* @param lang.ast.emit.Result $result
6161
* @param lang.ast.Node $node
6262
* @return bool
6363
*/
@@ -116,11 +116,11 @@ protected function constantType($type) {
116116
/**
117117
* Enclose a node inside a closure
118118
*
119-
* @param lang.ast.Result $result
119+
* @param lang.ast.emit.Result $result
120120
* @param lang.ast.Node $node
121121
* @param ?lang.ast.nodes.Signature $signature
122122
* @param bool $static
123-
* @param function(lang.ast.Result, lang.ast.Node): void $emit
123+
* @param function(lang.ast.emit.Result, lang.ast.Node): void $emit
124124
*/
125125
protected function enclose($result, $node, $signature, $static, $emit) {
126126
$capture= [];
@@ -159,7 +159,7 @@ protected function enclose($result, $node, $signature, $static, $emit) {
159159
/**
160160
* Emits local initializations
161161
*
162-
* @param lang.ast.Result $result
162+
* @param lang.ast.emit.Result $result
163163
* @param [:lang.ast.Node] $init
164164
* @return void
165165
*/
@@ -175,7 +175,7 @@ protected function emitInitializations($result, $init) {
175175
* Convert blocks to IIFEs to allow a list of statements where PHP syntactically
176176
* doesn't, e.g. `fn`-style lambdas or match expressions.
177177
*
178-
* @param lang.ast.Result $result
178+
* @param lang.ast.emit.Result $result
179179
* @param lang.ast.Node $expression
180180
* @return void
181181
*/
@@ -1208,15 +1208,4 @@ protected function emitFrom($result, $from) {
12081208
$result->out->write('yield from ');
12091209
$this->emitOne($result, $from->iterable);
12101210
}
1211-
1212-
/**
1213-
* Emit single nodes
1214-
*
1215-
* @param lang.ast.Result $result
1216-
* @param lang.ast.Node $node
1217-
* @return void
1218-
*/
1219-
public function emitOne($result, $node) {
1220-
parent::emitOne($result->at($node->line), $node);
1221-
}
12221211
}

src/main/php/lang/ast/emit/Result.class.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
class Result implements Closeable {
88
public $out;
99
public $codegen;
10+
public $line= 1;
1011
public $locals= [];
1112

1213
/**
@@ -31,6 +32,19 @@ public function from($file) {
3132
return $this;
3233
}
3334

35+
/**
36+
* Forwards output line to given line number
37+
*
38+
* @param int $line
39+
* @return self
40+
*/
41+
public function at($line) {
42+
if ($line > $this->line) {
43+
$this->out->write(str_repeat("\n", $line - $this->line));
44+
$this->line= $line;
45+
}
46+
return $this;
47+
}
3448

3549
/**
3650
* Initialize result. Guaranteed to be called *once* from constructor.

0 commit comments

Comments
 (0)