feat: 实现控制流语句并优化类型解析
- 新增了 ReturnStmt、BreakStmt 和 ContinueStmt 结构,以支持 AST 中的控制流。 - 引入了 TypeInfo 和 TypeContext 以实现更好的类型管理和解析。 - 对分析器进行了增强,能够处理函数定义和返回语句,包括类型检查和错误处理。 - 更新了编译器和解析器以适应新的控制流语句和类型解析逻辑。 - 重构了现有代码以提高清晰度和可维护性,包括对表达式和语句中的类型处理的更改。 - 删除了过时的 String 和 Struct 定义,代之以 StringObject 和 StructObject 以实现更好的对象表示。
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
#include <Ast/Expr/LiteralExpr.hpp>
|
#include <Ast/Expr/LiteralExpr.hpp>
|
||||||
#include <Ast/Expr/PrefixExpr.hpp>
|
#include <Ast/Expr/PrefixExpr.hpp>
|
||||||
|
|
||||||
|
#include <Ast/Stmt/ControlFlowStmts.hpp>
|
||||||
#include <Ast/Stmt/ExprStmt.hpp>
|
#include <Ast/Stmt/ExprStmt.hpp>
|
||||||
#include <Ast/Stmt/FnDefStmt.hpp>
|
#include <Ast/Stmt/FnDefStmt.hpp>
|
||||||
#include <Ast/Stmt/IfStmt.hpp>
|
#include <Ast/Stmt/IfStmt.hpp>
|
||||||
|
|||||||
@@ -33,12 +33,15 @@ namespace Fig
|
|||||||
CallExpr, // 后缀表达式,函数调用
|
CallExpr, // 后缀表达式,函数调用
|
||||||
|
|
||||||
/* Statements */
|
/* Statements */
|
||||||
ExprStmt, // 表达式语句,如 println(1)
|
ExprStmt, // 表达式语句,如 println(1)
|
||||||
VarDecl, // 变量声明
|
VarDecl, // 变量声明
|
||||||
IfStmt, // If语句
|
IfStmt, // If语句
|
||||||
ElseIfStmt, // ElseIf语句,不准悬空,平铺式else if
|
ElseIfStmt, // ElseIf语句,不准悬空,平铺式else if
|
||||||
WhileStmt, // while语句
|
WhileStmt, // while语句
|
||||||
FnDefStmt, // func函数定义语句
|
FnDefStmt, // func函数定义语句
|
||||||
|
ReturnStmt, // 返回语句
|
||||||
|
BreakStmt, // break语句
|
||||||
|
ContinueStmt, // continue语句
|
||||||
|
|
||||||
/* Type Expressions */
|
/* Type Expressions */
|
||||||
TypeExpr, // 基类
|
TypeExpr, // 基类
|
||||||
@@ -67,7 +70,7 @@ namespace Fig
|
|||||||
|
|
||||||
struct Expr : public AstNode
|
struct Expr : public AstNode
|
||||||
{
|
{
|
||||||
TypeTag resolvedType = TypeTag::Any;
|
TypeInfo *resolvedType = nullptr;
|
||||||
// TODO: 可选的常量折叠
|
// TODO: 可选的常量折叠
|
||||||
// 拓展 isConstExpr和 constValue槽位
|
// 拓展 isConstExpr和 constValue槽位
|
||||||
|
|
||||||
|
|||||||
72
src/Ast/Stmt/ControlFlowStmts.hpp
Normal file
72
src/Ast/Stmt/ControlFlowStmts.hpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*!
|
||||||
|
@file src/Ast/Stmt/ControlFlowStmts
|
||||||
|
@brief 控制流语句 return, break, continue 定义
|
||||||
|
@author PuqiAR (im@puqiar.top)
|
||||||
|
@date 2026-02-27
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Ast/Base.hpp>
|
||||||
|
|
||||||
|
namespace Fig
|
||||||
|
{
|
||||||
|
struct ReturnStmt final : public Stmt
|
||||||
|
{
|
||||||
|
Expr *value;
|
||||||
|
|
||||||
|
ReturnStmt()
|
||||||
|
{
|
||||||
|
type = AstType::ReturnStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnStmt(Expr *_value, SourceLocation _location) : value(_value)
|
||||||
|
{
|
||||||
|
type = AstType::ReturnStmt;
|
||||||
|
location = std::move(_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String toString() const override
|
||||||
|
{
|
||||||
|
return std::format("<ReturnStmt '{}'>", value->toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BreakStmt final : public Stmt
|
||||||
|
{
|
||||||
|
BreakStmt()
|
||||||
|
{
|
||||||
|
type = AstType::BreakStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakStmt(SourceLocation _location)
|
||||||
|
{
|
||||||
|
type = AstType::BreakStmt;
|
||||||
|
location = std::move(_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String toString() const override
|
||||||
|
{
|
||||||
|
return "<BreakStmt>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ContinueStmt final : public Stmt
|
||||||
|
{
|
||||||
|
ContinueStmt()
|
||||||
|
{
|
||||||
|
type = AstType::ContinueStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContinueStmt(SourceLocation _location)
|
||||||
|
{
|
||||||
|
type = AstType::ContinueStmt;
|
||||||
|
location = std::move(_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual String toString() const override
|
||||||
|
{
|
||||||
|
return "<ContinueStmt>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Fig
|
||||||
@@ -16,6 +16,9 @@ namespace Fig
|
|||||||
String name;
|
String name;
|
||||||
SourceLocation location;
|
SourceLocation location;
|
||||||
|
|
||||||
|
TypeInfo *resolvedType = nullptr;
|
||||||
|
int localId = -1;
|
||||||
|
|
||||||
virtual String toString() const = 0;
|
virtual String toString() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,18 +31,16 @@ namespace Fig
|
|||||||
PosParam(String _name, TypeExpr *_type, Expr *_defaultValue, SourceLocation _location) :
|
PosParam(String _name, TypeExpr *_type, Expr *_defaultValue, SourceLocation _location) :
|
||||||
type(_type), defaultValue(_defaultValue)
|
type(_type), defaultValue(_defaultValue)
|
||||||
{
|
{
|
||||||
name = std::move(_name);
|
name = std::move(_name);
|
||||||
location = std::move(_location);
|
location = std::move(_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual String toString() const override
|
virtual String toString() const override
|
||||||
{
|
{
|
||||||
return std::format(
|
return std::format("<Pos {}: {}{}>",
|
||||||
"<Pos {}: {}{}>",
|
|
||||||
name,
|
name,
|
||||||
(type ? type->toString() : "Any"),
|
(type ? type->toString() : "Any"),
|
||||||
(defaultValue ? " =" + defaultValue->toString() : "")
|
(defaultValue ? " =" + defaultValue->toString() : ""));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,6 +59,9 @@ namespace Fig
|
|||||||
TypeExpr *returnType;
|
TypeExpr *returnType;
|
||||||
BlockStmt *body;
|
BlockStmt *body;
|
||||||
|
|
||||||
|
TypeInfo *resolvedReturnType = nullptr;
|
||||||
|
int localId = -1;
|
||||||
|
|
||||||
FnDefStmt()
|
FnDefStmt()
|
||||||
{
|
{
|
||||||
type = AstType::FnDefStmt;
|
type = AstType::FnDefStmt;
|
||||||
@@ -87,14 +91,12 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
pStr += p->toString();
|
pStr += p->toString();
|
||||||
}
|
}
|
||||||
return std::format(
|
return std::format("<FnDefStmt {}{}({}) -> {} {{{}}}>",
|
||||||
"<FnDefStmt {}{}({}) -> {} {{{}}}>",
|
|
||||||
(isPublic ? "public " : ""),
|
(isPublic ? "public " : ""),
|
||||||
name,
|
name,
|
||||||
pStr,
|
pStr,
|
||||||
(returnType ? returnType->toString() : "Any"),
|
(returnType ? returnType->toString() : "Any"),
|
||||||
body->toString()
|
body->toString());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -34,8 +34,8 @@ namespace Fig
|
|||||||
int depth; // 物理作用域深度(用于 EndScope 释放寄存器)
|
int depth; // 物理作用域深度(用于 EndScope 释放寄存器)
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int MAX_LOCALS = 250;
|
inline constexpr int MAX_LOCALS = 250;
|
||||||
static constexpr int MAX_CONSTANTS = UINT16_MAX;
|
inline constexpr int MAX_CONSTANTS = UINT16_MAX + 1;
|
||||||
|
|
||||||
// 任何跨函数、跨模块的编译,都压入弹出这个 State
|
// 任何跨函数、跨模块的编译,都压入弹出这个 State
|
||||||
struct FuncState
|
struct FuncState
|
||||||
@@ -66,6 +66,24 @@ namespace Fig
|
|||||||
SourceManager &manager;
|
SourceManager &manager;
|
||||||
FuncState *current = nullptr; // 永远指向当前正在编译的上下文
|
FuncState *current = nullptr; // 永远指向当前正在编译的上下文
|
||||||
public:
|
public:
|
||||||
|
struct FuncStateProtector
|
||||||
|
{
|
||||||
|
Compiler *compiler;
|
||||||
|
FuncState *prevState;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
FuncStateProtector(Compiler *comp, FuncState *newState) :
|
||||||
|
compiler(comp), prevState(comp->current)
|
||||||
|
{
|
||||||
|
compiler->current = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
~FuncStateProtector()
|
||||||
|
{
|
||||||
|
compiler->current = prevState;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Compiler(String _fileName, SourceManager &_manager) :
|
Compiler(String _fileName, SourceManager &_manager) :
|
||||||
fileName(std::move(_fileName)), manager(_manager)
|
fileName(std::move(_fileName)), manager(_manager)
|
||||||
{
|
{
|
||||||
@@ -85,7 +103,6 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result<Proto *, Error> Compile(Program *program);
|
Result<Proto *, Error> Compile(Program *program);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PushState(String _name)
|
void PushState(String _name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: 未初始化提供初始值
|
||||||
varReg = DeclareLocal(varDecl->localId);
|
varReg = DeclareLocal(varDecl->localId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
src/Object/FunctionObject.hpp
Normal file
25
src/Object/FunctionObject.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*!
|
||||||
|
@file src/Object/FunctionObject.hpp
|
||||||
|
@brief 函数对象定义
|
||||||
|
@author PuqiAR (im@puqiar.top)
|
||||||
|
@date 2026-02-28
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Object/ObjectBase.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Fig
|
||||||
|
{
|
||||||
|
// 运行时闭包对象 (24字节 Base + 8字节 Proto指针 = 32 bytes)
|
||||||
|
|
||||||
|
struct Proto;
|
||||||
|
struct FunctionObject final : public Object
|
||||||
|
{
|
||||||
|
Proto *proto; // 指向编译器生成的只读字节码与常量池
|
||||||
|
|
||||||
|
// TODO: 实现闭包时 加一个 Upvalue 指针数组
|
||||||
|
// Value* upvalues;
|
||||||
|
};
|
||||||
|
} // namespace Fig
|
||||||
@@ -9,5 +9,31 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
constexpr String Value::ToString() const
|
||||||
|
{
|
||||||
|
if (IsNull())
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
else if (IsInt())
|
||||||
|
{
|
||||||
|
return std::to_string(AsInt());
|
||||||
|
}
|
||||||
|
else if (IsDouble())
|
||||||
|
{
|
||||||
|
return std::format("{}", AsDouble());
|
||||||
|
}
|
||||||
|
else if (IsBool())
|
||||||
|
{
|
||||||
|
return (AsBool() ? "true" : "false");
|
||||||
|
}
|
||||||
|
else if (IsObject())
|
||||||
|
{
|
||||||
|
return "Object"; // TODO: 分派
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "Unknow";
|
||||||
|
}
|
||||||
|
}
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -8,5 +8,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Object/ObjectBase.hpp>
|
#include <Object/ObjectBase.hpp>
|
||||||
#include <Object/String.hpp>
|
#include <Object/StringObject.hpp>
|
||||||
#include <Object/Struct.hpp>
|
#include <Object/StructObject.hpp>
|
||||||
|
#include <Object/FunctionObject.hpp>
|
||||||
@@ -111,11 +111,6 @@ namespace Fig
|
|||||||
return IsDouble() || IsInt();
|
return IsDouble() || IsInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool IsObject() const
|
|
||||||
{
|
|
||||||
return (v_ & (SIGN_BIT | QNAN_MASK)) == (SIGN_BIT | QNAN_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool IsNull() const
|
[[nodiscard]] constexpr bool IsNull() const
|
||||||
{
|
{
|
||||||
return v_ == (QNAN_MASK | TAG_NULL);
|
return v_ == (QNAN_MASK | TAG_NULL);
|
||||||
@@ -126,6 +121,11 @@ namespace Fig
|
|||||||
return (v_ | 1) == (QNAN_MASK | TAG_TRUE);
|
return (v_ | 1) == (QNAN_MASK | TAG_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr bool IsObject() const
|
||||||
|
{
|
||||||
|
return (v_ & (SIGN_BIT | QNAN_MASK)) == (SIGN_BIT | QNAN_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
// 提取数据 (Unbox / As)
|
// 提取数据 (Unbox / As)
|
||||||
[[nodiscard]] constexpr double AsDouble() const
|
[[nodiscard]] constexpr double AsDouble() const
|
||||||
{
|
{
|
||||||
@@ -182,33 +182,7 @@ namespace Fig
|
|||||||
// 类函数
|
// 类函数
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr String ToString() const
|
constexpr String ToString() const;
|
||||||
{
|
|
||||||
if (IsNull())
|
|
||||||
{
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
else if (IsInt())
|
|
||||||
{
|
|
||||||
return std::to_string(AsInt());
|
|
||||||
}
|
|
||||||
else if (IsDouble())
|
|
||||||
{
|
|
||||||
return std::format("{}", AsDouble());
|
|
||||||
}
|
|
||||||
else if (IsBool())
|
|
||||||
{
|
|
||||||
return (AsBool() ? "true" : "false");
|
|
||||||
}
|
|
||||||
else if (IsObject())
|
|
||||||
{
|
|
||||||
return "Object"; // TODO: 分派
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "Unknow";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -223,15 +197,35 @@ namespace Fig
|
|||||||
Instance,
|
Instance,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Struct /* : public Object */; // 结构体基类的定义,前向声明
|
struct StructObject /* : public Object */; // 结构体基类的定义,前向声明
|
||||||
|
|
||||||
// Total 24 bytes size
|
// Total 24 bytes size
|
||||||
struct Object
|
struct Object
|
||||||
{
|
{
|
||||||
Object *next; // 8 bytes: gc链表
|
Object *next; // 8 bytes: gc链表
|
||||||
Struct *klass; // 8 bytes: 一切皆对象,父类指针
|
StructObject *klass; // 8 bytes: 一切皆对象,父类指针
|
||||||
ObjectType type; // 1 byte : 类型
|
ObjectType type; // 1 byte : 类型
|
||||||
bool isMarked = false; // 1 byte : gc标记
|
bool isMarked = false; // 1 byte : gc标记
|
||||||
// + 6 bytes padding
|
// + 6 bytes padding
|
||||||
|
|
||||||
|
constexpr bool isString() const
|
||||||
|
{
|
||||||
|
return type == ObjectType::String;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool isFunction() const
|
||||||
|
{
|
||||||
|
return type == ObjectType::Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool isStruct() const
|
||||||
|
{
|
||||||
|
return type == ObjectType::Struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool isInstance() const
|
||||||
|
{
|
||||||
|
return type == ObjectType::Instance;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace Fig
|
} // namespace Fig
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
@file src/Object/String.hpp
|
@file src/Object/StringObject.hpp
|
||||||
@brief 字符串对象标识
|
@brief 字符串对象标识
|
||||||
@author PuqiAR (im@puqiar.top)
|
@author PuqiAR (im@puqiar.top)
|
||||||
@date 2026-02-19
|
@date 2026-02-19
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
@file src/Object/Struct.hpp
|
@file src/Object/StructObject.hpp
|
||||||
@brief 结构体类型 Struct定义
|
@brief 结构体类型 StructObject 定义
|
||||||
@author PuqiAR (im@puqiar.top)
|
@author PuqiAR (im@puqiar.top)
|
||||||
@date 2026-02-19
|
@date 2026-02-19
|
||||||
*/
|
*/
|
||||||
@@ -166,6 +166,9 @@ namespace Fig
|
|||||||
ParsingIf,
|
ParsingIf,
|
||||||
ParsingWhile,
|
ParsingWhile,
|
||||||
ParsingFnDefStmt,
|
ParsingFnDefStmt,
|
||||||
|
ParsingReturn,
|
||||||
|
ParsingBreak,
|
||||||
|
ParsingContinue,
|
||||||
|
|
||||||
ParsingNamedTypeExpr,
|
ParsingNamedTypeExpr,
|
||||||
|
|
||||||
@@ -305,6 +308,9 @@ namespace Fig
|
|||||||
Result<DynArray<Param *>, Error> parseFnParams(); // 由 parseFnDefStmt或lambda调用
|
Result<DynArray<Param *>, Error> parseFnParams(); // 由 parseFnDefStmt或lambda调用
|
||||||
Result<FnDefStmt *, Error> parseFnDefStmt(bool); // 由 parseStatement调用, 当前token为 func
|
Result<FnDefStmt *, Error> parseFnDefStmt(bool); // 由 parseStatement调用, 当前token为 func
|
||||||
|
|
||||||
|
Result<ReturnStmt *, Error> parseReturnStmt(); // 由 parseStatement调用, 当前token为 return
|
||||||
|
// continue break直接由parseStatement一步解析
|
||||||
|
|
||||||
Result<Stmt *, Error> parseStatement();
|
Result<Stmt *, Error> parseStatement();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -357,7 +357,8 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (!currentToken().isIdentifier())
|
if (!currentToken().isIdentifier())
|
||||||
{
|
{
|
||||||
return std::unexpected(makeUnexpectTokenError("fn params", "param name", currentToken()));
|
return std::unexpected(
|
||||||
|
makeUnexpectTokenError("fn params", "param name", currentToken()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,13 +419,36 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
delete returnType;
|
delete returnType;
|
||||||
}
|
}
|
||||||
body = *bodyResult;
|
return std::unexpected(bodyResult.error());
|
||||||
}
|
}
|
||||||
|
body = *bodyResult;
|
||||||
|
|
||||||
FnDefStmt *fnDef = new FnDefStmt(isPublic, name, params, returnType, body, location);
|
FnDefStmt *fnDef = new FnDefStmt(isPublic, name, params, returnType, body, location);
|
||||||
return fnDef;
|
return fnDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<ReturnStmt *, Error>
|
||||||
|
Parser::parseReturnStmt() // 由 parseStatement调用, 当前token为 return
|
||||||
|
{
|
||||||
|
StateProtector p(this, {State::ParsingReturn});
|
||||||
|
|
||||||
|
SourceLocation location = makeSourceLocation(consumeToken()); // consume `return`
|
||||||
|
auto result = parseExpression();
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr *value = *result;
|
||||||
|
ReturnStmt *returnStmt = new ReturnStmt(value, location);
|
||||||
|
|
||||||
|
if (!match(TokenType::Semicolon))
|
||||||
|
{
|
||||||
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
|
}
|
||||||
|
return returnStmt;
|
||||||
|
}
|
||||||
|
|
||||||
Result<Stmt *, Error> Parser::parseStatement()
|
Result<Stmt *, Error> Parser::parseStatement()
|
||||||
{
|
{
|
||||||
StateProtector p(this, {State::Standby});
|
StateProtector p(this, {State::Standby});
|
||||||
@@ -471,6 +495,33 @@ namespace Fig
|
|||||||
return parseFnDefStmt(false);
|
return parseFnDefStmt(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentToken().type == TokenType::Return)
|
||||||
|
{
|
||||||
|
return parseReturnStmt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(TokenType::Break))
|
||||||
|
{
|
||||||
|
SourceLocation location = makeSourceLocation(prevToken());
|
||||||
|
if (!match(TokenType::Semicolon))
|
||||||
|
{
|
||||||
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
|
}
|
||||||
|
BreakStmt *breakStmt = new BreakStmt(location);
|
||||||
|
return breakStmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(TokenType::Continue))
|
||||||
|
{
|
||||||
|
SourceLocation location = makeSourceLocation(prevToken());
|
||||||
|
if (!match(TokenType::Semicolon))
|
||||||
|
{
|
||||||
|
return std::unexpected(makeExpectSemicolonError());
|
||||||
|
}
|
||||||
|
ContinueStmt *continueStmt = new ContinueStmt(location);
|
||||||
|
return continueStmt;
|
||||||
|
}
|
||||||
|
|
||||||
if (isEOF)
|
if (isEOF)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -9,6 +9,29 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
Result<TypeInfo *, Error> Analyzer::resolveType(TypeExpr *typeExpr)
|
||||||
|
{
|
||||||
|
NamedTypeExpr *nte = dynamic_cast<NamedTypeExpr *>(typeExpr);
|
||||||
|
TypeInfo *type = nullptr;
|
||||||
|
if (nte)
|
||||||
|
{
|
||||||
|
type = typeCtx.ResolveTypePath(nte->path);
|
||||||
|
if (!type)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
|
std::format("no such type `{}` exists", nte->toString()),
|
||||||
|
"none",
|
||||||
|
makeSourceLocation(typeExpr)));
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
Result<void, Error> Analyzer::analyzeVarDecl(VarDecl *stmt)
|
Result<void, Error> Analyzer::analyzeVarDecl(VarDecl *stmt)
|
||||||
{
|
{
|
||||||
auto sym = env.Resolve(stmt->name);
|
auto sym = env.Resolve(stmt->name);
|
||||||
@@ -20,7 +43,7 @@ namespace Fig
|
|||||||
makeSourceLocation(stmt)));
|
makeSourceLocation(stmt)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTag initType = TypeTag::Any;
|
TypeInfo *initType = typeCtx.GetNull();
|
||||||
if (stmt->initExpr)
|
if (stmt->initExpr)
|
||||||
{
|
{
|
||||||
const auto &res = analyzeExpr(stmt->initExpr);
|
const auto &res = analyzeExpr(stmt->initExpr);
|
||||||
@@ -31,23 +54,29 @@ namespace Fig
|
|||||||
initType = stmt->initExpr->resolvedType;
|
initType = stmt->initExpr->resolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTag declaredType = TypeTag::Any;
|
TypeInfo *declaredType = typeCtx.GetAny();
|
||||||
if (stmt->typeSpecifier)
|
if (stmt->typeSpecifier)
|
||||||
{
|
{
|
||||||
// TODO: 解析类型定义
|
auto result = resolveType(stmt->typeSpecifier);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
|
||||||
|
declaredType = *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt->isInfer)
|
if (stmt->isInfer)
|
||||||
{
|
{
|
||||||
declaredType = initType;
|
declaredType = initType;
|
||||||
}
|
}
|
||||||
else if (declaredType != TypeTag::Any && declaredType != initType)
|
else if (stmt->initExpr && declaredType != typeCtx.GetAny() && declaredType != initType)
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
std::format("cannot assign type `{}` to variable {} which speicifer type is '{}'",
|
std::format("cannot assign type `{}` to variable {} which speicifer type is '{}'",
|
||||||
magic_enum::enum_name(initType),
|
initType->name,
|
||||||
stmt->name,
|
stmt->name,
|
||||||
magic_enum::enum_name(declaredType)),
|
declaredType->name),
|
||||||
"none",
|
"none",
|
||||||
makeSourceLocation(stmt->initExpr)));
|
makeSourceLocation(stmt->initExpr)));
|
||||||
}
|
}
|
||||||
@@ -62,11 +91,12 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
return condRes;
|
return condRes;
|
||||||
}
|
}
|
||||||
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
|
if (stmt->cond->resolvedType != typeCtx.GetAny()
|
||||||
|
&& stmt->cond->resolvedType != typeCtx.GetBool())
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
std::format("if condition must be boolean, got `{}`",
|
std::format(
|
||||||
magic_enum::enum_name(stmt->cond->resolvedType)),
|
"if condition must be boolean, got `{}`", stmt->cond->resolvedType->name),
|
||||||
"ensure condition is boolean",
|
"ensure condition is boolean",
|
||||||
makeSourceLocation(stmt->cond)));
|
makeSourceLocation(stmt->cond)));
|
||||||
}
|
}
|
||||||
@@ -79,12 +109,12 @@ namespace Fig
|
|||||||
for (ElseIfStmt *elif : stmt->elifs)
|
for (ElseIfStmt *elif : stmt->elifs)
|
||||||
{
|
{
|
||||||
auto condRes = analyzeExpr(elif->cond);
|
auto condRes = analyzeExpr(elif->cond);
|
||||||
if (elif->cond->resolvedType != TypeTag::Any
|
if (elif->cond->resolvedType != typeCtx.GetAny()
|
||||||
&& elif->cond->resolvedType != TypeTag::Bool)
|
&& elif->cond->resolvedType != typeCtx.GetBool())
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
std::format("else if condition must be boolean, got `{}`",
|
std::format("else if condition must be boolean, got `{}`",
|
||||||
magic_enum::enum_name(elif->cond->resolvedType)),
|
elif->cond->resolvedType->name),
|
||||||
"ensure condition is boolean",
|
"ensure condition is boolean",
|
||||||
makeSourceLocation(elif->cond)));
|
makeSourceLocation(elif->cond)));
|
||||||
}
|
}
|
||||||
@@ -114,11 +144,12 @@ namespace Fig
|
|||||||
return condRes;
|
return condRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool)
|
if (stmt->cond->resolvedType != typeCtx.GetAny()
|
||||||
|
&& stmt->cond->resolvedType != typeCtx.GetBool())
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
std::format("while condition must be boolean, got `{}`",
|
std::format(
|
||||||
magic_enum::enum_name(stmt->cond->resolvedType)),
|
"while condition must be boolean, got `{}`", stmt->cond->resolvedType->name),
|
||||||
"ensure condition is boolean",
|
"ensure condition is boolean",
|
||||||
makeSourceLocation(stmt->cond)));
|
makeSourceLocation(stmt->cond)));
|
||||||
}
|
}
|
||||||
@@ -131,6 +162,138 @@ namespace Fig
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<void, Error> Analyzer::analyzeFnDefStmt(FnDefStmt *stmt)
|
||||||
|
{
|
||||||
|
auto sym = env.Resolve(stmt->name);
|
||||||
|
if (sym != std::nullopt && sym->depth == env.GetDepth())
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::RedeclarationError,
|
||||||
|
std::format("function `{}` has already defined in this scope", stmt->name),
|
||||||
|
"change its name",
|
||||||
|
makeSourceLocation(stmt)));
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt->resolvedReturnType = typeCtx.GetAny(); // 默认Any
|
||||||
|
if (stmt->returnType)
|
||||||
|
{
|
||||||
|
auto result = resolveType(stmt->returnType);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
stmt->resolvedReturnType = *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt->localId = env.Define(stmt->name,
|
||||||
|
typeCtx.GetFunction(),
|
||||||
|
stmt->isPublic,
|
||||||
|
true); // 函数定义语句定义的函数为常量
|
||||||
|
|
||||||
|
env.EnterFunction();
|
||||||
|
env.EnterScope();
|
||||||
|
|
||||||
|
PosParam *lastDefaultValueP = nullptr;
|
||||||
|
for (Param *p : stmt->params)
|
||||||
|
{
|
||||||
|
PosParam *posParam = dynamic_cast<PosParam *>(p);
|
||||||
|
if (posParam)
|
||||||
|
{
|
||||||
|
posParam->resolvedType = typeCtx.GetAny();
|
||||||
|
if (posParam->type)
|
||||||
|
{
|
||||||
|
auto result = resolveType(posParam->type);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::unexpected(result.error());
|
||||||
|
}
|
||||||
|
posParam->resolvedType = *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!posParam->defaultValue && lastDefaultValueP)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
|
std::format("no-default parameter `{}` follows default parameter '{}'",
|
||||||
|
posParam->name,
|
||||||
|
lastDefaultValueP->name),
|
||||||
|
"reorder parameters",
|
||||||
|
posParam->location));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (posParam->defaultValue)
|
||||||
|
{
|
||||||
|
lastDefaultValueP = posParam;
|
||||||
|
|
||||||
|
auto result = analyzeExpr(posParam->defaultValue);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (posParam->resolvedType != typeCtx.GetAny()
|
||||||
|
&& posParam->defaultValue->resolvedType != posParam->resolvedType)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
|
std::format(
|
||||||
|
"in function '{}', parameter '{}' expects type '{}', but got default value type `{}`",
|
||||||
|
stmt->name,
|
||||||
|
posParam->name,
|
||||||
|
posParam->resolvedType->name,
|
||||||
|
posParam->defaultValue->resolvedType->name),
|
||||||
|
"none",
|
||||||
|
makeSourceLocation(posParam->defaultValue)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
posParam->localId =
|
||||||
|
env.Define(posParam->name, posParam->resolvedType, false, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ... 其他参数解析
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnTypeProtector p(this, stmt->resolvedReturnType);
|
||||||
|
|
||||||
|
auto bodyRes = analyzeStmt(stmt->body);
|
||||||
|
|
||||||
|
env.LeaveScope();
|
||||||
|
env.LeaveFunction();
|
||||||
|
|
||||||
|
if (!bodyRes)
|
||||||
|
{
|
||||||
|
return bodyRes;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void, Error> Analyzer::analyzeReturnStmt(ReturnStmt *stmt)
|
||||||
|
{
|
||||||
|
if (!currentReturnType)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
|
"return outside function",
|
||||||
|
"remove `return ...`",
|
||||||
|
makeSourceLocation(stmt)));
|
||||||
|
}
|
||||||
|
auto result = analyzeExpr(stmt->value);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo *valueType = stmt->value->resolvedType;
|
||||||
|
if (currentReturnType != typeCtx.GetAny() && currentReturnType != valueType)
|
||||||
|
{
|
||||||
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
|
std::format("return type mismatch: expects '{}', got `{}`",
|
||||||
|
currentReturnType->name,
|
||||||
|
stmt->value->resolvedType->name),
|
||||||
|
"none",
|
||||||
|
makeSourceLocation(stmt->value)));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Result<void, Error> Analyzer::analyzeIdentiExpr(IdentiExpr *expr)
|
Result<void, Error> Analyzer::analyzeIdentiExpr(IdentiExpr *expr)
|
||||||
{
|
{
|
||||||
auto sym = env.Resolve(expr->name);
|
auto sym = env.Resolve(expr->name);
|
||||||
@@ -146,7 +309,7 @@ namespace Fig
|
|||||||
|
|
||||||
expr->resolvedType = sym->type;
|
expr->resolvedType = sym->type;
|
||||||
expr->resolvedDepth = sym->depth;
|
expr->resolvedDepth = sym->depth;
|
||||||
expr->isGlobal = (sym->depth == 0);
|
expr->isGlobal = (sym->depth == 0);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -161,16 +324,16 @@ namespace Fig
|
|||||||
if (!resR)
|
if (!resR)
|
||||||
return std::unexpected(resR.error());
|
return std::unexpected(resR.error());
|
||||||
|
|
||||||
TypeTag lType = expr->left->resolvedType;
|
TypeInfo *lType = expr->left->resolvedType;
|
||||||
TypeTag rType = expr->right->resolvedType;
|
TypeInfo *rType = expr->right->resolvedType;
|
||||||
|
|
||||||
switch (expr->op)
|
switch (expr->op)
|
||||||
{
|
{
|
||||||
// 算术族 (+, -, *, /, **)
|
// 算术族 (+, -, *, /, **)
|
||||||
case BinaryOperator::Add:
|
case BinaryOperator::Add:
|
||||||
if (lType == TypeTag::String && rType == TypeTag::String)
|
if (lType == typeCtx.GetString() && rType == typeCtx.GetString())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::String;
|
expr->resolvedType = typeCtx.GetString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@@ -178,18 +341,18 @@ namespace Fig
|
|||||||
case BinaryOperator::Multiply:
|
case BinaryOperator::Multiply:
|
||||||
case BinaryOperator::Divide:
|
case BinaryOperator::Divide:
|
||||||
case BinaryOperator::Power:
|
case BinaryOperator::Power:
|
||||||
if (lType == TypeTag::Int && rType == TypeTag::Int)
|
if (lType == typeCtx.GetInt() && rType == typeCtx.GetInt())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Int;
|
expr->resolvedType = typeCtx.GetInt();
|
||||||
}
|
}
|
||||||
else if ((lType == TypeTag::Int || lType == TypeTag::Double)
|
else if ((lType == typeCtx.GetInt() || lType == typeCtx.GetDouble())
|
||||||
&& (rType == TypeTag::Int || rType == TypeTag::Double))
|
&& (rType == typeCtx.GetInt() || rType == typeCtx.GetDouble()))
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Double;
|
expr->resolvedType = typeCtx.GetDouble();
|
||||||
}
|
}
|
||||||
else if (lType == TypeTag::Any || rType == TypeTag::Any)
|
else if (lType == typeCtx.GetAny() || rType == typeCtx.GetAny())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Any;
|
expr->resolvedType = typeCtx.GetAny();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -207,13 +370,13 @@ namespace Fig
|
|||||||
case BinaryOperator::BitXor:
|
case BinaryOperator::BitXor:
|
||||||
case BinaryOperator::ShiftLeft:
|
case BinaryOperator::ShiftLeft:
|
||||||
case BinaryOperator::ShiftRight:
|
case BinaryOperator::ShiftRight:
|
||||||
if (lType == TypeTag::Int && rType == TypeTag::Int)
|
if (lType == typeCtx.GetInt() && rType == typeCtx.GetInt())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Int;
|
expr->resolvedType = typeCtx.GetInt();
|
||||||
}
|
}
|
||||||
else if (lType == TypeTag::Any || rType == TypeTag::Any)
|
else if (lType == typeCtx.GetAny() || rType == typeCtx.GetAny())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Any;
|
expr->resolvedType = typeCtx.GetAny();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -224,7 +387,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 比较族 (==, !=, <, >, <=, >=)
|
// 比较族 (==, !=, <, >, <=, >=)
|
||||||
|
|
||||||
case BinaryOperator::Equal:
|
case BinaryOperator::Equal:
|
||||||
case BinaryOperator::NotEqual:
|
case BinaryOperator::NotEqual:
|
||||||
@@ -233,11 +396,11 @@ namespace Fig
|
|||||||
case BinaryOperator::LessEqual:
|
case BinaryOperator::LessEqual:
|
||||||
case BinaryOperator::GreaterEqual:
|
case BinaryOperator::GreaterEqual:
|
||||||
case BinaryOperator::Is:
|
case BinaryOperator::Is:
|
||||||
if (lType != TypeTag::Any && rType != TypeTag::Any
|
if (lType != typeCtx.GetAny() && rType != typeCtx.GetAny()
|
||||||
&& lType != rType) // lType == rType放行
|
&& lType != rType) // lType == rType放行
|
||||||
{
|
{
|
||||||
if (!((lType == TypeTag::Int && rType == TypeTag::Double)
|
if (!((lType == typeCtx.GetInt() && rType == typeCtx.GetDouble())
|
||||||
|| (lType == TypeTag::Double && rType == TypeTag::Int)))
|
|| (lType == typeCtx.GetDouble() && rType == typeCtx.GetInt())))
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
"cannot compare different types",
|
"cannot compare different types",
|
||||||
@@ -250,19 +413,19 @@ namespace Fig
|
|||||||
// 如 1.2 is Int --> false
|
// 如 1.2 is Int --> false
|
||||||
// 1 is Int --> true
|
// 1 is Int --> true
|
||||||
|
|
||||||
expr->resolvedType = TypeTag::Bool;
|
expr->resolvedType = typeCtx.GetBool();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 逻辑族 (&&, ||)
|
// 逻辑族 (&&, ||)
|
||||||
case BinaryOperator::LogicalAnd:
|
case BinaryOperator::LogicalAnd:
|
||||||
case BinaryOperator::LogicalOr:
|
case BinaryOperator::LogicalOr:
|
||||||
if (lType == TypeTag::Bool && rType == TypeTag::Bool)
|
if (lType == typeCtx.GetBool() && rType == typeCtx.GetBool())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Bool;
|
expr->resolvedType = typeCtx.GetBool();
|
||||||
}
|
}
|
||||||
else if (lType == TypeTag::Any || rType == TypeTag::Any)
|
else if (lType == typeCtx.GetAny() || rType == typeCtx.GetAny())
|
||||||
{
|
{
|
||||||
expr->resolvedType = TypeTag::Bool;
|
expr->resolvedType = typeCtx.GetBool();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -294,9 +457,9 @@ namespace Fig
|
|||||||
// 类型匹配拦截 (纯赋值)
|
// 类型匹配拦截 (纯赋值)
|
||||||
if (expr->op == BinaryOperator::Assign)
|
if (expr->op == BinaryOperator::Assign)
|
||||||
{
|
{
|
||||||
if (lType != TypeTag::Any && rType != TypeTag::Any && lType != rType)
|
if (lType != typeCtx.GetAny() && rType != typeCtx.GetAny() && lType != rType)
|
||||||
{
|
{
|
||||||
if (!(lType == TypeTag::Double && rType == TypeTag::Int))
|
if (!(lType == typeCtx.GetDouble() && rType == typeCtx.GetInt()))
|
||||||
{ // 允许 Int 赋给 Double
|
{ // 允许 Int 赋给 Double
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
"cannot assign value to variable of different type",
|
"cannot assign value to variable of different type",
|
||||||
@@ -310,7 +473,7 @@ namespace Fig
|
|||||||
|
|
||||||
// 成员访问 (.)
|
// 成员访问 (.)
|
||||||
case BinaryOperator::MemberAccess:
|
case BinaryOperator::MemberAccess:
|
||||||
if (lType != TypeTag::Struct && lType != TypeTag::Any)
|
if (lType != typeCtx.GetStruct() && lType != typeCtx.GetAny())
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(ErrorType::TypeError,
|
return std::unexpected(Error(ErrorType::TypeError,
|
||||||
"member access requires a Struct object",
|
"member access requires a Struct object",
|
||||||
@@ -319,14 +482,13 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (expr->right->type != AstType::IdentiExpr)
|
if (expr->right->type != AstType::IdentiExpr)
|
||||||
{
|
{
|
||||||
return std::unexpected(Error(
|
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||||
ErrorType::SyntaxError,
|
std::format("expect field name after member access '.', got {}",
|
||||||
std::format("expect field name after member access '.', got {}", expr->right->toString()),
|
expr->right->toString()),
|
||||||
"none",
|
"none",
|
||||||
makeSourceLocation(expr->right)
|
makeSourceLocation(expr->right)));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
expr->resolvedType = TypeTag::Any;
|
expr->resolvedType = typeCtx.GetAny();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -373,6 +535,14 @@ namespace Fig
|
|||||||
return analyzeWhileStmt(static_cast<WhileStmt *>(stmt));
|
return analyzeWhileStmt(static_cast<WhileStmt *>(stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AstType::FnDefStmt: {
|
||||||
|
return analyzeFnDefStmt(static_cast<FnDefStmt *>(stmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
case AstType::ReturnStmt: {
|
||||||
|
return analyzeReturnStmt(static_cast<ReturnStmt *>(stmt));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 其他语句分析
|
// TODO: 其他语句分析
|
||||||
|
|
||||||
// default:
|
// default:
|
||||||
@@ -396,30 +566,30 @@ namespace Fig
|
|||||||
switch (lit->token.type)
|
switch (lit->token.type)
|
||||||
{
|
{
|
||||||
case TokenType::LiteralTrue:
|
case TokenType::LiteralTrue:
|
||||||
case TokenType::LiteralFalse: lit->resolvedType = TypeTag::Bool; break;
|
case TokenType::LiteralFalse: lit->resolvedType = typeCtx.GetBool(); break;
|
||||||
|
|
||||||
case TokenType::LiteralNull: lit->resolvedType = TypeTag::Null; break;
|
case TokenType::LiteralNull: lit->resolvedType = typeCtx.GetNull(); break;
|
||||||
|
|
||||||
case TokenType::LiteralNumber: {
|
case TokenType::LiteralNumber: {
|
||||||
const String &lexeme = manager.GetSub(lit->token.index, lit->token.length);
|
const String &lexeme = manager.GetSub(lit->token.index, lit->token.length);
|
||||||
if (lexeme.contains(U'.') || lexeme.contains(U'e'))
|
if (lexeme.contains(U'.') || lexeme.contains(U'e'))
|
||||||
{
|
{
|
||||||
lit->resolvedType = TypeTag::Double;
|
lit->resolvedType = typeCtx.GetDouble();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lit->resolvedType = TypeTag::Int;
|
lit->resolvedType = typeCtx.GetInt();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TokenType::LiteralString: {
|
case TokenType::LiteralString: {
|
||||||
lit->resolvedType = TypeTag::String;
|
lit->resolvedType = typeCtx.GetString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
lit->resolvedType = TypeTag::Any;
|
lit->resolvedType = typeCtx.GetAny();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,7 +605,7 @@ namespace Fig
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
// 对于还没实现的表达式,默认降级为 Any 防止崩溃
|
// 对于还没实现的表达式,默认降级为 Any 防止崩溃
|
||||||
expr->resolvedType = TypeTag::Any;
|
expr->resolvedType = typeCtx.GetAny();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,27 +10,50 @@
|
|||||||
#include <Sema/Environment.hpp>
|
#include <Sema/Environment.hpp>
|
||||||
#include <Sema/Type.hpp>
|
#include <Sema/Type.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <Ast/Ast.hpp>
|
#include <Ast/Ast.hpp>
|
||||||
#include <Deps/Deps.hpp>
|
#include <Deps/Deps.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
class Analyzer
|
class Analyzer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Environment env;
|
Environment env;
|
||||||
SourceManager &manager;
|
SourceManager &manager;
|
||||||
|
|
||||||
SourceLocation makeSourceLocation(AstNode *ast, std::source_location loc = std::source_location::current())
|
TypeContext typeCtx;
|
||||||
|
|
||||||
|
TypeInfo *currentReturnType = nullptr; // 正在分析的函数,预期返回类型
|
||||||
|
|
||||||
|
struct ReturnTypeProtector
|
||||||
{
|
{
|
||||||
return SourceLocation(
|
Analyzer *analyzer;
|
||||||
ast->location.sp,
|
TypeInfo *prevCurrentReturnType;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ReturnTypeProtector(Analyzer *_analyzer, TypeInfo *current) :
|
||||||
|
analyzer(_analyzer), prevCurrentReturnType(_analyzer->currentReturnType)
|
||||||
|
{
|
||||||
|
analyzer->currentReturnType = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ReturnTypeProtector()
|
||||||
|
{
|
||||||
|
analyzer->currentReturnType = prevCurrentReturnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnTypeProtector(const ReturnTypeProtector &) = delete;
|
||||||
|
ReturnTypeProtector &operator=(const ReturnTypeProtector &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SourceLocation makeSourceLocation(
|
||||||
|
AstNode *ast, std::source_location loc = std::source_location::current())
|
||||||
|
{
|
||||||
|
return SourceLocation(ast->location.sp,
|
||||||
ast->location.fileName,
|
ast->location.fileName,
|
||||||
"[internal analyzer]",
|
"[internal analyzer]",
|
||||||
loc.function_name()
|
loc.function_name());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidLvalue(Expr *expr)
|
bool isValidLvalue(Expr *expr)
|
||||||
@@ -54,18 +77,23 @@ namespace Fig
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<TypeInfo *, Error> resolveType(TypeExpr *);
|
||||||
|
|
||||||
Result<void, Error> analyzeVarDecl(VarDecl *);
|
Result<void, Error> analyzeVarDecl(VarDecl *);
|
||||||
Result<void, Error> analyzeIfStmt(IfStmt *);
|
Result<void, Error> analyzeIfStmt(IfStmt *);
|
||||||
Result<void, Error> analyzeWhileStmt(WhileStmt *);
|
Result<void, Error> analyzeWhileStmt(WhileStmt *);
|
||||||
|
Result<void, Error> analyzeFnDefStmt(FnDefStmt *);
|
||||||
|
Result<void, Error> analyzeReturnStmt(ReturnStmt *);
|
||||||
|
|
||||||
Result<void, Error> analyzeIdentiExpr(IdentiExpr *);
|
Result<void, Error> analyzeIdentiExpr(IdentiExpr *);
|
||||||
Result<void, Error> analyzeInfixExpr(InfixExpr *);
|
Result<void, Error> analyzeInfixExpr(InfixExpr *);
|
||||||
|
|
||||||
Result<void, Error> analyzeStmt(Stmt *);
|
Result<void, Error> analyzeStmt(Stmt *);
|
||||||
Result<void, Error> analyzeExpr(Expr *);
|
Result<void, Error> analyzeExpr(Expr *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Result<void, Error> Analyze(Program *);
|
Result<void, Error> Analyze(Program *);
|
||||||
|
|
||||||
Analyzer(SourceManager &_manager) : manager(_manager) {}
|
Analyzer(SourceManager &_manager) : manager(_manager), typeCtx() {}
|
||||||
};
|
};
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -19,11 +19,11 @@ namespace Fig
|
|||||||
// 记录在 Analyzer 中的符号元数据
|
// 记录在 Analyzer 中的符号元数据
|
||||||
struct Symbol
|
struct Symbol
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
TypeTag type;
|
TypeInfo *type;
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
int depth; // 词法作用域深度
|
int depth; // 词法作用域深度
|
||||||
bool isConstant; // 是否是 const 声明的不可变常量 (用于报错: 尝试修改常量)
|
bool isConstant; // 是否是 const 声明的不可变常量 (用于报错: 尝试修改常量)
|
||||||
|
|
||||||
int localId = -1; // Analyzer 虚拟槽位分配
|
int localId = -1; // Analyzer 虚拟槽位分配
|
||||||
};
|
};
|
||||||
@@ -111,7 +111,7 @@ namespace Fig
|
|||||||
// 符号操作
|
// 符号操作
|
||||||
|
|
||||||
// 注册符号, 返回分配的 localId。调用前内部执行同级作用域重定义断言
|
// 注册符号, 返回分配的 localId。调用前内部执行同级作用域重定义断言
|
||||||
int Define(const String &name, TypeTag type, bool isPublic, bool isConst)
|
int Define(const String &name, TypeInfo *type, bool isPublic, bool isConst)
|
||||||
{
|
{
|
||||||
for (auto it = symbols.rbegin(); it != symbols.rend(); ++it)
|
for (auto it = symbols.rbegin(); it != symbols.rend(); ++it)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
/*!
|
/*!
|
||||||
@file src/Sema/Type.hpp
|
@file src/Sema/Type.hpp
|
||||||
@brief 前端类型检查的类型定义
|
@brief 前端类型检查的类型定义和类型驻留池
|
||||||
@author PuqiAR (im@puqiar.top)
|
@author PuqiAR (im@puqiar.top)
|
||||||
@date 2026-02-23
|
@date 2026-02-23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Deps/Deps.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
@@ -23,6 +24,113 @@ namespace Fig
|
|||||||
Struct,
|
Struct,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: 复杂类型的推导(泛型,结构体)
|
struct TypeInfo
|
||||||
// 添加 TypeInfo 结构体,目前先用 TypeTag
|
{
|
||||||
};
|
TypeTag tag;
|
||||||
|
String name; // 完整路径序列化, 如 Int, std.file.File
|
||||||
|
|
||||||
|
bool isAny() const
|
||||||
|
{
|
||||||
|
return tag == TypeTag::Any;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全局唯一类型驻留池
|
||||||
|
class TypeContext
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DynArray<TypeInfo *> allTypes;
|
||||||
|
|
||||||
|
// 缓存
|
||||||
|
TypeInfo *typeAny;
|
||||||
|
TypeInfo *typeNull;
|
||||||
|
TypeInfo *typeInt;
|
||||||
|
TypeInfo *typeDouble;
|
||||||
|
TypeInfo *typeBool;
|
||||||
|
TypeInfo *typeString;
|
||||||
|
TypeInfo *typeFunction;
|
||||||
|
TypeInfo *typeStruct;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TypeInfo *GetAny()
|
||||||
|
{
|
||||||
|
return typeAny;
|
||||||
|
}
|
||||||
|
TypeInfo *GetNull()
|
||||||
|
{
|
||||||
|
return typeNull;
|
||||||
|
}
|
||||||
|
TypeInfo *GetInt()
|
||||||
|
{
|
||||||
|
return typeInt;
|
||||||
|
}
|
||||||
|
TypeInfo *GetDouble()
|
||||||
|
{
|
||||||
|
return typeDouble;
|
||||||
|
}
|
||||||
|
TypeInfo *GetBool()
|
||||||
|
{
|
||||||
|
return typeBool;
|
||||||
|
}
|
||||||
|
TypeInfo *GetString()
|
||||||
|
{
|
||||||
|
return typeString;
|
||||||
|
}
|
||||||
|
TypeInfo *GetFunction()
|
||||||
|
{
|
||||||
|
return typeFunction;
|
||||||
|
}
|
||||||
|
TypeInfo *GetStruct()
|
||||||
|
{
|
||||||
|
return typeStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo *ResolveTypePath(const String &fullName)
|
||||||
|
{
|
||||||
|
for (auto *t : allTypes)
|
||||||
|
{
|
||||||
|
if (t->name == fullName)
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return nullptr; // 没找到该类型
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo *ResolveTypePath(const DynArray<String> &path)
|
||||||
|
{
|
||||||
|
// TODO: 支持Module 系统, 查 Module 的导出表
|
||||||
|
String fullName = path.empty() ? "" : path[0];
|
||||||
|
for (size_t i = 1; i < path.size(); ++i)
|
||||||
|
{
|
||||||
|
fullName += "." + path[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResolveTypePath(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TypeContext()
|
||||||
|
{
|
||||||
|
for (TypeInfo *t : allTypes)
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeContext()
|
||||||
|
{
|
||||||
|
typeAny = createBuiltin(TypeTag::Any, "Any");
|
||||||
|
typeNull = createBuiltin(TypeTag::Null, "Null");
|
||||||
|
typeInt = createBuiltin(TypeTag::Int, "Int");
|
||||||
|
typeDouble = createBuiltin(TypeTag::Double, "Double");
|
||||||
|
typeBool = createBuiltin(TypeTag::Bool, "Bool");
|
||||||
|
typeString = createBuiltin(TypeTag::String, "String");
|
||||||
|
typeFunction = createBuiltin(TypeTag::Function, "Function");
|
||||||
|
typeStruct = createBuiltin(TypeTag::Struct, "Struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TypeInfo *createBuiltin(TypeTag tag, String name)
|
||||||
|
{
|
||||||
|
TypeInfo *t = new TypeInfo{tag, std::move(name)};
|
||||||
|
allTypes.push_back(t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}; // namespace Fig
|
||||||
Reference in New Issue
Block a user