Skip to content
Permalink
Browse files

Empty subroutines now have correct line numbers

  • Loading branch information...
stephanemagnenat committed Oct 1, 2008
1 parent 50f360c commit cd634bbc5862428d2393683f770a05f530454232
Showing with 42 additions and 30 deletions.
  1. +8 −8 compiler/compiler.cpp
  2. +31 −18 compiler/compiler.h
  3. +1 −1 compiler/parser.cpp
  4. +2 −3 compiler/tree-emit.cpp
@@ -166,7 +166,7 @@ namespace Aseba
delete program;

// fix-up (add of missing STOP and RET bytecodes at code generation)
preLinkBytecode.fixup();
preLinkBytecode.fixup(subroutineTable);

// linking (flattening of complex structure into linear vector)
if (!link(preLinkBytecode, bytecode))
@@ -220,7 +220,7 @@ namespace Aseba
++it
)
{
subroutineTable[it->first].second = bytecode.size();
subroutineTable[it->first].address = bytecode.size();
std::copy(it->second.begin(), it->second.end(), std::back_inserter(bytecode));
}

@@ -233,7 +233,7 @@ namespace Aseba
{
unsigned id = bytecode[pc] & 0x0fff;
assert(id < subroutineTable.size());
unsigned address = subroutineTable[id].second;
unsigned address = subroutineTable[id].address;
bytecode[pc].bytecode &= 0xf000;
bytecode[pc].bytecode |= address;
pc += 1;
@@ -269,8 +269,8 @@ namespace Aseba
std::map<unsigned, unsigned> subroutinesAddr;

// build subroutine map
for (size_t i = 0; i < subroutineTable.size(); ++i)
subroutinesAddr[subroutineTable[i].second] = i;
for (size_t id = 0; id < subroutineTable.size(); ++id)
subroutinesAddr[subroutineTable[id].address] = id;

// event table
unsigned eventVectSize = bytecode[0];
@@ -315,7 +315,7 @@ namespace Aseba

if (subroutinesAddr.find(pc) != subroutinesAddr.end())
{
dump << "sub " << subroutineTable[subroutinesAddr[pc]].first << ":\n";
dump << "sub " << subroutineTable[subroutinesAddr[pc]].name << ":\n";
}

dump << " ";
@@ -406,8 +406,8 @@ namespace Aseba
unsigned address = (bytecode[pc] & 0x0fff);
std::string name("unknown");
for (size_t i = 0; i < subroutineTable.size(); i++)
if (subroutineTable[i].second == address)
name = subroutineTable[i].first;
if (subroutineTable[i].address == address)
name = subroutineTable[i].name;
dump << "SUB_CALL to " << name << " @ " << address << "\n";
pc++;
}
@@ -109,22 +109,8 @@ namespace Aseba
//! Bytecode array in the form of a dequeue, for construction
typedef std::deque<BytecodeElement> BytecodeVector;

//! Bytecode use for compilation previous to linking
struct PreLinkBytecode
{
//! Map of events id to event bytecode
typedef std::map<unsigned, BytecodeVector> EventsBytecode;
EventsBytecode events; //!< bytecode for events

//! Map of routines id to routine bytecode
typedef std::map<unsigned, BytecodeVector> SubroutinesBytecode;
SubroutinesBytecode subroutines; //!< bytecode for routines

BytecodeVector *current; //!< pointer to bytecode being constructed

PreLinkBytecode();
void fixup();
};
// predeclaration
class PreLinkBytecode;

//! Position in a source file or string. First is line, second is column
struct SourcePos
@@ -268,8 +254,17 @@ namespace Aseba
typedef std::map<std::string, std::pair<unsigned, unsigned> > VariablesMap;
//! Lookup table for functions (name => id in target description)
typedef std::map<std::string, unsigned> FunctionsMap;
//! Lookup table for subroutines id => (name, address)
typedef std::vector<std::pair<std::string, unsigned> > SubroutineTable;
//! Description of a subroutine
struct SubroutineDescriptor
{
std::string name;
unsigned address;
unsigned line;

SubroutineDescriptor(const std::string& name, unsigned address, unsigned line) : name(name), address(address), line(line) {}
};
//! Lookup table for subroutines id => (name, address, line)
typedef std::vector<SubroutineDescriptor> SubroutineTable;
//! Reverse Lookup table for subroutines name => id
typedef std::map<std::string, unsigned> SubroutineReverseTable;
//! Lookup table to keep track of implemented events
@@ -346,6 +341,24 @@ namespace Aseba
const CommonDefinitions *commonDefinitions; //!< common definitions, such as events or some constants
}; // Compiler

//! Bytecode use for compilation previous to linking
struct PreLinkBytecode
{
//! Map of events id to event bytecode
typedef std::map<unsigned, BytecodeVector> EventsBytecode;
EventsBytecode events; //!< bytecode for events

//! Map of routines id to routine bytecode
typedef std::map<unsigned, BytecodeVector> SubroutinesBytecode;
SubroutinesBytecode subroutines; //!< bytecode for routines

BytecodeVector *current; //!< pointer to bytecode being constructed

PreLinkBytecode();

void fixup(const Compiler::SubroutineTable &subroutineTable);
};

/*@}*/

}; // Aseba
@@ -628,7 +628,7 @@ namespace Aseba
throw Error(tokens.front().pos, FormatableString("Subroutine %0 is already defined").arg(name));

unsigned subroutineId = subroutineTable.size();
subroutineTable.push_back(std::make_pair(name, 0));
subroutineTable.push_back(SubroutineDescriptor(name, 0, pos.row));
subroutineReverseTable[name] = subroutineId;

tokens.pop_front();
@@ -38,7 +38,7 @@ namespace Aseba

//! Fixup prelinked bytecodes by making sure that each vector is closed correctly,
//! i.e. with a STOP for events and a RET for subroutines
void PreLinkBytecode::fixup()
void PreLinkBytecode::fixup(const Compiler::SubroutineTable &subroutineTable)
{
// clear empty events entries
for (EventsBytecode::iterator it = events.begin(); it != events.end();)
@@ -64,9 +64,8 @@ namespace Aseba
if (bytecode.size())
bytecode.push_back(BytecodeElement(AsebaBytecodeFromId(ASEBA_BYTECODE_SUB_RET), bytecode[bytecode.size()-1].line));
else
bytecode.push_back(BytecodeElement(AsebaBytecodeFromId(ASEBA_BYTECODE_SUB_RET), 0));
bytecode.push_back(BytecodeElement(AsebaBytecodeFromId(ASEBA_BYTECODE_SUB_RET), subroutineTable[it->first].line));
}
// TODO: fix location
}

void BlockNode::emit(PreLinkBytecode& bytecodes) const

0 comments on commit cd634bb

Please sign in to comment.
You can’t perform that action at this time.