词法分析

编译原理概述 在编译性语言中,当使用类似 build 指令进行编译时,在其内部会严格进行下面机制的转换,从编码层转变为机器语言层或是汇编语言,从而运行代码赋予的操作在此机器上。但是这一过程对于我们使用者来说是便捷的,不用过多的考虑构建的过程,只需要注重其结果。 在编译型语言中,常见编译过程包括: 词法分析:源码转换为 Token 语法分析:将 Token 转换为 AST 语义分析:分析校验 AST 的合法性 代码生成:AST 到 SSA 的转换 在上述流程中,其主要是将源码一步步的抽象化,这种也像在设计一种编程语言时,通过将理念抽象,获得更直观的理解,也是方便编码从业者的使用。从这一方面可以看出,对于编译也是如此。从可读语言进行抽象化,其目的旨在后续分析做铺垫。 所以说编译器主要实现的步骤则是从字符序列转换为 SSA,而这一过程,在 Golang 中可通过命令进行显式输出为 HTML。 SSA 生成 例如最为常见的一个 Go 代码(下文所有分析依据于此片段): package main import "fmt" func main() { fmt.Println("Hello, world") } 这段无疑是最为熟悉,但从保存文件到运行,中间做了什么操作,对我们来说属于黑盒,得到的只有结果,而中间的过程是不可见的。所以作为有追求有梦想的开发者,必然是会将盒子打开来一探究竟,它是如何在盒子中运作的? 在使用 Go自带的 run 命令后,程序从编译态(Go 为静态语言)到运行态的过程,首先经过编译器,而其主要负责以下操作: 通过 Token 构建 AST,构建抽象语法树。当前阶段主要负责分析、检查和代码生成 加载 Runtime 运行,在 main 函数之前加载代码,比如 GC、Schedule 等 Terminal 中执行命令:GOSSAFUNC=main go build main.go, 即可在编译过程中将转换为 SSA 的流程暴露出来。命令执行后,会在当前目录下生成文件 ssa.html。SSA(Static Single Assignment)是指静态单赋值,也是编译器优化和转换源代码的中间表示形式(这是编译的最后阶段,暂时不做解读)。 命令执行输出结果如下图所示 将ssa.html文件打开,在浏览器中显示如下图 可以大致浏览下页面,从 Source Code 到 SSA 的转换,这就是在编译过程中,将我们可读的字符序列,转换或是说抽象为特定结构。 ...

一月 24, 2025 · 2 分钟 · anoya

初识Go内存管理

计算机存储设备的读写入读金字塔 我们所说的内存管理是在堆上,栈不需要操作,因为是自动回收的 栈:先进后出,出栈和入栈 内存管理基于 tcmalloc (thread-caching malloc), Page: 大小为 4kb,无论是申请还是释放内存都以 Page 为单位,也就是 4kb Span: 内存块,由多个 Page 构成 SizeClass: Object: 分配流程 当程序需要内存时,会像堆请求分配内存,得到响应后,堆内存会从为分配的内存中切割出一小块内存,用来分配。中间使用链表将各个小块堆内存连接起来 分配对象时,会优先在已分配(释放后)的内存中查找近似的大小块,如果没有合适的,将在未分配的堆内存中切割类似大小的内存用来分配。 当分配的内存多了起来,在每一段分配的内存中会存在未使用的内存,这就是碎片化产生的原因。那么如何将未使用的内存,也就是碎片的内存重新利用起来? 碎片化内存利用 内存对齐 CPU 访问内存时是以字长为单位,减少对内存的访问量,加大 CPU 处理的吞吐量 现在 CPU 普遍是 64 位,字长为 8 字节,32 位的CPU,字长位 4字节 内存对象 当 非内存对齐 TCMalloc Google 开源内存分配 小对象分配 小对象的分配基于 page,当需要分配的对象小于单个 page 时,采用小对象分配方式 page 单个 page 占用为 4kb, 定长对象分配 变长对象分配 内存分配时,“取整”操作,如7字节的占用,就分配8字节的长度。但是分配并不是按照2的幂数, 目前所得时8, 16, 32, 48, 64, 80(等待测试),这样分配的目的是为了减少碎片化,如果按照2的幂数计算,如65字节的占用,将会分配128字节的长度,碎片化占比接近一半。 大对象分批 span span 是一种分配单位, ...

