我发起并创立了一个 C 语言编译器 开源项目 InnerC
本文是 VMBC / D# 项目 的 系列文章,
有关 VMBC / D# , 见 《我发起并创立了一个 VMBC 的 子项目 D#》(以下简称 《D#》) https://www.cnblogs.com/KSongKing/p/10348190.html 。
VMBC 需要一个 内置 的 C 编译器, 想来想去, 觉得还是自己写一个,
计划用 C 语言 写, 因为 VMBC 的 C 编译器 要求是一个 本地库, 如果不要求是 本地库, 我就用 C# 写了, 呵呵呵 。
为什么 是 库 呢 ? 因为这是一个 内置编译器, 是由 ILBC 运行时 来 调用的 (ILBC 见 《D#》), 所以 是一个 库 。
这个 库 最好 能 尽可能的 小 。
C 语言 写的 代码 是 最贴近 底层(汇编) 的, 所以 C 语言 写的 库 应该是 最紧凑 的, 所以用 C 语言 来写 。
还有一个 原因 是, 我会的 语言 不多, C 算是 相对 更熟一点的, So 。
有 网友 说 C 语言 不适合 写 编译器, C 的抽象太低了, 建议用 函数式 语言写,
又举例 Rust 最早是用 OCaml 写的, 然后又用 Rust 写了一遍 。
好吧, 但 Rust 、OCaml 这些语言 的 名字 我都 没怎么听过, 还是用 C 吧 。
另外用 C 的话, 应该不用担心 操作系统 的 支持 的 问题 。
这个 项目 我只 实现 语法分析 和 类型检查 的 部分, 语法分析 包含了 语法检查 。
生成目标代码 链接(链接外部库) 这 2 个 部分 大家 如果有兴趣, 对 汇编 和 操作系统 了解 的话, 可以来补充 。
InnerC 是 ansi C 的 子集 + 扩展, 只支持 ansi C 的 部分特性, 同时还会加入一些 新特性 。
总的来说, InnerC 会 比 ansi C 简单 。
比如, InnerC 不支持 结构体(Struct), 因为 InnerC 是 作为 中间语言, 只需要是一种 “高级汇编语言” 就可以 。
不用 Struct, 那用什么 ?
用 数组, 包括 静态数组 和 从 堆 里 分配 的 数组 。
根据 偏移量 向 数组 的 相应位置 写入 字段 的 值, 这就是 Struct, 也是 对象 。
去掉 Struct 可以 省掉 不少 语法分析 的 开销 和 人力上的 研发成本 。
但 C 语言 里好像没有 按值 传递 数组 的 特性, 所以 InnerC 需要 加入 按值传递数组(拷贝传递数组) 的 特性 。
比如, InnerC 应该 增加 T [ n ] 类型, 用于 参数 和 返回值,
T [ n ] 类型 表示 按值传递数组(拷贝传递数组),
假设 A() 方法 调用 B() 方法, B() 方法有一个 T [ n ] arr 参数, 那么 A() 方法 传给 T [ n ] arr 参数 的 是一个 数组的 首地址 arr, 编译器会处理成 把 A() 里的 arr 数组 以 长度 n 拷贝到 B() 的 arr 里, 所以 B() 的 arr 也是 数组 的 首地址, 但是是 拷贝到 B() 的 堆栈 里的 数组 的 首地址 。
T [ n ] arr 表示 arr 参数 是 长度 为 n 的 数组, 编译器 会为 arr 在 B 的 堆栈 里 分配 长度为 n * sizeof(T) 的 内存空间 。 这个空间是 编译器 分配的, 是 静态分配 的, 等价于 声明一个 T arr[ n ] 这样的 静态数组 。
同理, 假设 B() 的 返回值 是 T [ n ] 类型, B() 实际返回的是一个 数组 的 首地址 arr, A() 里 用来 接收 B() 的 返回值 的 是一个 T arr[ n ] arr ; 静态数组 变量, 编译器会处理成 把 B() 里的 arr 数组 以 长度 n 拷贝到 A() 的 arr 里 。
InnerC 也不支持 对 函数指针 进行 类型检查,
不对 函数指针 类型检查 是指 函数指针 可以调用 任意 的 参数列表, 当然, 出了错 是 调用者 自己 负责 。^^
不过 对于 中间语言 来说, 基本上 不用担心 这个问题 。
InnerC 的 语法分析 可以 生成一个 表达式对象树, 把 表达式对象树 序列化 得到一个 byte [] (byte 数组),
这个 byte[] 就相当于 .Net 的 Op Code, 或者 java 的 Byte Code, 我们可以把 这个 byte[] 称为 ILBC Byte Code (简称 Byte Code) 。
这样一来, 问题就明朗了,
如果 开发期 编译 生成的 目标代码 就是 ILBC Byte Code, 那 JIT 速度 较慢 的 问题 就 解决了 。
这就是说, 可以把 C 语言 作为 第一级 中间代码, Byte Code 作为 第二级 中间代码 。
这样, InnerC 就可以由 2 个模块 组成:
1 InnerC to Byte Code
2 Byte Code to Native Code
当然, 可以在 开发期 编译 直接 生成 Native Code (本地代码), 这是 AOT 。
我发起并创立了一个 C 语言编译器 开源项目 InnerC的更多相关文章
- 我发起并创立了一个 Javascript 前端库 开源项目 jWebForm
在线演示地址: ( 在线演示 云平台 由 Kooboo 提供 https://www.kooboo.com/ ) 按钮: http://iwebform.kgeking.kooboo.si ...
- 我发起并创立了一个 VMBC 的 子项目 D#
大家好, 我发起并创立了一个 VMBC 的 子项目 D# . 有关 VMBC , 请参考 <我发起了一个 用 C 语言 作为 中间语言 的 编译器 项目 VMBC> https ...
- 我发起并创立了一个 EPWA 的 开源项目
EPWA , 是 Easy PWA 的 意思, PWA 取自于 Google 的 PWA, EPWA 是一个用 C# Cef Html js css 开发 桌面程序 的 架构 ...
- 第一个C语言编译器是怎样编写的?
首先向C语言之父Dennis MacAlistair Ritchie致敬! 当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用C语言编写的,有一些语言比如Clojure,Jython等是基于J ...
- 准备开一个地图SDK的开源项目
最近有点空闲时间了, 准备开一个地图SDK的开源项目, 现在的地图SDK已经有很多了, 再做一个跟重新发明个轮子差不多, 但还想做的原因是想在别的轮子的基础上造个轮子... 初步设想是基于开源的地图渲 ...
- 一个P2P点播直播开源项目:P2PCenter
最近跟着公司的项目走,我也研究了不少东西,尤其是在P2P方面,广泛涉猎各种开源项目,尤其是国外的开源项目,意外的发现了一个国内的项目,做的还不错,推荐一下.---------------------使 ...
- 一个基于 Vue3 的开源项目,3个月时间 star 终于破千!
本文主要是对如何做开源项目的一些思考. 前文回顾: <Vue3 来了,Vue3 开源商城项目重构计划正式启动!> <一个基于 Vue 3 + Vant 3 的开源商城项目> 关 ...
- 我发起并创立了一个 .Net 平台上的 Web 业务系统 基础库 开源项目 WebEasy
我 强调一点, 程序员 应该对 程序 有 控制感 . 过多的 控制反转 使 程序员 丧失了 对 程序 的 控制感 . 过多的 依赖注入 束缚了 程序员 的 创造力 . 过度复杂的 架构设计 束缚了 程 ...
- 第一个C语言的小项目
这里先写下主要的业务代码,一些库代码稍后补充上 /** * Feed新闻个性化推送 */ #include "push_service_news.h" /** * 保证单进程运行 ...
随机推荐
- 《Visual C# 从入门到精通》第一章使用变量、操作符和表达式——读书笔记
前言: 这个笔记是我个人总结,主要是熟练自己查看<Visual C# 从入门到精通>(第8版)这本书时,懵然起总结的想法,只是总结一些知识点,在工作项目会用得上,但是对毫无C#语言基础的, ...
- 拼接字符串,生成tree格式的JSON数组
之前做的执法文书的工作,现在需要从C#版本移植到网页版,从Thrift接口获取数据,加载到对应的控件中 之前用的easyui的Tree插件,通过<ul><li><span ...
- js Array.prototype.reduce()
例子: , , , ]; const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 ...
- DAY7 字符编码和文件操作
一.软件与python解释器打开文件的方法 1.软件打开文件读取数据的流程: 1. 打开软件 2. 往计算机发生一个打开文件的指令,来打开文件 3. 读取数据渲染给用户(存取编码不一致:乱码) 2.p ...
- Type I and type II errors | 第一类错误和第二类错误
偶尔能看懂,但是死活记不住,归根结底是没有彻底理解! Type I and type II errors - wiki type I error is the rejection of a true ...
- Python使用ldap3认证
一.安装ldap3模块(python版本为python3以上,Django=1.11.8)pip install ldap3 二.相关代码 from ldap3 import Server, Conn ...
- 『TensotFlow』转置卷积
网上解释 作者:张萌链接:https://www.zhihu.com/question/43609045/answer/120266511来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业 ...
- sublim 配置 用户默认绑定的格式化文本快捷键
//在绑定用户绑定配置中 加入 激活每个字母提示! "auto_complete": true,"auto_match_enabled": true, &q ...
- python 利用selectors实现异步I/O
它的功能与linux的epoll,还是select模块,poll等类似:实现高效的I/O multiplexing, 常用于非阻塞的socket的编程中: 简单介绍一下这个模块,更多内容查看 pyt ...
- ELK安装使用教程
一.说明 ELK是当下流行的日志监控系统.ELK是Elasticsearch.Logstash.Kibana三个软件的统称. 在ELK日志监控系统中,Logstash负责读取和结构化各类日志+发送给E ...