2026-07-25 23:01:18 +02:00
|
|
|
#include "bscript/compiler/astbuilder/SourceFileProcessor.h"
|
2020-08-18 23:32:57 -07:00
|
|
|
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/Profile.h"
|
|
|
|
|
#include "bscript/compiler/Report.h"
|
2024-08-12 21:59:31 +02:00
|
|
|
#include "bscript/compiler/ast/ClassBody.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/ast/ConstDeclaration.h"
|
|
|
|
|
#include "bscript/compiler/ast/Program.h"
|
|
|
|
|
#include "bscript/compiler/ast/Statement.h"
|
|
|
|
|
#include "bscript/compiler/ast/TopLevelStatements.h"
|
2024-08-11 23:01:38 +02:00
|
|
|
#include "bscript/compiler/astbuilder/AvailableParseTree.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/astbuilder/BuilderWorkspace.h"
|
2024-08-11 23:01:38 +02:00
|
|
|
#include "bscript/compiler/astbuilder/FunctionResolver.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/astbuilder/ModuleProcessor.h"
|
|
|
|
|
#include "bscript/compiler/file/SourceFile.h"
|
|
|
|
|
#include "bscript/compiler/file/SourceFileCache.h"
|
|
|
|
|
#include "bscript/compiler/file/SourceFileIdentifier.h"
|
|
|
|
|
#include "bscript/compiler/model/CompilerWorkspace.h"
|
2024-01-10 18:29:10 +01:00
|
|
|
#include "clib/fileutil.h"
|
|
|
|
|
#include "clib/logfacility.h"
|
|
|
|
|
#include "clib/timer.h"
|
2026-07-25 23:01:18 +02:00
|
|
|
#include "bscript/compilercfg.h"
|
2020-09-09 19:10:51 -07:00
|
|
|
#include "plib/pkg.h"
|
2020-08-18 23:32:57 -07:00
|
|
|
|
|
|
|
|
using EscriptGrammar::EscriptParser;
|
|
|
|
|
|
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
|
|
|
{
|
2021-03-06 01:39:26 +01:00
|
|
|
std::string getpathof( const std::string& fname );
|
|
|
|
|
|
2020-08-18 23:32:57 -07:00
|
|
|
SourceFileProcessor::SourceFileProcessor( const SourceFileIdentifier& source_file_identifier,
|
2020-09-13 00:41:45 -07:00
|
|
|
BuilderWorkspace& workspace, bool is_src,
|
|
|
|
|
UserFunctionInclusion user_function_inclusion )
|
2024-01-10 18:29:10 +01:00
|
|
|
: profile( workspace.profile ),
|
|
|
|
|
report( workspace.report ),
|
|
|
|
|
source_file_identifier( source_file_identifier ),
|
|
|
|
|
workspace( workspace ),
|
|
|
|
|
tree_builder( source_file_identifier, workspace ),
|
|
|
|
|
is_src( is_src ),
|
|
|
|
|
user_function_inclusion( user_function_inclusion )
|
2020-08-18 23:32:57 -07:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-23 15:01:39 -07:00
|
|
|
void SourceFileProcessor::use_module( const std::string& module_name,
|
|
|
|
|
SourceLocation& including_location,
|
|
|
|
|
long long* micros_counted )
|
|
|
|
|
{
|
2024-03-16 00:08:06 +01:00
|
|
|
std::string pathname =
|
|
|
|
|
Clib::FullPath( ( compilercfg.ModuleDirectory + module_name + ".em" ).c_str() );
|
2020-08-23 15:01:39 -07:00
|
|
|
if ( workspace.source_files.find( pathname ) != workspace.source_files.end() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
auto ident = std::make_unique<SourceFileIdentifier>(
|
2021-08-28 22:26:15 +02:00
|
|
|
static_cast<unsigned>(
|
|
|
|
|
workspace.compiler_workspace.referenced_source_file_identifiers.size() ),
|
|
|
|
|
pathname );
|
2020-08-23 15:01:39 -07:00
|
|
|
|
|
|
|
|
Pol::Tools::HighPerfTimer load_timer;
|
|
|
|
|
auto sf = workspace.em_cache.load( *ident, report );
|
|
|
|
|
long long load_elapsed = load_timer.ellapsed().count();
|
|
|
|
|
profile.load_em_micros += load_elapsed;
|
|
|
|
|
if ( !sf )
|
|
|
|
|
{
|
|
|
|
|
// This is fatal because if we keep going, we'll likely report a bunch of errors
|
|
|
|
|
// that would just be noise, like missing module function declarations or constants.
|
2024-01-12 06:51:44 +01:00
|
|
|
report.fatal( including_location, "Unable to use module '{}'.", module_name );
|
2020-08-23 15:01:39 -07:00
|
|
|
}
|
2024-01-10 18:29:10 +01:00
|
|
|
workspace.source_files[pathname] = sf;
|
2020-08-23 15:01:39 -07:00
|
|
|
|
|
|
|
|
ModuleProcessor module_processor( *ident, workspace, module_name );
|
|
|
|
|
workspace.compiler_workspace.referenced_source_file_identifiers.push_back( std::move( ident ) );
|
|
|
|
|
|
|
|
|
|
Pol::Tools::HighPerfTimer get_module_unit_timer;
|
|
|
|
|
auto module_unit_context = sf->get_module_unit( report, source_file_identifier );
|
|
|
|
|
long long parse_elapsed = get_module_unit_timer.ellapsed().count();
|
|
|
|
|
profile.parse_em_micros += parse_elapsed;
|
|
|
|
|
profile.parse_em_count++;
|
|
|
|
|
|
|
|
|
|
Pol::Tools::HighPerfTimer visit_module_unit_timer;
|
|
|
|
|
module_unit_context->accept( &module_processor );
|
|
|
|
|
long long ast_elapsed = visit_module_unit_timer.ellapsed().count();
|
|
|
|
|
profile.ast_em_micros.fetch_add( ast_elapsed );
|
|
|
|
|
|
|
|
|
|
if ( micros_counted )
|
|
|
|
|
*micros_counted = load_elapsed + parse_elapsed + ast_elapsed;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 10:43:08 -07:00
|
|
|
void SourceFileProcessor::process_source( SourceFile& sf )
|
|
|
|
|
{
|
|
|
|
|
Pol::Tools::HighPerfTimer parse_timer;
|
|
|
|
|
auto compilation_unit = sf.get_compilation_unit( report, source_file_identifier );
|
|
|
|
|
long long parse_us_counted = parse_timer.ellapsed().count();
|
|
|
|
|
|
|
|
|
|
profile.parse_src_micros.fetch_add( parse_us_counted );
|
|
|
|
|
profile.parse_src_count++;
|
|
|
|
|
|
|
|
|
|
if ( report.error_count() == 0 )
|
|
|
|
|
{
|
|
|
|
|
Pol::Tools::HighPerfTimer ast_timer;
|
|
|
|
|
compilation_unit->accept( this );
|
|
|
|
|
long long ast_us_elapsed = ast_timer.ellapsed().count();
|
|
|
|
|
|
|
|
|
|
profile.ast_src_micros.fetch_add( ast_us_elapsed );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 19:10:51 -07:00
|
|
|
void SourceFileProcessor::process_include( SourceFile& sf, long long* micros_counted )
|
|
|
|
|
{
|
|
|
|
|
Pol::Tools::HighPerfTimer parse_timer;
|
|
|
|
|
auto compilation_unit = sf.get_compilation_unit( report, source_file_identifier );
|
|
|
|
|
profile.parse_inc_count++;
|
|
|
|
|
long long parse_micros_elapsed = parse_timer.ellapsed().count();
|
|
|
|
|
profile.parse_inc_micros.fetch_add( parse_micros_elapsed );
|
|
|
|
|
*micros_counted += parse_micros_elapsed;
|
|
|
|
|
|
|
|
|
|
if ( report.error_count() == 0 )
|
|
|
|
|
{
|
|
|
|
|
Pol::Tools::HighPerfTimer ast_timer;
|
|
|
|
|
compilation_unit->accept( this );
|
|
|
|
|
long long ast_micros_elapsed = ast_timer.ellapsed().count();
|
|
|
|
|
profile.ast_inc_micros.fetch_add( ast_micros_elapsed );
|
|
|
|
|
*micros_counted += ast_micros_elapsed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SourceFileProcessor::handle_include_declaration( EscriptParser::IncludeDeclarationContext* ctx,
|
|
|
|
|
long long* micros_counted )
|
|
|
|
|
{
|
|
|
|
|
auto source_location = location_for( *ctx );
|
|
|
|
|
|
|
|
|
|
std::string include_name;
|
|
|
|
|
if ( auto string_literal = ctx->stringIdentifier()->STRING_LITERAL() )
|
|
|
|
|
include_name = tree_builder.unquote( string_literal );
|
|
|
|
|
else if ( auto identifier = ctx->stringIdentifier()->IDENTIFIER() )
|
|
|
|
|
include_name = identifier->getSymbol()->getText();
|
|
|
|
|
else
|
|
|
|
|
source_location.internal_error(
|
|
|
|
|
"Unable to include module: expected a string literal or identifier.\n" );
|
|
|
|
|
|
2020-09-27 12:25:02 -07:00
|
|
|
std::optional<std::string> maybe_canonical_include_pathname =
|
2020-09-09 19:10:51 -07:00
|
|
|
locate_include_file( source_location, include_name );
|
|
|
|
|
|
|
|
|
|
if ( !maybe_canonical_include_pathname )
|
|
|
|
|
{
|
|
|
|
|
report.error( source_location,
|
2024-01-12 06:51:44 +01:00
|
|
|
"Unable to include file '" + include_name + "': failed to locate." );
|
2020-09-09 19:10:51 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string canonical_include_pathname = maybe_canonical_include_pathname.value();
|
|
|
|
|
|
|
|
|
|
if ( workspace.source_files.count( canonical_include_pathname ) == 0 )
|
|
|
|
|
{
|
|
|
|
|
auto ident = std::make_unique<SourceFileIdentifier>(
|
2021-08-28 22:26:15 +02:00
|
|
|
static_cast<unsigned int>(
|
|
|
|
|
workspace.compiler_workspace.referenced_source_file_identifiers.size() ),
|
2020-09-09 19:10:51 -07:00
|
|
|
canonical_include_pathname );
|
|
|
|
|
auto sf = workspace.inc_cache.load( *ident, report );
|
|
|
|
|
if ( !sf )
|
|
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
report.error( source_location, "Unable to include file '{}': failed to load.",
|
|
|
|
|
canonical_include_pathname );
|
2020-09-09 19:10:51 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-13 00:41:45 -07:00
|
|
|
SourceFileProcessor include_processor( *ident, workspace, false, user_function_inclusion );
|
2020-09-09 19:10:51 -07:00
|
|
|
workspace.compiler_workspace.referenced_source_file_identifiers.push_back( std::move( ident ) );
|
|
|
|
|
workspace.source_files[sf->pathname] = sf;
|
|
|
|
|
|
|
|
|
|
include_processor.process_include( *sf, micros_counted );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 12:25:02 -07:00
|
|
|
std::optional<std::string> SourceFileProcessor::locate_include_file(
|
2020-09-09 19:10:51 -07:00
|
|
|
const SourceLocation& source_location, const std::string& include_name )
|
|
|
|
|
{
|
|
|
|
|
std::string filename_part = include_name + ".inc";
|
|
|
|
|
|
2021-03-06 01:39:26 +01:00
|
|
|
std::string current_file_path = getpathof( source_location.source_file_identifier->pathname );
|
2020-09-09 19:10:51 -07:00
|
|
|
std::string filename_full = current_file_path + filename_part;
|
|
|
|
|
|
|
|
|
|
if ( filename_part[0] == ':' )
|
|
|
|
|
{
|
|
|
|
|
const Plib::Package* pkg = nullptr;
|
|
|
|
|
std::string path;
|
|
|
|
|
if ( Plib::pkgdef_split( filename_part, nullptr, &pkg, &path ) )
|
|
|
|
|
{
|
|
|
|
|
if ( pkg != nullptr )
|
|
|
|
|
{
|
|
|
|
|
filename_full = pkg->dir() + path;
|
|
|
|
|
std::string try_filename_full = pkg->dir() + "include/" + path;
|
|
|
|
|
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
|
|
|
|
|
if ( !Clib::FileExists( filename_full.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for {}", try_filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
if ( Clib::FileExists( try_filename_full.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Found {}", try_filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
|
|
|
|
|
filename_full = try_filename_full;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Found {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
|
|
|
|
|
if ( Clib::FileExists( try_filename_full.c_str() ) )
|
2024-01-12 06:51:44 +01:00
|
|
|
report.warning( source_location, "Found '{}' and '{}'! Will use first file!",
|
|
|
|
|
filename_full, try_filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
filename_full = compilercfg.PolScriptRoot + path;
|
|
|
|
|
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
|
|
|
|
{
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
if ( Clib::FileExists( filename_full.c_str() ) )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Found {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// This is fatal because if we keep going, we'll likely report a bunch of errors
|
|
|
|
|
// that would just be noise, like missing functions or constants.
|
2024-01-12 06:51:44 +01:00
|
|
|
report.fatal( source_location, "Unable to read include file '{}'", include_name );
|
2020-09-09 19:10:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
|
|
|
|
|
if ( !Clib::FileExists( filename_full.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
std::string try_filename_full = compilercfg.IncludeDirectory + filename_part;
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for {}", try_filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
if ( Clib::FileExists( try_filename_full.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Found {}", try_filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
|
|
|
|
|
// cout << "Using " << try_filename << endl;
|
|
|
|
|
filename_full = try_filename_full;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( compilercfg.VerbosityLevel >= 10 )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Found {}", filename_full );
|
2020-09-09 19:10:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( SourceFile::enforced_case_sensitivity_mismatch( source_location, filename_full, report ) )
|
|
|
|
|
{
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filename_full = Clib::FullPath( filename_full.c_str() );
|
|
|
|
|
|
2020-09-27 12:25:02 -07:00
|
|
|
if ( !filename_full.empty() )
|
|
|
|
|
return std::optional<std::string>( filename_full );
|
2026-01-18 09:35:52 +01:00
|
|
|
return {};
|
2020-09-09 19:10:51 -07:00
|
|
|
}
|
|
|
|
|
|
2020-09-09 00:41:02 -07:00
|
|
|
void SourceFileProcessor::handle_use_declaration( EscriptParser::UseDeclarationContext* ctx,
|
|
|
|
|
long long* micros_used )
|
|
|
|
|
{
|
|
|
|
|
EscriptParser::StringIdentifierContext* stringId = ctx->stringIdentifier();
|
|
|
|
|
std::string modulename = stringId->STRING_LITERAL()
|
|
|
|
|
? tree_builder.unquote( stringId->STRING_LITERAL() )
|
|
|
|
|
: tree_builder.text( stringId->IDENTIFIER() );
|
|
|
|
|
auto source_location = location_for( *ctx );
|
|
|
|
|
use_module( modulename, source_location, micros_used );
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-11 23:01:38 +02:00
|
|
|
// Visits global user functions. Class functions are visited in UserFunctionVisitor.
|
2020-08-31 18:46:27 -07:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitFunctionDeclaration(
|
|
|
|
|
EscriptParser::FunctionDeclarationContext* ctx )
|
|
|
|
|
{
|
2020-09-11 01:16:24 -07:00
|
|
|
auto loc = location_for( *ctx );
|
2024-08-11 23:01:38 +02:00
|
|
|
bool force_reference = user_function_inclusion == UserFunctionInclusion::All;
|
|
|
|
|
workspace.function_resolver.register_available_user_function( loc, ctx, force_reference );
|
2020-09-13 00:41:45 -07:00
|
|
|
const std::string& function_name = tree_builder.text( ctx->IDENTIFIER() );
|
|
|
|
|
workspace.compiler_workspace.all_function_locations.emplace( function_name, loc );
|
2020-08-31 18:46:27 -07:00
|
|
|
return antlrcpp::Any();
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-10 15:27:25 +02:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitClassDeclaration(
|
|
|
|
|
EscriptGrammar::EscriptParser::ClassDeclarationContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *ctx );
|
|
|
|
|
auto class_name = tree_builder.text( ctx->IDENTIFIER() );
|
|
|
|
|
|
2024-08-12 21:59:31 +02:00
|
|
|
// Add var statements to top-level, as their declaration + semantic analysis
|
|
|
|
|
// needs to happen in-line with other statements:
|
2024-08-10 15:27:25 +02:00
|
|
|
//
|
|
|
|
|
// Foo::staticVar; // compilation error
|
|
|
|
|
// class Foo var staticVar := 2; endclass
|
|
|
|
|
// print(Foo::staticVar == 2); // true
|
|
|
|
|
//
|
2024-08-12 21:59:31 +02:00
|
|
|
// We add this `ClassBody` to the top level statements now. When the
|
|
|
|
|
// UserFunctionVisitor visits the class declaration, it will add its variable
|
|
|
|
|
// statements to this node.
|
|
|
|
|
auto var_statement_holder = std::make_unique<ClassBody>( loc );
|
2024-08-10 15:27:25 +02:00
|
|
|
|
2024-08-12 21:59:31 +02:00
|
|
|
workspace.function_resolver.register_available_class_declaration( loc, class_name, ctx,
|
|
|
|
|
var_statement_holder.get() );
|
2024-08-10 15:27:25 +02:00
|
|
|
|
2024-08-11 23:01:38 +02:00
|
|
|
workspace.compiler_workspace.all_class_locations.emplace( class_name, loc );
|
|
|
|
|
|
2024-08-12 21:59:31 +02:00
|
|
|
workspace.compiler_workspace.top_level_statements->children.push_back(
|
|
|
|
|
std::move( var_statement_holder ) );
|
|
|
|
|
|
2024-08-10 15:27:25 +02:00
|
|
|
if ( user_function_inclusion == UserFunctionInclusion::All )
|
2024-08-11 23:01:38 +02:00
|
|
|
{
|
|
|
|
|
for ( auto classStatement : ctx->classBody()->classStatement() )
|
|
|
|
|
{
|
|
|
|
|
if ( auto func_decl = classStatement->functionDeclaration() )
|
|
|
|
|
{
|
|
|
|
|
auto function_name = tree_builder.text( func_decl->IDENTIFIER() );
|
|
|
|
|
workspace.function_resolver.force_reference( ScopableName( class_name, function_name ),
|
|
|
|
|
loc );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-10 15:27:25 +02:00
|
|
|
return antlrcpp::Any();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 19:10:51 -07:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitIncludeDeclaration(
|
|
|
|
|
EscriptParser::IncludeDeclarationContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
long long micros_counted = 0;
|
|
|
|
|
handle_include_declaration( ctx, µs_counted );
|
|
|
|
|
if ( is_src )
|
|
|
|
|
profile.ast_src_micros.fetch_sub( micros_counted );
|
|
|
|
|
else
|
|
|
|
|
profile.ast_inc_micros.fetch_sub( micros_counted );
|
|
|
|
|
return antlrcpp::Any();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 22:45:07 -07:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitProgramDeclaration(
|
|
|
|
|
EscriptParser::ProgramDeclarationContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( workspace.compiler_workspace.program )
|
|
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
report.error( location_for( *ctx ),
|
|
|
|
|
"Multiple program statements.\n"
|
|
|
|
|
" Other declaration: {}",
|
|
|
|
|
workspace.compiler_workspace.program->source_location );
|
2020-08-28 22:45:07 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
workspace.compiler_workspace.program = tree_builder.program( ctx );
|
|
|
|
|
}
|
|
|
|
|
return antlrcpp::Any();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 10:43:08 -07:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitStatement( EscriptParser::StatementContext* ctx )
|
2020-08-18 23:32:57 -07:00
|
|
|
{
|
2020-08-19 10:43:08 -07:00
|
|
|
if ( auto constStatement = ctx->constStatement() )
|
|
|
|
|
{
|
2020-09-01 00:54:24 -07:00
|
|
|
workspace.compiler_workspace.const_declarations.push_back(
|
|
|
|
|
tree_builder.const_declaration( constStatement ) );
|
2020-08-19 10:43:08 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<Statement>> statements;
|
|
|
|
|
tree_builder.add_statements( ctx, statements );
|
|
|
|
|
for ( auto& statement : statements )
|
|
|
|
|
{
|
|
|
|
|
workspace.compiler_workspace.top_level_statements->children.push_back(
|
|
|
|
|
std::move( statement ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return antlrcpp::Any();
|
2020-08-18 23:32:57 -07:00
|
|
|
}
|
|
|
|
|
|
2020-09-09 00:41:02 -07:00
|
|
|
antlrcpp::Any SourceFileProcessor::visitUseDeclaration( EscriptParser::UseDeclarationContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
long long elapsed_micros = 0;
|
|
|
|
|
handle_use_declaration( ctx, &elapsed_micros );
|
|
|
|
|
if ( is_src )
|
|
|
|
|
profile.ast_src_micros.fetch_sub( elapsed_micros );
|
|
|
|
|
else
|
|
|
|
|
profile.ast_inc_micros.fetch_sub( elapsed_micros );
|
|
|
|
|
return antlrcpp::Any();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-18 23:32:57 -07:00
|
|
|
SourceLocation SourceFileProcessor::location_for( antlr4::ParserRuleContext& ctx ) const
|
|
|
|
|
{
|
|
|
|
|
return { &source_file_identifier, ctx };
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-06 01:39:26 +01:00
|
|
|
std::string getpathof( const std::string& fname )
|
|
|
|
|
{
|
|
|
|
|
std::string::size_type pos = fname.find_last_of( "\\/" );
|
|
|
|
|
if ( pos == std::string::npos )
|
|
|
|
|
return "./";
|
2026-01-18 09:35:52 +01:00
|
|
|
return fname.substr( 0, pos + 1 );
|
2021-03-06 01:39:26 +01:00
|
|
|
}
|
2020-08-18 23:32:57 -07:00
|
|
|
} // namespace Pol::Bscript::Compiler
|