Paste: joy

Author: inforichland
Mode: factor
Date: Mon, 3 Aug 2009 04:27:56
Plain Text |
! Copyright (C) 2009 Tim Wawrzynczak
! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces sequences accessors
joy.ast joy.parser joy.pprint vectors
combinators math assocs math.ranges random 
quotations prettyprint math.functions 
calendar math.order macros generalizations fry 
parser words stack-checker ;

IN: joy.eval

TUPLE: joy-env env { dstack vector } { rstack vector } ;

SYMBOL: joy

! 
! utilities
! 

MACRO: preserving ( quot -- )
    [ infer in>> length ] keep '[ _ ndup @ ] ;

: ifte ( pred t f -- )
    [ preserving ] 2dip if ; inline

! words for dealing with the joy environment

: default-env ( -- env )
    [ ] H{ } make-assoc ;

: dstack-empty? ( -- ? )
    joy get dstack>> empty? ;

: dstack-push ( value -- )
    joy get dstack>> push ;

: dstack-pop* ( -- value )
    joy get dstack>> pop ;

: dstack-pop ( -- )
    dstack-pop* drop ; inline

! evaluation

: eval-identifier ( identifier -- )
    joy get env>> at
    [ call ] [ "Invalid word!" throw ] if* ; inline

: add-word-to-env ( [quot-name] -- )
    [ first ] [ second ] bi
    joy get env>> set-at ;

! generic eval word

GENERIC: (@eval) ( ast -- )

M: ast-string (@eval) ( ast -- )
    string>> dstack-push ; inline

M: ast-number (@eval) ( ast -- )
    num>> dstack-push ; inline

M: ast-character (@eval) ( ast -- )
    char>> dstack-push ; inline

M: ast-identifier (@eval) ( ast -- )
    name>> eval-identifier ; inline

M: ast-quotation (@eval) ( ast -- )
    body>> >quotation dstack-push ; inline

M: ast-special (@eval) ( ast -- )
    value>> eval-identifier ; inline

M: ast-boolean (@eval) ( ast -- )
    value>> dstack-push ; inline

!
! helper functions
!
: unop ( quot -- )
    dstack-pop*
    swap call
    dstack-push ; inline

: binop ( quot -- )
    dstack-pop*
    dstack-pop* swap
    rot call
    dstack-push ; inline

! *************************************
! words you can use
! *************************************

! stack shuffling words

: dup-joy ( -- )
    dstack-pop* dup
    dstack-push
    dstack-push ; inline

: swap-joy ( -- )
    dstack-pop* dstack-pop*
    swap
    dstack-push dstack-push ; inline

: (dip-joy) ( quot -- )
    dstack-pop* ! pop TOS
    [ [ (@eval) ] each ] dip
    dstack-push ; inline ! push back on to TOS

: dip-joy ( -- )
    dstack-pop* dup
    quotation?
    [ (dip-joy) ] [ drop "Not a quotation!" throw ] if ; inline

: rollup-joy ( -- ) ! X Y Z -- Z X Y (1 2 3 -- 3 1 2)
    dstack-pop* dstack-pop* dstack-pop* ! z y x (3 2 1)
    [ swap ] dip swap ! 2 1 3
    dstack-push dstack-push dstack-push ; inline

: rolldown-joy ( -- ) ! X Y Z -- Y Z X (1 2 3 -- 2 3 1)
    dstack-pop* dstack-pop* dstack-pop* ! z y x (3 2 1)
    swap [ swap ] dip ! 1 3 2
    dstack-push dstack-push dstack-push ; inline

: rotate-joy ( -- ) ! X Y Z -- Z Y X (1 2 3 -- 3 2 1)
    dstack-pop* dstack-pop* dstack-pop* ! z y x (3 2 1)
    [ swap ] dip swap [ swap ] dip
    dstack-push dstack-push dstack-push ; inline

: dupd-joy ( -- ) dstack-pop* dup-joy dstack-push ; inline

: swapd-joy ( -- ) dstack-pop* swap-joy dstack-push ; inline

: rollupd-joy ( -- ) dstack-pop* rollup-joy dstack-push ; inline

: rolldownd-joy ( -- ) dstack-pop* rolldown-joy dstack-push ; inline

: rotated-joy ( -- ) dstack-pop* rotate-joy dstack-push ; inline

: pop-joy ( -- ) dstack-pop ; inline

: popd-joy ( -- ) dstack-pop* pop-joy dstack-push ; inline

: print-joy ( -- ) dstack-pop* pprint ; inline

! logic words

: or-joy ( -- )
    dstack-pop* dstack-pop* 
    {
        { [ dup boolean? ] [ or dstack-push ] }
        { [ dup number? ] [ [ 0 = ] bi@ and not dstack-push ] }
        [ 2drop "Invalid operands for 'or'!" throw ]
    } cond ; inline

: and-joy ( -- )
    dstack-pop* dstack-pop*
    {
        { [ dup boolean? ] [ and dstack-push ] }
        { [ dup number? ] [ [ 0 = ] bi@ or not dstack-push ] }
        [ 2drop "Invalid operands for 'and'!" throw ]
    } cond ; inline

