# ttlang **Repository Path**: penguin_Ku/ttlang ## Basic Information - **Project Name**: ttlang - **Description**: 用比较正规的方法来产生一个语言,这一次要比较注重性能 目前计划工具用c# VM用c++实现 - **Primary Language**: C# - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2021-04-07 - **Last Updated**: 2021-06-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ttlang 兔兔语言,乍一看人畜无害,一转眼战天斗地。 这个坑又往前推了一步,把readme进化一下 ## 介绍 兔兔语言是一个多功能辅助语言。 ``` //已废弃 语法采取 c like,使用方式类似c#,以项目的形式,将一个项目编译为一个库 ``` 语法采取ecmascript的方式 c语言是我的启蒙语言,所以对于c like 我可能有过多的倾向,于是我选择尽可能的多看一些别的语言,ecmascript这个形式也可以说 clike,最大的不同是类型后置,这在很多情况下反而更加清晰 lua过分轻了,而且lua和c语言的交互还挺复杂的,于是各种xxlua项目一大堆。 兔兔语言要举重若轻。 使用者学习成本极低,会点c++ c# java 都可以上手 兔兔语言可以被编译到各种平台 ### 使用场景 兔兔语言并重三种使用场景 1.为热更新服务,解释执行 2.tt->cpp 或者 c语言 3.tt->h5 ts 或者 js 或者wasm tt语言的目标就是立足成为一个多端应用开发的语言。 ## 语言设计 ``` 已废弃 首先tt 是一门真正的 oop语言。 已废弃 他的基本设计元素来自于c#。 ``` oop真的需要吗?我们可以保留各种oop的元素,但不应该把使用方式作为语言设计的一部分 不从向谁的角度考虑,只从目标的角度考虑。 因为目标是易用高性能脚本,使用模式是VM解释器和跨界编译 根据此目标可以推导出两个设计原则 ttlang的两个设计原则是贴近内存和信息充分,贴近内存的目标是为了VM的性能可以很高,信息充分的目标是为了跨界编译时可以生成高性能的代码 当然还有用户友好,目标易用 ### 贴近内存设计 必须保持内存一致的值类型 和 struct,struct的对齐可控 堆和栈概念不需要暴露给用户,但要为VM和编译器留下充分的信息 贴近内存设计的最直接表现就是 struct 和 字段对齐 c#的使用方式,可以采用特性标记每一个变量得位置,但是这会不安全,标记错误会实际上出现union得效果,而我们不愿意看到这种效果。 ttlang struct 采取固定变量顺序,一字节对齐。 为了对齐,可以增加空占位变量 _表示空变量,没有名字,不可访问 ```c struct aa { _:pack_space(4) //插入4个字节 ac:uint8 //pos 4,一字节 _:pack_tab(8) //pos 5,将插入3个字节,去保持到8字节对齐 ad:uint8 //pos 8,一字节 _:pack_tab(8) //pos 9,将插入7个字节 } ``` 默认得 变量 会尽量分配在栈上,不管你用不用new关键字 分配在堆上要么你的变量太大了,可能是64k,要么他是一个需要被长期引用得对象。 c#中一切都是对象,当一个值类型被一个object引用时,c#自动进行装箱 ttlang首先取消自动装箱功能,因为这实质上是memcpy,应该显示得由用户处理 ttlang里面值就是值,对象不包含值,有明显的界限,值类型就不会在栈上分配 只有当你声明了一个真正的引用对象,通常是class,并且这个变量有传出的行为 这些行为通常包括 1.被另外一个全局变量或成员变量保存 2.通过传参的形式调用其它函数 3.作为返回值 但是这里面又有一个意外,通过传参的形式调用函数,这个情况下有可能对方函数并不保持这个变量,只是计算使用,这种情况下这个变量就没必要分配在堆。 我们在信息充分设计是考虑如何处理这个问题 ### 信息充分设计 编译器需要充分的信息工作,不需要每件事都要用户关心,语法设计上尽量用户友好,但必须保持充分的信息供编译器优化 可是编译器不足以识别这种情况,除非提供额外的信息。 这就是rust的一些设计逻辑 ```ts shared aaa:string; callfuncerr(str:string ,str2;string):void { aaa = str;//ttlang里这会编译失败,因为参数string 是借用,不允许长期持有 } callfuncsucc(shared str:string,shared str2:string):void { aaa = str;//这才允许 tt.a =aaa;//这又不允许了, } ``` 我们把成员和参数 分为三种 值 对象 共享对象 值不用说了,可以随手复制 对象是借用,默认都是借用,此时不允许其它人(Type)保持这个对象,只能在栈上临时使用 共享对象 才是一个完整的通过引用计数可以随意引用记录的对象 有了这些信息,被借用的对象编译器将尽量分配在栈上,并在自己出栈时随即清理。其实在堆在栈不是那么重要,重要的是被借用对象的生存期被固定了,被借用对象的销毁时机是明确的。 考虑到有必要使用共享对象的情况实际上是很少的,这项设计可以将GC的压力极大减轻。 ## 用户友好设计 话痨式编译器 ttlang的编译器应该是一个话痨,尽可能提供足够多的信息给用户解释 反指针,反unsafe 用struct 和 ref 参数可以解决各种问题,所以我们不提供unsafe模式 对象的变量 是借用 共享对象的变量是指针 数组都是对象,数组和切片的变量是数组指针 不会暴漏原始指针给用户 ### 第二步 编码中 进度 设计中,编译器实现中 语法方向确定 大设计原则确定