git @ Cat's Eye Technologies Quylthulg / 10c52d4
Fix README. Fix foreach(?). Add -m option. Add example program. Chris Pressey 4 years ago
4 changed file(s) with 38 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
7777 Data Types
7878 ----------
7979
80 ### Strings and Integers
80 ### Strings and Integers ###
8181
8282 Yes. Also a special type called `abort`, of which there is a single
8383 value `abort`, which you'll learn about later.
8484
85 ### Lists
85 ### Lists ###
8686
8787 The sole data structure of note in Quylthulg is the list. Lists are
8888 essentially identical to those found in other functional languages such
116116 will be no tolerance for variables. There will, however, be tolerance
117117 for `goto`s and labels; see below for more on that.
118118
119 ### Cyclic Lists
119 ### Cyclic Lists ###
120120
121121 Labels and the `goto` construct enable the definition of cyclic data
122122 structures like so:
133133 insist on being referred to in `goto`s by the `$` syntax used for
134134 identifiers.
135135
136 ### List Operators
136 ### List Operators ###
137137
138138 The values contained in a `cons` cell can be extracted by the felicitous
139139 use of the binary operators `<` ('first') and `>` ('rest'). For both of
179179 (sub)list, `foreach` will begin traversing that (sub)list (with the
180180 same body and current accumulator, natch) instead of passing the
181181 (sub)list to the body; and
182 - *abortable*, meaning that the callback may evaluate to a special
182 - *abortable*, meaning that the loop-expr may evaluate to a special
183183 value `abort`, which causes traversal of the current (sub)list to
184184 cease immediately, returning to the traversal of the containing
185185 list, if any.
314314
315315 For example,
316316
317 foreach $x$ = :L:[1, 2, 3, goto L] with $a$ = 0 be $x$ else be null
317 foreach $x$ = :L:[1, 2, 3, goto $L$] with $a$ = 0 be $x$ else be null
318318
319319 never finishes evaluating, and in the body, `$x$` takes on the
320320 values 1, 2, 3, 1, 2, 3, ... ad infinitum.
0 foreach $x$ = :L:[1, 2, 3, goto $L$] with $a$ = 0 be $x$ else be null
55 main = do
66 args <- getArgs
77 case args of
8 ["-m", fileName] -> do
9 c <- readFile fileName
10 mrun c
11 return ()
812 [fileName] -> do
913 c <- readFile fileName
1014 putStrLn $ showRun c
1115 return ()
1216 _ -> do
13 putStrLn "Usage: qlzqqlzuup <filename.quylthulg>"
17 putStrLn "Usage: qlzqqlzuup [-m] <filename.quylthulg>"
7878 | Abort
7979 deriving (Show, Ord, Eq)
8080
81 isCons (Cons _ _) = True
82 isCons _ = False
83
8184 follow lenv (Label _ x) = follow lenv x
8285 follow lenv (Goto label) = follow lenv (findVal lenv label)
8386 follow lenv y = y
87
88 followSplit lenv (Cons first rest) =
89 if (follow lenv first) == first then
90 (first, follow lenv rest)
91 else
92 if isCons (follow lenv first) then
93 followSplit lenv (follow lenv first)
94 else
95 (follow lenv first, follow lenv rest)
8496
8597 --
8698 -- Terms support a number of operations which require the "meaning" of the
212224 qForEach list acc
213225 where
214226 qForEach Null acc = acc
227 qForEach (Label _ x) acc = qForEach x acc
215228 qForEach (Cons first@(Cons _ _) rest) acc =
229 -- "recursing"
216230 let
217231 first' = follow lenv first
218232 deepResult = qForEach first' acc
220234 nextResult = qForEach rest newAcc
221235 in
222236 follow lenv nextResult
223 qForEach (Cons first rest) acc =
237 qForEach term@(Cons first rest) acc =
224238 let
225 first' = follow lenv first
239 (first', rest') = followSplit lenv term
226240 env' = extendEnv env accvar acc
227241 env'' = extendEnv env' loopvar first'
228242 result = interpret env'' lenv applyExpr
229243 newAcc = follow lenv result
230 nextResult = qForEach rest newAcc
244 nextResult = qForEach rest' newAcc
231245 in
232246 if newAcc == Abort then
247 -- "abortable"
233248 acc
234249 else
235250 follow lenv nextResult
266281 where
267282 mqForEach Null acc =
268283 return acc
284 mqForEach (Label _ x) acc =
285 mqForEach x acc
269286 mqForEach (Cons first@(Cons _ _) rest) acc = do
287 -- "recursing"
270288 deepResult <- mqForEach (follow lenv first) acc
271289 nextResult <- mqForEach rest (follow lenv deepResult)
272290 return (follow lenv nextResult)
273 mqForEach (Cons first rest) acc = do
291 mqForEach term@(Cons first rest) acc = do
292 (first', rest') <- do return (followSplit lenv term)
274293 result <- mInterpret (
275 extendEnv (extendEnv env accvar acc) loopvar (follow lenv first)
294 extendEnv (extendEnv env accvar acc) loopvar (follow lenv first')
276295 ) lenv applyExpr
277296 newAcc <- do return (follow lenv result)
278 nextResult <- mqForEach rest newAcc
297 nextResult <- mqForEach rest' newAcc
279298 return (if newAcc == Abort then
299 -- "abortable"
280300 acc
281301 else
282302 follow lenv nextResult)