You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.0 KiB

// 编译期常量求值与常量初始化展开。
#pragma once
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
#include "SysYParser.h"
#include "sem/SymbolTable.h"
struct ConstValue {
SymbolDataType type = SymbolDataType::Unknown;
int64_t int_value = 0;
double float_value = 0.0;
bool bool_value = false;
static ConstValue FromInt(int64_t value);
static ConstValue FromFloat(double value);
static ConstValue FromBool(bool value);
bool IsScalar() const;
bool IsNumeric() const;
int64_t AsInt() const;
double AsFloat() const;
bool AsBool() const;
};
struct ConstArrayValue {
SymbolDataType elem_type = SymbolDataType::Unknown;
std::vector<int64_t> dims;
std::vector<ConstValue> elements;
};
class ConstEvalContext {
public:
ConstEvalContext();
void EnterScope();
void ExitScope();
bool DefineScalar(const std::string& name, ConstValue value);
bool DefineArray(const std::string& name, ConstArrayValue value);
const ConstValue* LookupScalar(const std::string& name) const;
const ConstArrayValue* LookupArray(const std::string& name) const;
private:
struct Binding {
bool is_array = false;
ConstValue scalar;
ConstArrayValue array;
};
using Scope = std::unordered_map<std::string, Binding>;
const Binding* LookupBinding(const std::string& name) const;
std::vector<Scope> scopes_;
};
class ConstEvaluator {
public:
ConstEvaluator(const SymbolTable& table, const ConstEvalContext& ctx);
ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx) const;
ConstValue EvaluateExp(SysYParser::ExpContext& ctx) const;
// 数组维度必须是正整数。
int64_t EvaluateArrayDim(SysYParser::ConstExpContext& ctx) const;
// 展平 const 初始化列表,结果按行优先顺序存放。
std::vector<ConstValue> EvaluateConstInitList(
SysYParser::ConstInitValContext& init, SymbolDataType elem_type,
const std::vector<int64_t>& dims) const;
private:
const SymbolTable& table_;
const ConstEvalContext& ctx_;
};