用 C 语言开发一门编程语言 — 函数库的设计与实现
Posted 范桂飓
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 C 语言开发一门编程语言 — 函数库的设计与实现相关的知识,希望对你有一定的参考价值。
目录
文章目录
前言
通过开发一门类 Lisp 的编程语言来理解编程语言的设计思想,本实践来自著名的《Build Your Own Lisp》。
- 代码实现:https://github.com/JmilkFan/Lispy
前文列表
《用 C 语言开发一门编程语言 — 交互式解析器》
《用 C 语言开发一门编程语言 — 语法解析器运行原理》
《用 C 语言开发一门编程语言 — 波兰表达式解析器》
《用 C 语言开发一门编程语言 — 表达式存储器》
《用 C 语言开发一门编程语言 — 符号表达式解析器》
《用 C 语言开发一门编程语言 — 引用表达式解析器》
《用 C 语言开发一门编程语言 — 变量的设计与实现》
《用 C 语言开发一门编程语言 — 基于 Lambda 表达式的函数设计与实现》
《用 C 语言开发一门编程语言 — 条件分支的设计与实现》
《用 C 语言开发一门编程语言 — 字符串的设计与实现》
基础功能演示
目前为止,我们开发的编程语言已经拥有了以下功能:
- 交互式解析器界面;
- MPC 语法解析器;
- 基于波兰表达式的数字运算;
- 基于符号表达式的代数运算;
- 基于引用表达式的变量;
- 基于 Lambda 表达式的函数;
- 条件分支逻辑控制语句;
- 文件加载;
- 等等。
在本文中,我们将完整的演示上述技术功能,并尝试通过预定义一些常用的函数库来辅助编程。
数字运算
lispy> + 4 5 // 4+5
9
lispy> - 8 3 // 8-3
5
lispy> * 6 2 // 6 * 2
12
lispy> / 10 5 // 10/5
2
lispy> / 10 0 // 10/0
Division By Zero!
lispy> - (* 10 10) (+ 1 1 1) // (10*10) - (1+1+1)
97
变量与代数运算
lispy> def x 1
()
lispy> + x 1
2
lispy> def y 2
()
lispy> + x y
3
lispy> def a b 2 3
()
lispy> + a b
5
lispy> + x (* a b) y // x + (a * b) + y
9
lispy> def arglist a b c d
()
lispy> def arglist 1 2 3 4
()
lispy> list a b c d
1 2 3 4
列表处理
lispy> def l1 1 2 3
()
lispy> def l2 4 5 6
()
lispy> head l1
1
lispy> tail l1
2 3
lispy> join l1 l2
1 2 3 4 5 6
lispy> list l1 l1
1 2 3 1 2 3
lispy> eval + 1 2 3
6
Lambda 函数
lispy> def add-mul (\\ x y + x (* x y))
()
lispy> add-mul 10 20
210
lispy> add-mul 30 40
1230
lispy> def add-mul-ten (add-mul 10)
()
lispy> add-mul-ten 50
510
条件分支
lispy> def x y 100 200
()
lispy> if (== x y) + x y - x y
-100
lispy> if (< x y) + x y - x y
300
字符串
lispy> print "Hello World!"
"Hello World!"
()
lispy> error "This is an error!"
This is an error!
源文件加载
$ cat hello.lspy
(print "hello world.")
$ main hello.lspy
"hello world."
函数库
列表处理函数库
- list.lspylib
; 空类型
(def nil )
; 布尔类型
(def true 1)
(def false 0)
; 函数定义 Lambda 表达式
(def fun (\\ f b
def (head f) (\\ (tail f) b)
))
; 取列表中的第一、二、三项
(fun fst l eval (head l) )
(fun snd l eval (head (tail l)) )
(fun trd l eval (head (tail (tail l))) )
; 获取列表长度
(fun len l
if (== l nil)
0
+ 1 (len (tail l))
)
; 取列表中的第 n 项
(fun nth n l
if (== n 0)
fst l
nth (- n 1) (tail l)
)
; 取列表中的最后一项
(fun last l nth (- (len l) 1) l)
; 取列表中的前 n 项
(fun take n l
if (== n 0)
nil
join (head l) (take (- n 1) (tail l))
)
; 删除列表中的前 n 项
(fun drop n l
if (== n 0)
l
drop (- n 1) (tail l)
)
; 从第 n 项分裂列表
(fun split n l list (take n l) (drop n l))
; 取元素的 idx
(fun elem x l
if (== l nil)
false
if (== x (fst l)) true elem x (tail l)
)
; Map 函数:所有列表元素执行相同的操作
(fun map f l
if (== l nil)
nil
join (list (f (fst l))) (map f (tail l))
)
; Filter 函数:根据过滤条件进行元素过滤
(fun filter f l
if (== l nil)
nil
join (if (f (fst l)) head l nil) (filter f (tail l))
)
; Fold Left 函数:向左折叠逐一执行指定函数操作
(fun foldl f z l
if (== l nil)
z
foldl f (f z (fst l)) (tail l)
)
; 向左折叠求和
(fun sum l foldl + 0 l)
; 向左折叠求积
(fun product l foldl * 1 l)
应用:列表处理。
lispy> load "./samples/list.lspylib"
()
lispy> def l1 1 2 3 4 5 6
()
lispy> len l1
6
lispy> nth 2 l1
3
lispy> last l1
6
lispy> take 3 l1
1 2 3
lispy> def l2 (drop 4 l1)
()
lispy> l2
5 6
lispy> split 5 l1
1 2 3 4 5 6
lispy> elem 1 l1
1
lispy> elem 7 l1
0
lispy> map (\\ x + x 10) 5 2 11 // 所有元素的数值 +10
15 12 21
lispy> filter (\\ x > x 2) 5 2 11 -7 8 1 // 过滤出 >2 的元素
5 11 8
lispy> sum l1 // 求和
21
lispy> product l1 // 求积
720
条件分支函数库
- condition.lspylib
; 空类型
(def nil )
; 布尔类型
(def true 1)
(def false 0)
; 函数定义 Lambda 表达式
(def fun (\\ f b
def (head f) (\\ (tail f) b)
))
; 取列表中的第一、二、三项
(fun fst l eval (head l) )
(fun snd l eval (head (tail l)) )
(fun trd l eval (head (tail (tail l))) )
; Unpack List for Function
(fun unpack f l
eval (join (list f) l)
)
; Pack List for Function
(fun pack f & xs f xs)
; switch 关键字
(fun switch & cs
if (== cs nil)
error "No Selection Found"
if (fst (fst cs)) snd (fst cs) unpack switch (tail cs)
)
; default 关键字
(def default true)
; case 关键字
(fun case x & cs
if (== cs nil)
error "No Case Found"
if (== x (fst (fst cs))) snd (fst cs)
unpack case (join (list x) (tail cs))
)
; 条件选择月份后缀函数
(fun month-day-suffix i
switch
(== i 0) "st"
(== i 1) "nd"
(== i 3) "rd"
default "th"
)
; 条件选择星期几函数
(fun day-name x
case x
0 "Monday"
1 "Tuesday"
2 "Wednesday"
3 "Thursday"
4 "Friday"
5 "Saturday"
6 "Sunday"
)
- 应用:switch/case 语句。
lispy> load "./samples/condition.lspylib"
()
lispy> month-day-suffix 1
"nd"
lispy> month-day-suffix 2
"th"
lispy> day-name 0
"Monday"
lispy> day-name 1
"Tuesday"
数学库
- fibonacci.lspylib
; 空类型
(def nil )
; 布尔类型
(def true 1)
(def false 0)
; 函数定义 Lambda 表达式
(def fun (\\ f b
def (head f) (\\ (tail f) b)
))
; 取列表中的第一、二、三项
(fun fst l eval (head l) )
(fun snd l eval (head (tail l)) )
(fun trd l eval (head (tail (tail l))) )
; Unpack List for Function
(fun unpack f l
eval (join (list f) l)
)
; Pack List for Function
(fun pack f & xs f xs)
; switch 关键字
(fun switch & cs
if (== cs nil)
error "No Selection Found"
if (fst (fst cs)) snd (fst cs) unpack switch (tail cs)
)
; default 关键字
(def default true)
; Fibonacci
(fun fib n
switch
(== n 0) 0
(== n 1) 1
default (+ (fib (- n 1)) (fib (- n 2)))
)
- 应用:
lispy> load "./samples/fibonacci.lspylib"
()
lispy>
()
lispy> fib 10
55
lispy> fib 20
6765
以上是关于用 C 语言开发一门编程语言 — 函数库的设计与实现的主要内容,如果未能解决你的问题,请参考以下文章