重构类型系统并改进诊断功能
- 更新了类型系统,新增了类型并优化了结构。 - 引入了基类型和派生类,用于函数、结构体和接口类型。 - 实现了类型上下文,用于管理内置类型和类型解析。 - 添加了诊断类,用于收集和报告警告和错误。 - 通过改进错误处理增强了虚拟机执行,以应对递归限制问题。 - 实现了反汇编器,将字节码转换为代码,以改善调试和分析。 - 添加了新的抽象语法树节点,用于成员表达式、对象初始化、接口和结构体定义。 - 引入了语义错误测试,包括重定义、未声明的变量和无效的结构字段。
This commit is contained in:
107
src/Ast/Base.hpp
107
src/Ast/Base.hpp
@@ -2,52 +2,55 @@
|
||||
@file src/Ast/Base.hpp
|
||||
@brief AstNode基类定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-14
|
||||
@date 2026-03-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Core/SourceLocations.hpp>
|
||||
#include <Deps/Deps.hpp>
|
||||
|
||||
#include <Sema/Type.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
enum class AstType : std::uint8_t
|
||||
{
|
||||
AstNode, // 基类
|
||||
Program, // 程序
|
||||
Expr, // 表达式
|
||||
Stmt, // 语句
|
||||
BlockStmt, // 块语句
|
||||
AstNode,
|
||||
Program,
|
||||
Expr,
|
||||
Stmt,
|
||||
BlockStmt,
|
||||
|
||||
/* Expressions */
|
||||
IdentiExpr, // 标识符表达式
|
||||
LiteralExpr, // 字面量表达式
|
||||
PrefixExpr, // 一元 前缀表达式
|
||||
InfixExpr, // 二元 中缀表达式
|
||||
|
||||
IndexExpr, // 后缀表达式,索引
|
||||
CallExpr, // 后缀表达式,函数调用
|
||||
IdentiExpr,
|
||||
LiteralExpr,
|
||||
PrefixExpr,
|
||||
InfixExpr,
|
||||
IndexExpr,
|
||||
CallExpr,
|
||||
MemberExpr, // obj.prop
|
||||
ObjectInitExpr, // new Point{}
|
||||
|
||||
/* Statements */
|
||||
ExprStmt, // 表达式语句,如 println(1)
|
||||
VarDecl, // 变量声明
|
||||
IfStmt, // If语句
|
||||
ElseIfStmt, // ElseIf语句,不准悬空,平铺式else if
|
||||
WhileStmt, // while语句
|
||||
FnDefStmt, // func函数定义语句
|
||||
ReturnStmt, // 返回语句
|
||||
BreakStmt, // break语句
|
||||
ContinueStmt, // continue语句
|
||||
ExprStmt,
|
||||
VarDecl,
|
||||
IfStmt,
|
||||
ElseIfStmt,
|
||||
WhileStmt,
|
||||
FnDefStmt,
|
||||
StructDefStmt,
|
||||
InterfaceDefStmt,
|
||||
ImplStmt, // impl Document for File {}
|
||||
ReturnStmt,
|
||||
BreakStmt,
|
||||
ContinueStmt,
|
||||
|
||||
/* Type Expressions */
|
||||
TypeExpr, // 基类
|
||||
NamedTypeExpr, // 命名类型,支持namespace, std.file这样的
|
||||
// 泛型等...
|
||||
TypeExpr,
|
||||
NamedTypeExpr,
|
||||
NullableTypeExpr
|
||||
};
|
||||
|
||||
struct AstNode
|
||||
{
|
||||
AstType type = AstType::AstNode;
|
||||
@@ -66,13 +69,10 @@ namespace Fig
|
||||
virtual ~TypeExpr() = default;
|
||||
};
|
||||
|
||||
struct Program;
|
||||
|
||||
struct Expr : public AstNode
|
||||
{
|
||||
TypeInfo *resolvedType = nullptr;
|
||||
// TODO: 可选的常量折叠
|
||||
// 拓展 isConstExpr和 constValue槽位
|
||||
// 语义分析后填充
|
||||
Type resolvedType;
|
||||
|
||||
Expr()
|
||||
{
|
||||
@@ -82,7 +82,7 @@ namespace Fig
|
||||
|
||||
struct Stmt : public AstNode
|
||||
{
|
||||
bool isPublic;
|
||||
bool isPublic = false;
|
||||
Stmt()
|
||||
{
|
||||
type = AstType::Stmt;
|
||||
@@ -92,22 +92,10 @@ namespace Fig
|
||||
struct Program final : public AstNode
|
||||
{
|
||||
DynArray<Stmt *> nodes;
|
||||
|
||||
Program()
|
||||
{
|
||||
type = AstType::Program;
|
||||
}
|
||||
|
||||
Program(DynArray<Stmt *> _nodes)
|
||||
{
|
||||
type = AstType::Program;
|
||||
nodes = std::move(_nodes);
|
||||
if (!_nodes.empty())
|
||||
{
|
||||
location = std::move(_nodes.back()->location);
|
||||
}
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return "<Program>";
|
||||
@@ -121,36 +109,9 @@ namespace Fig
|
||||
{
|
||||
type = AstType::BlockStmt;
|
||||
}
|
||||
BlockStmt(DynArray<Stmt *> _nodes)
|
||||
{
|
||||
type = AstType::BlockStmt;
|
||||
nodes = std::move(_nodes);
|
||||
if (!_nodes.empty())
|
||||
{
|
||||
location = std::move(_nodes.back()->location);
|
||||
}
|
||||
}
|
||||
virtual String toString() const override
|
||||
{
|
||||
return "<BlockStmt>";
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct std::formatter<Fig::AstNode *, char>
|
||||
{
|
||||
constexpr auto parse(std::format_parse_context &ctx)
|
||||
{
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Fig::AstNode *_node, FormatContext &ctx) const
|
||||
{
|
||||
return std::format_to(ctx.out(), "{}", _node->toString().toStdString());
|
||||
}
|
||||
};
|
||||
}; // namespace std
|
||||
} // namespace Fig
|
||||
|
||||
@@ -1,48 +1,32 @@
|
||||
/*!
|
||||
@file src/Ast/Expr/IdentiExpr.hpp
|
||||
@brief IdentiExpr定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-14
|
||||
@brief 标识符表达式定义
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
#include <Deps/Deps.hpp>
|
||||
#include <Sema/Environment.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct IdentiExpr final : Expr
|
||||
struct IdentiExpr final : public Expr
|
||||
{
|
||||
String name;
|
||||
|
||||
// Analyzer槽位
|
||||
|
||||
// 寻址空间
|
||||
bool isGlobal = false; // 是否全局, 全局变量存哈希/堆
|
||||
|
||||
// 仅 isGlobal = false 有效
|
||||
int resolvedDepth = -1; // 用于获取闭包上值, -1 代表未解析
|
||||
|
||||
// 栈内槽位
|
||||
int localId = -1; // 局部变量id, -1 未解析
|
||||
|
||||
String name;
|
||||
Symbol *resolvedSymbol = nullptr; // 语义分析后填充,Compiler 唯一的依赖
|
||||
|
||||
IdentiExpr()
|
||||
{
|
||||
type = AstType::IdentiExpr;
|
||||
}
|
||||
|
||||
IdentiExpr(String _name, SourceLocation _loc)
|
||||
IdentiExpr(String _name, SourceLocation _location) : name(std::move(_name))
|
||||
{
|
||||
type = AstType::IdentiExpr;
|
||||
name = std::move(_name);
|
||||
location = std::move(_loc);
|
||||
type = AstType::IdentiExpr;
|
||||
location = std::move(_location);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<IdentiExpr: {}>", name);
|
||||
return std::format("<IdentiExpr '{}'>", name);
|
||||
}
|
||||
};
|
||||
};
|
||||
} // namespace Fig
|
||||
|
||||
@@ -1,36 +1,27 @@
|
||||
/*!
|
||||
@file src/Ast/Expr/LiteralExpr.hpp
|
||||
@brief 字面量表达式定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-14
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
#include <Token/Token.hpp>
|
||||
|
||||
#include <Deps/Deps.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct LiteralExpr final : Expr
|
||||
struct LiteralExpr final : public Expr
|
||||
{
|
||||
Token token;
|
||||
Token literal;
|
||||
|
||||
LiteralExpr()
|
||||
{
|
||||
type = AstType::LiteralExpr;
|
||||
}
|
||||
LiteralExpr(const Token& token, SourceLocation _location) : token(token)
|
||||
LiteralExpr() { type = AstType::LiteralExpr; }
|
||||
LiteralExpr(const Token &_literal, SourceLocation _location) : literal(_literal)
|
||||
{
|
||||
type = AstType::LiteralExpr;
|
||||
location = std::move(_location);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<LiteralExpr: {}>", magic_enum::enum_name(token.type));
|
||||
virtual String toString() const override {
|
||||
return std::format("<LiteralExpr: {}>", magic_enum::enum_name(literal.type));
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
}
|
||||
|
||||
35
src/Ast/Expr/MemberExpr.hpp
Normal file
35
src/Ast/Expr/MemberExpr.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*!
|
||||
@file src/Ast/Expr/MemberExpr.hpp
|
||||
@brief 成员访问表达式定义:obj.member
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-03-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct MemberExpr final : public Expr
|
||||
{
|
||||
Expr *target; // 访问对象
|
||||
String name; // 成员名字
|
||||
|
||||
MemberExpr()
|
||||
{
|
||||
type = AstType::MemberExpr;
|
||||
}
|
||||
|
||||
MemberExpr(Expr *_t, String _n, SourceLocation _loc) : target(_t), name(std::move(_n))
|
||||
{
|
||||
type = AstType::MemberExpr;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<MemberExpr {}.{}>", target->toString(), name);
|
||||
}
|
||||
};
|
||||
} // namespace Fig
|
||||
50
src/Ast/Expr/ObjectInitExpr.hpp
Normal file
50
src/Ast/Expr/ObjectInitExpr.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*!
|
||||
@file src/Ast/Expr/ObjectInitExpr.hpp
|
||||
@brief 对象初始化表达式 AST 定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-03-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct ObjectInitExpr final : public Expr
|
||||
{
|
||||
struct Arg
|
||||
{
|
||||
String name;
|
||||
Expr *value;
|
||||
};
|
||||
TypeExpr *typeExpr;
|
||||
DynArray<Arg> args;
|
||||
|
||||
ObjectInitExpr()
|
||||
{
|
||||
type = AstType::ObjectInitExpr;
|
||||
}
|
||||
ObjectInitExpr(TypeExpr *_te, DynArray<Arg> _args, SourceLocation _loc) :
|
||||
typeExpr(_te), args(std::move(_args))
|
||||
{
|
||||
type = AstType::ObjectInitExpr;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
String res = "<ObjectInitExpr 'new " + typeExpr->toString() + "{";
|
||||
for (size_t i = 0; i < args.size(); ++i)
|
||||
{
|
||||
if (!args[i].name.empty())
|
||||
res += args[i].name + ": ";
|
||||
res += args[i].value->toString();
|
||||
if (i < args.size() - 1)
|
||||
res += ", ";
|
||||
}
|
||||
res += "}'>";
|
||||
return res;
|
||||
}
|
||||
};
|
||||
} // namespace Fig
|
||||
@@ -1,102 +1,47 @@
|
||||
/*!
|
||||
@file src/Ast/Stmt/FnDefStmt.hpp
|
||||
@brief FnDefStmt定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-25
|
||||
@brief 函数定义 AST 节点
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
#include <Sema/Environment.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct Param
|
||||
{
|
||||
String name;
|
||||
SourceLocation location;
|
||||
|
||||
TypeInfo *resolvedType = nullptr;
|
||||
int localId = -1;
|
||||
|
||||
virtual String toString() const = 0;
|
||||
};
|
||||
|
||||
struct PosParam final : public Param
|
||||
{
|
||||
TypeExpr *type;
|
||||
struct Param : public AstNode {
|
||||
String name;
|
||||
TypeExpr *typeSpecifier;
|
||||
Expr *defaultValue;
|
||||
|
||||
PosParam() {}
|
||||
PosParam(String _name, TypeExpr *_type, Expr *_defaultValue, SourceLocation _location) :
|
||||
type(_type), defaultValue(_defaultValue)
|
||||
{
|
||||
name = std::move(_name);
|
||||
location = std::move(_location);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<Pos {}: {}{}>",
|
||||
name,
|
||||
(type ? type->toString() : "Any"),
|
||||
(defaultValue ? " =" + defaultValue->toString() : ""));
|
||||
}
|
||||
Type resolvedType;
|
||||
Param() { type = AstType::AstNode; }
|
||||
virtual ~Param() = default;
|
||||
};
|
||||
|
||||
/*
|
||||
(public) func foo([name: (type) (= default value)]) (-> return type)
|
||||
{
|
||||
...
|
||||
struct PosParam final : public Param {
|
||||
PosParam(String _n, TypeExpr *_ts, Expr *_dv, SourceLocation _loc) {
|
||||
name = std::move(_n); typeSpecifier = _ts; defaultValue = _dv; location = std::move(_loc);
|
||||
}
|
||||
virtual String toString() const override { return name; }
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
struct FnDefStmt final : public Stmt
|
||||
{
|
||||
String name;
|
||||
struct FnDefStmt final : public Stmt {
|
||||
String name;
|
||||
DynArray<Param *> params;
|
||||
TypeExpr *returnType;
|
||||
BlockStmt *body;
|
||||
TypeExpr *returnTypeSpecifier;
|
||||
BlockStmt *body;
|
||||
Type resolvedReturnType;
|
||||
Symbol *resolvedSymbol = nullptr; // 连接物理符号
|
||||
|
||||
TypeInfo *resolvedReturnType = nullptr;
|
||||
int localId = -1;
|
||||
|
||||
FnDefStmt()
|
||||
FnDefStmt() { type = AstType::FnDefStmt; }
|
||||
FnDefStmt(bool _p, String _n, DynArray<Param *> _pa, TypeExpr *_rt, BlockStmt *_b, SourceLocation _loc)
|
||||
: name(std::move(_n)), params(std::move(_pa)), returnTypeSpecifier(_rt), body(_b)
|
||||
{
|
||||
type = AstType::FnDefStmt;
|
||||
type = AstType::FnDefStmt; isPublic = _p; location = std::move(_loc);
|
||||
}
|
||||
|
||||
FnDefStmt(bool _isPublic,
|
||||
String _name,
|
||||
DynArray<Param *> _params,
|
||||
TypeExpr *_returnType,
|
||||
BlockStmt *_body,
|
||||
SourceLocation _location) :
|
||||
name(std::move(_name)), params(std::move(_params)), returnType(_returnType), body(_body)
|
||||
{
|
||||
type = AstType::FnDefStmt;
|
||||
isPublic = _isPublic;
|
||||
location = std::move(_location);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
String pStr;
|
||||
for (const Param *p : params)
|
||||
{
|
||||
if (p != *params.begin())
|
||||
{
|
||||
pStr += ", ";
|
||||
}
|
||||
pStr += p->toString();
|
||||
}
|
||||
return std::format("<FnDefStmt {}{}({}) -> {} {{{}}}>",
|
||||
(isPublic ? "public " : ""),
|
||||
name,
|
||||
pStr,
|
||||
(returnType ? returnType->toString() : "Any"),
|
||||
body->toString());
|
||||
virtual String toString() const override {
|
||||
return std::format("<FnDefStmt '{}'>", name);
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
}
|
||||
|
||||
32
src/Ast/Stmt/ImplStmt.hpp
Normal file
32
src/Ast/Stmt/ImplStmt.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
@file src/Ast/Stmt/ImplStmt.hpp
|
||||
@brief 实现块 AST 节点
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Ast/Base.hpp>
|
||||
#include <Ast/Stmt/FnDefStmt.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct ImplStmt final : public Stmt
|
||||
{
|
||||
TypeExpr *interfaceType;
|
||||
TypeExpr *structType;
|
||||
DynArray<FnDefStmt *> methods;
|
||||
|
||||
ImplStmt(TypeExpr *_it, TypeExpr *_st, DynArray<FnDefStmt *> _m, SourceLocation _loc) :
|
||||
interfaceType(_it), structType(_st), methods(std::move(_m))
|
||||
{
|
||||
type = AstType::ImplStmt;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
String detail =
|
||||
(interfaceType ? interfaceType->toString() + " for " : "") + structType->toString();
|
||||
return std::format("<ImplStmt '{}'>", detail);
|
||||
}
|
||||
};
|
||||
} // namespace Fig
|
||||
39
src/Ast/Stmt/InterfaceDefStmt.hpp
Normal file
39
src/Ast/Stmt/InterfaceDefStmt.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
@file src/Ast/Stmt/InterfaceDefStmt.hpp
|
||||
@brief 接口定义 AST 节点
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-03-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Ast/Base.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct InterfaceDefStmt final : public Stmt
|
||||
{
|
||||
struct Method
|
||||
{
|
||||
String name;
|
||||
DynArray<TypeExpr*> params;
|
||||
TypeExpr *retType;
|
||||
SourceLocation location;
|
||||
};
|
||||
|
||||
bool isPublic;
|
||||
String name;
|
||||
DynArray<Method> methods;
|
||||
|
||||
InterfaceDefStmt() { type = AstType::InterfaceDefStmt; }
|
||||
|
||||
InterfaceDefStmt(bool _p, String _n, DynArray<Method> _m, SourceLocation _loc)
|
||||
: isPublic(_p), name(std::move(_n)), methods(std::move(_m))
|
||||
{
|
||||
type = AstType::InterfaceDefStmt;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override { return "<InterfaceDefStmt>"; }
|
||||
};
|
||||
} // namespace Fig
|
||||
56
src/Ast/Stmt/StructDefStmt.hpp
Normal file
56
src/Ast/Stmt/StructDefStmt.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*!
|
||||
@file src/Ast/Stmt/StructDefStmt.hpp
|
||||
@brief 结构体定义 AST 节点
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Ast/Base.hpp>
|
||||
#include <Ast/Stmt/FnDefStmt.hpp>
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
struct StructDefStmt final : public Stmt
|
||||
{
|
||||
struct Field
|
||||
{
|
||||
String name;
|
||||
TypeExpr *type;
|
||||
bool isPublic;
|
||||
};
|
||||
bool isPublic;
|
||||
String name;
|
||||
DynArray<String> typeParameters;
|
||||
DynArray<Field> fields;
|
||||
DynArray<FnDefStmt *> methods;
|
||||
|
||||
StructDefStmt()
|
||||
{
|
||||
type = AstType::StructDefStmt;
|
||||
}
|
||||
StructDefStmt(bool _p,
|
||||
String _n,
|
||||
DynArray<String> _tp,
|
||||
DynArray<Field> _f,
|
||||
DynArray<FnDefStmt *> _m,
|
||||
SourceLocation _loc) :
|
||||
isPublic(_p),
|
||||
name(std::move(_n)),
|
||||
typeParameters(std::move(_tp)),
|
||||
fields(std::move(_f)),
|
||||
methods(std::move(_m))
|
||||
{
|
||||
type = AstType::StructDefStmt;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
String detail = name;
|
||||
if (!typeParameters.empty())
|
||||
{
|
||||
detail += "<...>";
|
||||
}
|
||||
return std::format("<StructDefStmt '{}'>", detail);
|
||||
}
|
||||
};
|
||||
} // namespace Fig
|
||||
@@ -1,8 +1,6 @@
|
||||
/*!
|
||||
@file src/Ast/TypeExpr.hpp
|
||||
@brief TypeExpr定义
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-25
|
||||
@brief 类型表达式 AST 定义:支持泛型与空安全
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -11,26 +9,59 @@
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
|
||||
struct NamedTypeExpr final : public TypeExpr
|
||||
{
|
||||
DynArray<String> path; // {"std", "file"} etc.
|
||||
DynArray<String> path;
|
||||
DynArray<TypeExpr *> arguments;
|
||||
|
||||
NamedTypeExpr()
|
||||
{
|
||||
type = AstType::NamedTypeExpr;
|
||||
}
|
||||
|
||||
NamedTypeExpr(DynArray<String> _path, SourceLocation _location) :
|
||||
path(std::move(_path))
|
||||
NamedTypeExpr(DynArray<String> _p, DynArray<TypeExpr *> _args, SourceLocation _loc) :
|
||||
path(std::move(_p)), arguments(std::move(_args))
|
||||
{
|
||||
type = AstType::NamedTypeExpr;
|
||||
location = std::move(_location);
|
||||
type = AstType::NamedTypeExpr;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<NamedTypeExpr '{}'>", path);
|
||||
String detail = "";
|
||||
for (size_t i = 0; i < path.size(); ++i)
|
||||
{
|
||||
detail += path[i];
|
||||
if (i < path.size() - 1)
|
||||
detail += ".";
|
||||
}
|
||||
if (!arguments.empty())
|
||||
{
|
||||
detail += "<";
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
{
|
||||
detail += arguments[i]->toString();
|
||||
if (i < arguments.size() - 1)
|
||||
detail += ", ";
|
||||
}
|
||||
detail += ">";
|
||||
}
|
||||
return std::format("<NamedTypeExpr '{}'>", detail);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct NullableTypeExpr final : public TypeExpr
|
||||
{
|
||||
TypeExpr *inner;
|
||||
|
||||
NullableTypeExpr(TypeExpr *_inner, SourceLocation _loc) : inner(_inner)
|
||||
{
|
||||
type = AstType::NullableTypeExpr;
|
||||
location = std::move(_loc);
|
||||
}
|
||||
|
||||
virtual String toString() const override
|
||||
{
|
||||
return std::format("<NullableTypeExpr '{}?'>", inner->toString());
|
||||
}
|
||||
};
|
||||
} // namespace Fig
|
||||
|
||||
Reference in New Issue
Block a user