posts - 33,  comments - 33,  trackbacks - 0

一、缘起
一直很想做一个自己的动态语言了,记得三年前学习Compiler的时候做了不成器的Tiny++和语法全部按足《编译原理实践》的C--,其中C--还做得非常不好(基本只能看看用不了),然后上次看了《游戏脚本高级编程》,里面介绍的XScript虽然非常简单,但已经有语言的影子。然后又看了《python源码剖析》,看了python的源码,学习了很多python的内部机理,感觉python虽强大巧妙但由于源码是C语言的,读上去总觉得拗口。
在这些基础下,我鼓足勇气,实现一个动态语言,名字叫AnyC,名字怎么起的忘记了(好像是看了三星手机。。。),反正先这样吧。

二、语言特性
这个语言语法上模仿C++和Java(其实更像javascript),以后打算模仿其他语言的优秀特性,支持动态类型、面向对象OOP和函数式编程,内置整形、浮点、array、string、表等类型,支持继承、异常处理、子段数组、lambda表达式、尾递归等。内存管理方面稍差,目前采用引用计数。。。。
例子1:动态特性

function _Main()
{
    
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"
);
}


例子2:快速排序

function Divide(arr,low,high)
{
    
var tmp =
 arr[low];
    
var left =
 low;
    
var right = high+1
;
    
while(left <
 right)
    
{
        
while(left < high && arr[++left] <
 tmp);
        
while(right >low && arr[--right] >
 tmp);
        
if(left <
 right)
        
{
            
var kk =
 arr[left];
            arr[left] 
=
 arr[right];
            arr[right] 
=
 kk;
        }

    }

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


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

}


function Main()
{
    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)
    
{
        write_console(val 
+ " "
);
    }

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

    write_console(
"\n");
}


例子3: 桥接模式

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

    
function write(log);
}
;

class DatabaseLog : Log
{
public:
    
function
 write(log)
    
{
        write_console(
"日志写入数据库\n"
);
        implementor.execute(log);
    }

}
;

class TextFileLog : Log
{
public:
    
function
 write(log)
    
{
        write_console(
"日志写入文件\n"
);
        implementor.execute(log);
    }

}
;

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

class DotNetPlatfrom : ImpLog
{
public:
    
function
 execute(_string_)
    
{
        write_console(
".net 平台中\n"
);
        write_console(
"写入 " + _string_ + "\n"
);
    }

}
;

class JavaPlatfrom : ImpLog
{
public:
    
function
 execute(_string_)
    
{
        write_console(
"Java 平台中\n"
);
        write_console(
"写入 " + _string_ + "\n"
);
    }

}
;

function
 _Main()
{
    write_console(
"面向对象编程--设计模式--桥接模式演示例子!\n"
);
    
//.NET平台下的Database Log

        var dblog = DatabaseLog();
        dblog.set(DotNetPlatfrom ());
        dblog.write(
"今天完成了XXX任务\n"
);    

        
//Java平台下的Text File Log

        var txtlog = TextFileLog();
        txtlog.set(JavaPlatfrom());
        txtlog.write(
"今天学会用Java了\n"
);

}


例子4: 数组操作

function _Main()
{
    
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()
{
    
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"
);
}




例子5 lambda for sort

function sort(arr,len,cmpFun)
{
    
var tmp = 0
;
    
var
 i ,j;
    
for(i = 0; i < len; ++
i)
    
{
        
for(j = 0;j < len-i-1;++
j)
        
{
            
if(cmpFun(arr[j],arr[j+1
]))
            
{
                tmp 
=
 arr[j];
                arr[j] 
= arr[j+1
];
                arr[j
+1=
 tmp;
            }

        }

    }

}


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

    
for(var k = 0; k < len; ++
k)
    
{
        write_console(datas[k] 
+ " "
);
    }

    write_console(
"\n");
}


例子6 函数式

function outerFunction()
{
    
var outVar=0
;
    
return function
()
    
{
            outVar
++
;
             write_console(outVar
+"\n"
);
    }

}

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

    
var instance2=
outerFunction();
    instance2();

    instance();

    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 阅读(686) 评论(4)  编辑 收藏 引用 所属分类: Windows Programming

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理