Skip to content

Commit

Permalink
Pass functions test again
Browse files Browse the repository at this point in the history
  • Loading branch information
tjammer committed Jan 12, 2024
1 parent 0a8c09f commit e553253
Show file tree
Hide file tree
Showing 25 changed files with 371 additions and 416 deletions.
4 changes: 2 additions & 2 deletions test/functions.t/binop.smu
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
(print (fmt-str (- 10 2 3 4)))
(print (fmt-str (+ 10 2 3 4)))
print(fmt(10 - 2 - 3 - 4))
print(fmt(10 + 2 + 3 + 4))
24 changes: 12 additions & 12 deletions test/functions.t/closure.smu
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
(type capturable {:a& int})
(def a {:a 10})
type capturable = {a& : int}

(defn capture_a ()
(+ (.a a) 2))
let a = {a = 10}

(defn capture_a_wrapped ()
fun capture_a():
a.a + 2

fun capture_a_wrapped():
-- empty function. In order for this to work, the closure
-- needs to be propagated in env
(defn wrap ()
(defn inner ()
(+ (.a a) 2))
(inner))
(wrap))
fun wrap():
fun inner(): a.a + 2
inner()
wrap()

(ignore (capture_a))
(capture_a_wrapped)
ignore(capture_a())
capture_a_wrapped()
10 changes: 5 additions & 5 deletions test/functions.t/closure_dtor.smu
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(defn return-closure (name)
fun return_closure(name):
-- create object on heap
(def n (fmt-str "++" name))
(fn () (print n )))
let n = fmt("++", name)
fun (): print(n)

