Skip to content

Commit

Permalink
Adds inference for block invocation arguments
Browse files Browse the repository at this point in the history
Issue: #17
  • Loading branch information
0x7CFE committed May 25, 2016
1 parent b0d8b87 commit bdeb3c0
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
4 changes: 3 additions & 1 deletion include/inference.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class TypeAnalyzer {
TypeAnalyzer(TypeSystem& system, ControlGraph& graph, InferContext& context)
: m_system(system), m_graph(graph), m_context(context), m_walker(*this) {}

void run();
void run(const Type* blockType = 0);

private:
void processInstruction(const InstructionNode& instruction);
Expand Down Expand Up @@ -350,6 +350,8 @@ class TypeAnalyzer {

bool m_baseRun;
bool m_literalBranch;

const Type* m_blockType;
};

} // namespace type
Expand Down
21 changes: 18 additions & 3 deletions src/TypeAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ std::string Type::toString(bool subtypesOnly /*= false*/) const {
return stream.str();
}

void TypeAnalyzer::run() {
void TypeAnalyzer::run(const Type* blockType /*= 0*/) {
if (m_graph.isEmpty())
return;

m_blockType = blockType;

// FIXME For correct inference we need to perform in-width traverse

m_baseRun = true;
Expand Down Expand Up @@ -328,20 +330,33 @@ void TypeAnalyzer::doPushTemporary(const InstructionNode& instruction) {
processTau(*tau);

m_context[instruction] = tauType;
} else if (m_blockType) {
// Block invocation primitive pass block arguments through creating method's temporaries.
// To simplify inference, we pass their types as context arguments.

const uint16_t argIndex = TInteger(m_blockType->getSubTypes()[2].getValue());
const TSmalltalkInstruction::TArgument tempIndex = instruction.getInstruction().getArgument();

if (tempIndex >= argIndex)
m_context[instruction] = m_context.getArgument(tempIndex - argIndex);
else
m_context[instruction] = Type(Type::tkPolytype);
}
}

void TypeAnalyzer::doPushBlock(const InstructionNode& instruction) {
if (const PushBlockNode* const pushBlock = instruction.cast<PushBlockNode>()) {
TMethod* const origin = pushBlock->getParsedBlock()->getContainer()->getOrigin();
const uint16_t offset = pushBlock->getParsedBlock()->getStartOffset();
const uint16_t argIndex = instruction.getInstruction().getArgument();

// Block[origin, offset]
Type& blockType = m_context[instruction];

blockType.set(globals.blockClass, Type::tkMonotype);
blockType.addSubType(origin);
blockType.addSubType(Type(TInteger(offset)));
blockType.addSubType(Type(TInteger(argIndex)));
}
}

Expand Down Expand Up @@ -708,11 +723,11 @@ InferContext* TypeSystem::inferBlock(const Type& block, const Type& arguments) {
}

type::TypeAnalyzer analyzer(*this, *blockGraph, *inferContext);
analyzer.run();
analyzer.run(&block);

std::printf("%s::%s -> %s, ^%s\n", arguments.toString().c_str(), block.toString().c_str(),
inferContext->getReturnType().toString().c_str(),
inferContext->getBlockReturnType().toString().c_str());

return 0;
return inferContext;
}

0 comments on commit bdeb3c0

Please sign in to comment.