Fixing up smalltalk to the point where it can run fib, slowly

db4
Slava Pestov 2009-04-01 02:47:51 -05:00
parent 8ab7328899
commit 3885ba02a6
9 changed files with 57 additions and 29 deletions

View File

@ -45,5 +45,9 @@ M: ast-sequence arguments>> drop { } ;
[ ast-cascade boa ]
if ;
! Methods return self by default
: <ast-method> ( class arguments body -- method )
self suffix <ast-block> ast-method boa ;
TUPLE: symbol { name string } ;
MEMO: intern ( name -- symbol ) symbol boa ;

View File

@ -21,11 +21,22 @@ M: ast-name compile-ast name>> swap lookup-reader ;
: compile-arguments ( lexenv ast -- quot )
arguments>> [ compile-ast ] with map [ ] join ;
M: ast-message-send compile-ast
[ compile-arguments ]
: compile-ifTrue:ifFalse: ( lexenv ast -- quot )
[ receiver>> compile-ast ]
[ nip selector>> selector>generic ]
2tri [ append ] dip suffix ;
[ compile-arguments ] 2bi
[ if ] 3append ;
M: ast-message-send compile-ast
dup selector>> {
{ "ifTrue:ifFalse:" [ compile-ifTrue:ifFalse: ] }
[
drop
[ compile-arguments ]
[ receiver>> compile-ast ]
[ nip selector>> selector>generic ]
2tri [ append ] dip suffix
]
} case ;
M: ast-cascade compile-ast
[ receiver>> compile-ast ]
@ -40,8 +51,8 @@ M: ast-cascade compile-ast
] 2bi append ;
M: ast-return compile-ast
value>> compile-ast
[ return-continuation get continue-with ] append ;
[ value>> compile-ast ] [ drop return>> 1quotation ] 2bi
[ continue-with ] 3append ;
: (compile-sequence) ( lexenv asts -- quot )
[ drop [ nil ] ] [
@ -106,7 +117,7 @@ M: ast-block compile-ast
[ lexenv self>> suffix ] dip <lambda> ;
: compile-method-body ( lexenv block -- quot )
[ [ (compile-method-body) ] [ arguments>> length 1+ ] bi ] keep
[ [ (compile-method-body) ] [ arguments>> length 1+ ] bi ] 2keep
make-return ;
: compile-method ( lexenv ast-method -- )
@ -115,7 +126,7 @@ M: ast-block compile-ast
2bi define ;
: <class-lexenv> ( class -- lexenv )
<lexenv> swap >>class "self" <local-reader> >>self ;
<lexenv> swap >>class "self" <local> >>self "^" <local> >>return ;
M: ast-class compile-ast
nip
@ -136,5 +147,5 @@ M: ast-foreign compile-ast
[ nil ] ;
: compile-smalltalk ( statement -- quot )
[ [ empty-lexenv ] dip compile-sequence nip 0 ]
keep make-return ;
[ empty-lexenv ] dip [ compile-sequence nip 0 ]
2keep make-return ;

View File

@ -10,7 +10,7 @@ IN: smalltalk.compiler.lexenv
! self: word or f for top-level forms
! class: class word or f for top-level forms
! method: generic word or f for top-level forms
TUPLE: lexenv local-readers local-writers self class method ;
TUPLE: lexenv local-readers local-writers self return class method ;
: <lexenv> ( -- lexenv ) lexenv new ; inline
@ -21,6 +21,7 @@ CONSTANT: empty-lexenv T{ lexenv }
[ [ local-readers>> ] bi@ assoc-union >>local-readers ]
[ [ local-writers>> ] bi@ assoc-union >>local-writers ]
[ [ self>> ] either? >>self ]
[ [ return>> ] either? >>return ]
[ [ class>> ] either? >>class ]
[ [ method>> ] either? >>method ]
} 2cleave ;

View File

@ -0,0 +1,3 @@
USING: smalltalk.parser smalltalk.compiler.return tools.test ;
[ t ] [ "(i <= 1) ifTrue: [^1] ifFalse: [^((Fib new i:(i-1)) compute + (Fib new i:(i-2)) compute)]" parse-smalltalk need-return-continuation? ] unit-test

