我做了一个决定:开发一门语言。
这是很多coder的梦想,但只有很少人才能真正做出来,做出来后只有很少人能真正使用这门语言。
请不要在这里说语言已经很多了,做了也是白做之类的话,反正浪费的不是你的时间。
~~~~~~~~~~~~~~~~~
我已经确认在技术水平上这个语言是完全可以做出来的。语言最后一定会做出来的。
发表此文的目的,是为了在语言设计完成前参考下各位coder的意见,
作为一个coder,你一定想过自己做一个语言,只是你可能不会做,不敢做,或者没时间,或者觉得做这个零回报。
但是你可以在这里把你关于语言(特别是语法)的想法说出来,如果真的是不错的想法我会采纳你的意见。
当然你不会在你的工作中使用这门语言,不过纯吐槽吐槽不也是挺好的么。
~~~~~~~~~~~~~~~~~~
先说我要做的语言的大致特点:1. C风格,更符合C++用户的习惯。2. 强类型、需要编译执行。3. 可以编译为原生机器码,当然GC之类的也是会有的。
语言的设计目标不是高运行效率,也不是简单稳定完美。而是:做业务需求更方便。
~~~~~~~~~~~~~~~~~~
接下来就是目前已经设计好的语法和吐槽点了。欢迎提供建议和批评。
一、基本结构
1. 全局下只能有:全局函数、全局变量、名字空间和类。程序入口函数默认是 main 函数。 hello world 代码如下:
void main(){ System.Console.writeLine("hello world"); }
其中,System 是系统包。对于代码中的所有点都可以省略,代码如下:
using System;
void main(){ Console.writeLine("hello world"); }
更甚至是:
using System.Console;
void main(){ writeLine("hello world"); }
2. 代码中支持C中经典的预处理符,但是不允许 #define a b 的形式,因为这东西会让代码非常难读懂。所以同时 #ifdef 之类的也改成了 #if 。也没有#include ,因为这东西让编译速度急速下降。其实这些情况和C#完全一样。
二、语句和表达式
1. 代码允许缺少分号,只要不出现歧义。还有 if for 等语句的小括号也可以省略,只要不出现歧义。
2. switch 语句case之间不贯穿,这意味着不需要break。相同处理情况的case可以使用一个case,然后后面表达式逗号隔开。
3. 使用和JavaScript相同的 for in 语句(内部使用 yield 语句)。同时还支持下面语法:
for(object value, int i in arr){}
for(int i = 0 to 100){} until(a){} // 即 while(!a) do {} until(a) // 即 while(!a)
loop {} // 死循环 loop(100){} // 循环100次
4. 自动识别类型。
auto i = 1; // 自动识别 auto 到 int dynamic j = 1; // 动态类型 // 注意以上两者是本质区别的,前者是静态类型,编译时就已知类型了,后者动态 var k = 1; // 智能的类型判断,如果 k 在生命周期内只有一个类型,那么它是静态类型,相当于 auto 了。否则,k有多个类型可能的话,即 dynamic 。
5. 使用 dispose 来释放外部资源
var s = new FileStream("C:\\a.txt"); s.dispose(); // 释放s所占的资源(但s对象本身肯能是受GC管理而没有释放的) // 也可以使用语法糖写成: let(var s = new FileStream("C:\\a.txt")){}
6. 类型转换问题
int a = 1 as long // 即C的 int a = 1L; int b = a as long // 即C的 int a = (long)b;
int c = "111" as int
string d = 1 as string; // 可见不存在 .toString() 函数。(as 操作同样可以使用参数)
// 对于明确类型的变量定义。可以直接省略 as 调用
string s = 1; // 省略一个 as string
// 但是其它地方是不允许省略的。
// 类型转换也可以使用这个语法糖:
int("111") // 等效于 "111" as int
// 类型转换也存在和C一样的隐式方式。
7. 指针问题
语法上不直接提供指针功能,同时使用类似API的方式使用:
int i = 0; Ptr<int> pi = i as Ptr<int>; int j = pi++.value;
8. 变量约束
int i : i > 5 ; i = 4; // 运行时错误: i 必须大于 5
使用变量约束可以大幅增加代码的稳定性。变量约束同样可以应用在参数和字段。
9. 衍生类型
int[] p = [1, 2, 3]; int? p = null // 可空类型 string! p = null // 不可空类型(此代码运行时报错) // ? 和 ! 是两种相反的特殊类型, ?适于值类型, !适于引用类型。
10. 使用类名来获取类型本身并用来反射
Type s = String; // 直接获取此类型本身 Method d =String.replace; // 直接返回此函数本身 string ns = d.call("", "a", "b");
11. 模板字符串
int i = 1; string s = `v is $i` // 最后 v is 1
12. 支持 goto
三、类
1. class 都是引用类型。 struct 都是结构类型。
2. 默认 public, 名字以 _ 前缀的默认 private
3. interface 可以包含默认的实现。
4. 允许动态扩展类成员。
5. 没有析构函数。(提升 GC 的效率)
请不要说这些东西不符合面向对象。我压根没打算做面向对象,我做的是原创的面向接口。
6. 支持函数动态重载。
class A{} class B:A{} class C:A{} // 定义动态重载 void fn(case B i){} void fn(case C i){} A a = getA(); fn(a); // 调用动态重载 // 如果没有 case ,那么是静态重载。此时因为不存在 fn(A i) 所以报错。 // 但是有 case证明动态重载,那么fn在运行时选择真正函数 。
7. 使用 base 表示基类。内部类不能直接访问外部类非静态成员。
附 Object 类源码:
class Object { protected Object memberwiseClone(){ return Native.memberwiseClone(this); } protected virtual void finalize(){ } Type getType() { return Native.getType(this); } virtual int getHashCode() { return Native.getHashCode(this); } virtual as String { return this.type as String; }
as void* { return Native.getPtr(this); } virtual bool == (Object value) { return Object.referenceEquals(this, value); } virtual >> { >> this as String; } static bool referenceEquals(Object objA, Object objB) { return Native.referenceEquals(objA, objB); } }
欢迎补充。
string