0x822a5b87的博客

到码头整点薯条吃

Strategies of Evaluate Infix Operator

when we are implementing a compiler, there is always a difficult problem we will encounter.

How can we evaluate an infix operator?

What is Infix Operator

An infix operator is an operator placed between two expressions, like minus, plus, asterisk, slash and so forth. Here are some common infix operator:

阅读全文 »

Strategies of Evaluation

Evaluation is where interpreter implementations diverge the most.There are a lot of different strategies to choose from when evaluating source code.so looking at different options is worthwhile.

Before we start, though, it's also worthy noting again that the line between interpreter and compiler is a blurry one.

tree-walking interpreter

the most obvious and classical choice of what to do with the AST is to just interpret it. Traverse the AST,visit each node and do what the node signifies: print a string,add two number, execute a function's body.Sometimes their evaluation is preceded by small optimization that rewrite the AST(e.g. remove unused variable bindings) or convert it into another intermediate representation(IR) that's more suitable for recursive and repeated evaluation.

阅读全文 »

使用本文记录学习 Pratt Parser 的过程,全部代码实现基于 go version go1.20.14 darwin/arm64 实现,代码地址位于:0x822a5b87/test-pratt-parsing

什么是 Pratt Parser

语法解析器(Parser)的工作过程中,我们通常会将一个字符串转换为一个抽象语法树(Abstract Syntax Tree)

---
title: The workflow of Paser
---
flowchart LR
	Input["0 + 1 + 2! * -3"] -->|Parser| AST
	
	subgraph AST
		Add --> Add2[Add]
		Add2 --> 0
		Add2 --> 1
		Add --> Mul
		Mul --> ! --> 2w
		Mul --> - --> 3
	end

在这个解析过程中,我们会碰到许多问题:

阅读全文 »

前言

今天,有个朋友突然问了我一个问题,为什么在以下代码中会发生以下这种情况呢?

  1. secretId == "" 可以正常的进行比较;
  2. printString(secretId) 会提示类型不匹配;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import "fmt"

type Password string

func printString(str string) {
fmt.Println(str)
}

func testPrint() {
var secretId Password = "0"

// 这里不会报错
if secretId == "" {
fmt.Println(secretId)
}

// Cannot use 'secretId' (type Password) as the type string
printString(secretId)
}

看到这个问题我的第一反应是由于 类型推导(Type inference)"" 被直接推导为 Password 类型,所以可以直接和 secretId 对象进行比较。可惜的是,在 golang 反编译的代码中已经丢失了类型信息,所以只能慢慢探索了。

阅读全文 »

简述Generics

Generics 是一种基本所有现代高级强类型编程语言中都会提供的特性,各个语言的实现模式不一样,例如:

  • java基于类型擦除(Type Erasure)实现,简单来说就是被在运行时被实际转换为声明的类型(如果没有声明就是object)。这意味着在运行时我们已经丢失实际的类型。
  • cpp 基于 Template 来实现泛型,模版在编译时进行实例化
  • golang 基于 类型参数约束 来实现泛型。

总的来说优缺点如下表所示:

特性/语言 Java 泛型 C++ 模板 Go 泛型
实现方式 类型擦除(Type Erasure) 编译时实例化 类型参数和约束
类型安全
编译时类型检查
灵活性 极高,支持模板化和模板元变成 一般
复杂性 简单 极复杂 简单
运行时开销
缺点 - 运行时无法获取泛型类型信息
- 不能创建泛型数组
- 不能使用基本类型作为泛型参数
- 不能在静态上下文中使用泛型类型参数
- 不能直接实例化泛型类型参数
- 编译速度慢:模板实例化可能导致编译时间增加
- 代码膨胀:大量模板实例化可能导致生成的二进制代码体积增大
- 错误信息复杂:模板错误信息可能难以理解和调试
- 相对较新的特性,生态系统和社区支持可能还不够成熟
- 可能引入一些性能开销,具体需要根据实际使用场景评估
阅读全文 »

calcite入门--RBO模型和CBO模型

由于最近接手了公司的一些血缘解析,SQL优化相关的任务,同时也涉及到了一些DSL的开发,在开发的过程中涉及到大量的calcite规则(Rule)定制,用此文章记录一下calcite的学习心得。

解析

sql parse 的过程

flowchart LR

subgraph 模版
	direction LR
	模板Parser.jj
	compoundIdentifier.ftl
	parserImpls.ftl
	config.fmpp
	default_config.fmpp
end

模版 --> FMPP --> Parser.jj:::underline --> JavaCC --> SqlParserImpl:::underline

classDef underline fill:#f9f,stroke:#333,stroke-width:4px;
阅读全文 »

SQL 查询优化原理与 Volcano Optimizer 介绍

本文是对 SQL 查询优化原理与 Volcano Optimizer 介绍 这篇文章的阅读一些补充和记录。

基于规则的优化方法的要点在于结构匹配和替换。 应用规则的算法一般需要先在关系代数结构上匹配一部分局部的结构, 再根据结构的特点进行变换乃至替换操作。

pattern-match-rule

Volcano Optimizer

阅读全文 »

pprof

pprof 是 golang 内置的一种用于调优和性能分析的工具,有三种最常用的方式使用:

  1. ​ 在启动时引入 "net/http/pprof" 包,在包中会初始化一个http服务,随后可以通过http服务对pprof进行访问;
  2. 通过 wget 的方式访问 /debug/pprof/profile 接口(也需要通过1监听http端口)下载文件,文件可以通过 go tool pprof 打开并进入可视化界面;
  3. 通过 go test 进入测试用例剖析;

net/http/pprof

如果我们想要使用pprof服务,可以通过如下两种方式开启:

阅读全文 »

Golang异步编程总结

常用方式

基于go关键词

匿名函数

1
2
3
4
5
6
7
8
9
10
func main() {
for i := 0; i < 10; i++ {
go func(val int) {
fmt.Println(val)
}(i)
}

// 这里其实是一个未定义行为
time.Sleep(1 * time.Second)
}
阅读全文 »
0%