1 Star 1 Fork 1

U语言组织 / U语言

forked from 秋来冬风 / U语言 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
test.go 3.87 KB
一键复制 编辑 原始数据 按行查看 历史
//go:build !notest
package parser
import (
"bufio"
"os"
"path/filepath"
"strings"
"sync"
"unsafe"
"gitee.com/u-language/u-language/ucom/ast"
"gitee.com/u-language/u-language/ucom/check"
"gitee.com/u-language/u-language/ucom/errcode"
"gitee.com/u-language/u-language/ucom/internal/errutil"
"gitee.com/u-language/u-language/ucom/internal/time"
"gitee.com/u-language/u-language/ucom/lex"
)
// cacheOsFile 为测试缓存需要系统调用的内容
type cacheOsFile struct {
fd *os.File
buf []byte
size int64
}
// 仅测试使用
var (
testmaplock sync.RWMutex //同步map
testmap map[string]cacheOsFile = make(map[string]cacheOsFile, 4) //缓存测试时的系统调用的内容
strbufpool = sync.Pool{ //缓存字符串读取
New: func() interface{} {
return strings.NewReader("")
},
}
bufreadpool = sync.Pool{
New: func() interface{} {
return bufio.NewReader(nil)
},
}
)
// openfileAndInfo 同时获取文件描述符和文件大小
func openfileAndInfo(path string) (*os.File, int64, []byte, error) {
if test { //在测试
testmaplock.RLock() //读取加读锁
if v, ok := testmap[path]; ok { //有缓存
testmaplock.RUnlock() //释放读锁
return v.fd, v.size, v.buf, nil //返回缓存值
}
//写入加写锁
testmaplock.RUnlock() //持有的读锁释放
testmaplock.Lock()
fd, Info, err := openfileAndStat(path)
if err != nil {
return nil, 0, nil, err
}
buf, err := os.ReadFile(path) //获取全部内容
if err != nil {
return nil, 0, nil, err
}
testmap[path] = cacheOsFile{fd: fd, size: Info.Size(), buf: buf} //缓存
testmaplock.Unlock() //释放锁
return fd, Info.Size(), buf, err //返回缓存内容
}
//非测试
file, Info, err := openfileAndStat(path)
if err != nil {
return nil, 0, nil, err
}
return file, Info.Size(), nil, err
}
func openfileAndStat(path string) (*os.File, os.FileInfo, error) {
// 打开文件
file, err := os.Open(path)
if err != nil {
return nil, nil, err
}
info, err := file.Stat()
if err != nil {
return nil, nil, err
}
return file, info, err
}
// ParserFile 从一个代码文件创建ast树
// - path是文件路径
// - errctx是错误处理上下文
// - IsCheck是控制是否进行语义检查
// - Thread是控制是否并发
func ParserFile(path string, errctx *errcode.ErrCtx, IsCheck bool, ImportPackage *map[string]*ast.Package, Thread bool) (*ast.Tree, error) {
file, size, buf, err := openfileAndInfo(path) //获取文件描述符,文件大小,测试时还有全部内容
if err != nil {
return nil, err
}
var r *bufio.Reader
if test { //测试时,这些是为了在Benchmark时获得的数据是从去除换行符到抽象语法树生成完毕,不包括打开文件等操作
str := *(*string)(unsafe.Pointer(&buf))
sbuf := strbufpool.Get().(*strings.Reader)
defer strbufpool.Put(sbuf)
sbuf.Reset(str)
r = bufreadpool.Get().(*bufio.Reader)
defer bufreadpool.Put(r)
r.Reset(sbuf)
} else {
r = bufio.NewReaderSize(file, int(size))
}
var t time.Time
try_new_print_LexTime(&t)
FT := lex.Lex2(path, r, errctx, false) //进行词法分析
try_Print_Time(&t)
try_print_FT(FT)
if errctx.Errbol() { //如果词法分析有错误·
return nil, errutil.NewErr2("错误", "词法分析有错")
}
try_new_print_AstTime(&t)
tree := ast.NewTree(FT, errctx, ast.NewSbt(Thread), ImportPackage) //创建抽象语法树
try_Print_Time(&t)
try_print(tree)
err = loadAllImport(filepath.Dir(path), tree.ImportTable, tree.ImportPackage, tree.ImportLoacl, Thread, errctx, tree.Sbt)
if err != nil {
return nil, err
}
if IsCheck { //如果要进行语义检查
try_new_print_check(&t)
check.CheckTree(tree, errctx, Thread)
try_Print_Time(&t)
}
return tree, nil
}
Go
1
https://gitee.com/u-language/u-language.git
git@gitee.com:u-language/u-language.git
u-language
u-language
U语言
a214d6007862

搜索帮助