Skip to content

Commit

Permalink
Adds stub for block inference
Browse files Browse the repository at this point in the history
Issue: #17
  • Loading branch information
0x7CFE committed May 25, 2016
1 parent 719e6ec commit feddc12
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
12 changes: 12 additions & 0 deletions include/inference.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,25 @@ class InferContext {
Type m_returnType;
};

class BlockInferContext : public InferContext {
public:
BlockInferContext(std::size_t index, const Type& arguments)
: InferContext(index, arguments) {}

Type& getBlockReturnType() { return m_blockReturnType; }

private:
Type m_blockReturnType;
};

class TypeSystem {
public:
TypeSystem(SmalltalkVM& vm) : m_vm(vm), m_lastContextIndex(0) {}

typedef TSymbol* TSelector;

InferContext* inferMessage(TSelector selector, const Type& arguments);
InferContext* inferBlock(const Type& block, const Type& arguments);

ControlGraph* getControlGraph(TMethod* method);

Expand Down
70 changes: 69 additions & 1 deletion src/TypeAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,17 @@ void TypeAnalyzer::doPushTemporary(const InstructionNode& instruction) {
}

void TypeAnalyzer::doPushBlock(const InstructionNode& instruction) {
m_context[instruction] = Type(globals.blockClass, Type::tkLiteral);
if (const PushBlockNode* const pushBlock = instruction.cast<PushBlockNode>()) {
TMethod* const origin = pushBlock->getParsedBlock()->getContainer()->getOrigin();
const uint16_t offset = pushBlock->getParsedBlock()->getStartOffset();

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

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

void TypeAnalyzer::doAssignTemporary(const InstructionNode& instruction) {
Expand Down Expand Up @@ -440,6 +450,24 @@ void TypeAnalyzer::doPrimitive(const InstructionNode& instruction) {
break;
}

case primitive::blockInvoke: {
const Type& block = m_context[*instruction.getArgument(0)];
const Type& arg = m_context[*instruction.getArgument(1)];

Type arguments(Type::tkArray);
arguments.addSubType(arg);

if (instruction.getArgumentsCount() == 3)
arguments.addSubType(m_context[*instruction.getArgument(2)]);

if (InferContext* invokeContext = m_system.inferBlock(block, arguments))
primitiveResult = invokeContext->getReturnType();
else
primitiveResult = Type(Type::tkPolytype);

break;
}

case primitive::smallIntSub:
case primitive::smallIntDiv:
case primitive::smallIntMod:
Expand Down Expand Up @@ -643,3 +671,43 @@ InferContext* TypeSystem::inferMessage(TSelector selector, const Type& arguments

return inferContext;
}

InferContext* TypeSystem::inferBlock(const Type& block, const Type& arguments) {
if (block.getKind() != Type::tkMonotype || arguments.getSubTypes().empty())
return 0;

// TODO Cache
BlockInferContext* const inferContext = new BlockInferContext(m_lastContextIndex++, arguments);

TMethod* const method = block.getSubTypes()[0].getValue()->cast<TMethod>();
const uint16_t offset = TInteger(block.getSubTypes()[1].getValue());

ControlGraph* const methodGraph = getControlGraph(method);
assert(controlGraph);

std::printf("Analyzing block %s::%s ...\n", arguments.toString().c_str(), block.toString().c_str());

st::ParsedMethod* const parsedMethod = methodGraph->getParsedMethod();
st::ParsedBlock* const parsedBlock = parsedMethod->getParsedBlockByOffset(offset);

// TODO Cache
ControlGraph* const blockGraph = new ControlGraph(parsedMethod, parsedBlock);
blockGraph->buildGraph();

{
std::ostringstream ss;
ss << method->klass->name->toString() << ">>" << method->name->toString() << "@" << offset;

ControlGraphVisualizer vis(blockGraph, ss.str(), "dots/");
vis.run();
}

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

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;
}

0 comments on commit feddc12

Please sign in to comment.