: xor-joy ( -- )
    dstack-pop* dstack-pop*
    {
        { [ dup boolean? ] [ xor dstack-push ] }
        { [ dup number? ] [ = not dstack-push ] }
        [ 2drop "Invalid operands for 'xor'!" throw ]
    } cond ; inline 

! miscellaneous words

: false-joy ( -- ) f dstack-push ; inline
: true-joy  ( -- ) t dstack-push ; inline

: rand-joy ( -- ) 1 32767 [a,b] random dstack-push ; inline

: id-joy ( -- ) ; inline

: time-joy ( -- )
    now
    1970 1 1 0 0 0 0 hours <timestamp>
    time- duration>seconds floor dstack-push ; inline

! unary operations

: (sign) ( n -- n' )
    {
        { [ dup 0 > ] [ drop 1 ] }
        { [ dup 0 < ] [ drop -1 ] }
        [ drop 0 ]
    } cond ; inline
    
: sign-joy ( -- ) [ (sign) ] unop ; inline
: neg-joy ( -- ) [ 0 swap - ] unop ; inline
: abs-joy ( -- ) [ abs ] unop ; inline

! trig functions

: cos-joy ( -- ) [ cos ] unop ; inline
: sin-joy ( -- ) [ sin ] unop ; inline
: tan-joy ( -- ) [ tan ] unop ; inline
: acos-joy ( -- ) [ acos ] unop ; inline
: asin-joy ( -- ) [ asin ] unop ; inline
: atan-joy ( -- ) [ atan ] unop ; inline
: cosh-joy ( -- ) [ cosh ] unop ; inline
: sinh-joy ( -- ) [ sinh ] unop ; inline
: tanh-joy ( -- ) [ tanh ] unop ; inline

! binary operations

: +-joy ( -- ) [ + ] binop ; inline
: --joy ( -- ) [ - ] binop ; inline
: *-joy ( -- ) [ * ] binop ; inline
: /-joy ( -- ) [ / ] binop ; inline
: rem-joy ( -- ) [ mod ] binop ; inline
: div-joy ( -- ) [ /mod ] binop dstack-push ; inline
: ceil-joy ( -- ) [ ceiling ] unop ; inline
: floor-joy ( -- ) [ floor ] unop ; inline
: exp-joy ( -- ) [ exp ] unop ; inline
: trunc-joy ( -- ) [ truncate ] unop ; inline
: pred-joy ( -- ) [ 1 - ] unop ; inline
: succ-joy ( -- ) [ 1 + ] unop ; inline
: max-joy ( -- ) [ max ] binop ; inline
: min-joy ( -- ) [ min ] binop ; inline

! regenerate the environment
: (env) ( -- )
    joy-env new default-env >>env
    V{ } clone >>dstack
    V{ } clone >>rstack
    joy set ;

: env ( -- )
    (env)
    ! add words to the environment
    {
        { [ +-joy ] "+" }
        { [ --joy ] "-" }
        { [ *-joy ] "*" }
        { [ /-joy ] "/" }
        { [ rand-joy ] "rand" }
        { [ time-joy ] "time" }

        { [ dup-joy ] "dup" }
        { [ swap-joy ] "swap" }
        { [ dip-joy ] "dip" }
        { [ pop-joy ] "pop" }
        { [ print-joy ] "." }
        { [ rollup-joy ] "rollup" }
        { [ rolldown-joy ] "rolldown" }
        { [ rotate-joy ] "rotate" }
        { [ dupd-joy ] "dupd" }
        { [ swapd-joy ] "swapd" }
        { [ rollupd-joy ] "rollupd" }
        { [ rolldownd-joy ] "rolldownd" }
        { [ rotated-joy ] "rotated" }
        { [ popd-joy ] "popd" }
        { [ id-joy ] "id" }

        { [ or-joy ] "or" }
        { [ and-joy ] "and" }
        { [ xor-joy ] "xor" }

        { [ rem-joy ] "rem" }
        { [ div-joy ] "div" }
        { [ sign-joy ] "sign" }
        { [ neg-joy ] "neg" }
        { [ ceil-joy ] "ceil" }
        { [ floor-joy ] "floor" }
        { [ abs-joy ] "abs" }
        { [ exp-joy ] "exp" }
        { [ trunc-joy ] "trunc" }
        { [ pred-joy ] "pred" }
        { [ succ-joy ] "succ" }
        { [ max-joy ] "max" }
        { [ min-joy ] "min" }

        { [ cos-joy ] "cos" }
        { [ sin-joy ] "sin" }
        { [ tan-joy ] "tan" }
        { [ cosh-joy ] "cosh" }
        { [ sinh-joy ] "sinh" }
        { [ tanh-joy ] "tanh" }
        { [ acos-joy ] "acos" }
        { [ asin-joy ] "asin" }
        { [ atan-joy ] "atan" }
        
    } [ add-word-to-env ] each ;

! actual eval 

: (eval) ( string -- )
    parse-joy
    [ (@eval) ] each ;

: eval ( string -- )
    env ! new environment
    (eval) ;

New Annotation

Summary:
Author:
Mode:
Body: