一、缘起
一直很想做一个自己的动态语言了,记得三年前学习Compiler的时候做了不成器的Tiny++和语法全部按足《编译原理实践》的C--,其中C--还做得非常不好(基本只能看看用不了),然后上次看了《游戏脚本高级编程》,里面介绍的XScript虽然非常简单,但已经有语言的影子。然后又看了《python源码剖析》,看了python的源码,学习了很多python的内部机理,感觉python虽强大巧妙但由于源码是C语言的,读上去总觉得拗口。
在这些基础下,我鼓足勇气,实现一个动态语言,名字叫AnyC,名字怎么起的忘记了(好像是看了三星手机。。。),反正先这样吧。
二、语言特性
这个语言语法上模仿C++和Java(其实更像javascript),以后打算模仿其他语言的优秀特性,支持动态类型、面向对象OOP和函数式编程,内置整形、浮点、array、string、表等类型,支持继承、异常处理、子段数组、lambda表达式、尾递归等。内存管理方面稍差,目前采用引用计数。。。。
例子1:动态特性
function _Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var k = "hello world";//string类
write_console(k+"\n");
k = 10; //int类
write_console(k+"\n");
k = [1,2,3,4,5]; //数组类
for(var i = 0; i < 5; ++i)
write_console(k[i]+" ");
write_console("\n");
}
![](/images/cppblog_com/bennycen/未命名1.PNG)
例子2:快速排序
function Divide(arr,low,high)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var tmp = arr[low];
var left = low;
var right = high+1;
while(left < right)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
while(left < high && arr[++left] < tmp);
while(right >low && arr[--right] > tmp);
if(left < right)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
var kk = arr[left];
arr[left] = arr[right];
arr[right] = kk;
}
}
var kk = arr[low];
arr[low] = arr[right];
arr[right] = kk;
return right;
}
![](/Images/OutliningIndicators/None.gif)
function qsort(arr,low,high)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
if(low < high)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
var mid = Divide(arr,low,high);
qsort(arr,low,mid-1);
qsort(arr,mid+1,high);
}
}
![](/Images/OutliningIndicators/None.gif)
function Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
write_console("快速排序演示: \n");
var datas = [-9,0,0,98,-576,98,74,34,5,3,7,8,1];
write_console("排序前:\n");
foreach(idx,val in datas)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console(val + " ");
}
qsort(datas,0,12);
write_console("\n排序后:\n");
foreach(idx,val in datas)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console(val + " ");
}
write_console("\n");
}
![](/images/cppblog_com/bennycen/未命名2.PNG)
例子3: 桥接模式
class Log
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
protected:
implementor = null;
public:
function set(value)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
implementor = value;
}
function write(log);
};
![](/Images/OutliningIndicators/None.gif)
class DatabaseLog : Log
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
function write(log)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console("日志写入数据库
\n");
implementor.execute(log);
}
};
![](/Images/OutliningIndicators/None.gif)
class TextFileLog : Log
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
function write(log)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console("日志写入文件
\n");
implementor.execute(log);
}
};
![](/Images/OutliningIndicators/None.gif)
class ImpLog
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
function execute(_string_);
};
![](/Images/OutliningIndicators/None.gif)
class DotNetPlatfrom : ImpLog
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
function execute(_string_)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console(".net 平台中
\n");
write_console("写入 " + _string_ + "\n");
}
};
![](/Images/OutliningIndicators/None.gif)
class JavaPlatfrom : ImpLog
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
function execute(_string_)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console("Java 平台中
\n");
write_console("写入 " + _string_ + "\n");
}
};
![](/Images/OutliningIndicators/None.gif)
function _Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
write_console("面向对象编程--设计模式--桥接模式演示例子!\n");
//.NET平台下的Database Log
var dblog = DatabaseLog();
dblog.set(DotNetPlatfrom ());
dblog.write("今天完成了XXX任务\n");
![](/Images/OutliningIndicators/InBlock.gif)
//Java平台下的Text File Log
var txtlog = TextFileLog();
txtlog.set(JavaPlatfrom());
txtlog.write("今天学会用Java了\n");
![](/Images/OutliningIndicators/InBlock.gif)
}
![](/images/cppblog_com/bennycen/未命名3.PNG)
例子4: 数组操作
function _Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var k = [1,2,3,4];
var q = [4,5,6];
q[0 -> 1] = k[0:2];
write_console("---结果为【1,2,6】--\n");
foreach(val in q)
write_console(val + "\n");
q[2 <- 0] = k[1:3];
write_console("---结果为【4,3,2】--\n");
foreach(val in q)
write_console(val + "\n");
q[0:3] = k[0:3];
write_console("---结果为【1,2,3】--\n");
foreach(val in q)
write_console(val + "\n");
write_console("---结果为【2,1】--\n");
q[2 <- 0] = k[0:2];
foreach(val in q)
write_console(val + "\n");
}
function _Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var a = ["spam", "eggs",123,1234];
a[0:2] = [];
foreach(val in a)
write_console(val + "\n");
write_console("------------\n");
a[1:0] = ["bletch","xyzzy"];
foreach(val in a)
write_console(val + "\n");
a[a.length() : 0] = a;
write_console("------------\n");
foreach(val in a)
write_console(val + "\n");
}
![](http://www.cppblog.com/images/cppblog_com/bennycen/未命名4.PNG)
![](http://www.cppblog.com/images/cppblog_com/bennycen/未命名5.PNG)
例子5 lambda for sort
function sort(arr,len,cmpFun)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var tmp = 0;
var i ,j;
for(i = 0; i < len; ++i)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(j = 0;j < len-i-1;++j)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(cmpFun(arr[j],arr[j+1]))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
![](/Images/OutliningIndicators/None.gif)
function Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var datas = [3,4,1,6,8];
var len = 5;
write_console("开始排序:\n");
sort(datas,len,lambda(a,b) a > b);
![](/Images/OutliningIndicators/InBlock.gif)
for(var k = 0; k < len; ++k)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
write_console(datas[k] + " ");
}
write_console("\n");
}
![](/images/cppblog_com/bennycen/未命名6.PNG)
例子6 函数式
function outerFunction()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var outVar=0;
return function()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
outVar++;
write_console(outVar+"\n");
}
}
function _Main()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
var instance=outerFunction();
instance();
![](/Images/OutliningIndicators/InBlock.gif)
var instance2=outerFunction();
instance2();
![](/Images/OutliningIndicators/InBlock.gif)
instance();
![](/Images/OutliningIndicators/InBlock.gif)
instance2();
}
![](/Images/OutliningIndicators/None.gif)
![](/images/cppblog_com/bennycen/未命名7.PNG)
三、实现心得
这个语言的主要思想很大一部分参考了python,是基于虚拟机的脚本语言,首先进行lexer提取token,然后手写递归下降器解析生成语法树,
然后用visitor访问语法树生成字节码,最后启动虚拟机运行。
我认为实现动态语言主要分4个环节:
1. 基本库的建立
这个并不是指脚本的库,是指C++的库,用到的一些东西如智能指针、链表等数据结构(也可用STL)、文件类等是必须的。
2. 动态对象环境
主要是在C++层面上实现一个“动态对象”,它是一个基于引用计数的指针对象,可以指向指定的对象,并实现内置动态对象的一些功能接口。
3. 词法语法分析及语义翻译
此过程比较规则化,前两者可以用lexer和yacc做,我觉得不复杂的话手写也不错,毕竟手写灵活性大一点,成功生成语法树后就是语法翻译成
字节码,翻译是比较困难的环节,难的话还会考虑各种代码优化计算、编译成本地的JIT等。
4. 虚拟机
虚拟机负责分析字节码,自己创建一个虚拟的运行环境,提供HostAPI插件接口和调用规则。可以说虚拟机是比较复杂的一部分,因为它涉及的东西很杂,当然也可以很简单(如果虚拟机低效和功能小的话)。
四、结语
接下来还要做很多去完善这个东西,包括如何和C++进行良好对接,丰富脚本API以及丰富语言特性如提供正则表达式内置对象等。
posted on 2012-03-08 11:05
bennycen 阅读(695)
评论(4) 编辑 收藏 引用 所属分类:
Windows Programming