一、缘起
一直很想做一个自己的动态语言了,记得三年前学习Compiler的时候做了不成器的Tiny++和语法全部按足《编译原理实践》的C--,其中C--还做得非常不好(基本只能看看用不了),然后上次看了《游戏脚本高级编程》,里面介绍的XScript虽然非常简单,但已经有语言的影子。然后又看了《python源码剖析》,看了python的源码,学习了很多python的内部机理,感觉python虽强大巧妙但由于源码是C语言的,读上去总觉得拗口。
在这些基础下,我鼓足勇气,实现一个动态语言,名字叫AnyC,名字怎么起的忘记了(好像是看了三星手机。。。),反正先这样吧。
二、语言特性
这个语言语法上模仿C++和Java(其实更像javascript),以后打算模仿其他语言的优秀特性,支持动态类型、面向对象OOP和函数式编程,内置整形、浮点、array、string、表等类型,支持继承、异常处理、子段数组、lambda表达式、尾递归等。内存管理方面稍差,目前采用引用计数。。。。
例子1:动态特性
 function _Main()
function _Main()


 {
{
 var k = "hello world";//string类
    var k = "hello world";//string类
 write_console(k+"\n");
    write_console(k+"\n");
 k = 10;            //int类
    k = 10;            //int类
 write_console(k+"\n");
    write_console(k+"\n");
 k = [1,2,3,4,5];    //数组类
    k = [1,2,3,4,5];    //数组类
 for(var i = 0; i < 5; ++i)
    for(var i = 0; i < 5; ++i)
 write_console(k[i]+" ");
        write_console(k[i]+" ");
 write_console("\n");
    write_console("\n");
 }
}
例子2:快速排序
 function Divide(arr,low,high)
function Divide(arr,low,high)


 {
{
 var tmp = arr[low];
    var tmp = arr[low];
 var left = low;
    var left = low;
 var right = high+1;
    var right = high+1;
 while(left < right)
    while(left < right)

 
     {
{
 while(left < high && arr[++left] < tmp);
        while(left < high && arr[++left] < tmp);
 while(right >low && arr[--right] > tmp);
        while(right >low && arr[--right] > tmp);
 if(left < right)
        if(left < right)

 
         {
{
 var kk = arr[left];
            var kk = arr[left];
 arr[left] = arr[right];
            arr[left] = arr[right];
 arr[right] = kk;
            arr[right] = kk;
 }
        }
 }
    }
 var kk = arr[low];
    var kk = arr[low];
 arr[low] = arr[right];
    arr[low] = arr[right];
 arr[right] = kk;
    arr[right] = kk;
 return right;
    return right;
 }
}

 function qsort(arr,low,high)
function qsort(arr,low,high)


 {
{
 if(low < high)
    if(low < high)

 
     {
{
 var mid = Divide(arr,low,high);
        var mid = Divide(arr,low,high);
 qsort(arr,low,mid-1);
        qsort(arr,low,mid-1);
 qsort(arr,mid+1,high);
        qsort(arr,mid+1,high);
 }
    }
 }
}

 function Main()
function Main()


 {
{
 write_console("快速排序演示: \n");
    write_console("快速排序演示: \n");
 var datas = [-9,0,0,98,-576,98,74,34,5,3,7,8,1];
    var datas = [-9,0,0,98,-576,98,74,34,5,3,7,8,1];
 write_console("排序前:\n");
    write_console("排序前:\n");
 foreach(idx,val in datas)
    foreach(idx,val in datas)

 
     {
{
 write_console(val + " ");
        write_console(val + " ");
 }
    }
 qsort(datas,0,12);
    qsort(datas,0,12);
 write_console("\n排序后:\n");
    write_console("\n排序后:\n");
 foreach(idx,val in datas)
    foreach(idx,val in datas)

 
     {
{
 write_console(val + " ");
        write_console(val + " ");
 }
    }
 write_console("\n");
    write_console("\n");
 }
}
例子3: 桥接模式
 class Log
class Log


 {
{
 protected:
protected:
 implementor = null;
    implementor = null;
 public:
public:
 function set(value)
    function set(value)

 
     {
{
 implementor = value;
        implementor = value;
 }
    }
 function write(log);
    function write(log);
 };
};

 class DatabaseLog : Log
