Skip to content

Instantly share code, notes, and snippets.

@ephe-meral
Forked from missingfaktor/joy-in-factor.factor
Created May 21, 2019 20:54
Show Gist options
  • Save ephe-meral/89c504c3e63b17d4bc0ab07b2a06f291 to your computer and use it in GitHub Desktop.
Save ephe-meral/89c504c3e63b17d4bc0ab07b2a06f291 to your computer and use it in GitHub Desktop.
! Fork from: http://paste.factorcode.org/paste?id=808
! 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) ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment