如何评估二元运算?

问题描述 投票:0回答:1

我编写自己的编译(或解释?)语言只是为了好玩,主要作为一个学习项目。我确信我还可以进行许多其他优化领域,但我当前遇到的问题是关于左侧和右侧的实际计算运算符(二元运算)。我必须假设我对此过度思考或过度设计。

下面是我遇到的问题的简单重现。我想避免的是对每种类型组合到处都硬编码

std::holds_alternative
std::get
。您可以对整数、浮点数、字符串、布尔值运行任何基本运算符(假设组合实际上有效),而无需手动写出每个组合。

#include <string>
#include <variant>
#include <vector>
#include <iostream>

using namespace std;

typedef variant<int, float> Variant; // Could have any number of basic types.. string, bool, etc.

Variant Execute(Variant* Left, Variant* Right)
{
    if (std::holds_alternative<float>(*Left) && std::holds_alternative<float>(*Right))
    {
        float L = std::get<float>(*Left);
        float R = std::get<float>(*Right);
        return L + R;
    }
    else if (std::holds_alternative<int>(*Left) && std::holds_alternative<int>(*Right))
    {
        int L = std::get<int>(*Left);
        int R = std::get<int>(*Right);
        return L + R;
    }
    else if (std::holds_alternative<float>(*Left) && std::holds_alternative<int>(*Right))
    {
        float L = std::get<float>(*Left);
        int   R = std::get<int>(*Right);
        return L + R;
    }
    else if (std::holds_alternative<int>(*Left) && std::holds_alternative<float>(*Right))
    {
        int   L = std::get<int>(*Left);
        float R = std::get<float>(*Right);
        return L + R;
    }
}

int main()
{
    // Evaluating 5 + 5.0 + 10 + 10.0
    auto A = new Variant(5);
    auto B = new Variant(5.0f);
    auto C = new Variant(10);
    auto D = new Variant(20.0f);

    std::vector<Variant*> Values;
    Values.push_back(A);
    Values.push_back(B);
    Values.push_back(C);
    Values.push_back(D);

    Variant* Result;
    int      Index = 0;
    for (auto V : Values)
    {
        // Equivalent of operator overloading?
        Result = &Execute(Result, V);
        Index++;
    }

    // Should come out as a float value 40.0f
    if (std::holds_alternative<int>(*Result))
    {
        std::cout << std::get<int>(*Result) << std::endl;
    }
    else
    {
        std::cout << std::get<float>(*Result) << std::endl;
    }

    return 0;
}

很高兴发布更多上下文代码!感谢您的帮助!

c++ compiler-construction operators evaluation
1个回答
0
投票

我在我编写的 lisp 解释器中解决了这个问题,使用 std::unordered_map、EvaluationFunc*> 并针对每个参数使用 typeid(var).hash_code() 来查找密钥。

对于大多数数学运算,我有单独的映射,但有一个用于比较的统一映射,仅使用元组而不是对,操作类型作为元组的一部分。

这允许我的解释器加载定义附加类型的 DLL,这些类型可以简单地插入评估系统。

它确实需要编写大量相当重复的函数(例如 bool_bool_add、bool_int_add、int_bool_add、int_int_add,...)。

© www.soinside.com 2019 - 2024. All rights reserved.