本文是 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的更多相关文章

  1. 我发起并创立了一个 Javascript 前端库 开源项目 jWebForm

    在线演示地址: ( 在线演示 云平台 由 Kooboo 提供  https://www.kooboo.com/ ) 按钮:      http://iwebform.kgeking.kooboo.si ...

  2. 我发起并创立了一个 VMBC 的 子项目 D#

    大家好, 我发起并创立了一个 VMBC 的 子项目 D#  . 有关 VMBC ,  请参考 <我发起了一个 用 C 语言 作为 中间语言 的 编译器 项目 VMBC>     https ...

  3. 我发起并创立了一个 EPWA 的 开源项目

    EPWA ,  是  Easy PWA  的 意思, PWA 取自于 Google 的 PWA, EPWA   是一个用   C#  Cef  Html  js  css   开发 桌面程序 的 架构 ...

  4. 第一个C语言编译器是怎样编写的?

    首先向C语言之父Dennis MacAlistair Ritchie致敬! 当今几乎所有的实用的编译器/解释器(以下统称编译器)都是用C语言编写的,有一些语言比如Clojure,Jython等是基于J ...

  5. 准备开一个地图SDK的开源项目

    最近有点空闲时间了, 准备开一个地图SDK的开源项目, 现在的地图SDK已经有很多了, 再做一个跟重新发明个轮子差不多, 但还想做的原因是想在别的轮子的基础上造个轮子... 初步设想是基于开源的地图渲 ...

  6. 一个P2P点播直播开源项目:P2PCenter

    最近跟着公司的项目走,我也研究了不少东西,尤其是在P2P方面,广泛涉猎各种开源项目,尤其是国外的开源项目,意外的发现了一个国内的项目,做的还不错,推荐一下.---------------------使 ...

  7. 一个基于 Vue3 的开源项目,3个月时间 star 终于破千!

    本文主要是对如何做开源项目的一些思考. 前文回顾: <Vue3 来了,Vue3 开源商城项目重构计划正式启动!> <一个基于 Vue 3 + Vant 3 的开源商城项目> 关 ...

  8. 我发起并创立了一个 .Net 平台上的 Web 业务系统 基础库 开源项目 WebEasy

    我 强调一点, 程序员 应该对 程序 有 控制感 . 过多的 控制反转 使 程序员 丧失了 对 程序 的 控制感 . 过多的 依赖注入 束缚了 程序员 的 创造力 . 过度复杂的 架构设计 束缚了 程 ...

  9. 第一个C语言的小项目

    这里先写下主要的业务代码,一些库代码稍后补充上 /** * Feed新闻个性化推送 */ #include "push_service_news.h" /** * 保证单进程运行 ...

随机推荐

  1. 在客户端先通过JS验证后再将表单提交到服务器

    问题:想要在客户端先通过JS验证后再将表单提交到服务器 参考资料: jQuery 事件 - submit() 方法 试验过程: 服务器端使用PHP <html> <head> ...

  2. URL URI

    URL 是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理 ...

  3. mongodump and mongorestore

    mongoexport和mongoimport只能导出/导入某个特定集合 1 mongoexport bin目录下 ./mongoexport <hostname><:port> ...

  4. PAT 1092 To Buy or Not to Buy

    1092 To Buy or Not to Buy (20 分)   Eva would like to make a string of beads with her favorite colors ...

  5. element-ui <el-input> +<el-tree>使用

    <template> <!-- 需求:通过点击<el-input> 将<el-tree>树型结构打开,选中<el-tree>某个值显示在<e ...

  6. Java 模拟面试题

    1.面向对象的特点 继承,封装,多态 2.对象和类的区别是什么? 对象是对客观事物的抽象,类是对对象的抽象.类是一种抽象的数据类型,它们的关系是,对象是类的实例,类是对象的模板. 3.静态成员和实例成 ...

  7. day37-多进程多线程二-锁

    Lock组件 当我们用多进程来读写文件的时候,如果一个进程是写文件,一个进程是读文件,如果两个文件同时进行,肯定是不行的,必须是文件写结束以后,才可以进行读操作.或者是多个进程在共享一些资源的时候,同 ...

  8. SSH登录异常(someone is doing something nasty)

    在平时工作中,有时候需要SSH登陆到别的Linux主机上去,但有时候SSH登陆会被禁止,并弹出如下类似提示: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ...

  9. Zabbix4.0报警配置-企业微信报警

    一:前期准备 1.1:企业号注册 https://qy.weixin.qq.com/  微信调用接口说明 http://qydev.weixin.qq.com/wiki/index.php?title ...

  10. java集合之List。

    实际上有两种List:一种是基本的ArrayList其优点在于随机访问元素,另一种是更强大的LinkedList它并不是为快速随机访问设计的,而是具有一套更通用的方法. List:次序是List最重要 ...