Extract common parsing code
This commit is contained in:
@@ -269,18 +269,18 @@ by prepending the word "temp" to that number. We start
|
||||
with `temp0`, then `temp1`, and so on. To keep a counter,
|
||||
we can use a state monad:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 269 269 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 230 230 >}}
|
||||
|
||||
Don't worry about the `Map.Map String [String]`, we'll get to that in a bit.
|
||||
For now, all we have to worry about is the second element of the tuple,
|
||||
the integer counting how many temporary variables we've used. We can
|
||||
get the current temporary variable as follows:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 271 274 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 232 235 >}}
|
||||
|
||||
We can also get a fresh temporary variable like this:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 276 279 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 237 240 >}}
|
||||
|
||||
Now, the
|
||||
{{< sidenote "left" "code-note" "code" >}}
|
||||
@@ -297,7 +297,7 @@ source code for the blog (which includes this project)
|
||||
<a href="https://dev.danilafe.com/Web-Projects/blog-static">here</a>.
|
||||
{{< /sidenote >}}
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 364 369 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 325 330 >}}
|
||||
|
||||
##### Implementing "lazy evaluation"
|
||||
Lazy evaluation in functional programs usually arises from
|
||||
@@ -344,20 +344,20 @@ and also of the dependencies of each variable (the variables that need
|
||||
to be access before the variable itself). We compute such a map for
|
||||
each selector as follows:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 337 337 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 298 298 >}}
|
||||
|
||||
We update the existing map using `Map.union`:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 338 338 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 299 299 >}}
|
||||
|
||||
And, after we're done generating expressions in the body of this selector,
|
||||
we clear it to its previous value `vs`:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 341 341 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 302 302 >}}
|
||||
|
||||
We generate a single selector as follows:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 307 320 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 268 281 >}}
|
||||
|
||||
This generates a function definition statement, which we will examine in
|
||||
generated Python code later on.
|
||||
@@ -366,7 +366,7 @@ Solving the problem this way also introduces another gotcha: sometimes,
|
||||
a variable is produced by a function call, and other times the variable
|
||||
is just a Python variable. We write this as follows:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 322 327 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 283 288 >}}
|
||||
|
||||
##### Special Case Insertion
|
||||
This is a silly language for a single homework assignment. I'm not
|
||||
@@ -377,7 +377,7 @@ a list, it can also return the list from its base case. Thus,
|
||||
that's all we will try to figure out. The checking code is so
|
||||
short that we can include the whole snippet at once:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 258 266 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 219 227 >}}
|
||||
|
||||
`mergePossibleType`
|
||||
{{< sidenote "right" "bool-identity-note" "figures out" >}}
|
||||
@@ -404,7 +404,7 @@ My Haskell linter actually suggested a pretty clever way of writing
|
||||
the whole "add a base case if this function returns a list" code.
|
||||
Check it out:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 299 305 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageOne.hs" 260 266 >}}
|
||||
|
||||
Specifically, look at the line with `let fastReturn = ...`. It
|
||||
uses a list comprehension: we take a parameter `p` from the list of
|
||||
|
||||
@@ -87,14 +87,14 @@ time, and nor do we have to perform any fancy Python nested function declaration
|
||||
To keep with the Python convention of lowercase variables, we'll translate the
|
||||
uppercase "global" variables to lowercase. We'll do it like so:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageTwo.hs" 211 220 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageTwo.hs" 167 176 >}}
|
||||
|
||||
Note that we translated "L" and "R" to integer literals. We'll indicate the source of
|
||||
each element with an integer, since there's no real point to representing it with
|
||||
a string or a variable. We'll need to be aware of this when we implement the actual, generic
|
||||
mergesort code. Let's do that now:
|
||||
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageTwo.hs" 145 205 >}}
|
||||
{{< codelines "Haskell" "cs325-langs/src/LanguageTwo.hs" 101 161 >}}
|
||||
|
||||
This is probably the ugliest part of this assignment: we handwrote a Python
|
||||
AST in Haskell that implements mergesort with our augmentations. Note that
|
||||
|
||||
Reference in New Issue
Block a user