一月 24, 2025 · 1 分钟 · anoya

Flutter模块之Provider

添加依赖 dependencies: provider: ^4.3.2+4 MultiProvider 对多个 Provider 整理 name description Provider 最基础的 provider 组成,接收一个值并暴露它, 无论值是什么。 ListenableProvider 供可监听对象使用的特殊 provider,ListenableProvider 会监听对象,并在监听器被调用时更新依赖此对象的 widgets。 ChangeNotifierProvider 为 ChangeNotifier 提供的 ListenableProvider 规范,会在需要时自动调用ChangeNotifier.dispose。 ValueListenableProvider 监听 ValueListenable,并且只暴露出ValueListenable.value。 StreamProvider 监听流,并暴露出当前的最新值。 FutureProvider 接收一个Future,并在其进入 complete 状态时更新依赖它的组件。 Provider 最基础的 provider 组成,接收一个值并暴露它, 无论值是什么。但是不是会 ui 上刷新 生成 model class CountModel { // 全局状态 int count = 0; // 状态指定方法 add() { this.count++; print(this.count); } } main.dart import 'package:FlutterProvider/model/CountModel.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; main() { runApp( // 使用Provider管理 Provider<CountModel>( create: (_) { return CountModel(0); }, child: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({Key key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: "Provider", home: HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({Key key}) : super(key: key); @override Widget build(BuildContext context) { // 获取Provider管理的model CountModel count = Provider.of<CountModel>(context); return Scaffold( appBar: AppBar( title: Text("Flutter Provider"), ), body: Center( child: Text("当前的值:${count.count.toString()}"), ), floatingActionButton: FloatingActionButton( onPressed: () { // 调用model中的方法,会在control中输出,但是不会在ui上更新 count.add(); }, child: Icon(Icons.add), ), ); } } ChangeNotifierProvider(常用) 为 ChangeNotifier 提供的 ListenableProvider 规范,会在需要时自动调用ChangeNotifier.dispose。 ...

一月 24, 2025 · 2 分钟 · anoya

Colima启动异常

vz driver is running but host agent is not 记录一次 Colima 的使用异常 在 MacOS 更新到 14.4.1 (23E224)后,使用命令colima start提示错误: ➜ ~ colima start INFO[0000] starting colima INFO[0000] runtime: docker INFO[0001] starting ... context=vm > Using the existing instance "colima" > errors inspecting instance: [vz driver is running but host agent is not] FATA[0001] error starting vm: error at 'starting': exit status 1 在网络上找了很久的解决办法,尝试了许多也都无法解决。后来又在 Colima 的 github 上创建了 Issue,一时半会也没有人来解答。也有人遇到这个问题创建了Issues,下拉看了好长也没有一个标准的解决方法。 Troubleshooting and FAQs Check here for Frequently Asked Questions. 在 Colima 的 README.md 中看到了希望。点击去一目十行的浏览下来,找到了关键词Colima not starting。我知道问题将被解决掉,大致浏览了下,原因是在电脑关机时,Colima 创建的 Vm 没有安全退出(优雅关机)。所以在开机启动 Vm 后的状态处于Broken ...

一月 24, 2025 · 1 分钟 · anoya

修改Obsidian‘s Mininal主题样式

一、问题 1、标题样式 Obsidian的Minimal主题样式存在些问题,也不是很大,只是看着有点不舒服 标题与正文样式只有加黑的区别,无法直观看出层级 原因在于主题的css对h[x]标签做了大小的限制,并未继承html原样式 2、字体类型 在定义h4、h5、h6 标签时,如果输入英文会出现显示为大写状态,如下图所示: 与大纲下的文字对比,发现func全转为了大写 二、解决办法 1、样式问题 自定义css样式 打开目录文件,创建任意名称以css结尾,添加css :root { --h1: 2em; --h2: 1.5em; --h3: 1.37em; --h4: 1.25em; --h5: 1.12em; --h6: 1.12em; } 保存后退出,进入Obsidian中刷新后并开启css片段 2、字体类型 使用开发者模式,定位dom元素后,排查问题,可以看出h4的variant不同于前三个标题 老样子,直接在css中替换 将此样式加入在上面创建的css文件中,保存并刷新 --h4-variant: normal; --h5-variant: normal; --h6-variant: normal; 恢复正常

一月 24, 2025 · 1 分钟 · anoya