-
Notifications
You must be signed in to change notification settings - Fork 0
FTC Design
Bubbler-4 edited this page Aug 23, 2021
·
2 revisions
- High-level ASCII lambda syntax to define a pure function
- Ident:
^[a-z][a-zA-Z0-9_]*$
, which applies to both functions, types, and type constructors - Keywords start with uppercase.
- Recursion is not allowed.
- Multi-line definition is the same as
let
binding, which in turn is a syntax sugar for lambda abstraction-application. e.g.f = expr1; g = expr2
compiles tog = (\f. expr2) expr1
ifexpr2
has a reference tof
.
- Ident:
succ = \n f x. f (n f x)
pred = \n f x. n (\g h. h (g f)) (\u. x) (\u. u)
fix = \f. (\x. f (x x)) (\x. f (x x))
true = \x y. x
false = \x y. y
iszero = \n. n (\x. false) true
mult = \m n f. m (n f)
facfix = \f n. (iszero n) (\f x. f x) (mult n (f (pred n)))
fac = fix facfix
- Syntax sugar for Church/Scott numerals and lists
-
123
for Church numeral (typenat
),$123
for Scott numeral (typenatS
) -
[a, b, c]
for Church list (typelist T
),$[a, b, c]
for Scott list (typelistS T
;$[
is a single token) -
"xyz" == [ord('x'), ord('y'), ord('z')]
, which has typelist nat
-
- Custom type declarations for Scott encoding
- The language itself is untyped; types are only used for I/O in test cases, and an error will be generated at runtime if the output cannot be interpreted as having the given type
Type natS = zeroS | succS natS
-- which generates
zeroS = \c1 c2. c1
succS = \n. \c1 c2. c2 n
-- and formatting will be done by
-- `fmt_natS = \f. f print_zeroS print_succS`
-- where a call of `print_zeroS` will print `"zeroS"` and `print_succS n` will print `"succS(" + fmt_natS n + ")"`
- Optimizing lambda-to-SKI compiler
- Can be ported from AndersK's one and another one from the creator of Crazy L
- Also Church literals may use AndersK's results hardcoded (running at runtime is infeasible)
- Test cases support
-
Test fn [args...] As ty
should runfn
onargs
and format the result using type declarationty
-
- Compiler, post formatter, source importer for BLC, BCL, SKI, Unlambda, Iota, Jot, Godel-LC
-
Import* "filepath" As fnname
would do, where*
is one ofBLC, BCL, SKI, Unlambda, Iota, Jot, GodelLC
-
- How to justify the byte count of Godel-LC (or other langs, for that matter)?
- A way to reference an external file would be enough. That way I can claim "the size of this file is the size of the function".
- Such a statement would look like
ImportGodel "filepath" as name
- Good way to compile code like this:
f1 = expr1
f2 = f1_smth2
f3 = f1_smth3
f4 = f2_f3_smth
-- naive:
f4 = (\f1. (\f2. (\f3. f2_f3_smth ) f1_smth3 ) f1_smth2 ) expr1
-- is this better?
f4 = (\f1. (\f2. \f3. f2_f3_smth) f1_smth2 f1_smth3) expr1
-- it has equal term size, but lower de Bruijn indices overall
-- which is slightly better for BLC coding... but probably not worth the effort;
-- human can (and should) hand-optimize various aspects anyway
- Supplied by reddit user Noughtmare
- Claims to rely on the laziness of NBEEnv
data ULC = Var !Int | Lam ULC | App ULC ULC
deriving (Show, Eq, Generic)
data NBEVal = VFree !Int | VVar !Int | VApp !NBEVal !NBEVal | VLam !NBEClosure
deriving Show
data NBEClosure = Closure !NBEEnv !ULC deriving Show
data NBEEnv = EEmpty | ECons NBEVal NBEEnv deriving Show
semanticNBE e = quote 1 (eval EEmpty e) where
($$) :: NBEClosure -> NBEVal -> NBEVal
($$) (Closure env t) u = eval (ECons u env) t
elookup :: Int -> NBEEnv -> NBEVal
elookup i EEmpty = VFree i
elookup 1 (ECons x _) = x
elookup n (ECons _ xs) = elookup (n-1) xs
eval :: NBEEnv -> ULC -> NBEVal
eval env = \case
Var i -> elookup i env
Lam t -> VLam (Closure env t)
App t u -> case (eval env t, eval env u) of
(VLam t, u) -> t $$ u
(t, u) -> VApp t u
quote :: Int -> NBEVal -> ULC
quote l = \case
VFree i -> Var i
VVar i -> Var (l - i)
VLam t -> Lam (quote (l + 1) (t $$ VVar l))
VApp t u -> App (quote l t) (quote l u)