我在QQ上加了一个专门讨论DirectX的群,里面有不少的高手。这让我也有机会去感受一下GNU之父——斯托曼在大学时代曾经体会过的那些快乐。客观地讲,这就是传统黑客(有技术和共享合作精神,而非入侵他人计算机)。
在讨论技术之余,我发现大家都在抨击C++的语法问题。臃肿、复杂、难以理解,很多时候不够灵活,也无法榨干硬件能力。其他那些C++之外的语言更是如此。像Java这种语言只能被抨击为邪语(类似邪·教这种)。
仔细看不难发现,甚至没有哪种主流的编程语言是中国人发明的(其实还是有的,比如易语言,但很少见有人用这种东西)。最近华为非常高调,宣称已经造出了自主研发的操作系统(鸿蒙OS),下一步还要开发自主研发的编程语言。这其实是好事。但要落地,而绝不能画饼。可以以旧的编程语言为参照,改进轮子,大功一件。
我对脚本语言(比如Python、JavaScript),以及像Java这种半编译语言兴趣不大。以后再说。
本文专讲未来的编译语言。我只能算编程业余爱好者,水平不高,想到哪儿说哪儿。
自娱自乐,不必太当真。
一、pos_t类型
size_t类型大家都不陌生。这是一种typedef的无符号整数,且同指针有通常的长度(x86下是32位=4字节,x64下是64位=8字节)。而pos_t同size_t具有同样的长度,也是无符号整数。这东西什么用?请看下面的代码:
void func()
{
pos_t pos = End;
goto pos;
End:
return;
}
也就是说,要允许将标签赋值给变量,并以变量为目标进行跳转。ASM(汇编)是有这个能力的。在至少1/3以上的函数内,对于保证代码的效率而言是必须的。写过代码的人必深有体会。
函数内的标签还应该可以被导出来。上代码:
int func1(pos_t pos)
{
goto pos;
Pos1:
return 1;
Pos2:
return 2
}
void func2()
{
pos_t pos = func1:.Pos2;
int x = func1(pos);
printf("%d", x);
}
对于像dll这样的外部函数,其内部跳转点的导出应该设置其他的机制。一定要实现的话并不难。
C/C++是不允许这样的语法的。事实上在C的时代就应该实现这样的功能。而现在,通过内联汇编可以模拟这样的功能。
上代码:
#define assign_label(value, label)
__asm push eax \
__asm mov eax, label \
__asm mov value, eax \
__asm pop eax
#define jump_to(pos) __asm { jmp pos }
void func()
{
pos_t pos;
assign_label(pos, _B); //实际上这一句就相当于pos = _B; 但是C/C++不允许这样的语法。
jump_to(_B); //这一句就相当于goto pos; 同样,C/C++不允许这样的语法。
_A:
printf(L"A");
return;
_B:
printf(L"B");
return;
}
遗憾的是,这两个宏只能在x86下使用。x64下是不能用的。VC编译器的x64模式根本不能使用内联汇编。GCC是可以的。但要修改为GCC的汇编语法。
二、以相关函数代替成员函数
上代码:
struct type1_t
{
int a, b;
}
void type1_t.print()
{
printf("(%d, %d)", a, b);
}
类(或结构体)不再有成员函数,只有相关函数。且在外部进行定义(或声明)。
也就是说,在任何位置都可以扩充类的方法。而不限于类的内部。
构造和析构函数也是如此。
三、全文(通透式)编译,无定义次序依赖
上代码:
void func1(){ func2(); }
void func2(){ func3(); }
void func3(){ print("OK!"); }
完全没有问题。并且:
void func(type1_t t){ printf("%d", t.x); }
struct type1_t
{
int x, y;
}
完全没有问题。这就叫全文(通透式)编译。不依赖于定义次序。
四、底层关键字
底层关键字事实上就是G语言自定义语法的实现途径。实际上,一套丰富健全的底层关键字 + 高级宏 = 自定义语法。
G语言的上层语法其实都是通过高级宏包装的底层关键字加以实现的自定义语法。
G语言可以模拟其他编译语言(甚至是脚本语言)的语法,虽然不能100%,但是能模仿个八九分像。方式就是通过底层关键字将通用核心语义抽象出来。
/*/底层关键字/*/
___keyword_function
___keyword_void
___keyword_return
___keyword_goto
___keyword_switch
___keyword_struct
___keyword_enum
___keyword_if
___keyword_else
___keyword_while
___keyword_for
___keyword_do
___keyword_break
___keyword_continue
___core_operator_('(')
___core_operator(')')
___core_operator_('{')
___core_operator('}')
___core_operator_('[')
___core_operator(']')
___core_operator('.')
___core_operator('+')
___core_operator('-')
___core_operator('*')
___core_operator('/')
___core_operator('<')
___core_operator('>')
___core_operator('!')
___core_operator('~')
___core_operator('&')
___core_operator('|')
___core_operator(">=")
___core_operator("&&")
___core_operator("||")
___core_operator("&=")
___core_operator("|=")
___core_operator("<=")
___core_operator("==")
___core_operator("!=")
___core_operator("++")
___core_operator("--")
___core_operator("->")
无论怎样定义语法,编译器最终都会将代码先翻译成底层关键字语法形式,再进行底层语法代码编译。例如下面的代码:
void func()
{
if(1 > 0)
return;
}
会被翻译为如下底层码:
___keyword_function((___keyword_void), func1, ())
___core_operator('{')
___keyword_if
___core_operator('(')
1 ___core_operator('>') 0
___core_operator(')')
___keyword_return
___core_operator(';')
___core_operator('}')
五、高级宏
这一部分我还仅仅想了一个大概。C/C++的宏功能强大,但还没有强大到能够让人非常满意的程度。
高级宏的主要目标是,让旧的C/C++宏更加强大,更容易理解和键入,且支持G语言自定义语法功能。
#define big_macro
#{
Line1;
Line2;
Line3;
...
}#
#define big_macro2
#{
#define big_macro3
#{
Line1;
Line2;
Line3;
}#
}#
#define use_std_grammar
#{
#define #operator [ ___core_operator('[')
#define #operator ] ___core_operator(']')
#define #operator + ___core_operator('+')
#define #operator - ___core_operator('-')
#define #operator * ___core_operator('*')
#define #operator / ___core_operator('/')
...
}#
#define unuse_std_grammar
#{
#undef #operator [
#undef #operator ]
#undef #operator +
#undef #operator -
#undef #operator *
#undef #operator /
...
}#
其实这些只是高级宏丰富功能的冰山一角。
六、局部语法
宏定义语法#define太长了。#include也很长。其实可以像下面这样。
#define #macro def define
#define #macro inc include
#inc<g_grammar> //内含g语言语法定义项。
#inc<g_stdio>
use_g_std_grammar; //这一句必须,定义g语言语法。
#def m1 int main
m1()
{
return 0;
}
unuse_g_std_grammar; //这一句是必要的。
上面这个缺少让人醒目的功效。但是下面这一个就不一样了。
#include<g_grammar>
#include"my_own_grammar.g"
use_g_std_grammar;
void func()
{
return;
}
unuse_g_std_grammar;
use_my_own_grammar;
...
unuse_my_own_grammar;
G语言对局部语法有强大的支持,因此甚至在一个函数内使用两套以上的语法都绝对不是问题。
如果感觉某项任务难以用传统语法达成,就可以尝试局部语法来完成任务。
七、G语言常量字符串
上代码:
void func()
{
str_t s = "你好,G语言。";
char * s8 = s;
wchar_t s16 = s;
size_t sz8 = s.size<char>();
size_t sz16 = s.size<wchar_t>();
s.begin();
s.end();
}
G语言常量字符串可以自动转化为宽窄两种版本。并提供起止位置,长度等相关方法。是内置类型。
...(未完待续)...