Skip to content

Commit dea153a

Browse files
committed
Compiler: Allow local variables in blocks #51
E.g. this code: [ | a | a := 1. a + 1 ] value. Will return 2.
1 parent f93c385 commit dea153a

3 files changed

Lines changed: 28 additions & 5 deletions

File tree

Compiler/src/ClassCompiler.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export class ClassCompiler
204204
{
205205
while( !this.parser.atMethodEnd() ) {
206206
this.compileConstructor();
207-
this.compileLocalVariables();
207+
this.compileMethodVariables();
208208
this.compileStatements();
209209
}
210210

@@ -222,16 +222,16 @@ export class ClassCompiler
222222
this.method.body.add( node );
223223
}
224224

225-
private compileLocalVariables()
225+
private compileMethodVariables()
226226
{
227227
if( !this.parser.tryParseTerm( "|" ) )
228228
return;
229229

230230
while( !this.parser.tryParseTerm( "|" ) )
231-
this.compileLocalVariable();
231+
this.compileVariable();
232232
}
233233

234-
private compileLocalVariable()
234+
private compileVariable(): SourceNode
235235
{
236236
let variableName: string = this.parser.parseVariableName();
237237

@@ -248,8 +248,10 @@ export class ClassCompiler
248248
compiledVariable.node = this.sourceNode( source, "variable" );
249249

250250
this.method.vars.push( compiledVariable );
251+
return compiledVariable.node;
251252
}
252253

254+
253255
private compileStatements()
254256
{
255257
while( !this.parser.atMethodEnd() ) {
@@ -379,18 +381,22 @@ export class ClassCompiler
379381
let node = this.sourceNode( "stBlock$class.$fromJs$( " + asyncString + "( ", "block" );
380382

381383
let oldArgs = this.method.args.slice();
384+
let oldVars = this.method.vars.slice();
382385

383386
if( this.parser.peekTerm() == ":" )
384387
this.compileBlockArguments( node );
385388

386389
node.add( " ) => {\n" );
387390

391+
this.compileBlockVariables( node );
392+
388393
while( ! this.parser.tryParseTerm( "]" ) )
389394
node.add( this.compileBlockStatement() );
390395

391396
node.add( "\t\t\t} )" );
392397

393398
this.method.args = oldArgs;
399+
this.method.vars = oldVars;
394400

395401
this.addClassReferenceToClassAndMethod( "Block" );
396402

@@ -416,6 +422,19 @@ export class ClassCompiler
416422
this.parser.mustParseTerm( "|" );
417423
}
418424

425+
// Parse block local variables and add them to method variables (temporarily).
426+
427+
compileBlockVariables( node: SourceNode )
428+
{
429+
if( !this.parser.tryParseTerm( "|" ) )
430+
return;
431+
432+
while( !this.parser.tryParseTerm( "|" ) ) {
433+
node.add( "\t\t" );
434+
node.add( this.compileVariable() );
435+
}
436+
}
437+
419438
// A block statement consists of an expression,
420439
// possibly preceded by the return operator "^".
421440

Smalltalk/Core/Base/Object.st

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ CLASSMETHODS
1111
async myTest
1212
"This is the first method compiled.
1313
Can be changed when testing the compiler."
14-
await 1 + 2.
14+
| result |
15+
result := [ | a | a := 1. a + 1 ] value.
1516
!
1617

1718
"Creating"

Smalltalk/Core/Base/Test/TestBlock.st

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ test
1616
num := 0.
1717
[ num < 3 ] whileTrue: [ num := num + 1 ].
1818
self assert: [ num = 3 ].
19+
20+
num := [ | a | a := 1. a + 1 ] value.
21+
self assert: [ num = 2 ].
1922
!
2023
async testValueAwait
2124
| result |

0 commit comments

Comments
 (0)