Skip to content

Commit

Permalink
Fixes analyzer and context, adds handling of conditional branches
Browse files Browse the repository at this point in the history
Issue: #17
  • Loading branch information
0x7CFE committed May 21, 2016
1 parent aa97c11 commit 55e65b4
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 29 deletions.
32 changes: 15 additions & 17 deletions include/inference.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class Type {
std::string toString() const;

Type(TKind kind = tkUndefined) : m_kind(kind), m_value(0) {}
Type(TObject* literal) { set(literal); }
Type(TClass* klass) { set(klass); }
Type(TObject* literal, TKind kind = tkLiteral) { set(literal, kind); }
Type(TClass* klass, TKind kind = tkMonotype) { set(klass, kind); }

void setKind(TKind kind) { m_kind = kind; }
TKind getKind() const { return m_kind; }
Expand Down Expand Up @@ -65,15 +65,13 @@ class Type {
TSubTypes m_subTypes;
};

typedef std::vector<Type> TTypeList;
typedef std::size_t TNodeIndex;
typedef std::map<TNodeIndex, Type> TTypeList;

class CallContext {
public:
CallContext(std::size_t index, const Type& arguments, std::size_t nodeCount)
: m_index(index), m_arguments(arguments)
{
m_instructions.resize(nodeCount);
}
CallContext(std::size_t index, const Type& arguments)
: m_index(index), m_arguments(arguments) {}

std::size_t getIndex() const { return m_index; }

Expand All @@ -86,11 +84,12 @@ class CallContext {
return polytype;
}
const Type& getArguments() const { return m_arguments; }
const TTypeList& getTypeList() const { return m_instructions; }

Type& getReturnType() { return m_returnType; }

Type& getInstructionType(std::size_t index) { return m_instructions[index]; }
Type& operator[] (std::size_t index) { return m_instructions[index]; }
Type& getInstructionType(TNodeIndex index) { return m_instructions[index]; }
Type& operator[] (TNodeIndex index) { return m_instructions[index]; }
Type& operator[] (const ControlNode& node) { return getInstructionType(node.getIndex()); }

private:
Expand All @@ -110,20 +109,15 @@ class TypeSystem {
class TypeAnalyzer {
public:
TypeAnalyzer(ControlGraph& graph, CallContext& context)
: m_graph(graph), m_context(context) {}
: m_graph(graph), m_context(context), m_walker(*this) {}

void run() {
if (m_graph.isEmpty())
return;

Walker walker(*this);
walker.run(*m_graph.nodes_begin(), Walker::wdForward);
m_walker.run(*m_graph.nodes_begin(), Walker::wdForward);
}

private:
ControlGraph& m_graph;
CallContext& m_context;

private:
void processInstruction(const InstructionNode& instruction);
void processPhi(const PhiNode& phi);
Expand Down Expand Up @@ -169,6 +163,10 @@ class TypeAnalyzer {
TypeAnalyzer& analyzer;
};

private:
ControlGraph& m_graph;
CallContext& m_context;
Walker m_walker;
};

} // namespace type
Expand Down
74 changes: 62 additions & 12 deletions src/TypeAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ std::string Type::toString() const {
else if (getValue()->getClass() == globals.stringClass)
stream << "'" << getValue()->cast<TString>()->toString() << "'";
else if (getValue()->getClass() == globals.badMethodSymbol->getClass())
stream << "'" << getValue()->cast<TSymbol>()->toString() << "'";
stream << "#" << getValue()->cast<TSymbol>()->toString();
else if (getValue()->getClass()->name->toString().find("Meta", 0, 4) != std::string::npos)
stream << getValue()->cast<TClass>()->name->toString();
else
stream << "~" << getValue()->getClass()->name->toString();
break;

case tkMonotype:
Expand All @@ -48,6 +52,8 @@ std::string Type::toString() const {
}

void TypeAnalyzer::processInstruction(const InstructionNode& instruction) {
std::printf("processing %.2u\n", instruction.getIndex());

const TSmalltalkInstruction::TArgument argument = instruction.getInstruction().getArgument();

switch (instruction.getInstruction().getOpcode()) {
Expand All @@ -59,13 +65,61 @@ void TypeAnalyzer::processInstruction(const InstructionNode& instruction) {
case opcode::pushLiteral: doPushLiteral(instruction); break;
case opcode::markArguments: doMarkArguments(instruction); break;

case opcode::sendUnary: doSendUnary(instruction); break;
case opcode::sendBinary: doSendBinary(instruction); break;

case opcode::assignTemporary:
m_context[instruction.getTauNode()->getIndex()] = m_context[*instruction.getArgument()];
break;

case opcode::sendMessage:
// For now, treat method call as *
m_context[instruction] = Type(Type::tkPolytype);
break;

case opcode::doPrimitive:
m_context.getReturnType().addSubType(Type(Type::tkPolytype));
break;

case opcode::doSpecial: {
switch (argument) {
case special::branchIfFalse:
case special::branchIfTrue: {
const bool branchIfTrue = (argument == special::branchIfTrue);

const Type& argType = m_context[*instruction.getArgument()];
const BranchNode* const branch = instruction.cast<BranchNode>();

if (argType.getValue() == globals.trueObject || argType.getValue() == globals.trueObject->getClass())
m_walker.addStopNode(branchIfTrue ? branch->getSkipNode() : branch->getTargetNode());
else if (argType.getValue() == globals.falseObject || argType.getValue() == globals.falseObject->getClass())
m_walker.addStopNode(branchIfTrue ? branch->getTargetNode() : branch->getSkipNode());

break;
}

case special::stackReturn:
m_context.getReturnType().addSubType(m_context[*instruction.getArgument()]);
break;

case special::selfReturn:
m_context.getReturnType().addSubType(m_context.getArgument(0));
break;

case special::sendToSuper:
// For now, treat method call as *
m_context[instruction] = Type(Type::tkPolytype);
break;

case special::duplicate:
m_context[instruction] = m_context[*instruction.getArgument()];
break;
}

break;
}


default:
break;
}
Expand Down Expand Up @@ -130,7 +184,7 @@ void TypeAnalyzer::doSendUnary(const InstructionNode& instruction) {
default:
// * isNil = (Boolean)
// * notNil = (Boolean)
result.set(globals.trueObject->getClass()->getClass());
result.set(globals.trueObject->getClass()->parentClass);
}

}
Expand All @@ -142,7 +196,7 @@ void TypeAnalyzer::doSendBinary(const InstructionNode& instruction) {

Type& result = m_context[instruction];

if (isSmallInteger(type1.getValue()) && isSmallInteger(type1.getValue())) {
if (isSmallInteger(type1.getValue()) && isSmallInteger(type2.getValue())) {
const int32_t rightOperand = TInteger(type2.getValue());
const int32_t leftOperand = TInteger(type1.getValue());

Expand Down Expand Up @@ -175,7 +229,7 @@ void TypeAnalyzer::doSendBinary(const InstructionNode& instruction) {
case binaryBuiltIns::operatorLess:
case binaryBuiltIns::operatorLessOrEq:
// (SmallInt) <= (SmallInt) = (Boolean)
result.set(globals.trueObject->getClass()->getClass());
result.set(globals.trueObject->getClass()->parentClass);
break;

case binaryBuiltIns::operatorPlus:
Expand All @@ -197,17 +251,13 @@ void TypeAnalyzer::doSendBinary(const InstructionNode& instruction) {
}

void TypeAnalyzer::doMarkArguments(const InstructionNode& instruction) {
const Type& argsType = m_context[*instruction.getArgument()];
Type& result = m_context[instruction];

if (argsType.getKind() == Type::tkUndefined || argsType.getKind() == Type::tkPolytype) {
result.set(globals.arrayClass);
return;
for (std::size_t index = 0; index < instruction.getArgumentsCount(); index++) {
const Type& argsType = m_context[*instruction.getArgument(index)];
result.addSubType(argsType);
}

for (std::size_t index = 0; index < argsType.getSubTypes().size(); index++)
result.addSubType(argsType[index]);

result.set(globals.arrayClass, Type::tkArray);
}

Expand All @@ -228,5 +278,5 @@ void TypeAnalyzer::processTau(const TauNode& tau) {
}

void TypeAnalyzer::walkComplete() {

std::printf("walk complete\n");
}

0 comments on commit 55e65b4

Please sign in to comment.