Skip to content

Commit

Permalink
Eval built-in function: len
Browse files Browse the repository at this point in the history
  • Loading branch information
dwayne committed May 20, 2022
1 parent 64807df commit 37e8c2b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 14 deletions.
6 changes: 5 additions & 1 deletion src/Monkey/Environment.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Monkey.Environment exposing
( Environment
, empty
, empty, fromList

, LookupResult(..)
, lookup
Expand All @@ -23,6 +23,10 @@ empty : Environment k v
empty = Empty


fromList : List (k, v) -> Environment k v
fromList assocs = Many assocs Empty


type LookupResult v
= NotFound
| FoundValue v
Expand Down
57 changes: 44 additions & 13 deletions src/Monkey/Interpreter.elm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Value
| VArray (Array Value)
| VHash (Hash Value)
| VFunction Closure
| VBuiltInFunction BuiltInFunction


type alias Closure =
Expand All @@ -34,6 +35,9 @@ type alias Closure =
}


type alias BuiltInFunction = List Value -> Eval RuntimeError Value


type alias Env = Env.Environment P.Id Value


Expand Down Expand Up @@ -68,7 +72,7 @@ run input =
case P.parse input of
Ok program ->
evalProgram program
|> Eval.run Env.empty
|> Eval.run builtInFunctions
|> Result.map Tuple.second
|> Result.mapError RuntimeError

Expand Down Expand Up @@ -402,8 +406,15 @@ computeDiv valueA valueB =

evalCall : Value -> List Value -> Eval RuntimeError Value
evalCall value args =
expectFunction value
|> Eval.andThen (\closure -> applyClosure closure args)
case value of
VFunction closure ->
applyClosure closure args

VBuiltInFunction builtInFunction ->
builtInFunction args

_ ->
Eval.fail <| TypeError [TFunction] (typeOf value)


applyClosure : Closure -> List Value -> Eval RuntimeError Value
Expand Down Expand Up @@ -461,16 +472,6 @@ evalIndex valueA valueB =
Eval.fail <| TypeError [TArray, THash] (typeOf valueA)


expectFunction : Value -> Eval RuntimeError Closure
expectFunction value =
case value of
VFunction closure ->
Eval.succeed closure

_ ->
Eval.fail <| TypeError [TFunction] (typeOf value)


expectInt : Value -> Eval RuntimeError Int
expectInt value =
case value of
Expand Down Expand Up @@ -534,6 +535,9 @@ typeOf value =
VFunction _ ->
TFunction

VBuiltInFunction _ ->
TFunction


answerToString : Answer -> String
answerToString answer =
Expand Down Expand Up @@ -585,3 +589,30 @@ valueToString value =

VFunction _ ->
"<function>"

VBuiltInFunction _ ->
"<built-in-function>"


builtInFunctions : Env
builtInFunctions =
[ ("len", builtInLen)
]
|> List.map (Tuple.mapSecond VBuiltInFunction)
|> Env.fromList


builtInLen : BuiltInFunction
builtInLen args =
case args of
[VString s] ->
Eval.succeed <| VNum <| String.length s

[VArray a] ->
Eval.succeed <| VNum <| Array.length a

[arg] ->
Eval.fail <| TypeError [TString, TArray] (typeOf arg)

_ ->
Eval.fail <| ArgumentError 1 (List.length args)
39 changes: 39 additions & 0 deletions tests/Test/Monkey/Interpreter.elm
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ suite =
, infixSuite
, ifSuite
, functionSuite
, builtInFunctionsSuite
, answerToStringSuite
]

Expand Down Expand Up @@ -510,6 +511,44 @@ functionSuite =
]


builtInFunctionsSuite : Test
builtInFunctionsSuite =
describe "built-in functions"
[ describe "len"
[ makeGoodExamples
[ ( """
len("")
"""
, VNum 0
)
, ( """
len("four")
"""
, VNum 4
)
, ( """
len("hello world")
"""
, VNum 11
)
]

, makeBadExamples
[ ( """
len(1)
"""
, TypeError [TString, TArray] TInt
)
, ( """
len("one", "two")
"""
, ArgumentError 1 2
)
]
]
]


answerToStringSuite : Test
answerToStringSuite =
describe "answerToString"
Expand Down

0 comments on commit 37e8c2b

Please sign in to comment.