Skip to content

Commit

Permalink
add Enum Type
Browse files Browse the repository at this point in the history
  • Loading branch information
chloro-pn committed Jun 13, 2024
1 parent 3861332 commit b4ee243
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 38 deletions.
5 changes: 4 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
* [done] 将interpreter的进入退出运行时栈接口改为私有的,不对用户暴露
* [done] lambda捕获列表支持move
* [done] 内置/注册函数支持赋值给callable【目前不支持内置函数返回类型,因为有些内置函数是模板化的,其类型根据输入参数确定】
* 支持enum
* [done] 支持enum
- enum的字面量格式应该是什么样的?
- [done] enum type:enum_item
* [done] 优化内置方法的错误提示
* [done] 支持变量引用(不涉及类型系统)
* [done] 支持自增运算符
Expand All @@ -37,3 +39,4 @@
* 返回类型为void时的return语句优化
* [done] 支持析构函数
* 支持内置函数assert
* 支持 enum to string
17 changes: 17 additions & 0 deletions include/wamon/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,23 @@ class VoidIteralExpr : public Expression {
std::shared_ptr<Variable> Calculate(Interpreter& interpreter) override { return std::make_shared<VoidVariable>(); }
};

class EnumIteralExpr : public Expression {
public:
std::shared_ptr<Variable> Calculate(Interpreter& Interpreter) override;

void SetEnumType(std::unique_ptr<Type>&& type) { type_ = std::move(type); }

void SetEnumItem(const std::string& item) { enum_item_ = item; }

const std::unique_ptr<Type>& GetEnumType() const { return type_; }

const std::string& GetEnumItem() const { return enum_item_; }

private:
std::unique_ptr<Type> type_;
std::string enum_item_;
};

class SelfExpr : public Expression {
public:
std::shared_ptr<Variable> Calculate(Interpreter& interpreter) override;
Expand Down
7 changes: 6 additions & 1 deletion include/wamon/enum_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ class EnumDef {

const std::vector<std::string>& GetEnumItems() const { return enum_items_; }

bool ItemExist(const std::string& item) const {
auto it = std::find(enum_items_.begin(), enum_items_.end(), item);
return it != enum_items_.end();
}

private:
std::string enum_name_;
std::vector<std::string> enum_items_;
};

} // namespace wamon
} // namespace wamon
2 changes: 1 addition & 1 deletion include/wamon/inner_type_method.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class InnerTypeMethod {
}

