如何为需要任意数量参数的函数生成C#IL代码? [英] How do I generate C# IL code for a function which takes an arbitrary amount of parameters?

查看:68
本文介绍了如何为需要任意数量参数的函数生成C#IL代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

那里。我目前正在使用C#和通用中间语言(CIL)创建一个基本的编译器来创建一个基本的编程语言(只是为了我业余时间的乐趣)。我从GitHub分叉了原始项目并开始添加它。原始项目允许基本的控制台输出,允许用户打印字符串文字,整数或传入变量(其类型为字符串或int)。像这样:

Hi, there. I'm currently working on a basic compiler using C# and the Common Intermediate Language (CIL) to create a basic programming language (just for fun in my spare time). I forked the original project from GitHub and began adding to it. The original project allowed for basic console output, which allowed users to print either string literals, integers, or pass in variables (whose type would be string or int). Like this:

print "some line of text.";
print 50;
var x = 150;
print x; // prints 150, of course.



我现在正处于我想让用户直接将变量注入字符串,解析字符串,然后变量被替换为它们的值。我想我可能没有解释得那么好,所以这里是我正在尝试做的一个例子(注意,我对语言做的一个改变是语法):


I'm now at a point where I want to allow users to inject variables into a string directly, have the string parsed, then the variables get replaced with their values. I think I may not have explained that well, so here's an example of what I'm trying to do (note, one change I made to the language was the syntax):

String player_name = "Ra";
Integer player_health = 2000;

// This ideally would print "Hello, Ra! You have 2000 health."
@IO:Print("Hello, {$player_name}! You have {$player_health} health.");



目前,我只能输出我想要的文字:


At the moment, I can only output my intended Text by doing:

@IO:Print("Hello, ");
@IO:Print(player_name);
@IO:Print("! You have ");
@IO:Print(player_health);
@IO:Print(" health.");



尽管这样做有用,看起来很可怕,需要多个函数调用等等代码行。因此,为什么我要将变量直接注入字符串。



就像参考这里是我分叉的原始项目的链接,此处 是我的分叉版本的链接。哦,如果你点击我的存储库的链接,请注意我还没有完全评论。 :(



很可能有一些我没有完全解释的东西。请随意让我详细说明。



- MaidenKeebs



我尝试过:



当我说my_string时,我只是指这个字符串:


Despite the fact that this works, it's horrible to look at, requires multiple function calls, and more lines of code. Hence why I want to 'inject' variables directly into strings.

Just as reference here is a link to the original project that I forked, and here
is a link to my forked version. Oh, and if you click the link to my repository, note I haven't exactly commented things yet. :(

Chances are there's something I haven't quite explained properly. Feel free to ask me to elaborate.

- MaidenKeebs

What I have tried:

When I say "my_string", I'm just referring to this string:

"Hello, {$player_name}! You have {$player_health} health!"



是的,我把my_string分成了段到一个List< string>这给了我这个:


Right, I split my_string up into segments to a List<string> which gave me this:

s[0] = "Hello, ";
s[1] = "$player_name";
s[2] = "! You have ";
s[3] = "$player_health";
s[4] = " health.";



然后我为上面列表中的每个字符串生成IL。我在这里使用的规则是,如果字符串以$开头,生成IL代码将变量加载到堆栈(Ldloc)。否则只需加载字符串(Ldstr)。



之后,我生成IL代码来调用IO:打印功能。现在,因为IO:打印的文本会输出到屏幕包含字符串文字和变量(以及各自的变量),我将IO:打印功能定义为:


Then I generate IL for each string in the list above. The rules I use here is that if the string starts with "$", generate IL code to load the variable to the stack (Ldloc). Otherwise just load the string (Ldstr).

After that, I generate IL code to call the "IO:Print" function. Now, because the text that "IO:Print" would output to the screen contains string literals AND variables (and a varied number of each), I defined the "IO:Print" function as:

// Maybe something wrong with this?
public sealed class IO
{
    public static void Print(params[] string arguments)
    {
        // Probably wrong.
        Console.WriteLine(arguments.ToString());
    }
}



同样,我使用ILDasm来查看生成的IL,这就是它所显示的内容:


Just as a thing, I used ILDasm to look at the generated IL and this is what it shows:

ldstr   "Hello, "
ldloc.0                  // 0 points to 'player_name'.
ldstr   "! You have "
ldloc.1                  // 1 points to 'player_health
ldstr   " health."
call    void [gfn]GfnCompiler.GfnStdLib.IO::Print(params[] string)





对我来说, IL代码已正确生成,但该函数不使用预期的字符串/变量参数调用。

推荐答案

player_name}!你有{
player_name}! You have {


player_health}健康。);
player_health} health.");



目前,我只能输出我想要的文字:


At the moment, I can only output my intended Text by doing:

@IO:Print("Hello, ");
@IO:Print(player_name);
@IO:Print("! You have ");
@IO:Print(player_health);
@IO:Print(" health.");



尽管事实如此工作,看起来很可怕,需要多个函数调用,以及更多行代码。这就是为什么我要将变量直接注入字符串。



就像参考此处是我分叉的原始项目的链接,在哪里 是我的分叉版本的链接。哦,如果你点击我的链接知识库,请注意我还没有完全评论过。:(



有可能我还没有解释过的东西好的。请随意让我详细说明。



- MaidenKeebs



我有什么尝试过:



当我说my_string时,我只是指这个字符串:


Despite the fact that this works, it's horrible to look at, requires multiple function calls, and more lines of code. Hence why I want to 'inject' variables directly into strings.

Just as reference here is a link to the original project that I forked, and here
is a link to my forked version. Oh, and if you click the link to my repository, note I haven't exactly commented things yet. :(

Chances are there's something I haven't quite explained properly. Feel free to ask me to elaborate.

- MaidenKeebs

What I have tried:

When I say "my_string", I'm just referring to this string:

"Hello, {


player_name}!你有{
player_name}! You have {


这篇关于如何为需要任意数量参数的函数生成C#IL代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