class DatabaseLog : Log


 {
{
 public:
public:
 function write(log)
    function write(log)

 
     {
{
 write_console("日志写入数据库
        write_console("日志写入数据库 \n");
\n");
 implementor.execute(log);
        implementor.execute(log);
 }
    }
 };
};

 class TextFileLog : Log
class TextFileLog : Log


 {
{
 public:
public:
 function write(log)
    function write(log)

 
     {
{
 write_console("日志写入文件
        write_console("日志写入文件 \n");
\n");
 implementor.execute(log);
        implementor.execute(log);
 }
    }
 };
};

 class ImpLog
class ImpLog


 {
{
 public:
public:
 function execute(_string_);
    function execute(_string_);
 };
};

 class DotNetPlatfrom : ImpLog
class DotNetPlatfrom : ImpLog


 {
{
 public:
public:
 function execute(_string_)
    function execute(_string_)

 
     {
{
 write_console(".net 平台中
        write_console(".net 平台中 \n");
\n");
 write_console("写入 " + _string_ + "\n");
        write_console("写入 " + _string_ + "\n");
 }
    }
 };
};

 class JavaPlatfrom : ImpLog
class JavaPlatfrom : ImpLog


 {
{
 public:
public:
 function execute(_string_)
    function execute(_string_)

 
     {
{
 write_console("Java 平台中
        write_console("Java 平台中 \n");
\n");
 write_console("写入 " + _string_ + "\n");
        write_console("写入 " + _string_ + "\n");
 }
    }
 };
};

 function _Main()
function _Main()


 {
{
 write_console("面向对象编程--设计模式--桥接模式演示例子!\n");
    write_console("面向对象编程--设计模式--桥接模式演示例子!\n");
 //.NET平台下的Database Log
    //.NET平台下的Database Log
 var dblog = DatabaseLog();
        var dblog = DatabaseLog();
 dblog.set(DotNetPlatfrom ());
        dblog.set(DotNetPlatfrom ());
 dblog.write("今天完成了XXX任务\n");
        dblog.write("今天完成了XXX任务\n");    

 //Java平台下的Text File Log
        //Java平台下的Text File Log
 var txtlog = TextFileLog();
        var txtlog = TextFileLog();
 txtlog.set(JavaPlatfrom());
        txtlog.set(JavaPlatfrom());
 txtlog.write("今天学会用Java了\n");
        txtlog.write("今天学会用Java了\n");

 }
}
例子4: 数组操作
 function _Main()
function _Main()


 {
{
 var k = [1,2,3,4];
    var k = [1,2,3,4];
 var q = [4,5,6];
    var q = [4,5,6];
 q[0 -> 1] = k[0:2];
    q[0 -> 1] = k[0:2];
 write_console("---结果为【1,2,6】--\n");
    write_console("---结果为【1,2,6】--\n");
 foreach(val in q)
    foreach(val in q)
 write_console(val + "\n");
        write_console(val + "\n");
 q[2 <- 0] = k[1:3];
    q[2 <- 0] = k[1:3];
 write_console("---结果为【4,3,2】--\n");
    write_console("---结果为【4,3,2】--\n");
 foreach(val in q)
    foreach(val in q)
 write_console(val + "\n");
        write_console(val + "\n");
 q[0:3] = k[0:3];
    q[0:3] = k[0:3];
 write_console("---结果为【1,2,3】--\n");
    write_console("---结果为【1,2,3】--\n");
 foreach(val in q)
    foreach(val in q)
 write_console(val + "\n");
        write_console(val + "\n");
 write_console("---结果为【2,1】--\n");
    write_console("---结果为【2,1】--\n");
 q[2 <- 0] = k[0:2];
    q[2 <- 0] = k[0:2];
 foreach(val in q)
    foreach(val in q)
 write_console(val + "\n");
        write_console(val + "\n");
 }
}
 function _Main()
function _Main()


 {
{
 var a = ["spam", "eggs",123,1234];
    var a = ["spam", "eggs",123,1234];
 a[0:2] = [];
    a[0:2] = [];
 foreach(val in a)
    foreach(val in a)
 write_console(val + "\n");
        write_console(val + "\n");
 write_console("------------\n");
    write_console("------------\n");
 a[1:0] = ["bletch","xyzzy"];
    a[1:0] = ["bletch","xyzzy"];
 foreach(val in a)
    foreach(val in a)
 write_console(val + "\n");
        write_console(val + "\n");
 a[a.length() : 0] = a;
    a[a.length() : 0] = a;
 write_console("------------\n");
    write_console("------------\n");
 foreach(val in a)
    foreach(val in a)
 write_console(val + "\n");
        write_console(val + "\n");
 }
}

例子5 lambda for sort
 function sort(arr,len,cmpFun)
function sort(arr,len,cmpFun)


 {
{
 var tmp = 0;
    var tmp = 0;
 var i ,j;
    var i ,j;
 for(i = 0; i < len; ++i)
    for(i = 0; i < len; ++i)

 
     {
{
 for(j = 0;j < len-i-1;++j)
        for(j = 0;j < len-i-1;++j)

 
         {
{
 if(cmpFun(arr[j],arr[j+1]))
            if(cmpFun(arr[j],arr[j+1]))

 
             {
{
 tmp = arr[j];
                tmp = arr[j];
 arr[j] = arr[j+1];
                arr[j] = arr[j+1];
 arr[j+1] = tmp;
                arr[j+1] = tmp;
 }
            }
 }
        }
 }
    }
 }
}

 function Main()
function Main()


 {
{
 var datas = [3,4,1,6,8];
    var datas = [3,4,1,6,8];
 var len = 5;
    var len = 5;
 
    
 write_console("开始排序:\n");
    write_console("开始排序:\n");    
 sort(datas,len,lambda(a,b) a > b);
    sort(datas,len,lambda(a,b) a > b);

 for(var k = 0; k < len; ++k)
    for(var k = 0; k < len; ++k)

 
     {
{
 write_console(datas[k] + " ");
        write_console(datas[k] + " ");
 }
    }
 write_console("\n");
    write_console("\n");
 }
}
例子6 函数式
 function outerFunction()
function outerFunction()


 {
{
 var outVar=0;
    var outVar=0;
 return function()
    return function()

 
     {
{
 outVar++;
            outVar++;
 write_console(outVar+"\n");
             write_console(outVar+"\n");
 }
    }
 }
}
 function _Main()
function _Main()


 {
{
 var instance=outerFunction();
    var instance=outerFunction();
 instance();
    instance();

 var instance2=outerFunction();
    var instance2=outerFunction();
 instance2();
    instance2();

 instance();
    instance();

 instance2();
    instance2();
 }
}

 
三、实现心得
这个语言的主要思想很大一部分参考了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 阅读(753) 
评论(4)  编辑 收藏 引用  所属分类: 
Windows Programming