脚本语言:Xmas(三)
自从将Xmas的GC换成现在的非迁移式的全局收集器后,最近几个月一直耗在Xmas上面;最明显的改变就是:更彻底地支持了面向对象、更强大的编译器。
所以,本文就来说说,真正的Xmas。
一、目标
一门语言有什么目标吗?比如C#什么的;可惜的是我并不关心。作为一门脚本语言,其目的无非只有一个:简化编程。方式,也是直接明了:在更高的抽象上构建代码。那么什么是“更高的抽象”?个人认为,大抵是亮点:1、更方便的操作语义 2、更多的限制。
第一点,是指Xmas可以几乎毫无代价地大量使用宿主语言的现有代码;而且是以【语法】的方式。比如,Xmas要有正则表达式,可以有.....只需要使用XmasRef包装宿主语言中的现有Regex即可。事实上,Xmas所有的库函数,都只是C++中本人代码库中的对应物。——这正是脚本,所存在的意义(一旦开始自己构造自己,如C++等,便不再是脚本了)。
第二点,这其实是由第一点造成的。很多东西一旦固化到语言本身,便意味着“不可改变”(永远地)。抽象程度越高,意味着,离二进制越远,能控制的东西,更少。最大的限制就是:有了GC,内存是什么?可以吃的吗?在代码里,永远地消失了(意味着,你不再可以控制)。
最近,其实一直在思考一个不可能的话题:是否将静态类型加入到Xmas中? 之所以不可能,Xmas只是一门脚本语言。
所以,下面,我们就来聊聊“脚本”。
二、动态
一门合格的动态语言:其必须可以【本能】地识别“字符串”。或者说,所有的东西都可以通过“字符串”来构造(替代):
func = new Function("print");
val = ");
func(val);//打印一个整型12
通过字符串,我们构造了一个函数(库打印函数print)和一个数字12。当然,我们可以更彻底一点:
print = new Function("print");
intctr = new Function("Integer");
val = intctr(");
print(val);
是的,在Xmas中,几乎一切都是【函数】。而函数本身,只是由字符串构成的标识符而已;所以,我们可以推迟一切的操作,变成另一门真正的只有函数的语言:
function doSome(str1, str2, str3)
{
func1 = new Function(str1);
func2 = new Function(str2);
value = func2(str3);
func1(value);
}
这时,我们能够通过上面的代码,做任何能够想象的事情(只要有对应的函数,和对应的逻辑)。但是,这种“究极”的动态,有意义吗?没有。因为,上面的代码除了符合Xmas的语法外,并没有任何可识别的逻辑。
doSome(");
print();
上面两行代码,执行了相同的逻辑:打印数字12。
动态能力,是为了在必要的时候,绕过编译器的语法/语义检查,而通过“自定义”的方式,访问Xmas的运行时。这个能够在很多时候是有那么一些用处的:
function to_string(val)
{
){
return val.toString();
}
return new String(val);
}
这是早些时候,Xmas将一个对象转化为String的函数。在动态语言中,很多动态性是直接由【语法】本身直接提供的;这也正是“动态”之处。而其他类型的语言,想要达到相同的目的:1、通过反射(java/c#等)2、通过类型系统(C++的类型萃取,通过模板元编程)。
当然,这一切是有足够的代价的:更慢、更多的错误。
三、便捷
var1 = new Exp.Var(new var1);
var2 = new Exp.Var(new var2);
cond = new Exp.Less(var1, var2);
set1 = new Exp.Set(new var3, var1);
set2 = new Exp.Set(new var3, var2);
exp1 = new Exp.Select(cond, set1, set2);
exp2 = ));
exps = new Exp.Exps();
exps.addExp(exp1);
exps.addExp(exp2);
env = new Exp.Env();
env.addVar();
env.addVar();
exps.exec(env);
put(exps);
put(env);
上面的代码,是以面向对象的方式构建了一颗表达式树(可对应C#);其执行后的结果:
((var1 < var2) ? var3 = var1 : var3 = var2)
var4 = Integer:
//以上,对应了put(exps),打印表达式树本身
var3: var4: var1: var2:
//以上,是树执行后的结果
上面的代码只是干了两件事:1、获取var1与var2中的最小值,并将其赋给var3 2、将var4设置为数字12
这些代码本身没有任何惊奇的地方;甚至有些多余:
var1 = ;
var2 = ;
var3 = eval("function main(var1, var2){ if(var1 < var2) return var1; return var2;}", var1, var2);
var4 = ;
这四行代码干了同样的事情,以更清晰和动态的方式。所以,重要的并非这些代码,而是支撑这些代码的“代码”,居然出奇的少:只有97行。
class Exp{
class Env: Xmas{
function Env(){
this.vars = new Map();
}
function addVar(label, val){
this.vars[label] = val;
}
function setVar(label, val){
this.vars[label] = val;
}
function var(label){
return this.vars[label];
}
function toString(){
ret new String(this.vars);
}
}
class Val: Xmas{
function Val(val){
this.val = val;
}
function exec(){
return this.val;
}
function toString(){
return String.format("{}:{}", typeof(this.val), this.val);
}
}
class Var: Xmas{
function Var(label){
this.label = label;
}
function exec(env){
return env.var(this.label);
}
function toString(){
return new String(this.label);
}
}
class Set: Xmas{
function Set(label, val){
this.label = label;
this.val = val;
}
function exec(env){
env.setVar(this.label, this.val.exec(env));
}
function toString(){
ret String.format("{} = {}", this.label, this.val.toString());
}
}
class Less: Xmas{
function Less(a, b){
this.a = a;
this.b = b;
}
function exec(env){
return this.a.exec(env) < this.b.exec(env);
}
function toString(){
return String.format("({} < {})", this.a.toString(), this.b.toString());
}
}
class Select: Xmas{
function Select(condition, a, b){
this.condition = condition;
this.a = a;
this.b = b;
}
function exec(env){
if(this.condition.exec(env)){
return this.a.exec(env);
}
return this.b.exec(env);
}
function toString(){
return String.format("({} ? {} : {})", this.condition.toString(), this.a.toString(), this.b.toString());
}
}
class Exps: Xmas{
function Exps(){
this.exps = new Array();
}
function addExp(exp){
Array.push_back(this.exps, exp);
}
function exec(env){
foreach(this.exps, function(exp){ exp.exec(env);});
}
function toString(){
str = new Object{ str : ""};
foreach(this.exps, function(exp){ str.str += exp.toString() + String.line();});
ret str.str;
}
}
}//CLASS OF EXPRESSIONS
我并不知道C#中为了相同的目的,需要多少行代码的支持;但无疑,会高一个数量级。这正是脚本的力量,Xmas的力量——可以更快,更高效地构建我们想要的东西。
四、结语
我有在想过,是否要讲讲Xmas的编译器?词法分析、语法分析、代码生成.......
也有思考有没有必要说说Xmas的虚拟机?GC、运行时环境、字节码......
无疑,我都不想讲。毕竟那些都是那么低枯燥而乏味。
Xmas本身肯定不止前面所讲的这些;但,又如何?其不过是本人库中的一个较大的子模块,而已。所以,本系列,完。
PS:另外的两个系列,多半是要“太监”。
脚本语言:Xmas(三)的更多相关文章
- C#调用脚本语言(三)-- IronJS 与 IronLua 简单方法性能比较
1. 测试环境 1.1. 硬件环境 CPU:intel Core i7-740QM 内存:8GDDR3 Memory 1.2. 系统 系统:Windows 8 Enterprise 开发工具:Vs ...
- 脚本语言:Xmas(一)
很偶然的一个想法,在从北京回成都的高铁上:我想要一个计算器.于是在火车上花了十来个小时,完成了一个模型:能够处理+-*/的优先级,以及"()",比如:1+(3+2)*4.这已是一年 ...
- 脚本语言:Xmas(二)
本篇,来谈谈类型系统,以及部分与垃圾收集器相关的内容. 一.基本类型 Xmas的基本类型:Null.Boolean.Label.String.Ref.Function.Integer.Float.De ...
- Unity3d中如何混用三种脚本语言?
首先要明白,这三种说的混用是指文件级别的混用,就是说一个文件是由一种语言写的.而不是说你这一个文件可以混用这三种语言,注意这是不允许的. 第二要明白,在unity3d中为什么可以使用三种语言混合开发? ...
- (三)Lua脚本语言入门
又要找工作了,变的忧虑了,唯有学习才让内心变得踏实,今天玩了一下午的王者荣耀,正事都忘了...... 如果认为所谓的毅力是每分每秒的"艰苦忍耐"式的奋斗,那这是一种很不足的心理状态 ...
- (三)Lua脚本语言入门(数组)
又要找工作了,变的忧虑了,唯有学习才让内心变得踏实,今天玩了一下午的王者荣耀,正事都忘了...... 如果认为所谓的毅力是每分每秒的“艰苦忍耐”式的奋斗,那这是一种很不足的心理状态.毅力是一种习惯,毅 ...
- InstallShield 脚本语言学习笔记
InstallShield脚本语言是类似C语言,利用InstallShield的向导或模板都可以生成基本的脚本程序框架,可以在此基础上按自己的意愿进行修改和添加. 一.基本语法规则 ...
- JS脚本语言是什么意思?
javascript,Javascript是一种浏览器端的脚本语言,用来在网页客户端处理与用户的交互,以及实现页面特效.比如提交表单前先验证数据合法性,减少服务器错误和压力.根据客户操作,给出一些提升 ...
- 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
随机推荐
- Kali linux learning note
from:http://blog.sina.com.cn/s/blog_40983e5e0101dhz0.html 因为kali linux基于debian 7,当然要把这台Acer 4736 ...
- jeesite学习(一) common部分(1)
我们按照先细节后整体的方式来进行学习,即先了解各个包中包含的内容,再从整体上看各个包之间的关系. 0 common中的包 先看jeesite的common组件,common中共包含14个包(如下图), ...
- python+request接口自动化框架
python+request接口自动化框架搭建 1.数据准备2.用python获取Excel文件中测试用例数据3.通过requests测试接口4.根据接口返回的code值和Excel对比 但本章只讲整 ...
- JavaWeb之Listener监听器
监听在Java体系中运用的很广泛,在安卓开发.JavaWeb开发中到处存在,在其他语言也有类似的,如果有了解过设计模式那很容易理解实现的原理.不过对于开发者来说,使用观察者模式只需实现相应的接口就好, ...
- IPhone 、Webkit手机浏览器Div滚动、滑动卡,遮罩层被穿透的解决办法
在滚动条的层上面加上-webkit-overflow-scrolling:touch;样式即可解决!
- javascript 将数字(金额)转成大写
将计算好的金额转换成大写,这些功能非常多,下面我改进了一下代码(原文在这里:http://www.cnblogs.com/zsanhong/p/3509464.html). /** * _SetNum ...
- iphone与安卓的兼容性问题汇总
1.日期问题 当使用yyyy-mm-dd格式时,iphone不认,安卓没问题 解决办法:new Date(res.data[i].inventoryDate.replace(/-/g, "/ ...
- jQuery控制input不可编辑
1.开启disabled,是input不可以编辑 $("#id").attr("disabled","disabled"); 2.关闭dis ...
- Android线程池使用终结版
有一段时间没写博文了,今天抽空总结一下,也希望能通过自己写的这些文章,加深理解的同时能帮 助在技术方面有疑点的朋友搞清楚个所以然来,由于经常会在网上或群里看到有朋友会问线程方面的 东西,就像我一个朋友 ...
- JavaScript设计模式读书笔记之一:接口
接口 在JavaScrip中模仿接口 用注释描述接口 用属性检查模仿接口 用鸭式辨型模仿接口 依赖于接口的设计模式 工厂模式 组合模式 装饰者模式 命令模式 接口 在JavaScrip中模仿接口 用注 ...