Skip to content

Commit

Permalink
Parse and execute for
Browse files Browse the repository at this point in the history
  • Loading branch information
cruessler committed Feb 8, 2024
1 parent 440a5af commit 730e674
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 8 deletions.
31 changes: 31 additions & 0 deletions app/elm/Compiler/Ast.elm
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Node
| Repeat Node (List Node)
| Until Node (List Node)
| Foreach Node (List Node)
| For String Node Node (List Node)
| Map Node (List Node)
| Filter Node (List Node)
| If Node (List Node)
Expand Down Expand Up @@ -161,6 +162,9 @@ typeOfCallee node =
Foreach _ _ ->
Command { name = "foreach" }

For _ _ _ _ ->
Command { name = "for" }

Map _ _ ->
Primitive { name = "map" }

Expand Down Expand Up @@ -606,6 +610,33 @@ compile context node =
]
|> List.concat

For variable start end children ->
let
compiledStart =
compileInContext (Expression { caller = "for" }) start

compiledEnd =
compileInContext (Expression { caller = "for" }) end

compiledChildren =
List.concatMap (compileInContext Statement) children
in
[ compiledStart
, [ StoreVariable variable ]
, compiledChildren
, [ PushVariable variable ]
, compiledEnd
, [ Eval2 { name = "greaterp", f = P.greaterp }
, JumpIfFalse 6
, PushVariable variable
, PushValue (Type.Int 1)
, Eval2 { name = "+", f = P.sum2 }
, StoreVariable variable
, Jump (List.length compiledChildren + List.length compiledEnd + 7 |> negate)
]
]
|> List.concat

Map iterator children ->
compileMap iterator children

Expand Down
21 changes: 21 additions & 0 deletions app/elm/Compiler/Parser.elm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Compiler.Parser exposing
, defaultState
, functionDefinition
, output
, statement
, term
, withExistingFunctions
)
Expand Down Expand Up @@ -279,6 +280,7 @@ statement state =
[ inParentheses state
, P.lazy (\_ -> ifElse state)
, P.lazy (\_ -> foreach state)
, P.lazy (\_ -> for state)
, P.lazy (\_ -> map state)
, P.lazy (\_ -> filter state)
, P.lazy (\_ -> repeat state)
Expand Down Expand Up @@ -395,6 +397,25 @@ foreach state =
P.lazy (\_ -> controlStructure state { keyword = "foreach", constructor = Ast.Foreach })


for : State -> Parser Ast.Node
for state =
P.inContext (Keyword "for") <|
P.succeed Ast.For
|. Helper.keyword "for"
|. Helper.spaces
|. Helper.symbol "["
|. Helper.maybeSpaces
|= Value.rawWordInList
|. Helper.spaces
|= booleanExpression state
|. Helper.spaces
|= booleanExpression state
|. Helper.maybeSpaces
|. Helper.symbol "]"
|. Helper.spaces
|= instructionList state


map : State -> Parser Ast.Node
map state =
P.lazy (\_ -> invertedControlStructure state { keyword = "map", constructor = Ast.Map })
Expand Down
19 changes: 11 additions & 8 deletions app/elm/Compiler/Parser/Value.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Compiler.Parser.Value exposing
( value
, wordOutsideList
( rawWordInList
, value
)

{-| This module provides functions for parsing Logo values.
Expand All @@ -22,7 +22,6 @@ import Parser.Advanced as P
, map
, oneOf
, succeed
, symbol
)
import Vm.Type as Type

Expand Down Expand Up @@ -117,8 +116,8 @@ valueInList =
]


wordInList : Parser context Problem Type.Value
wordInList =
rawWordInList : Parser context Problem String
rawWordInList =
let
isWordCharacter : Char -> Bool
isWordCharacter c =
Expand All @@ -136,10 +135,14 @@ wordInList =
&& (c /= '<')
&& (c /= '>')
in
((succeed ()
(succeed ()
|. chompIf isWordCharacter ExpectingStartOfWord
|. chompWhile isWordCharacter
)
|> getChompedString
)
|> getChompedString


wordInList : Parser context Problem Type.Value
wordInList =
rawWordInList
|> map Type.Word
28 changes: 28 additions & 0 deletions tests/Test/Parser.elm
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,31 @@ booleanAlgebra =
, parsesBooleanExpression "1 <> 1"
, parsesBooleanExpression "2 * (3 + 1) = (4 + 4) * 7"
]


parsesStatement : String -> Test
parsesStatement statement =
let
match : Result (List (DeadEnd context problem)) Ast.Node -> Expectation
match result =
case result of
Ok _ ->
Expect.pass

Err _ ->
Expect.fail <| "could not parse statement \"" ++ statement ++ "\""
in
test statement <|
\_ ->
match
(Parser.run (Parser.statement defaultState) statement)


controlStructures : Test
controlStructures =
describe "control structures" <|
[ describe "for" <|
[ parsesStatement "for [ i 0 10 ] [ print :i ]"
, parsesStatement "for [i 0 10] [ print :i ]"
]
]
8 changes: 8 additions & 0 deletions tests/Test/Run.elm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ foreachWithTemplateVariable =
]


for : Test
for =
describe "for" <|
[ printsLines "for [ i 0 3 ] [ print :i ]" [ "0", "1", "2", "3" ]
, printsLines "make \"a 0 make \"b 3 for [ i :a :b ] [ print :i ]" [ "0", "1", "2", "3" ]
]


map : Test
map =
describe "map" <|
Expand Down
2 changes: 2 additions & 0 deletions tests/Test/Run/Builtin.elm
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ primitives =
, describe "greaterp" <|
[ printsLine "print greaterp 1 1" "false"
, printsLine "print greater? 1 1" "false"
, printsLine "print greaterp 2 1" "true"
]
, describe "lessp" <|
[ printsLine "print lessp 1 1" "false"
, printsLine "print less? 1 1" "false"
, printsLine "print lessp 1 2" "true"
]
, describe "remainder" <|
[ printsLine "print remainder 1 1" "0" ]
Expand Down

0 comments on commit 730e674

Please sign in to comment.