polserver/pol-core/bscript/compiler/ast/ClassDeclaration.cpp
Kevin Eady ddc1b5d26b
Add Escript support for uninitialized class functions (#808)
* update grammar

* AST nodes and test

* Address self-review comments
- Replace `super` comment with something more explanatory
- Rename `make_user_function`

* add class analysis for uninit functions

* fix ast test after disallowing static uninit funcs

* use std::ranges::find_if

* add tests

* use SUPER constant; add test

* Remove unreachable code leftover from #809

Since #809, the super function is only generated for a class when
registering a parent class, and therefore it will always have a body. A
"No base class defines a constructor" will only occur if super was never
generated, and is handled in the "No function linked through
FunctionResolver" section of semantic analyzer.

* Address review comments
- use std::ranges::move instead of move iterators
- use std::is_same_v<> vs std::is_same<>::value
- use switch vs chained ternary conditionals

* update escript guide, create tests that are in escript guide

* add core-changes

* Error on uninit and defined constructor

* Move methods' FunctionLink construction to builder

This allows the error message for the uninit function to have a "See
Also" that point to the defined function.

* Move error checks for uninit and defined functions

These semantic checks should be in the ... SemanticAnalyzer.

* fix typo in core-changes
2025-09-05 23:23:59 +02:00

71 lines
2.4 KiB
C++

#include "ClassDeclaration.h"
#include "bscript/compiler/ast/ClassParameterDeclaration.h"
#include "bscript/compiler/ast/ClassParameterList.h"
#include "bscript/compiler/ast/NodeVisitor.h"
#include "bscript/compiler/ast/UninitializedFunctionDeclaration.h"
#include "bscript/compiler/ast/UserFunction.h"
#include "bscript/compiler/file/SourceFileIdentifier.h"
#include "bscript/compiler/model/ClassLink.h"
#include "bscript/compiler/model/FunctionLink.h"
#include <ranges>
namespace Pol::Bscript::Compiler
{
ClassDeclaration::ClassDeclaration(
const SourceLocation& source_location, std::string name,
std::unique_ptr<ClassParameterList> parameters, std::shared_ptr<FunctionLink> constructor_link,
ClassMethodMap methods, Node* class_body,
std::vector<std::shared_ptr<ClassLink>> base_class_links,
std::vector<std::unique_ptr<UninitializedFunctionDeclaration>> uninit_functions )
: Node( source_location ),
name( std::move( name ) ),
methods( std::move( methods ) ),
class_body( class_body ),
constructor_link( std::move( constructor_link ) ),
base_class_links( std::move( base_class_links ) )
{
children.reserve( 1 + uninit_functions.size() );
children.push_back( std::move( parameters ) );
std::ranges::move( uninit_functions, std::back_inserter( children ) );
}
void ClassDeclaration::accept( NodeVisitor& visitor )
{
visitor.visit_class_declaration( *this );
}
void ClassDeclaration::describe_to( std::string& w ) const
{
fmt::format_to( std::back_inserter( w ), "class-declaration({})", name );
}
std::vector<std::reference_wrapper<ClassParameterDeclaration>> ClassDeclaration::parameters()
{
std::vector<std::reference_wrapper<ClassParameterDeclaration>> params;
child<ClassParameterList>( 0 ).get_children<ClassParameterDeclaration>( params );
return params;
}
std::vector<std::reference_wrapper<UninitializedFunctionDeclaration>>
ClassDeclaration::uninit_functions()
{
std::vector<std::reference_wrapper<UninitializedFunctionDeclaration>> params;
// The first child is a `ClassParameterList`, so skip it.
for ( auto& param : children | std::views::drop( 1 ) )
{
params.emplace_back( *static_cast<UninitializedFunctionDeclaration*>( param.get() ) );
}
return params;
}
std::string ClassDeclaration::type_tag() const
{
return fmt::format( "{}@{}", name, source_location.source_file_identifier->pathname );
}
} // namespace Pol::Bscript::Compiler