polserver/pol-core/bscript/compiler/codegen/InstructionEmitter.cpp
Eric Swanson a77ddd028e
New compiler: Add optimized unary expressions (#244)
Adds:
- UnaryOperator: AST node for unary operators -, ++, --, and so forth
- UnaryOperatorOptimizer: optimizes a unary operator with its operand
  - now integer and float negation, and integer inversion
  - later x[y]++ to a single instruction

Also:
- automatically include basic.em, which includes some parameter defaults like -1.

This allows the compiler to generate output for a hello, world script with the exact same .ecl output as the legacy compiler.
2020-08-26 19:24:47 -07:00

127 lines
3.5 KiB
C++

#include "InstructionEmitter.h"
#include "StoredToken.h"
#include "compiler/ast/ModuleFunctionDeclaration.h"
#include "compiler/codegen/ModuleDeclarationRegistrar.h"
#include "compiler/model/Variable.h"
#include "compiler/representation/CompiledScript.h"
#include "escriptv.h"
#include "modules.h"
#include "token.h"
#include "tokens.h"
namespace Pol::Bscript::Compiler
{
InstructionEmitter::InstructionEmitter( CodeSection& code, DataSection& data,
ModuleDeclarationRegistrar& module_declaration_registrar )
: code_emitter( code ),
data_emitter( data ),
module_declaration_registrar( module_declaration_registrar )
{
initialize_data();
}
void InstructionEmitter::initialize_data()
{
std::byte nul{};
data_emitter.store( &nul, sizeof nul );
}
void InstructionEmitter::access_variable( const Variable& v )
{
BTokenId token_id = v.scope == VariableScope::Global ? TOK_GLOBALVAR : TOK_LOCALVAR;
emit_token( token_id, TYP_OPERAND, v.index );
}
void InstructionEmitter::array_declare()
{
emit_token( INS_DECLARE_ARRAY, TYP_RESERVED );
}
void InstructionEmitter::assign()
{
emit_token( TOK_ASSIGN, TYP_OPERATOR );
}
void InstructionEmitter::call_method_id( MethodID method_id, unsigned argument_count )
{
emit_token( INS_CALL_METHOD_ID, (BTokenType)argument_count, method_id );
}
void InstructionEmitter::call_method( const std::string& name, unsigned argument_count )
{
unsigned offset = emit_data( name );
emit_token( INS_CALL_METHOD, (BTokenType)argument_count, offset );
}
void InstructionEmitter::call_modulefunc(
const ModuleFunctionDeclaration& module_function_declaration )
{
unsigned module_id, function_index;
module_declaration_registrar.lookup_or_register_module_function( module_function_declaration,
module_id, function_index );
unsigned sympos = include_debug ? emit_data( module_function_declaration.name ) : 0;
StoredToken token(
module_id, TOK_FUNC,
static_cast<BTokenType>(
function_index ), // function index, stored in Token.lval, saved in StoredToken.type
sympos );
append_token( token );
}
void InstructionEmitter::consume()
{
emit_token( TOK_CONSUMER, TYP_UNARY_OPERATOR );
}
void InstructionEmitter::declare_variable( const Variable& v )
{
BTokenId token_id = v.scope == VariableScope::Global ? RSV_GLOBAL : RSV_LOCAL;
emit_token( token_id, TYP_RESERVED, v.index );
}
void InstructionEmitter::progend()
{
emit_token( CTRL_PROGEND, TYP_CONTROL );
}
void InstructionEmitter::unary_operator( BTokenId token_id )
{
emit_token( token_id, TYP_UNARY_OPERATOR );
}
void InstructionEmitter::value( double v )
{
unsigned offset = data_emitter.append( v );
emit_token( TOK_DOUBLE, TYP_OPERAND, offset );
}
void InstructionEmitter::value( int v )
{
unsigned offset = data_emitter.append( v );
emit_token( TOK_LONG, TYP_OPERAND, offset );
}
void InstructionEmitter::value( const std::string& v )
{
unsigned data_offset = emit_data( v );
emit_token( TOK_STRING, TYP_OPERAND, data_offset );
}
unsigned InstructionEmitter::emit_data( const std::string& s )
{
return data_emitter.store( s );
}
unsigned InstructionEmitter::emit_token( BTokenId id, BTokenType type, unsigned offset )
{
StoredToken token( Mod_Basic, id, type, offset );
return append_token( token );
}
unsigned InstructionEmitter::append_token( StoredToken& token )
{
return code_emitter.append( token );
}
} // namespace Pol::Bscript::Compiler