Skip to content

Commit e39e7f2

Browse files
functions partially implemented
1 parent c75da7b commit e39e7f2

File tree

7 files changed

+161
-6
lines changed

7 files changed

+161
-6
lines changed

Diff for: package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
<filein>src/Parser.st</filein>
1818
<filein>src/RuntimeError.st</filein>
1919
<filein>src/Environment.st</filein>
20+
<filein>src/Callable.st</filein>
2021
<filein>src/Interpreter.st</filein>
2122
</package>

Diff for: src/Callable.st

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Object subclass: Callable [
2+
<comment: 'My instances can be called.'>
3+
call: anInterpreter arguments: someArguments [
4+
"Evaluate the function/class call"
5+
6+
<category: 'evaluation'>
7+
self subclassResponsibility
8+
]
9+
10+
arity [
11+
<category: 'evaluation'>
12+
self subclassResponsibility
13+
]
14+
]
15+
16+
Callable subclass: Clock [
17+
<comment: 'A native function to measure time'>
18+
call: anInterpreter arguments: someArguments [
19+
"Evaluate the clock() function call, returning seconds since
20+
midnight 01/01/1901"
21+
22+
<category: 'evaluation'>
23+
^Time secondClock
24+
]
25+
26+
arity [
27+
<category: 'evaluation'>
28+
^0
29+
]
30+
]
31+
32+
Eval [
33+
Time initialize
34+
]

Diff for: src/Expr.st

+47
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,53 @@ Expr subclass: ExprBinary [
8787
]
8888
]
8989

90+
Expr subclass: ExprCall [
91+
| callee paren arguments |
92+
93+
ExprCall class >> callee: aCallee paren: aParen arguments: anArguments [
94+
<category: 'instance creation'>
95+
^self new
96+
callee: aCallee;
97+
paren: aParen;
98+
arguments: anArguments;
99+
yourself.
100+
]
101+
102+
callee: aCallee [
103+
<category: 'setter'>
104+
callee := aCallee.
105+
]
106+
107+
callee [
108+
<category: 'getter'>
109+
^callee.
110+
]
111+
112+
paren: aParen [
113+
<category: 'setter'>
114+
paren := aParen.
115+
]
116+
117+
paren [
118+
<category: 'getter'>
119+
^paren.
120+
]
121+
122+
arguments: anArguments [
123+
<category: 'setter'>
124+
arguments := anArguments.
125+
]
126+
127+
arguments [
128+
<category: 'getter'>
129+
^arguments.
130+
]
131+
132+
accept: aVisitor [
133+
^aVisitor visitCallExpr: self.
134+
]
135+
]
136+
90137
Expr subclass: ExprGrouping [
91138
| expression |
92139

Diff for: src/Interpreter.st

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Object subclass: Interpreter [
2-
| environment |
2+
| environment globals |
33
<comment: 'My instances are evaluators for the Lox programming language.'>
44

55
Interpreter class >> new [
@@ -16,7 +16,9 @@ Object subclass: Interpreter [
1616
"Initialize the interpreter environment"
1717

1818
<category: 'initialization'>
19-
environment := Environment new.
19+
globals := Environment new.
20+
globals define: 'clock' value: Clock new.
21+
environment := globals
2022
]
2123

2224
interpret: statements [
@@ -300,4 +302,28 @@ Object subclass: Interpreter [
300302
"Unreachable"
301303
^nil
302304
]
305+
306+
visitCallExpr: expr [
307+
"Evaluate a functional call expression"
308+
309+
<category: 'evaluation'>
310+
| callee arguments function |
311+
callee := self evaluate: (expr callee).
312+
(callee isKindOf: Callable) ifFalse: [
313+
^RuntimeError
314+
error: (expr paren)
315+
message: 'Can only call functions and classes.'
316+
].
317+
318+
arguments := OrderedCollection new.
319+
(expr arguments) do: [ :each | arguments add: (self evaluate: each) ].
320+
(arguments size ~= callee arity) ifTrue: [
321+
^RuntimeError
322+
error: (expr paren)
323+
message: 'Expected ' , callee arity displayString ,
324+
' arguments but got ' , arguments size displayString , '.'
325+
].
326+
327+
^callee call: self arguments: arguments
328+
]
303329
]

Diff for: src/Lox.st

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ either running programs from source or providing an interactive interpreter.'>
2121

2222
<category: 'debugging'>
2323
stderr
24-
nextPutAll: '[line ', aLine displayString, '] Error' , aLocation , ': ' , aMessage;
24+
nextPutAll: '[line ', aLine displayString ,
25+
'] Error' , aLocation , ': ' , aMessage;
2526
nl;
2627
flush.
2728
hadError := true
@@ -41,7 +42,10 @@ either running programs from source or providing an interactive interpreter.'>
4142
aToken type = #EOF ifTrue: [
4243
Lox report: aToken line where: ' at end' message: aMessage.
4344
] ifFalse: [
44-
Lox report: aToken line where: (' at ''' , aToken lexeme , '''') message: aMessage.
45+
Lox
46+
report: aToken line
47+
where: (' at ''' , aToken lexeme , '''')
48+
message: aMessage.
4549
]
4650
]
4751

Diff for: src/Parser.st

+44-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ the Lox programming language.'>
168168
self consume: #LeftParen expect: 'Expect ''('' after ''for''.'.
169169

170170
(self match: #(#Semicolon)) ifTrue: [ ini := nil ].
171-
(self match: #(#Var)) ifTrue: [
171+
(self match: #(#Var)) ifTrue: [
172172
ini := self varDeclaration
173173
] ifFalse: [
174174
ini := self expressionStatement
@@ -389,7 +389,49 @@ the Lox programming language.'>
389389
right := self unary.
390390
^ExprUnary operator: operator right: right
391391
].
392-
^self primary.
392+
^self call.
393+
]
394+
395+
finishCall: callee [
396+
"Helper to parse function arguments"
397+
398+
<category: 'helper'>
399+
| arguments paren |
400+
arguments := OrderedCollection new.
401+
(self check: #RightParen) ifFalse: [
402+
arguments add: (self expression).
403+
[ self match: #(#Comma) ] whileTrue: [
404+
((arguments size) >= 255) ifTrue: [
405+
^ParseError
406+
error: (self peek)
407+
message: 'Can''t have more than 255 arguments'
408+
].
409+
arguments add: (self expression)
410+
]
411+
].
412+
413+
paren := self
414+
consume: #RightParen
415+
expect: 'Expect '')'' after arguments.'.
416+
^ExprCall callee: callee paren: paren arguments: arguments.
417+
]
418+
419+
call [
420+
"Grammar rule for a function call"
421+
422+
<category: 'rule'>
423+
| expr done |
424+
expr := self primary.
425+
done := false.
426+
[ done ] whileFalse: [
427+
(self match: #(#LeftParen)) ifTrue: [
428+
expr := self finishCall: expr
429+
] ifFalse: [
430+
done := true
431+
]
432+
].
433+
434+
^expr.
393435
]
394436

395437
primary [

Diff for: tool/generate_ast

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class code for different types of node in the Lox abstract syntax tree'>
2222
base: 'Expr'
2323
types: #('Assign: name value'
2424
'Binary: left operator right'
25+
'Call: callee paren arguments'
2526
'Grouping: expression'
2627
'Literal: value'
2728
'Logical: left operator right'

0 commit comments

Comments
 (0)