git @ Cat's Eye Technologies Argyle / 130a23c
Add `if-apply` built-in function. Chris Pressey 3 months ago
4 changed file(s) with 32 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
1212 also hygienic in the sense that all defined ABT operations are, quite unlike
1313 Lisp's `cons` lists, designed to preserve their name-binding structure.
1414
15 _This is an extremely preliminary release of the language, aiming only to_
15 _This is an embryonic iteration of the language, aiming only to_
1616 _present a proof-of-concept. The basic ideas are implemented but their exact_
17 _design and implementation surely can and surely will be improved upon._
17 _design and implementation surely can and ideally will be improved upon._
1818
1919 For more details on the language, [see "Documentation" below](#documentation).
2020
4545
4646 What follows is a more informal introduction.
4747
48 Lisp is usualy promoted as being homoiconic, but explanations of its
48 Lisp is usualy promoted as being homoiconic, but presentations of its
4949 homoiconicity often gloss over the following detail: not every
50 valid S-expression is a valid Lisp program. In essence there are
50 valid S-expression is a valid Lisp program. In essence Lisp has
5151 two syntaxes, the "low-level syntax" of S-expressions, and the
52 "high-level syntax" of special forms. Despite this, traditionally,
53 `(quote (let 123))` is a perfectly good quoted form (even though
54 `(let 123)` is not a valid expression) and the argument to `eval`
55 is a list (even though it need not contain a valid expression).
52 "high-level syntax" of special forms. The traditional treatment
53 is to completely ignore that fact, and allow expressions such as
54 `(quote (let 123))` to be perfectly acceptable quoted form, even though
55 `(let 123)` is not a valid expression -- and to have the argument to
56 `eval` is a list, even though a list need not contain a valid expression.
5657
57 This is a shortcoming. Argyle intends to address it. Although
58 given in an S-expression syntax, Argyle programs are not parsed
58 Argyle regards this as a shortcoming, and intends to address it. Although
59 they are written in an S-expression syntax, Argyle programs are not parsed
5960 into cons lists. More precisely, even if the implementation parses
6061 them into cons lists (as the reference implementation does), those
6162 cons lists are not directly exposed to the interpreter. Rather, the
7273 ----
7374
7475 * Continue to clean up ABT helper functions as needed
75 * `if` operator
7676 * Equality operator
7777 * Test that equality operator treats ABTs as alpha-equivalent
7878 * `letrec` - implement in code first, eventually look towards
123123
124124 (let ((s "hello")) s)
125125 ===> "hello"
126
127 ### `if-apply` Function
128
129 (if-apply 1 (lambda (x) 123) (lambda (x) "no"))
130 ===> 123
131
132 (if-apply 0 (lambda (x) 123) (lambda (x) "no"))
133 ===> "no"
126134
127135 ### Lambda expressions and function application
128136
2121 initialEnv = Map.fromList
2222 [ -- Arithmetic operators
2323 ("add", VBuiltin "add" $ \case
24 [VNum a, VNum b] -> Right $ VNum (a + b)
2524 [VNum a] -> Right $ VBuiltin "add" $ \case
2625 [VNum b] -> Right $ VNum (a + b)
2726 _ -> Left "add: second argument must be a number"
2827 _ -> Left "'add' expects two numbers")
2928
3029 , ("mul", VBuiltin "mul" $ \case
31 [VNum a, VNum b] -> Right $ VNum (a * b)
3230 [VNum a] -> Right $ VBuiltin "mul" $ \case
3331 [VNum b] -> Right $ VNum (a * b)
3432 _ -> Left "mul: second argument must be a number"
3735 , ("neg", VBuiltin "neg" $ \case
3836 [VNum a] -> Right $ VNum (0 - a)
3937 _ -> Left "'neg' expects one number")
38
39 , ("if-apply", VBuiltin "if-apply" $ \args -> case args of
40 [VNum n] -> Right $ VBuiltin "if-apply" $ \args' -> case args' of
41 [VClosure _ thenBody thenEnv] -> Right $ VBuiltin "if-apply" $ \args'' -> case args'' of
42 [VClosure _ elseBody elseEnv] ->
43 if n /= 0
44 then runReaderT (eval thenBody) thenEnv
45 else runReaderT (eval elseBody) elseEnv
46 _ ->
47 Left "if-apply: expected 'else' lambda"
48 _ -> Left "if-apply: expected 'then' lambda"
49 _ -> Left "if-apply: expected numeric test expression")
4050
4151 -- Core homoiconic functions
4252 , ("eval", VBuiltin "eval" $ \case
101101 ("add", VNum 1)
102102 , ("mul", VNum 2)
103103 , ("neg", VNum 3)
104 , ("if-apply", VNum 4)
104105 , ("eval", VNum 4)
105106 , ("subst", VNum 5)
106107 , ("abt", VNum 6)