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.
This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
// 极简语义分析:只检查变量是否先声明再使用。
// 如需扩展,可在此基础上加入:
// - 常量折叠/类型检查
// - 函数签名/参数数量校验
// - 控制流相关检查( return 覆盖、break/continue 合法性等)
# include "sem/Sema.h"
# include <stdexcept>
# include <string>
# include <unordered_set>
# include "ast/AstNodes.h"
# include "sem/SymbolTable.h"
namespace {
class SemaVisitor {
public :
explicit SemaVisitor ( SymbolTable & table ) : table_ ( table ) { }
void CheckBlock ( const ast : : Block & block ) {
for ( const auto & item : block . items ) {
if ( auto decl = dynamic_cast < ast : : VarDecl * > ( item . get ( ) ) ) {
table_ . Add ( decl - > name ) ;
if ( decl - > init ) CheckExpr ( * decl - > init ) ;
continue ;
}
if ( auto ret = dynamic_cast < ast : : ReturnStmt * > ( item . get ( ) ) ) {
CheckExpr ( * ret - > value ) ;
}
}
}
void CheckExpr ( const ast : : Expr & expr ) {
if ( auto var = dynamic_cast < const ast : : VarExpr * > ( & expr ) ) {
if ( ! table_ . Contains ( var - > name ) ) {
throw std : : runtime_error ( " [sema] 使用了未定义的变量: " + var - > name ) ;
}
} else if ( auto bin = dynamic_cast < const ast : : BinaryExpr * > ( & expr ) ) {
CheckExpr ( * bin - > lhs ) ;
CheckExpr ( * bin - > rhs ) ;
}
}
private :
SymbolTable & table_ ;
} ;
} // namespace
std : : shared_ptr < ast : : CompUnit > RunSema ( std : : shared_ptr < ast : : CompUnit > ast ) {
if ( ! ast | | ! ast - > func | | ! ast - > func - > body ) return ast ;
SymbolTable table ;
SemaVisitor visitor ( table ) ;
visitor . CheckBlock ( * ast - > func - > body ) ;
return ast ;
}