- 浏览: 497778 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hypercube:
markin'
配置D语言编程环境 -
qiezi:
qiezi 写道yangyang_08 写道1 ...
我的编程语言学习经历 -
qiezi:
yangyang_08 写道1、现在如果做并发服务器,楼主选用 ...
我的编程语言学习经历 -
yangyang_08:
1、现在如果做并发服务器,楼主选用什么样的语言架构?2、lua ...
我的编程语言学习经历 -
dearplain:
我也是语言爱好者,不过我一直坚持使用c。
我的编程语言学习经历
借助D语言新的mixin表达式,可以完成一些代码生成功能,比如:
下面的大段代码演示了另一个功能,编译期字符串解析:
只需要编译它,就可以在编译期把字符串"a bc /a\\\\34/ \"bbc\" s 32 33 abv"解析为标记。
上面的代码全部使用模板来完成,实现极其复杂,而且无法在动态代码中重用,所以D 1.006加入了编译期执行方法,让这类代码可以在编译期和执行期都可以使用,不过目前为止,仅有小部分代码可以这样,但这会是它的大方向。
结合编译期生成和编译期执行这2项技术,可以完成一些复杂的编译器功能,一个理想的工作方式如下:
大概是这样的工作方式,在编译期就可以检查出SQL和IDL字符串的语法。
template attr_accessor(T, char[] name){ mixin(" private T _" ~ name ~ "; public " ~ name ~ "(){ return _" ~ name ~ "; } public " ~ name ~ "(T v){ _" ~ name " = v; } "); } class Foo{ mixin attr_accessor!(int, "bar"); } void main(){ auto foo = new Foo; foo.bar = 3; writefln(foo.bar); }
下面的大段代码演示了另一个功能,编译期字符串解析:
import std.metastrings; template drop_white(char[] s){ static if (s.length && (s[0] == ' ' || s[0] == '\t' || s[0] == '\r' || s[0] == '\n')) const char[] drop_white = s[1..$]; else const char[] drop_white = s; } template drop_comment(char[] s){ static if (s.length >= 2 && (s[0] == '/' && s[1] == '*')) const char[] drop_comment = scan_comment_end!(s[2..$]); else const char[] drop_comment = s; } template scan_comment_end(char[] s){ static if (s.length >= 2){ static if (s[0] == '*' && s[1] == '/') const char[] scan_comment_end = s[2..$]; else const char[] scan_comment_end = scan_comment_end!(s[2..$]); }else{ pragma(msg, "Failed to scan comment end"); static assert(false); } } template Token(char[] t, char[] v, char[] r){ const char[] type = t; const char[] value = v; const char[] remain = r; static if (t != "eof") alias next_token!(r) next; } template is_digit(char c){ const bool is_digit = c >= '0' && c <= '9'; } template is_letter(char c){ const bool is_letter = c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'; } template get_token(char[] s){ static if (s.length == 0 || s[0] == '\0'){ const char[] type = "eof"; const char[] value = ""; const char[] remain = ""; }else static if (s[0] == '_' || is_letter!(s[0])){ alias parse_id!(s) token; const char[] type = "id"; const char[] value = token.first; const char[] remain = token.second; }else static if (s[0] == '"'){ alias parse_string!(s) token; const char[] type = "string"; const char[] value = token.first; const char[] remain = token.second; }else static if (is_digit!(s[0])){ alias parse_number!(s) token; const char[] type = "number"; const char[] value = token.first; const char[] remain = token.second; }else static if (s[0] == '/'){ alias parse_regexp!(s) token; const char[] type = "regexp"; const char[] value = token.first; const char[] remain = token.second; }else{ pragma(msg, "Can't parse token from: " ~ s); static assert(false); } debug pragma(msg, "Get token: " ~ value); } template parse_id(char[] s){ static if (s.length && (s[0] == '_' || is_letter!(s[0]) || is_digit!(s[0]))){ alias parse_id!(s[1..$]) id; const first = s[0..1] ~ id.first; alias id.second second; }else{ const char[] first = ""; alias s second; } } template parse_string(char[] s){ static if (s[0] == '"') alias scan_string_end!(s[1..$]) parse_string; else{ pragma(msg, "Failed to parse string"); static assert(false); } } template parse_number(char[] s){ static if (s.length && is_digit!(s[0])){ alias parse_number!(s[1..$]) number; const char[] first = s[0..1] ~ number.first; const char[] second = number.second; }else{ const char[] first = ""; const char[] second = s; } } template parse_regexp(char[] s){ static if (s.length && s[0] == '/') alias scan_regexp_end!(s[1..$]) parse_regexp; else{ pragma(msg, "Failed to parse regexp"); static assert(false); } } template scan_regexp_end(char[] s){ static if (s.length){ static if (s[0] == '/'){ alias pair!("", s[1..$]) scan_regexp_end; }else static if (s.length >= 2 && s[0] == '\\'){ alias scan_regexp_end!(s[2..$]) r; const char[] first = escape!(s[1]) ~ r.first; const char[] second = r.second; }else{ alias scan_regexp_end!(s[1..$]) r; const char[] first = s[0..1] ~ r.first; const char[] second = r.second; } }else{ pragma(msg, "Failed to parse regexp: " ~ s); static assert(false); } } template scan_string_end(char[] s){ static if (s.length){ static if (s[0] == '"') alias pair!("", s[1..$]) scan_string_end; else static if (s.length >= 2 && s[0] == '\\'){ alias scan_string_end!(s[2..$]) s; alias pair!(escape!(s[1]) ~ r.first, r.second) scan_string_end; }else{ alias scan_string_end!(s[1..$]) string; const char[] first = s[0..1] ~ string.first; const char[] second = string.second; } }else{ pragma(msg, "Failed to parse string"); static assert(false); } } template escape(char c){ static if (c == 'n') const char[] escape = "\n"; else static if (c == 't') const char[] escape = "\t"; else static if (c == 'r') const char[] escape = "\r"; else static if (c == '\\') const char[] escape = "\\"; else{ pragma(msg, "Failed to escape char '" ~ std.metastrings.ToString!(c) ~ "'"); static assert(false); } } template next_token(char[] s){ static if (s.length == 0){ const char[] type = "eof"; const char[] value = ""; const char[] remain = ""; }else{ const char[] comment_and_white_dropped = drop_comment!(drop_white!(s)); static if (s.length != comment_and_white_dropped.length){ alias next_token!(comment_and_white_dropped) t; }else{ alias get_token!(s) t; } alias t.type type; const char[] value = t.value; const char[] remain = t.remain; } static if (type != "eof") alias next_token!(remain) next; } template pair(char[] F, char[] S){ alias F first; alias S second; } import std.stdio; template output_token(alias T){ static if (T.type != "eof"){ pragma(msg, T.type ~ ": " ~ T.value); alias output_token!(T.next) output_token; } } template output(char[] token_parser, char[] source){ mixin("alias " ~ token_parser ~ "!(source) parser;"); alias output_token!(parser) output; } mixin output!("next_token", "a bc /a\\\\34/ \"bbc\" s 32 33 abv");
只需要编译它,就可以在编译期把字符串"a bc /a\\\\34/ \"bbc\" s 32 33 abv"解析为标记。
上面的代码全部使用模板来完成,实现极其复杂,而且无法在动态代码中重用,所以D 1.006加入了编译期执行方法,让这类代码可以在编译期和执行期都可以使用,不过目前为止,仅有小部分代码可以这样,但这会是它的大方向。
结合编译期生成和编译期执行这2项技术,可以完成一些复杂的编译器功能,一个理想的工作方式如下:
alias BNF!(import("ebnf.bnf")) EBNF; alias EBNF!(import("sql92.ebnf")) SQL; // 插入更多生成代码,或者是利用mixin生成。 User[] users = SQL!("select * from users where status = ?", 1); alias EBNF!(import("idl.ebnf")) IDL; mixin IDL!("interface X{} interface Y: X{}");
大概是这样的工作方式,在编译期就可以检查出SQL和IDL字符串的语法。
评论
3 楼
qiezi
2007-02-27
混淆倒是不容易。
你后面说的这个“Walter 应该把可以解释执行的代码范围放宽”,目前看来他应该正在做这件事。1.007比1.006多出来的功能里面主要就是这部分。
你后面说的这个“Walter 应该把可以解释执行的代码范围放宽”,目前看来他应该正在做这件事。1.007比1.006多出来的功能里面主要就是这部分。
2 楼
oldrev
2007-02-26
编译期执行是好东西,不过我觉得应该添加一个关键字:eval,让它表示在编译器执行代码求值,避免编译器混淆出错,如:
其次 Walter 应该把可以解释执行的代码范围放宽,我个人认为只要编译器看得到所需源代码就应该允许编译期执行。
int sqr(x) { return x*x; } const int foo = eval(sqr()); //编译时执行 const int bar = sqr();
其次 Walter 应该把可以解释执行的代码范围放宽,我个人认为只要编译器看得到所需源代码就应该允许编译期执行。
1 楼
ideage
2007-02-25
真是个 理想工作方式.
更理想的是动态语言嵌入了.
更理想的是动态语言嵌入了.
发表评论
-
D语言模板和编译期执行
2012-07-29 00:15 0D语言模板继承了C++模板的基本用法,在其上做了相当多扩充,近 ... -
Generator
2008-04-09 13:46 2009几种并发编程模型开销(从大到小): Process > ... -
lambda之路...
2007-11-09 22:57 2867DMD最近的版本号加入了闭包,感觉非常有用,虽然有些背后动作, ... -
像Erlang一样写D程序
2007-09-15 10:23 6732琢磨了好久,一直没时间来做它。在讨论这个问题的时候就已经有这想 ... -
[D语言] qsort的尴尬
2007-05-06 21:31 5080phobos里面在stc.c.stdlib里提供了qsort, ... -
强类型数值计算
2007-04-10 21:45 4722以前曾经讨论过使用typedef来完成强类型的数值计算,最终遇 ... -
简单的单元测试框架
2007-04-10 21:20 3147做了个简单的单元测试框架,只算个毛坯,遇到一些问题。 1、由 ... -
仿STL的vector,写了一组array操作方法。
2007-04-05 23:55 12031文档从MSDN抄过来的,稍稍改了一下。 module ar ... -
编译期执行的效率
2007-03-15 15:58 4223写了一个编译期执行的fibonacci模板: templ ... -
如何获得一个方法的名字?
2007-01-15 19:24 3491在D语言中,一个方法你可以得到它的指针(函数指针或委托),但不 ... -
D语言的函数编程
2007-01-07 11:17 3858前阵子论坛上有人问我D语言做函数编程怎样,老实说我没怎么想过这 ... -
D语言和python的差异
2007-01-07 10:12 6554这2个语言的比较怪怪的,我最近转换了一些twisted的源文件 ... -
从简单测试看D数组内存分配策略
2007-01-07 09:43 3228D语言动态数组可以在运行期改变大小,这和C++的vector相 ... -
DMD 0.178发布
2006-12-24 15:32 4602What's New for D 0.178 ... -
GDC 0.20发布
2006-12-17 14:35 2798引用 * Updated to DMD 0.177 * Fix ... -
DMD 0.177发布
2006-12-09 18:47 2275没什么亮点,BUG修复得也不多,BUG数量始终保持在250-2 ... -
DMD 0.176发布
2006-12-03 14:22 3072引用 What's New for D 0.176 Dec ... -
D语言的成员函数模板
2006-12-02 20:29 3075DMD 0.166 特性列表中有一条: * ncorp ... -
D语言 在栈上分配对象 以及 无需GC拖管对象
2006-11-28 13:18 2811一、栈上分配对象 C++可以轻易实现在栈上和堆上分配对象,例 ... -
打算把twisted移植到D语言上
2006-11-26 20:14 4210twisted是一个优秀的python网络开发库,以前用它做过 ...
相关推荐
由于可以直接生成机器码,D语言的程序执行速度快,而且它的模板元编程和内联函数等功能,允许在编译期进行计算,进一步提高了代码的运行效率。 此外,D语言还有强大的标准库,涵盖了字符串处理、网络编程、并发处理...
D语言在Win32平台上的应用主要涉及调用约定、可执行文件格式等方面。其中,调用约定(Calling Conventions)是指函数参数传递的方式,D语言支持多种调用约定,如`cdecl`、`pascal`、`stdcall`、`fastcall`等,以适应...
2. **编译的必要性**:用高级语言编写的源程序必须先通过编译,生成机器语言或汇编语言的目标代码,然后才能在计算机上执行。因此,上述说法是正确的。 3. **目标程序性质**:编译程序生成的目标程序并不总是机器...
3. Constant Folding:该技术可以将常量表达式计算结果缓存在编译期,以提高代码的执行速度。 4. Strength Reduction:该技术可以将复杂的运算简化为简单的运算,以提高代码的执行速度。 5. Register Allocation:...
- **模板元编程**:GCC支持C++模板元编程技术,这使得可以在编译期完成复杂的计算任务。 #### 七、Objective-C运行时特性 Objective-C是一种面向对象的编程语言,GCC-v4.3支持Objective-C的一些特殊特性,如: - **...
动态网页制作技术包括PHP、JSP和ASP.NET,它们允许服务器端处理数据并生成动态内容,而CSS(Cascading Style Sheets)是样式表语言,用于定义静态网页的外观,所以选项D不是动态网页技术,正确答案是B。 在域名...
《编译原理》期末试题包含了多个关于编译器设计的核心知识点,主要涉及正则表达式、LR(1)文法、LL(1)分析表、语法制导定义、中间代码生成、作用域与生存期、类型系统以及编译器移植等。 1. **正则表达式的DFA状态...
第10章 早期(编译期)优化 10.1 概述 10.2 Javac编译器 10.2.1 Javac的源码与调试 10.2.2 解析与填充符号表 10.2.3 注解处理器 10.2.4 语义分析与字节码生成 10.3 Java语法糖的味道 10.3.1 泛型与类型擦除...
2. **编译源代码**:使用GCC(GNU Compiler Collection)编译源代码,生成机器码。 3. **把目标代码链接起来**:将编译产生的多个目标文件链接成一个可执行文件。 4. **调试程序**:使用调试工具(如GDB)查找并修复...
- **编译时和运行时检查**:C++的模板元编程和运行时类型信息(RTTI)可以在编译期或运行期提供额外的安全检查。 4. **飞机大战游戏具体实现**: - **飞机模型**:每个飞机可以是一个类,包含位置、速度、生命值...
相比之下,VC++作为一款成熟的C/C++集成开发环境,其编译的程序运行效率高,可以生成独立于开发环境的可执行文件,适合大规模软件开发和部署。 #### COM技术的运用 为了融合两种语言的优点,文章提出了基于COM技术...
16. ASP.NET运行机制:ASP.NET中,`.aspx`页面首次执行时会编译生成对应的`.dll`文件,第二次执行时直接使用编译后的结果,故第一次执行通常比第二次执行慢。选项a)正确。 17. DWR框架:Direct Web Remoting (DWR)...
### 数据库系统原理知识点解析 #### 一、单项选择题解析 **1....- **选项分析**: - A.... - B.... - C. 编译系统:同样与数据管理...这些知识点涵盖了数据库系统的基本理论和技术,对于理解数据库系统的工作原理非常重要。
- MATLAB Compiler能够将MATLAB编写的代码编译成独立的可执行程序或DLL文件。 - 在本项目中,它被用来将MATLAB编写的分析代码转化为VC++可以调用的形式,从而实现数据处理和图形展示的功能。 #### 三、数据分析...
一个对象的生命期包括三个阶段:创建对象、对象的引用和释放对 象 。 1.8.3 创建对象 创建对象包括声明、实例化和初始化三方面的内容。通常的格式为 : 1. 声明对象 对象声明实际上是给对象命名,也称定义一个实例...
张晓冬 等编著 )和《16/32 位微机原理、汇编语言及接口技术》(作者: 钟晓捷 陈涛 ,机械工业出版社 出版)等,可以在较大型的科技书店里查找或者直接从网上订购。 6. 初学者到底是应该先学C还是汇编? ...
1. CPU 中,控制器负责保证指令的正确执行和处理异常事件。 2. 循环冗余校验码(CRC)是一种数据校验方法,使用生成多项式进行编码,数据位和校验位的格式为 k 个数据位之后跟 r 个校验位。 3. 存储器可以按寻址...