众所周知,Roslyn project已经开源一年多了。简单的说,Roslyn是:1)用C#/VB写的C#/VB的编译器,以及与IDE集成;2)编译器的功能以API的方式暴露出来(即一组DLL)。

Roslyn对大多数开发者来说没啥用处,你关心的是你的应用程序的逻辑与构建而不需要关心编译器是怎么运行的。有时你觉得C#/VB有需要增强的地方,于是你兴致勃勃的跑到Roslyn论坛去发表一个proposal,MS的guy会给你的issue打上Area-Language Design的标签,网友们也许会来讨论一下,然后呢?就没有然后了,这有点像在求雨,下不下、什么时候下、下多大全凭神仙们(MS guys)的“心情”。

求人不如求己,既然Roslyn已经以MIT方式开源,咱们就站在巨人的肩膀上自己动手丰衣足食吧,也就是,扩展C#,做(屌丝级的)complier guy!

众所周知,C#是门general-purpose的编程语言,你想添加的feature既可以是general的,也可以是specific的。比如,XML literal是个general的C# feature,下两图展示了一个specific的feature,让C#支持Windows Workflow Foundation(WF)的activity:





其实,这不该叫“扩展C#”,而该叫做“创建一门衍生自C#的DSL”,如果你对WF感兴趣,请访问Metah.W: A Workflow Metaprogramming Language

姑且就用“扩展C#”这个叫法。如上两图所示,Metah.W(MW)在C#中加入了activity的构造,在概念上,activity是C# class和function的合体,在图一中,public sealed class摇身一变成为public sealed activity,接着宣告activity的名字,小括号中宣告parameters,如string BookmarkName, string Text,接着宣告可选的return type,如activity Promptas int宣告返回类型是int,若无as XXX宣告则返回void。Activity的body中是变量的宣告和statement的使用,statement可以是:1)C# expression statement,如图一中的target = new Random().Next(1, MaxNumber) + 1;;2)well-known statement,如if-else, while, do-while, foreach, try-catch-finally等;3)special statement,如图二中的statemachine, delay。因为activity是class和function的合体,可以调用它并将返回值赋给变量/参数,如guess = new Prompt().Invoke(...)

将FirstLook.mw送进MW编译器,将产生下面的C#代码:

//FirstLook.mw.cs, generated by the MW compiler
namespace HelloMW.FirstLook
{
public sealed class SequentialNumberGuess : global::System.Activities.Activity
{
public global::System.Activities.InArgument<int> MaxNumber { get; set; }
public global::System.Activities.OutArgument<int> Turns { get; set; } private global::System.Activities.Activity __GetImplementation__()
{
global::System.Activities.Activity __vroot__;
{
var __v__0 = new global::System.Activities.Statements.Sequence();
var target = new global::System.Activities.Variable<int>();
__v__0.Variables.Add(target);
var guess = new global::System.Activities.Variable<int>();
__v__0.Variables.Add(guess);
__v__0.Activities.Add(new global::MetahWActionActivity(__ctx__ =>
{
target.SetEx(__ctx__, new Random().Next(1, MaxNumber.Get(__ctx__)) + 1);
}
));
var __v__1 = new global::System.Activities.Statements.DoWhile();
__v__1.Condition = new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) != target.Get(__ctx__));
{
var __v__2 = new global::System.Activities.Statements.Sequence();
__v__2.Activities.Add(new Prompt().Initialize(__activity2__ =>
{
__activity2__.BookmarkName = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => "EnterGuess"));
__activity2__.Text = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => "Please enter a number between 1 and " + MaxNumber.Get(__ctx__)));
__activity2__.Result = new global::System.Activities.OutArgument<int>(new global::MetahWLocationActivity<int>(guess));
}
));
__v__2.Activities.Add(new global::MetahWActionActivity(__ctx__ =>
{
Turns.SetEx(__ctx__, __val__ => ++__val__, true);
}
));
var __v__3 = new global::System.Activities.Statements.If();
__v__3.Condition = new global::System.Activities.InArgument<bool>(new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) != target.Get(__ctx__)));
var __v__4 = new global::System.Activities.Statements.If();
__v__4.Condition = new global::System.Activities.InArgument<bool>(new global::MetahWFuncActivity<bool>(__ctx__ => guess.Get(__ctx__) < target.Get(__ctx__)));
__v__4.Then = new global::MetahWActionActivity(__ctx__ =>
{
Console.WriteLine("Your guess is too low.");
}
);
__v__4.Else = new global::MetahWActionActivity(__ctx__ =>
{
Console.WriteLine("Your guess is too high.");
}
);
__v__3.Then = __v__4;
__v__2.Activities.Add(__v__3);
__v__1.Body = __v__2;
}
__v__0.Activities.Add(__v__1);
__vroot__ = __v__0;
}
return __vroot__;
} private global::System.Func<global::System.Activities.Activity> __implementation__;
protected override global::System.Func<global::System.Activities.Activity> Implementation
{
get
{
return __implementation__ ?? (__implementation__ = __GetImplementation__);
}
set
{
throw new global::System.NotSupportedException();
}
}
} public sealed class Prompt : global::System.Activities.Activity<int>
{
public global::System.Activities.InArgument<string> BookmarkName { get; set; }
public global::System.Activities.InArgument<string> Text { get; set; } private global::System.Activities.Activity __GetImplementation__()
{
global::System.Activities.Activity __vroot__;
var __v__0 = new global::System.Activities.Statements.Sequence();
__v__0.Activities.Add(new global::MetahWActionActivity(__ctx__ =>
{
Console.WriteLine(Text.Get(__ctx__));
}
));
__v__0.Activities.Add(new ReadInt().Initialize(__activity2__ =>
{
__activity2__.BookmarkName = new global::System.Activities.InArgument<string>(new global::MetahWFuncActivity<string>(__ctx__ => BookmarkName.Get(__ctx__)));
__activity2__.Result = new global::System.Activities.OutArgument<int>(new global::MetahWLocationActivity<int>(Result));
}
));
__vroot__ = __v__0;
return __vroot__;
} private global::System.Func<global::System.Activities.Activity> __implementation__;
protected override global::System.Func<global::System.Activities.Activity> Implementation
{
get
{
return __implementation__ ?? (__implementation__ = __GetImplementation__);
}
set
{
throw new global::System.NotSupportedException();
}
}
}
}

