示例工程【免费下载链接】malmal - Make a Lisp项目地址https://gitcode.com/gh_mirrors/ma/mal点击查看免费下载导读本文围绕 malMake a Lisp开源项目中 C 实现的编译与运行展开系统讲解 impls/cpp/README.md 中记载的 macOSHomebrew g、Ubuntuclang libreadline-dev与 Docker 容器三种构建路径并深入 Makefile、Dockerfile、docker.sh 与源码入口step0_repl.cpp 到 stepA_mal.cpp帮你理解 C 版 mal 的依赖关系、构建产物与运行方式。读完本文你可以在一台干净的机器上从零编译并运行完整的 stepA_mal REPL也能独立编写脚本化构建流程。一、项目背景mal 的 C 实现是什么mal 是一个以 Make a Lisp 为目标的系列教程项目用上百种语言分别实现同一套 Lisp 解释器。C 实现位于 impls/cpp 目录包含从step0_repl到stepA_mal的 11 个递进阶段详见 process/guide.md每个阶段都在前一个阶段基础上增加语言特性。该实现的源码结构如下通用基础String.h/String.cpp字符串封装与格式化、MAL.h全局类型声明与READ/EVAL/PRINT/rep接口核心运行时Types.h/Types.cppmal 值类型体系、Environment.h/Environment.cpp词法环境、Reader.cpp读取器、Core.cpp内置函数、ReadLine.cpp交互行输入与历史记录构建脚本Makefile、Dockerfile、docker.sh、run测试与辅助tests/目录下 1 个.mal测试文件、Debug.h、Validation.cpp/Validation.h参数校验二、macOS 编译g GNU ReadlineHomebrew根据 impls/cpp/README.md该 C 实现最初在 Mac OS X Yosemite 上开发使用系统自带的 g 编译器唯一的额外依赖是 GNU Readline。2.1 安装依赖Readline 通过 Homebrew 安装brew install readline2.2 调整 Makefile 中的 READLINE 路径README 明确指出安装后可能需要编辑 Makefile 中的 READLINE 路径。查看 impls/cpp/Makefile 可以确认Darwin 平台下的构建路径默认指向 Homebrew 的 readline 安装位置uname_S : $(shell sh -c uname -s 2/dev/null || echo not) CXXg ifeq ($(uname_S),Darwin) # Native build on yosemite. Requires: brew install readline READLINE/usr/local/opt/readline INCPATHS-I$(READLINE)/include LIBPATHS-L$(READLINE)/lib endif如果你的 readline 安装在不同位置例如 Apple Silicon Mac 上 Homebrew 前缀不同需要同步修改READLINE变量使-I指向其include目录、-L指向其lib目录。2.3 编译参数要点Makefile 中关键的编译与链接参数如下DEBUG-ggdb CXXFLAGS-O3 -Wall $(DEBUG) $(INCPATHS) -stdc11 LDFLAGS-O3 $(DEBUG) $(LIBPATHS) -L. -lreadline -lhistory-stdc11要求 C11 标准支持-O3 -Wall开启最高优化与全部警告-ggdb生成 GDB 调试信息方便用调试器跟踪 EVAL 执行-lreadline -lhistory链接 GNU Readline 及其历史记录库。所有step*.cpp主程序通过通配符自动收集并逐一链接MAINS$(wildcard step*.cpp) TARGETS$(MAINS:%.cpp%)编译全部目标只需makemake clean可清除.o、可执行文件、libmal.a、.deps与mal链接产物。三、Ubuntu 编译clang libreadline-dev在 Ubuntu 14.10/15.04 上README 推荐安装以下三个软件包apt-get install clang-3.5 libreadline-dev makeclang-3.5C 编译器对应版本可替换为当前发行版提供的 clanglibreadline-devGNU Readline 的开发头文件与静态库ReadLine.cpp中#include readline/readline.h、readline/history.h、readline/tilde.h均依赖它make构建工具。注意Linux 下 Makefile 走非 Darwin 分支不设置READLINE路径直接使用系统默认头文件路径。因此只要 libreadline-dev 安装到位make即可完成构建。四、Docker 构建一条命令搞定环境对于其他平台或希望隔离环境的用户仓库提供了 impls/cpp/Dockerfile 与 impls/cpp/docker.shREADME 给出了完整的四步用法。4.1 README 中的标准流程# 构建 docker 镜像 ./docker build # 编译 MAL 二进制 ./docker make # 运行其中一个实现如完整的 stepA_mal ./docker run ./stepA_mal # 在 docker 容器内打开 shell ./docker run注意README 中./docker build是文档笔误实际脚本名为docker.sh正确命令为./docker.sh build、./docker.sh make、./docker.sh run。4.2 docker.sh 的工作机制查看 impls/cpp/docker.sh 源码可以了解其背后逻辑IMAGE_NAMEmal-cpp CONTAINER_NAMEmal-cpp-running run() { docker rm -f $CONTAINER_NAME /dev/null 2/dev/null docker run -v $PWD:/mal -ti --name $CONTAINER_NAME $IMAGE_NAME $ } case $1 in build) docker build -t $IMAGE_NAME . ;; run) shift run $ ;; make) shift run make $ ;; ...build用当前目录的 Dockerfile 构建名为mal-cpp的镜像make在容器内执行make编译全部 step 可执行文件run在容器内执行任意命令核心技巧是通过-v $PWD:/mal把宿主当前目录挂载到容器/mal因此编译产物会直接落在宿主的 impls/cpp 目录中无需进入容器即可直接运行./stepA_mal每次run前会先删除同名旧容器mal-cpp-running保证环境干净。4.3 Dockerfile 环境内容impls/cpp/Dockerfile 基于ubuntu:20.04核心安装项为RUN apt-get -y update RUN apt-get -y install make python3 RUN ln -fs /usr/bin/python3 /usr/local/bin/python # Specific implementation requirements RUN apt-get -y install g libreadline-devg与libreadline-devC 编译链与 readline 依赖make构建工具python3并软链为python供仓库根目录的 runtest.py 测试驱动脚本使用WORKDIR /mal容器内工作目录与挂载点对应。五、构建产物与运行方式5.1 可执行文件清单编译完成后impls/cpp下会出现从step0_repl到stepA_mal共 11 个可执行文件。此外dist: mal mal: stepA_mal cp $ $make mal会把stepA_mal复制为mal便于统一命名调用。5.2 通过 run 脚本选择步骤仓库提供通用启动脚本 impls/cpp/run#!/usr/bin/env bash exec $(dirname $0)/${STEP:-stepA_mal} ${}默认运行stepA_mal也可通过环境变量指定任意阶段例如STEPstep4_if_fn_do ./run该脚本同时服务于仓库根目录的测试框架STEP变量配合 tests 目录下的step0_repl.mal、stepA_mal.mal等测试文件可逐阶段验证实现正确性测试驱动见 runtest.py。5.3 运行 REPL 与脚本文件直接运行./stepA_mal进入 REPL提示符为user。历史记录保存在~/.mal-history见 ReadLine.cpp 中read_history/add_history/append_history的调用。带参数运行会加载并执行脚本见 stepA_mal.cpp 的 main 逻辑if (argc 1) { String filename escape(argv[1]); safeRep(STRF((load-file %s), filename.c_str()), replEnv); return 0; }即./stepA_mal hello.mal等价于在 REPL 中执行(load-file hello.mal)argv[2]起的参数会以字符串列表形式绑定到*ARGV*static void makeArgv(malEnvPtr env, int argc, char* argv[]) { malValueVec* args new malValueVec(); for (int i 0; i argc; i) { args-push_back(mal::string(argv[i])); } env-set(*ARGV*, mal::list(args)); }六、深入源码C 实现的内部结构结合编译配置理解该实现的核心组件有助于排查构建与运行问题。6.1 类型体系Types.himpls/cpp/Types.h 以malValue为基类定义了 mal 的全部数据类型malConstantnil/true/false 单例、malInteger64 位整数、malString/malKeyword/malSymbolmalSequence派生出的malList与malVectormalHash基于std::mapString, malValuePtr的哈希表malApplicable派生的malBuiltIn内置函数与malLambda用户函数含宏标记malAtom原子类型支持deref/reset所有对象均以RefCountedPtr见 RefCountedPtr.h管理生命周期VALUE_CAST/DYNAMIC_CAST宏定义于 Types.h 顶部负责类型安全转换。6.2 环境Environment.himpls/cpp/Environment.h 提供malEnv内部是一个std::map加指向外层环境的m_outer指针实现词法作用域与闭包class malEnv : public RefCounted { public: malEnv(malEnvPtr outer NULL); malValuePtr get(const String symbol); malEnvPtr find(const String symbol); malValuePtr set(const String symbol, malValuePtr value); malEnvPtr getRoot(); private: Map m_map; malEnvPtr m_outer; };6.3 EVAL 与特殊形式stepA_mal.cpp 中的EVAL采用「循环而非递归」的 TCO尾调用优化写法if、let*、do、quasiquote、try*等特殊形式在修改ast/env后continue避免 C 栈随深递归增长。同时支持DEBUG-EVAL调试开关当环境中DEBUG-EVAL为真时每次 EVAL 前打印当前 AST。6.4 REPL 错误处理safeRep统一捕获三类异常并格式化为Error: ...输出malEmptyInputException空输入直接忽略malValuePtrmal 值类型的异常如throw抛出的对象String普通字符串异常。这保证了 REPL 遇到错误不会崩溃可以持续交互。七、常见问题排查现象可能原因与解决macOS 编译报找不到readline/readline.hbrew install readline未执行或 Makefile 中READLINE路径与安装位置不符按 2.2 节调整Linux 编译报readline链接错误缺少libreadline-dev执行apt-get install libreadline-devDocker 构建网络失败需保证可访问 Ubuntu apt 源也可改用本地已安装的 g 直接make运行./docker提示 command not found脚本名为docker.sh应执行./docker.sh build等输入命令无历史记录检查~/.mal-history是否可写ReadLine 每次append_history都会写入八、结语本文完整覆盖了 impls/cpp/README.md 中记载的三条构建路径macOS 的 g Homebrew Readline需注意 Makefile 路径、Ubuntu 的 clang libreadline-dev、以及普适性最强的 Docker 方案docker.sh的 build/make/run 三命令。结合 Makefile、Dockerfile 与 stepA_mal.cpp 等源码可清晰理解该实现的依赖结构、构建产物与运行机制。无论你是在本机学习 Lisp 解释器实现还是在 CI 环境中自动化构建测试上述路径都提供了开箱即用的方案。赞分享示例工程【免费下载链接】malmal - Make a Lisp项目地址https://gitcode.com/gh_mirrors/ma/mal点击查看免费下载相关推荐gRPC C 依赖接入与构建全指南Bazel、CMake、pkg-config 三种集成路径详解gRPC C 依赖接入与构建全指南Bazel、CMake、pkg config 三种集成路径详解 导读 src/cpp/README.md 是 gRPC后端RPC框架微服务通信VCClient 实时语音转换客户端部署指南预编译包、Docker 与 Anaconda 三种运行方式详解VCClient 实时语音转换客户端部署指南预编译包、Docker 与 Anaconda 三种运行方式详解 导读 VCClientRealtime Voic人工智能语音模型推理服务深度学习V8 Builtins 架构详解Torque、CSA、C 与汇编四种实现路径及加载机制V8 Builtins 架构详解Torque、CSA、C 与汇编四种实现路径及加载机制 V8 的 Builtins内建函数是预编译好的可执行代码负责语言运行时编译器JIT编译解释器内存管理上一篇终极指南如何用Mac Mouse Fix让普通鼠标在macOS上超越苹果触控板下一篇N_m3u8DL-RE一条命令完整保存 m3u8/MPD 流媒体自动解密自动合并创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
爆火的本地AI语音工具VoiceStudio测评:热门但远未成熟 文章目录1. 先搞清楚:VoiceStudio 到底是干嘛的2. 数字很漂亮,先别急着高潮3. 架构长啥样,数据是怎么走的4. 三条边界,逐条核对5. 什么人适合玩这个6. 先掂量掂量你电脑的分量7. 验收别只靠耳朵8. 我的判断:热门 ≠ 成… · 2026/9/24 18:19:39
开源低代码平台选型与实战:从拖拉拽表单到TOP5深度拆解 做低代码选型这几年,我每年都会被问到同一个问题:“2026年TOP级低代码平台到底怎么排?”说实话,“排名”这两个字本身就很容易把人带偏。每个平台官网都挂着“行业领先”“客户第一”的横幅,可真正落到你公司那套业务上… · 2026/9/24 21:17:30
AI漫剧制作全流程:ComfyUI与LoRA角色一致性实战指南 AI漫剧这个词最近半年在圈子里出现的频率越来越高,但真正动手做过一整集的人其实不多。很多人卡在第一步——不知道从哪下手,工具装了一堆,工作流跑不通,角色脸一变再变,最后做出来的东西自己都不想看第二遍。这篇内容… · 2026/9/24 21:17:17
Python人口普查可视化:从数据清洗到地图大屏的完整实战 简介:这份Python人口普查与各省人口数量变化可视化项目源码,面向高校学生、数据分析初学者及需要完成期末大作业或课程设计的开发者,帮助解决人口数据整理、趋势分析与图表呈现的完整实现问题。压缩包共10个文件,约9.24MB… · 2026/9/24 21:17:17
自走棋日常任务自动化脚本:图像识别与状态机实战解析 我平时写脚本有个习惯:先把能自动化的环节全列出来,再一个个去啃,绝不会为了写脚本而写脚本。最近花了两周时间搓了一套“一将成名自走棋”的日常自动化脚本,从最初的鼠标模拟乱点,到后来稳定的状态识别加任务调度&… · 2026/9/24 21:17:17
LLM高并发调用限流实战:从秒杀思维到并发闸门的架构演进 1. 从一次线上事故说起:为什么秒杀那套限流思路在 LLM 场景下会翻车去年年底我接手了一个 AI 客服中台项目,底层对接了三家不同厂商的大模型服务,上层是十几个业务方通过 HTTP 接口调用。上线第一周就出了事:某个业务方做了一轮批… · 2026/9/24 21:17:11
AI接口高并发≠秒杀高并发:LLM汇聚点并发限流实战 1. 从一次线上事故说起:为什么秒杀那套限流方案在 LLM 场景下会翻车去年年底我接手了一个 AI 应用的后端治理工作,系统本身不算复杂:一个对话式产品,前端把用户输入发到网关,网关做鉴权、路由,然后调用后端… · 2026/9/24 21:17:11
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44