【问题标题】:Managing libraries and imports in a programming language用编程语言管理库和导入
【发布时间】:2010-04-03 12:21:17
【问题描述】:

我用 C++ 为一门愚蠢的编程语言创建了一个解释器,整个核心结构都完成了(标记器、解析器、解释器,包括符号表、核心函数等)。

现在我在为这个解释器创建和管理函数库时遇到了问题(我稍后会解释我的意思)

所以目前我的核心函数处理程序是可怕的

// Simplified version
myLangResult SystemFunction( name, argc, argv )
{
      if ( name == "print" )
      {
         if( argc < 1 )
         {
           Error('blah');
         }
         cout << argv[ 0 ];
       } else if ( name == "input" ) {
         if( argc < 1 )
         {
           Error('blah');
         }
         string res;
         getline( cin, res );
         SetVariable( argv[ 0 ], res );
       } else if ( name == "exit ) {
         exit( 0 ); 
}

现在想想如果要复杂 10 倍并且系统功能多了 25 个,那么每个其他的。无法维护,感觉很糟糕,很可怕。

所以我想:如何创建某种包含所有函数的库,如果它们被导入,则初始化它们自己并将它们的函数添加到正在运行的解释器的符号表中。

但是,这就是我真的不知道该怎么做的地方。

我想要实现的是,例如:我的语言的(外部?)字符串库,例如:字符串,并且它是从该语言的程序中导入的,例如:

import string
myString = "abcde"
print string.at( myString, 2 ) # output: c

我的问题:

  • 如何将函数库与核心解释器分离并加载?
  • 如何将它们的所有函数放入一个列表中,并在需要时将其添加到符号表中?

我想做什么:

在解释器启动时,所有库都用它编译,每个函数都会调用类似RegisterFunction( string namespace, myLangResult (*functionPtr) ); 的东西,它将自己添加到列表中。当从语言中调用import X 时,使用RegisterFunction 构建的列表随后被添加到符号表中。

想到的缺点:

所有库都直接在解释器核心中,大小会增长,它肯定会减慢速度。

【问题讨论】:

    标签: c++ design-patterns interpreter


    【解决方案1】:

    如果您的解释器是作为库实现的,它将被其他人的 C++ 代码调用。他们不得不从他们自己的代码中调用你的库中的函数来向解释器添加函数,这并不是不合理的。这就是我自己的表达式评估器所做的。用户代码中的类似内容:

    Interpreter in;    // an instance of the interpreter
    in.AddFunc( lenfun, "length", 1 );
    in.AddFunc( catfun, "concat", 2 );
    

    调用者必须提供一个指向实现函数的指针,以及函数的名称和参数数量。这适用于无类型设置 - 如果您执行严格的类型,当然还有很多工作要做。

    【讨论】:

      【解决方案2】:

      我认为您应该研究Command 模式。然后,您可以将每个函数实现为 Command,并拥有一个将函数名称映射到 Command 对象的映射。

      这还可以让您从外部库加载其他函数,方法是让每个库都有一个初始化函数,将其函数添加到映射中。

      【讨论】:

        【解决方案3】:

        目前尚不清楚您的目标是功能齐全的编程语言,还是这是一个玩具,所以我不知道您要投入多少时间。我怀疑动态库加载会比你需要的复杂得多。您可能需要一个库位置的 PATH 列表,或者您需要注册命名空间 - 这会让您回到现在所在的位置。

        一种更简单的方法是保留一个全局符号表,以及相关的处理程序。

        使用 std::map(或 hash_map)比 if/else 构造更快的函数查找。让所有函数在符号表中注册自己。

        存储在符号表中的“处理程序”可以是简单的对象(或函数指针),并且可以进行自己的参数检查。

        class FuncHandler {
          virtual MyLangResult Run(argv, argc) = 0;
        }
        
        typedef std::map<string, FuncHandler*> FuncTableType;
        
        // Simplified version
        myLangResult SystemFunction(name, argc, argv )
        {
          FuncTableType::const_iterator it = function_table_.find(name);
          if (it == function_table_.end()) return Error("Unknown function: " + name);
          return it->second(argc, argv);
        }
        

        我写了一些代码来为这个问题中的类执行自我注册,但这里不一定需要它: Accessing C++ Functions From Text storage

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多