65.9K
CodeProject 正在变化。 阅读更多。
Home

C# for MS-DOS: 将表达式树编译为 16 位 MS-DOS 二进制文件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (14投票s)

2008 年 9 月 4 日

CPOL

2分钟阅读

viewsIcon

44263

downloadIcon

361

C# 算术表达式编译成 8086 机器码(是的,你可以在 Vista 上运行它 :-))

示例的作用

它将 C# lambda 表达式编译成 16 位可执行文件。

为什么有趣?

C# 表达式树允许你分析 C# 代码并以不同的方式重新解释它。例如,LINQ-to-SQL 接受用 C# 编写的表达式,并将其转换为 SQL 语句。

这个示例将(一小部分)C# 转换为 8086 机器码。

背景

我读过很多关于 LINQ 表达式树的博客,以及它们“多么酷”。然而,很少有文章解释表达式树的真正用途。这个示例演示了一种可能的用法。也许有一天,我会扩展这篇文章,进一步讨论表达式树在生活中的地位。

为什么选择 .Com 文件?

我选择.com 文件是因为它们是尽可能简单的可执行文件格式。只是一个 8086 机器码数组,没有任何头部或元数据。编译器编写者的天堂。而且它仍然可以在所有版本的 Windows 上执行。

注意:这里的“com”仅仅是一个文件扩展名,例如xy.com。它与在.com 文件出现 10 年后出现的组件对象模型无关。

编译表达式

表达式可以包含变量和三个算术运算:+、- 和 *。所有算术运算都在无符号 16 位整数中进行。

当生成的 COM 文件执行时,它会打印一个横幅,提示用户输入参数值(如果有),计算结果并显示它。COM 文件应在控制台窗口中执行,例如从cmd.exe

例如,表达式 (x,y) => 2*x + 3*y 在编译和执行后会产生以下输出(用户输入以粗体显示)

C# for MS-DOS, version 1.0
x? 10
y? 20
((2 * x) + (3 * y)) = 80

调用表达式编译器

该示例提供了类 ExpressionCompiler86,其中包含方法 Compile(Expression expr)。以下是主类 Program 编译三个表达式的方式

    // a little wrapper to makes things simpler
    static void Compile<T>(string file, Expression<T> expr)
    {
        using (ExpressionCompiler86 compiler = new ExpressionCompiler86(file))
        {
            compiler.Compile(expr);
        }
    }

    ...

    Compile<Func<int>>( "constant.com", () => 42);
    Compile<Func<int>>( "noparams.com&", () => 1+2+3*4);
    Compile<Func<int,int,int>>( "xy.com", (x,y) => 2*x + 3*y );

免责声明 

请对代码质量宽容一些。这不是生产代码。它只是一个示例,或者说,一个概念验证。它写于一天之内。它不包含任何自动化测试。绝对没有任何溢出检查或类似的东西。类名可能值得怀疑。很可能存在错误。 

尽情享用!

历史

  • 2008 年 9 月 4 日:初始发布
© . All rights reserved.