HandleType& Get(std::shared_ptr<Variable>& obj, const std::string& method_name) const {
assert(!IsStructType(obj->GetType()));
assert(!IsStructOrEnumType(obj->GetType()));
auto handle_id = GetHandleId(obj->GetType(), method_name);
auto it = handles_.find(handle_id);
assert(it != handles_.end());
Expand Down
2 changes: 1 addition & 1 deletion include/wamon/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ class Interpreter {
// 注意:CallMethodByName会尝试进行struct trait -> struct的转换,而CallMethod不会,因此用户不要直接使用CallMethod接口
std::shared_ptr<Variable> CallMethodByName(std::shared_ptr<Variable> obj, const std::string& method_name,
std::vector<std::shared_ptr<Variable>>&& params) {
if (!IsStructType(obj->GetType())) {
if (!IsStructOrEnumType(obj->GetType())) {
return CallMethod(obj, method_name, std::move(params));
}
auto type = obj->GetTypeInfo();
Expand Down
11 changes: 11 additions & 0 deletions include/wamon/package_unit.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class PackageUnit {

void AddEnumDef(std::unique_ptr<EnumDef>&& enum_def) {
auto name = enum_def->GetEnumName();
if (enum_def->GetEnumItems().empty()) {
throw WamonException("AddEnumDef error, empty enum {}", name);
}
if (enums_.find(name) != enums_.end()) {
throw WamonException("duplicate enum {}", name);
}
Expand Down Expand Up @@ -102,6 +105,14 @@ class PackageUnit {
return it->second.get();
}

const EnumDef* FindEnum(const std::string& enum_name) const {
auto it = enums_.find(enum_name);
if (it == enums_.end()) {
return nullptr;
}
return it->second.get();
}

const FunctionDef* FindFunction(const std::string& function_name) const {
auto it = funcs_.find(function_name);
if (it == funcs_.end()) {
Expand Down
5 changes: 4 additions & 1 deletion include/wamon/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* - bool
* - void
* - 结构体类型
* - 枚举类型
* - 复合类型(类型加工器):
* - 指针类型 * int*
* - 列表类型 [num] int[2]
Expand Down Expand Up @@ -180,7 +181,9 @@ inline bool IsBuiltInType(const std::unique_ptr<Type>& type) {
type->GetTypeInfo() == "byte" || type->GetTypeInfo() == "bool" || type->GetTypeInfo() == "void";
}

inline bool IsStructType(const std::unique_ptr<Type>& type) { return type->IsBasicType() && !IsBuiltInType(type); }
inline bool IsStructOrEnumType(const std::unique_ptr<Type>& type) {
return type->IsBasicType() && !IsBuiltInType(type);
}

namespace detail {

Expand Down
29 changes: 29 additions & 0 deletions include/wamon/variable.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace wamon {

class StructDef;
class EnumDef;

/*
* Variable为运行时变量类型的基类,每个Variable一定包含一个type成员标识其类型
Expand Down Expand Up @@ -446,6 +447,34 @@ inline StructVariable* AsStructVariable(const std::shared_ptr<Variable>& v) {
return static_cast<StructVariable*>(v.get());
}

class EnumVariable : public Variable {
public:
EnumVariable(const EnumDef* def, ValueCategory vc, const std::string& name);

void ConstructByFields(const std::vector<std::shared_ptr<Variable>>& fields) override;

void DefaultConstruct() override;

// Clone函数返回值的 ValueCategory == RValue,name == ""
std::shared_ptr<Variable> Clone() override;

bool Compare(const std::shared_ptr<Variable>& other) override;

void Assign(const std::shared_ptr<Variable>& other) override;

nlohmann::json Print() override;

void SetEnumItem(const std::string& enum_item) { enum_item_ = enum_item; }

const std::string& GetEnumItem() const { return enum_item_; }

private:
const EnumDef* def_;
std::string enum_item_;
};

inline EnumVariable* AsEnumVariable(const std::shared_ptr<Variable>& v) { return static_cast<EnumVariable*>(v.get()); }

class CompoundVariable : public Variable {
public:
CompoundVariable(std::unique_ptr<Type>&& t, ValueCategory vc, const std::string& name)
Expand Down
8 changes: 7 additions & 1 deletion src/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ std::shared_ptr<Variable> MethodCallExpr::Calculate(Interpreter& interpreter) {
params.push_back(std::move(v));
}
auto v = caller_->Calculate(interpreter);
if (!IsStructType(v->GetType())) {
if (!IsStructOrEnumType(v->GetType())) {
auto result = interpreter.CallMethod(v, method_name_, std::move(params));
return result;
}
Expand Down Expand Up @@ -122,6 +122,12 @@ std::shared_ptr<Variable> IdExpr::Calculate(Interpreter& interpreter) {
}
}

std::shared_ptr<Variable> EnumIteralExpr::Calculate(Interpreter& Interpreter) {
auto v = VariableFactory(type_, Variable::ValueCategory::RValue, "", Interpreter);
AsEnumVariable(v)->SetEnumItem(enum_item_);
return v;
}

std::shared_ptr<Variable> SelfExpr::Calculate(Interpreter& interpreter) { return interpreter.GetSelfObject(); }

std::shared_ptr<Variable> LambdaExpr::Calculate(Interpreter& interpreter) {
Expand Down
14 changes: 14 additions & 0 deletions src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,20 @@ std::unique_ptr<Expression> ParseExpression(PackageUnit &pu, const std::vector<W
operands.push(AttachUnaryOperators(std::move(bool_iter_expr), u_operators));
continue;
}
// enum 字面量表达式
// enum enum_type : enum_item
if (current_token == Token::ENUM) {
i += 1;
std::unique_ptr<EnumIteralExpr> enum_expr(new EnumIteralExpr());
auto type = ParseType(pu, tokens, i);
AssertTokenOrThrow(tokens, i, Token::COLON, __FILE__, __LINE__);
auto enum_item = ParseIdentifier<true>(pu, tokens, i);
enum_expr->SetEnumType(std::move(type));
enum_expr->SetEnumItem(enum_item.second);
i -= 1;
operands.push(AttachUnaryOperators(std::move(enum_expr), u_operators));
continue;
}
if (current_token == Token::SELF) {
std::unique_ptr<SelfExpr> self_expr(new SelfExpr());
operands.push(AttachUnaryOperators(std::move(self_expr), u_operators));
Expand Down
50 changes: 27 additions & 23 deletions src/type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void CheckCanConstructBy(const PackageUnit& pu, const std::unique_ptr<Type>& var
if (param_types.size() == 1 && IsSameType(var_type, param_types[0])) {
return;
}
if (param_types.size() == 1 && IsStructType(param_types[0])) {
if (param_types.size() == 1 && IsStructOrEnumType(param_types[0])) {
// 重载了()运算符的结构体类型的对象
auto method_name = OperatorDef::CreateName(Token::LEFT_PARENTHESIS, GetParamType(var_type));
auto struct_def = pu.FindStruct(param_types[0]->GetTypeInfo());
Expand All @@ -123,6 +123,7 @@ void CheckCanConstructBy(const PackageUnit& pu, const std::unique_ptr<Type>& var
return;
}
// 所有相同类型的单个对象均可以执行构造(复制操作)
// also handle enum here
if (param_types.size() == 1 && IsSameType(var_type, param_types[0])) {
return;
}
Expand All @@ -143,36 +144,39 @@ void CheckCanConstructBy(const PackageUnit& pu, const std::unique_ptr<Type>& var
return;
}
// struct 类型
if (IsStructType(var_type)) {
if (IsStructOrEnumType(var_type)) {
// 这里不需要考虑Enum的情况,因为Enum的合理构造在 相同类型的单个对象构造中完成。
auto struct_def = pu.FindStruct(var_type->GetTypeInfo());
if (struct_def == nullptr) {
throw WamonException("construct check error, invalid struct name {}", var_type->GetTypeInfo());
}
// struct trait
if (struct_def->IsTrait()) {
if (param_types.size() != 1) {
throw WamonException("struct trait {} construct check error, params should be only 1 but {}",
var_type->GetTypeInfo(), param_types.size());
if (struct_def != nullptr) {
// struct trait
if (struct_def->IsTrait()) {
if (param_types.size() != 1) {
throw WamonException("struct trait {} construct check error, params should be only 1 but {}",
var_type->GetTypeInfo(), param_types.size());
}
std::string reason;
if (CheckTraitConstraint(pu, var_type, param_types[0], reason) == false) {
throw WamonException("struct trait {} construct check error, trait constraint check failed, reason : {}",
var_type->GetTypeInfo(), reason);
}
return;
}
std::string reason;
if (CheckTraitConstraint(pu, var_type, param_types[0], reason) == false) {
throw WamonException("struct trait {} construct check error, trait constraint check failed, reason : {}",
var_type->GetTypeInfo(), reason);
const auto& dms = struct_def->GetDataMembers();
if (dms.size() != param_types.size()) {
throw WamonException("struct construct check error, {} != {}", dms.size(), param_types.size());
}
return;
}
const auto& dms = struct_def->GetDataMembers();
if (dms.size() != param_types.size()) {
throw WamonException("struct construct check error, {} != {}", dms.size(), param_types.size());
}
for (size_t i = 0; i < dms.size(); ++i) {
if (!IsSameType(dms[i].second, param_types[i])) {
throw WamonException(
"struct construct check error, {}th data member is constructd by the dismatch type, {} != {}", i,
dms[i].second->GetTypeInfo(), param_types[i]->GetTypeInfo());
for (size_t i = 0; i < dms.size(); ++i) {
if (!IsSameType(dms[i].second, param_types[i])) {
throw WamonException(
"struct construct check error, {}th data member is constructd by the dismatch type, {} != {}", i,
dms[i].second->GetTypeInfo(), param_types[i]->GetTypeInfo());
}
}
return;
}
return;
}
throw WamonException("CheckCanConstructBy check error, type {} can not be constructed by {} ",
var_type->GetTypeInfo(), fmt::join(type_infos, ", "));
Expand Down
25 changes: 21 additions & 4 deletions src/type_checker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ void TypeChecker::CheckType(const std::unique_ptr<Type>& type, const std::string
if (!IsBuiltInType(type)) {
const PackageUnit& pu = static_analyzer_.GetPackageUnit();
const auto& struct_def = pu.FindStruct(type->GetTypeInfo());
if (struct_def == nullptr) {
throw WamonTypeCheck(context_info, type->GetTypeInfo(), "invalid struct type");
const auto& enum_def = pu.FindEnum(type->GetTypeInfo());
if (struct_def == nullptr && enum_def == nullptr) {
throw WamonTypeCheck(context_info, type->GetTypeInfo(), "invalid struct type or enum type");
}
} else {
if (can_be_void == false && IsVoidType(type)) {
Expand Down Expand Up @@ -268,6 +269,19 @@ std::unique_ptr<Type> CheckAndGetSSResultType(const TypeChecker& tc, BinaryExpr*
return list_type->GetHoldType();
}

std::unique_ptr<Type> CheckAndGetEnumIteralResultType(const TypeChecker& tc, EnumIteralExpr* enum_expr) {
const auto& pu = tc.GetStaticAnalyzer().GetPackageUnit();
auto enum_def = pu.FindEnum(enum_expr->GetEnumType()->GetTypeInfo());
if (enum_def == nullptr) {
throw WamonException("invalid enum type : {}", enum_expr->GetEnumType()->GetTypeInfo());
}
if (enum_def->ItemExist(enum_expr->GetEnumItem()) == false) {
throw WamonException("invalid enum item {} for enum type {}", enum_expr->GetEnumItem(),
enum_expr->GetEnumType()->GetTypeInfo());
}
return enum_expr->GetEnumType()->Clone();
}

std::unique_ptr<Type> CheckAndGetMemberAccessResultType(const TypeChecker& tc, BinaryExpr* binary_expr) {
assert(binary_expr->op_ == Token::MEMBER_ACCESS);
auto left_type = tc.GetExpressionType(binary_expr->left_.get());
Expand Down Expand Up @@ -498,7 +512,7 @@ std::unique_ptr<Type> CheckAndGetOperatorOverrideReturnType(const TypeChecker& t

std::unique_ptr<Type> CheckAndGetInnerMethodReturnType(const TypeChecker& tc, const std::unique_ptr<Type>& ctype,
const MethodCallExpr* call_expr) {
assert(!IsStructType(ctype));
assert(!IsStructOrEnumType(ctype));
std::vector<std::unique_ptr<Type>> params_type;
for (auto& each : call_expr->parameters_) {
params_type.push_back(tc.GetExpressionType(each.get()));
Expand Down Expand Up @@ -582,7 +596,7 @@ std::unique_ptr<Type> CheckParamTypeAndGetResultTypeForFunction(const TypeChecke

std::unique_ptr<Type> CheckParamTypeAndGetResultTypeForMethod(const TypeChecker& tc, MethodCallExpr* method_call_expr) {
std::unique_ptr<Type> find_type = tc.GetExpressionType(method_call_expr->caller_.get());
if (!IsStructType(find_type)) {
if (!IsStructOrEnumType(find_type)) {
return CheckAndGetInnerMethodReturnType(tc, find_type, method_call_expr);
}
// if not find, throw exception
Expand Down Expand Up @@ -657,6 +671,9 @@ std::unique_ptr<Type> TypeChecker::GetExpressionType(Expression* expr) const {
if (dynamic_cast<VoidIteralExpr*>(expr)) {
return std::make_unique<BasicType>(GetTokenStr(Token::VOID));
}
if (auto tmp = dynamic_cast<EnumIteralExpr*>(expr)) {
return CheckAndGetEnumIteralResultType(*this, tmp);
}
if (auto tmp = dynamic_cast<BinaryExpr*>(expr)) {
// 特殊的二元运算符,第二个操作数的类型由查询第一个运算符类型的定义得到
if (tmp->op_ == Token::MEMBER_ACCESS) {
Expand Down
Loading

0 comments on commit b4ee243

Please sign in to comment.