这就是元编程,把语法糖解糖的过程,即把高级抽象的描述翻译成低级具体的实现。我觉得,“语法糖”是个肤浅的认识,实际上,多数的“语法糖”都涉及到语义,不仅仅是简单的语法转换。元编程的另一个例子,早期某些C++编译器能将C++代码翻译成等价的C代码,即C++是门元编程语言,它是C的“语法糖”。

日光之下,并无新事。元编程是个非常“古老”的概念,但在每个“时代”它都能玩出耳目一新的花样。

欲知后事如何,请听下回分解。

最新文章

  1. 基于EasyUI Treegrid的权限管理资源列表
  2. js-JavaScript高级程序设计学习笔记20
  3. [转]asp.net webform 与mvc 共享session
  4. Capistrano SSH::AuthenticationFailed, not prompting for password
  5. maven 常用5个命令
  6. Jordan Lecture Note-2: Maximal Margin Classifier
  7. 清除NT Kernel &amp; System占用80端口
  8. CSS自学笔记(4):CSS样式表的使用
  9. Linux内核源代码解析之——sock&#39;s buffer参数
  10. linux_之sed用法
  11. 全文检索工具推荐FileLocator
  12. qt编译的基于xlib cairo的桌面程序
  13. poj 3321Apple Tree
  14. Linux之软链接与硬链接
  15. Rabbit MQ 延迟插件rabbitmq_delayed_message_exchange的使用
  16. shell 通过EOF在脚本中输入需要的用户名或密码
  17. HCNA-链路聚合(手工模式)
  18. 静态链接库与动态链接库----C/C++
  19. CentOS 6.9搭建CDH 5.12.0集成环境
  20. 图像处理项目——生成csv文件提高读取效率

热门文章

  1. yield对性能提升的一次小小测试
  2. ASP.NET Web API 全局权限和异常处理
  3. SpringCloud统一配置之使用配置
  4. 【Spring学习笔记-MVC-17】Spring MVC之拦截器
  5. [转]LAMP(Linux-Apache-MySQL-PHP)网站架构
  6. JVM的DirectMemory设置
  7. Linux 期中架构 SSH
  8. apache 服务器在ubuntu上图片无法显示解决
  9. Log4j发送邮件
  10. hibernate vs ibatis