View File

@ -1,8 +1,8 @@
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays combinators.short-circuit continuations
fry generalizations kernel locals.rewrite.closures namespaces
sequences smalltalk.ast ;
fry generalizations kernel locals locals.types locals.rewrite.closures
namespaces make sequences smalltalk.ast ;
IN: smalltalk.compiler.return
SYMBOL: return-continuation
@ -17,13 +17,13 @@ M: ast-message-send need-return-continuation?
{
[ receiver>> need-return-continuation? ]
[ arguments>> need-return-continuation? ]
} 1&& ;
} 1|| ;
M: ast-cascade need-return-continuation?
{
[ receiver>> need-return-continuation? ]
[ messages>> need-return-continuation? ]
} 1&& ;
} 1|| ;
M: ast-message need-return-continuation?
arguments>> need-return-continuation? ;
@ -38,13 +38,8 @@ M: array need-return-continuation? [ need-return-continuation? ] any? ;
M: object need-return-continuation? drop f ;
: make-return ( quot n block -- quot )
need-return-continuation? [
'[
[
_ _ ncurry
[ return-continuation set ] prepose callcc1
] with-scope
]
] [ drop ] if
rewrite-closures first ;
:: make-return ( quot n lexenv block -- quot )
block need-return-continuation? [
quot clone [ lexenv return>> <def> '[ _ ] prepend ] change-body
n '[ _ _ ncurry callcc1 ]
] [ quot ] if rewrite-closures first ;

View File

@ -1,5 +1,5 @@
IN: smalltalk.eval.tests
USING: smalltalk.eval tools.test io.streams.string ;
USING: smalltalk.eval tools.test io.streams.string kernel ;
[ 3 ] [ "1+2" eval-smalltalk ] unit-test
[ "HAI" ] [ "(1<10) ifTrue:['HAI'] ifFalse:['BAI']" eval-smalltalk ] unit-test
@ -7,3 +7,5 @@ USING: smalltalk.eval tools.test io.streams.string ;
[ 6 "5\n6\n" ] [ [ "[:x|x print] value: 5; value: 6" eval-smalltalk ] with-string-writer ] unit-test
[ 5 ] [ "|x| x:=5. x" eval-smalltalk ] unit-test
[ 11 ] [ "[:i| |x| x:=5. i+x] value: 6" eval-smalltalk ] unit-test
[ t ] [ "class Blah [method foo [5]]. Blah new foo" eval-smalltalk tuple? ] unit-test
[ 196418 ] [ "vocab:smalltalk/eval/fib.st" eval-smalltalk-file ] unit-test

View File

@ -0,0 +1,11 @@
class Fib [
|i|
method i: newI [i:=newI].
method compute [
(i <= 1)
ifTrue: [^1]
ifFalse: [^((Fib new i:(i-1)) compute + (Fib new i:(i-2)) compute)]
].
].
[(Fib new i: 26) compute] time

View File

@ -1,5 +1,6 @@
IN: smalltalk.parser.tests
USING: smalltalk.parser smalltalk.ast peg.ebnf tools.test accessors
USING: smalltalk.parser smalltalk.ast
peg.ebnf tools.test accessors
io.files io.encodings.ascii kernel ;
EBNF: test-Character
@ -296,4 +297,4 @@ test = <foreign parse-smalltalk LocalVariableDeclarationList>
[ ] [ "class Foo []. Tests blah " parse-smalltalk drop ] unit-test
[ ] [ "vocab:smalltalk/parser/test.st" ascii file-contents parse-smalltalk drop ] unit-test
[ ] [ "vocab:smalltalk/parser/test.st" ascii file-contents parse-smalltalk drop ] unit-test

View File

@ -200,7 +200,7 @@ MethodDeclaration = OptionalWhiteSpace "method" OptionalWhiteSpace MethodHeader:
OptionalWhiteSpace "["
ExecutableCode:code
"]"
=> [[ header first2 code <ast-block> ast-method boa ]]
=> [[ header first2 code <ast-method> ]]
ClassDeclaration = OptionalWhiteSpace "class" OptionalWhiteSpace Identifier:name
OptionalWhiteSpace