Download
84 lines 1.6 KiBTextModified 2022-09-24 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
macro swap(x,y)
    tmp := x
    x = y
    y = tmp

// Check macros are hygienic by using the same var as the macro:
tmp := "tmp"
baz := "baz"
swap tmp baz
fail unless tmp == "baz" and baz == "tmp"
say "After swapping: tmp=$tmp baz=$baz"

macro doubled(expr) expr + expr

say "Doubles: $(doubled "hello") $(doubled 4)"

macro let(name, val)
    name := val

let myvar 5
fail unless myvar == 5
say "myvar: $myvar"

CONST := "CONST:"
macro withconst(x) CONST + x
fail unless withconst("hi") == "CONST:hi"
say "$(withconst "hi")"

macro usefn(x)
    def foo(y:String)
        say "$y"
    foo(x)

def foo(y:String)
    fail "Check fndec hygiene"
usefn "asdf"

macro best(xs, x, expr)
    if #xs > 0
        x := xs[1]
        best := x
        best_score := expr
        for x in xs[2..]
            score := expr
            if score > best_score
                best = x
                best_score = score
        best

struct Foo { height:Int }
things := [Foo{1}, Foo{5}, Foo{2}, Foo{-99}]

tallest := best(things, x, x.height)
say "Tallest of $things: $tallest"
fail unless "$tallest" == "Foo{height=5}"

macro max(xs)
    if #xs > 0
        best := xs[1]
        for x in xs[2..]
            if x > best
                best = x
        best

nums := [5,4,1,99,0]
max_num := max nums
say "max of $nums: $(max nums)"
fail unless max_num == 99

def local_macro(things:[Foo])
    macro any(xs, x, expr)
        ret := no
        for x in xs
            if expr
                ret = yes
                stop
        ret

    result := any(things, x, x.height > 2)
    say "any x.height > 2 for x in $things: $result"
    fail unless result

local_macro(things)