C++ C++;从文件运行实际代码而不编译它
我正在尝试制作一个程序,它可以从一个文件中读取代码(类似于一个文件,但不那么复杂),将其存储到一个线性列表中,然后在需要时执行它 这就是我想让这个“解释者”知道的: 因为我可以一个命令一个命令地执行它,所以我可以在执行特定数量的命令时停止/启动,这在尝试同时执行更多操作时非常有用(类似于),因此,我将该类命名为C++ C++;从文件运行实际代码而不编译它,c++,file,C++,File,我正在尝试制作一个程序,它可以从一个文件中读取代码(类似于一个文件,但不那么复杂),将其存储到一个线性列表中,然后在需要时执行它 这就是我想让这个“解释者”知道的: 因为我可以一个命令一个命令地执行它,所以我可以在执行特定数量的命令时停止/启动,这在尝试同时执行更多操作时非常有用(类似于),因此,我将该类命名为\u MINI\u THREAD。下面是struct命令和class\u MINI\u线程的声明: struct COMMAND { unsigned int ID; ch
\u MINI\u THREAD
。下面是struct命令
和class\u MINI\u线程
的声明:
struct COMMAND
{
unsigned int ID;
char command_text[151];
COMMAND* next;
COMMAND* prev;
};
class _MINI_THREAD
{
public:
void allocate_memory()
{
while (start_of_list == NULL)
start_of_list = new (std::nothrow) COMMAND;
while (end_of_list == NULL)
end_of_list = new (std::nothrow) COMMAND;
start_of_list -> prev = NULL;
start_of_list -> next = end_of_list;
end_of_list -> prev = start_of_list;
end_of_list -> next = NULL;
}
void free_memory()
{
for(COMMAND* i=start_of_list -> next;i!=end_of_list;i=i->next)
delete i -> prev;
delete end_of_list -> prev;
delete end_of_list;
}
bool execute_command(unsigned int number_of_commands)
{
for(unsigned int i=0;i<number_of_commands;i++)
{
/*match id of current command pointed by the cursor with a function from the map*/
if (cursor==end_of_list) return false;
else cursor=cursor->next;
}
return true;
}
bool if_finished()
{
if (cursor==end_of_list)return true;
else return false;
}
unsigned int get_ticks()
{
return ticks_per_loop;
}
void set_ticks(unsigned int ticks)
{
ticks_per_loop = ticks;
}
private:
unsigned int ticks_per_loop;
COMMAND* cursor=NULL;
COMMAND* start_of_list=NULL;
COMMAND* end_of_list=NULL;
};
在实际程序中,类\u MINI\u THREAD
的对象thread1
包含一个数字分配列表(为了便于理解,我将它显示为数组)
现在我的问题实际上是实现IF\u CONTROL\u结构。因为您可能需要键入if(a==b)
或if(foo())
等。。。我不知道如何测试这些东西
我设法使光标
相应地移动到任何结构(while
,do…while
,for
等),但我仍然无法检查每个结构的条件。你真的想写一些(可能使用一些)。阅读更多关于
写一个好的口译员不是一件小事。考虑使用一些现有的,例如,…并花一些时间研究他们的自由软件实现
否则,花几个月的时间阅读材料,尤其是:
- 绝对是必须阅读的(可免费下载)
- 关于
请注意,需要一整本书(至少)来解释解释器是如何工作的。另见相关会议
许多(多线程友好的)解释器都有一些。一个真正的多线程解释器(没有任何GIL)很难设计(它的具体功能是什么?),多线程垃圾收集器也很难实现和调试(考虑使用现有的解释器,也许是或)
因此,“你的简单工作”可能需要几年的全职工作(并可能让你获得博士学位)
更简单的方法
阅读并熟悉一些类似语言(可能有些,例如TURU)后,你可以决定一些更简单的方法(基本上是一个小的LISP解释器,你可以用几百行C++来编码,不像以前提到的成熟的解释程序那么严重)。
您首先需要在纸上(至少是英文)定义脚本语言的名称和名称。从Lisp及其应用程序中获得强大的灵感。您可能希望您的脚本语言是(所以您的脚本语言就是您语言的值),并且它(像Lisp)只有表达式(而没有语句)。所以条件是三元的,如C++ +<
您将把脚本语言表示为一些C++数据结构(可能是一些<代码>类< /代码>,使用一些虚拟方法)。将一些脚本文件放入AST(或AST序列,可能会馈送到某个REPL)是非常经典的,我甚至不会解释;您可能会使用一些语法分析器生成器-调用不当(如或)
然后,您将至少实现一些功能。它有两个参数Exp和Env:第一个参数Exp是要计算的表达式的AST,第二个参数Env是某种绑定环境(定义脚本语言的局部变量绑定,它可以像从变量到值的映射堆栈一样简单)。而eval
函数返回一些值。它可能是AST类的成员函数(Exp是this
,receiver…)。当然,您的脚本语言的AST和值是一些(如果愿意,您可以将其表示为类层次结构)
递归地实现这样的<代码> EVA/COD>在C++中是相当简单的。下面是一些伪代码:
eval Exp Env :
if (Exp is some constant) {
return that constant }
if (Exp is a variable Var) {
return the bounded value of that Var in Env }
if (Exp is some primitive binary operator Op /* like + */
with operands Exp1 Exp2) {
compute V1 = eval Exp1 Env
and V2 = Exp2 Env
return the application of Op /* eg addition */ on V1 and V2
}
if (Exp is a conditional If Exp1 Exp2 Exp3) {
compute V1 = eval Exp1 Env
if (V1 is true) {
compute V2 = eval Exp2 Env
return V2
} else { /*V1 is false*/
compute V3 = eval Exp3 Env
return V3
}
}
.... etc....
有很多其他的情况要考虑(例如,一些<代码> ,有些<代码>让<代码> >或代码> LeReC< <代码>,这可能会增加<代码> Env,不同操作的原始操作,<代码>应用< /代码>任意的函数值,将其作为一个练习留给读者。当然,有些表达式在求值时会出现错误
SICP和Lisp在小片段中都很好地解释了这个想法。了解。没有读过SICP就不要编码 您问题中的代码块是一个设计错误(即使是MINI_线程
也是一个错误)。花几周时间阅读更多内容,将代码扔进垃圾桶,然后重新开始。一定要使用一些系统(我强烈推荐)
当然,您希望能够解释递归函数。没有比非递归的更难解释的了
另外,我对你的工作很感兴趣。请给我发一些电子邮件,和/或发布您的暂定源代码。您是否正在尝试编写口译员?为什么需要编写自己的口译员?C++与许多脚本语言有很好的互操作性,最显著的是代码“Loa< /Cord>”。这听起来像是“我在IF结构中使用的是AST结构而不是线性列表。据我所知,您正在询问一种发明语言的解释器,您被困在如何实现控制结构上。我感谢你提供的链接文档,尽管我只需要这个解释器来做简单的算法。这就是为什么我没有直接去寻找一个真正的解释器并开始构建自己的解释器。最简单的方法是嵌入一些现有的解释器。问:“它的REPL到底是什么?”为什么能够在新线程中运行代码与h不兼容
Source_file.txt
int a;
input_file fin ("numbers.in");
output_file fout ("numbers.out");
while loop_one ( fin.read(a,int,skipws) )
{
fout.print(a,int);
fout.print(32,char); /*prints a space after each number*/
}
close_input_file fin;
close_output_file fout;
/*This code is supposed to take all numbers from the input file and */
/* move them into the output file */
_MINI_THREAD thread1;
/*read from Source_file.txt each command into thread1 command array*/
thread1.commandarr={
define_integer("a"),
open_input_file("numbers.in",fin),
open_output_file("numbers.out",fout),
define_label_while("loop_one",fin.read()), /*if the condition is false the `cursor` will jump to labe_while_end*/
type_to_file(fout,a,int),
type_to_file(fout,32,char),
label_while_return("loop_one"), /*returns the cursor to the first line after the while declaration*/
label_while_end("loop_one"), /*marks the line after the while return point*/
close_input_file("numbers.in",fin),
close_output_file("numbers.out",fout),
};
/*the cursor is already pointing at the first command (define_integer("a"))*/
/*this will execute commands until the cursor reaches the end_of_list*/
while(thread1.execute_commands(1))NULL;
thread1.free_memory();
eval Exp Env :
if (Exp is some constant) {
return that constant }
if (Exp is a variable Var) {
return the bounded value of that Var in Env }
if (Exp is some primitive binary operator Op /* like + */
with operands Exp1 Exp2) {
compute V1 = eval Exp1 Env
and V2 = Exp2 Env
return the application of Op /* eg addition */ on V1 and V2
}
if (Exp is a conditional If Exp1 Exp2 Exp3) {
compute V1 = eval Exp1 Env
if (V1 is true) {
compute V2 = eval Exp2 Env
return V2
} else { /*V1 is false*/
compute V3 = eval Exp3 Env
return V3
}
}
.... etc....