Skip to content

Commit 8a627c3

Browse files
committed
core: Add lambda anonymous function support
1 parent e1a9121 commit 8a627c3

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

Changes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
changes:
55
- core: Improve error messages
66
- core: Fix bugs with auto-declare
7+
- core: Add lambda anonymous function support
78

89
- version: 0.1.24
910
date: Sat Dec 9 10:28:21 PM PST 2023

core/src/yamlscript/re.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
(def lnum #"-?\d+") ; Integer token
5050
; Operator token
5151
(def oper #"(?:[-+*/<=>|&]{1,3}|\.\.|\|\||&&)")
52+
(def lamb #"(?:\\\()") ; Lambda start token
53+
(def narg #"(?:%\d*)") ; Numbered argument token
5254
(def fops #"(?:=>|->)")
5355
(def strg #"(?x)
5456
\#? # Possibly a regex

core/src/yamlscript/ysreader.clj

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
(:use yamlscript.debug)
99
(:require
1010
[clojure.string :as str]
11+
[clojure.walk :as walk]
1112
[yamlscript.ast :refer :all]
1213
[yamlscript.re :as re])
1314
(:refer-clojure :exclude [read-string resolve]))
@@ -24,6 +25,9 @@
2425
(defn is-namespace? [token]
2526
(and token (re-matches re/nspc (str token))))
2627

28+
(defn is-narg? [token]
29+
(and token (re-matches re/narg (str token))))
30+
2731
(defn is-number? [token]
2832
(and token (re-matches re/lnum (str token))))
2933

@@ -64,6 +68,8 @@
6468
$symb | # Symbol token
6569
$oper | # Operator token
6670
$char | # Character token
71+
$lamb | # Lambda start token
72+
$narg | # Numbered argument token
6773
# Reader macros
6874
\#\_ | # Ignore next form
6975
\#\' | # Var
@@ -123,6 +129,40 @@
123129
(cons op)))
124130
expr)))
125131

132+
(defn lambda-arg-list [node]
133+
(let [args (atom {})
134+
maxn (atom 0)]
135+
(walk/prewalk
136+
#(if (map? %)
137+
(let [[[key val]] (seq %)
138+
val (str val)]
139+
(if (and (= :Sym key) (re-matches #"_\d+" val))
140+
(let [n (parse-long (subs val 1))]
141+
(swap! args assoc n true)
142+
(swap! maxn max n))
143+
%))
144+
%)
145+
node)
146+
(map
147+
#(if (get @args %)
148+
(Sym (str "_" %))
149+
(Sym "_"))
150+
(range 1 (inc @maxn)))))
151+
152+
(defn read-lambda [[_ & tokens]]
153+
(loop [tokens tokens
154+
list []]
155+
(when (not (seq tokens))
156+
(throw (Exception. "Unexpected end of input")))
157+
158+
(if (= (first tokens) ")")
159+
(let [form (yes-expr list)
160+
args (lambda-arg-list form)
161+
expr (Lst [(Sym 'fn) (Vec args) (Lst form)])]
162+
[expr (rest tokens)])
163+
(let [[form tokens] (read-form tokens)]
164+
(recur tokens (conj list form))))))
165+
126166
(defn read-list [[_ & tokens] type end]
127167
(loop [tokens tokens
128168
list []]
@@ -149,6 +189,14 @@
149189
(= "nil" token) [(Nil) tokens]
150190
(= "true" token) [(Bln token) tokens]
151191
(= "false" token) [(Bln token) tokens]
192+
(is-narg? token) (let [n (subs token 1)
193+
n (if (empty? n) 1 (parse-long n))
194+
_ (when (or (<= n 0) (> n 20))
195+
(throw (Exception.
196+
(str "Invalid numbered argument: "
197+
token))))
198+
n (str "_" n)]
199+
[(Sym n) tokens])
152200
(is-number? token) [(Int token) tokens]
153201
(is-operator? token) [(Sym token) tokens]
154202
(is-string? token) [(Str (normalize-string token)) tokens]
@@ -176,6 +224,7 @@
176224
["(" (conj (rest tokens) sym "(")])
177225
[token tokens])]
178226
(case token
227+
"\\(" (read-lambda tokens)
179228
"(" (read-list tokens Lst ")")
180229
"[" (read-list tokens Vec "]")
181230
"{" (read-list tokens Map "}")

core/test/compiler.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,29 @@
266266
(ys.std/say ys)
267267
268268
269+
- name: Lambda function
270+
yamlscript: |
271+
!yamlscript/v0
272+
foo =: \(% + %4)
273+
build: |
274+
{:ysm
275+
([{:Sym def} {:Sym foo}]
276+
{:Lst
277+
[{:Sym fn}
278+
{:Vec [{:Sym _1} {:Sym _} {:Sym _} {:Sym _4}]}
279+
{:Lst [{:Sym +} {:Sym _1} {:Sym _4}]}]})}
280+
clojure: |
281+
(def foo (fn [_1 _ _ _4] (+ _1 _4)))
282+
283+
284+
- name: Lambda function 2
285+
yamlscript: |
286+
!yamlscript/v0
287+
map: \(str ((% / %3) + %2)) (1 .. 3)
288+
clojure: |
289+
(map (fn [_1 _2 _3] (str (+ (/ _1 _3) _2))) (rng 1 3))
290+
291+
269292
- name: Default mapping semantic is a list of pairs
270293
yamlscript: |
271294
!yamlscript/v0

0 commit comments

Comments
 (0)