This commit is contained in:
Daniel Kirchner 2023-06-24 01:45:56 +02:00
parent 7d094b3be6
commit 62a5291bbd
4 changed files with 31 additions and 3 deletions

View File

@ -287,6 +287,24 @@ experimental::Type TypeEnvironment::resolve(Type _type) const
return result;
}
experimental::Type TypeEnvironment::resolveRecursive(Type _type) const
{
return std::visit(util::GenericVisitor{
[&](TypeExpression const& _type) -> Type {
return TypeExpression{
_type.constructor,
_type.arguments | ranges::views::transform([&](Type _argType) {
return resolveRecursive(_argType);
}) | ranges::to<vector<Type>>
};
},
[&](TypeVariable const&) -> Type {
return _type;
},
}, resolve(_type));
}
void TypeSystem::declareBuiltinType(BuiltinType _builtinType, std::string _name, uint64_t _arguments)
{
declareTypeConstructor(_builtinType, _name, _arguments);

View File

@ -128,6 +128,7 @@ public:
TypeEnvironment& operator=(TypeEnvironment const&) = delete;
TypeEnvironment clone() const;
Type resolve(Type _type) const;
Type resolveRecursive(Type _type) const;
Type fresh(Type _type, bool _generalize);
struct UnificationFailure { Type a; Type b; };
[[nodiscard]] std::vector<UnificationFailure> unify(Type _a, Type _b);

View File

@ -98,7 +98,7 @@ string IRGenerator::generate(ContractDefinition const& _contract)
{
auto type = m_context.analysis.annotation<TypeInference>(*_contract.fallbackFunction()).type;
solAssert(type);
type = m_context.analysis.typeSystem().env().resolve(*type);
type = m_context.env->resolve(*type);
code << IRNames::function(*_contract.fallbackFunction(), *type) << "()\n";
m_context.enqueueFunctionDefinition(_contract.fallbackFunction(), *type);
}
@ -121,6 +121,14 @@ string IRGenerator::generate(ContractDefinition const& _contract)
string IRGenerator::generate(FunctionDefinition const& _function, Type _type)
{
TypeEnvironment newEnv = m_context.env->clone();
ScopedSaveAndRestore envRestore{m_context.env, &newEnv};
auto type = m_context.analysis.annotation<TypeInference>(_function).type;
solAssert(type);
for (auto err: newEnv.unify(*type, _type))
{
solAssert(false, newEnv.typeToString(*type) + " <-> " + newEnv.typeToString(_type));
}
std::stringstream code;
code << "function " << IRNames::function(_function, _type) << "(";
if (_function.parameters().size() > 1)

View File

@ -196,9 +196,10 @@ bool IRGeneratorForStatements::visit(FunctionCall const& _functionCall)
solAssert(false, "Complex function call expressions not supported.");
solAssert(functionDefinition);
auto functionType = m_context.analysis.annotation<TypeInference>(_functionCall).type;
auto functionType = m_context.analysis.annotation<TypeInference>(_functionCall.expression()).type;
solAssert(functionType);
functionType = m_context.analysis.typeSystem().env().resolve(*functionType);
// TODO: get around resolveRecursive by passing the environment further down?
functionType = m_context.env->resolveRecursive(*functionType);
m_context.enqueueFunctionDefinition(functionDefinition, *functionType);
m_code << "let " << IRNames::localVariable(_functionCall) << " := " << IRNames::function(*functionDefinition, *functionType) << "(";
auto const& arguments = _functionCall.arguments();