(def f (return-closure "aoeu"))
(f)
let f = return_closure("aoeu")
f()
95 changes: 48 additions & 47 deletions test/functions.t/closure_inference.smu
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
(type lexbuf {:buf string :curr int})
(type view {:pbuf string :start int :len int})
(type ok {:rem lexbuf :mtch view})
(type parse-result ((#ok ok) (#err lexbuf)))

(defn char (c)
(fn (buf)
(if (char-equal (string/get buf.buf buf.curr) c)
(#ok {:mtch {:pbuf (copy buf.buf) :start buf.curr :len 1}
:rem {@(copy buf) :curr (+ 1 buf.curr)}})
(#err (copy buf)))))

(defn string-of-view (view)
(let ((ret& (array/create (+ 1 view.len))))
(iter-range (.start view) (+ view.start view.len)
(fn (c) (array/push &ret !(string/get view.pbuf c))))
(array/push &ret !'\000')
(array/drop-back &ret)
ret))

(defn view-of-lexbuf (lb)
{:pbuf (copy lb.buf) :start lb.curr :len (- (string/len lb.buf) lb.curr)})

(defn print-result (res)
(-> (match res
((#ok {:rem :mtch})
(fmt-str "(\"" (string-of-view (view-of-lexbuf rem))
"\", \"" (string-of-view mtch) "\")"))
((#err lexbuf)
(fmt-str "(\"" (string-of-view (view-of-lexbuf lexbuf)) "\", \"\")")))
print))

(defn alt (a b)
(fn :copy a b (buf) -- This variable is polymorphic
(match (a buf)
((#ok r) (#ok r))
((#err _) (b buf)))))

(def lx {:buf "x" :curr 0})
(def li {:buf "ix" :curr 0})
(def l0 {:buf "xi" :curr 0})

(def c (alt (char 'x') (char 'i')))

(print-result (c lx))
(print-result (c li))
(print-result (c l0))
type lexbuf = {buf : string, curr : int}
type view = {pbuf : string, start : int, len : int}
type ok = {rem : lexbuf, mtch : view}
type parse_result = Ok(ok) | Err(lexbuf)

fun char(c):
fun buf:
if char_equal(String.get(buf.buf, buf.curr), c):
Ok({mtch = {pbuf = copy(buf.buf), start = buf.curr, len = 1},
rem = {copy(buf) with curr = buf.curr + 1}})
else:
Err(copy(buf))

fun string_of_view(view):
let ret& = Array.create(view.len + 1)
iter_range(view.start, view.start + view.len, fun c:
Array.push(&ret, !String.get(view.pbuf, c)))
Array.push(&ret, !'\000')
Array.drop_back(&ret)
ret

fun view_of_lexbuf(lb):
{pbuf = copy(lb.buf), start = lb.curr, len = String.len(lb.buf) - lb.curr}

fun print_result(res):
match res:
Ok({rem, mtch}):
fmt("(\"", string_of_view(view_of_lexbuf(rem)), "\", \"",
string_of_view(mtch), "\")")
Err(lexbuf):
fmt("\"", string_of_view(view_of_lexbuf(lexbuf)), "\", \"")
-> print

fun alt(a, b):
fun (buf) [a, b]: -- [buf] is polymorphic
match a(buf):
Ok(r): Ok(r)
Err(_): b(buf)

let lx = {buf = "x", curr = 0}
let li = {buf = "ix", curr = 0}
let l0 = {buf = "xi", curr = 0}

let c = alt(char('x'), char('i'))

print_result(c(lx))
print_result(c(li))
print_result(c(l0))
12 changes: 6 additions & 6 deletions test/functions.t/closures_to_env.smu
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(external printf (fun string/cstr int unit))
external printf : (String.cstr, int) -> unit

(def a 20)
let a = 20

(defn close_over_a () a)
fun close_over_a(): a

(defn use_above ()
(printf (string/data "%i\n") (close_over_a)))
fun use_above():
printf(String.data("%i\n"), close_over_a())

(use_above)
use_above()
11 changes: 4 additions & 7 deletions test/functions.t/fib.smu
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
(external printi (fun int unit))
fun fib(n):
if n < 2: n
else: fib(n - 1) + fib(n - 2)

(defn fib (n)
(if (< n 2)
n
(+ (fib (- n 1)) (fib (- n 2)))))

(printi (fib 30))
print(fmt(fib(30)))
38 changes: 15 additions & 23 deletions test/functions.t/first_class.smu
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
(external printi (fun int unit))
external printi : (int) -> unit

(defn apply (x f) (f x))
fun apply(x, f): f(x)

(defn add1 (x) (+ x 1))
fun add1(x): x + 1

-- We also pass polymorphic functions
(defn pass (x) (copy x))
fun pass(x): copy(x)

-- ...and a lambda
(def pass2 (fn (x) (copy x)))
-- ..and a lambda
let pass2 = fun x: copy(x)

(defn makefalse (b)
(if b
false
b))
fun makefalse(b):
if b: false else: b

(defn int_of_bool (b)
(if b 1 0))
fun int_of_bool(b): if b: 1 else: 0

-- TODO polymorphic recursion example

(-> (apply 0 add1)
printi)
(-> (apply 1 (fn (x) (+ x 1)))
printi)
(-> true
(apply makefalse)
int_of_bool
printi)
(printi (apply 3 (fn (x) (copy x)))) -- Shoulde be inferred with concrete type
(printi (apply 4 pass))
(printi (apply 5 pass2))
apply(0, add1) -> printi
apply(1, fun x: x + 1) -> printi
true -> apply(makefalse) -> int_of_bool -> printi
printi(apply(3, fun x: copy(x)))
printi(apply(4, pass))
printi(apply(5, pass2))
65 changes: 30 additions & 35 deletions test/functions.t/generic_fun_arg.smu
Original file line number Diff line number Diff line change
@@ -1,51 +1,46 @@
(external printi (fun int unit))
external printi : (int) -> unit

(type (t 'a) {:x 'a})
type t('a) = {x : 'a}

-- This fn is generic
(defn apply ([x 'a] [f (fun 'a 'b)])
(f x))
fun apply(x : 'a, f : ('a) -> 'b):
f(x)

(def a 2)
let a = 2

(defn add_closed (x)
fun add_closed(x):
-- we close over
(+ x a))
x + a

-- simple int -> int
(defn add1 (x) (+ x 1))
-- simple (int) -> int
fun add1(x): x + 1

(defn print_bool (b)
(if b
(printi 1)
(printi 0)))
fun print_bool(b):
if b: printi(1)
else: printi(0)

-- simple bool -> bool
(defn makefalse (b)
(if b
false
b))
-- simple (bool) -> bool
fun makefalse(b):
if b: false else: b

-- bool t -> bool t
(defn make_rec_false (r)
(if (.x r)
{:x false}
r))
fun make_rec_false(r):
if r.x:
{x = false}
else: r

-- simple t -> t
(defn add3_rec (t)
{:x (+ (.x t) 3)})
fun add3_rec(t):
{x = t.x + 3}

-- A polymorphic function which will get monomorphized
(def f (fn (x) (copy x)))

(printi (apply 20 add1))
(printi (apply 20 add_closed))
(printi (.x (apply {:x 20} add3_rec)))
(print_bool (.x (apply {:x true} make_rec_false)))
(print_bool (apply true makefalse))
(printi (.x (f {:x 17})))
let f = fun x : copy(x)

printi(apply(20, add1))
printi(apply(20, add_closed))
printi(apply({x = 20}, add3_rec).x)
print_bool(apply({x = true}, make_rec_false).x)
print_bool(apply(true, makefalse))
printi(f({x = 17}).x)
-- inline polymorphic function
(-> 18
(fn (x) (copy x))
printi)
18 -> (fun x: copy(x)) -> printi
19 changes: 6 additions & 13 deletions test/functions.t/generic_pass.smu
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
(external printi (fun int unit))
external printi : (int) -> unit

(type t {:i int :b bool})
type t = {i : int, b : bool}

(defn pass (x) (copy x))
fun pass(x): copy(x)
fun apply(f, x): f(x)

(defn apply (f x) (f x))

-- printi(apply(pass, 20))
(-> (apply pass 20)
printi)
-- printi(apply(pass, { i = 700, b = false }).i)
(->> {:i 700 :b false}
(apply pass)
(.i)
printi)
printi(apply(pass, 20))
({i = 700, b = false} |> apply(pass)).i -> printi
18 changes: 8 additions & 10 deletions test/functions.t/if_return_void.smu
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
(external printi (fun int unit))
external printi : (int) -> unit

(defn foo (i)
(if (< i 2)
(printi (- i 1))
(do
(if (< i 400)
(printi i)
(printi (+ i 1)))
(foo (- i 1)))))
fun foo(i):
if i < 2: printi(i - 1)
else:
if i < 400: printi(i)
else: printi(i + 1)
foo(i - 1)

(foo 4)
foo(4)
28 changes: 13 additions & 15 deletions test/functions.t/indirect_closure.smu
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
(external printi (fun int unit))
external printi : (int) -> unit

(type (t 'a) {:x 'a})
type t('a) = {x : 'a}

(defn apply (x f env)
(f x env))
fun apply(x, f, env): f(x, env)

(defn apply2 ([x 'a] [f (fun 'a (fun 'a 'b) 'b)] [env (fun 'a 'b)])
(f x env))
fun apply2(x : 'a, f : ('a, ('a) -> 'b) -> 'b, env : ('a) -> 'b):
f(x, env)

(defn add1 ([x int])
(+ x 1))
fun add1(x : int): x + 1

(defn boxed2int_int (t env)
(def a (env (.x t)))
{:x a})
fun boxed2int_int(t, env):
let a = env(t.x)
{x = a}

(def a (.x (apply {:x 15} boxed2int_int add1)))
(printi a)
(def b (.x (apply2 {:x 15} boxed2int_int add1)))
(printi b)
let a = apply({x = 15}, boxed2int_int, add1).x
printi(a)
let b = apply2({x = 15}, boxed2int_int, add1).x
printi(b)
Loading

0 comments on commit e553253

Please sign in to comment.