mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #14566 from ethereum/new-analysis-defining-builtins
Defining built-ins in experimental analysis
This commit is contained in:
commit
bdd2f02c83
@ -272,14 +272,10 @@ namespace solidity::langutil
|
||||
/* Experimental Solidity specific keywords. */ \
|
||||
K(Class, "class", 0) \
|
||||
K(Instantiation, "instantiation", 0) \
|
||||
K(Word, "word", 0) \
|
||||
K(Integer, "integer", 0) \
|
||||
K(Integer, "Integer", 0) \
|
||||
K(Itself, "itself", 0) \
|
||||
K(Void, "void", 0) \
|
||||
K(Pair, "pair", 0) \
|
||||
K(Fun, "fun", 0) \
|
||||
K(Unit, "unit", 0) \
|
||||
K(StaticAssert, "static_assert", 0) \
|
||||
K(Builtin, "__builtin", 0) \
|
||||
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
|
||||
\
|
||||
/* Illegal token - not able to scan. */ \
|
||||
@ -304,12 +300,7 @@ namespace TokenTraits
|
||||
constexpr size_t count() { return static_cast<size_t>(Token::NUM_TOKENS); }
|
||||
|
||||
// Predicates
|
||||
constexpr bool isElementaryTypeName(Token tok)
|
||||
{
|
||||
return (Token::Int <= tok && tok < Token::TypesEnd) ||
|
||||
tok == Token::Word || tok == Token::Void || tok == Token::Integer ||
|
||||
tok == Token::Pair || tok == Token::Unit || tok == Token::Fun;
|
||||
}
|
||||
constexpr bool isElementaryTypeName(Token tok) { return Token::Int <= tok && tok < Token::TypesEnd; }
|
||||
constexpr bool isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; }
|
||||
constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; }
|
||||
constexpr bool isCommutativeOp(Token op) { return op == Token::BitOr || op == Token::BitXor || op == Token::BitAnd ||
|
||||
@ -350,7 +341,7 @@ namespace TokenTraits
|
||||
{
|
||||
return tok == Token::Assembly || tok == Token::Contract || tok == Token::External || tok == Token::Fallback ||
|
||||
tok == Token::Pragma || tok == Token::Import || tok == Token::As || tok == Token::Function || tok == Token::Let ||
|
||||
tok == Token::Return || tok == Token::Type || tok == Token::Bool || tok == Token::If || tok == Token::Else ||
|
||||
tok == Token::Return || tok == Token::Type || tok == Token::If || tok == Token::Else ||
|
||||
tok == Token::Do || tok == Token::While || tok == Token::For || tok == Token::Continue || tok == Token::Break ||
|
||||
(tok > Token::NonExperimentalEnd && tok < Token::ExperimentalEnd);
|
||||
}
|
||||
|
@ -2596,6 +2596,35 @@ private:
|
||||
std::variant<Token, ASTPointer<IdentifierPath>> m_name;
|
||||
};
|
||||
|
||||
class Builtin: public Expression
|
||||
{
|
||||
public:
|
||||
Builtin(
|
||||
int64_t _id,
|
||||
SourceLocation _location,
|
||||
ASTPointer<ASTString> _nameParameter,
|
||||
SourceLocation _nameParameterLocation
|
||||
):
|
||||
Expression(_id, std::move(_location)),
|
||||
m_nameParameter(std::move(_nameParameter)),
|
||||
m_nameParameterLocation(std::move(_nameParameterLocation))
|
||||
{
|
||||
solAssert(m_nameParameter);
|
||||
}
|
||||
|
||||
void accept(ASTVisitor& _visitor) override;
|
||||
void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
bool experimentalSolidityOnly() const override { return true; }
|
||||
|
||||
ASTString const& nameParameter() const { return *m_nameParameter; }
|
||||
SourceLocation const& nameParameterLocation() const { return m_nameParameterLocation; }
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_nameParameter;
|
||||
SourceLocation m_nameParameterLocation;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ class TypeClassDefinition;
|
||||
class TypeClassInstantiation;
|
||||
class TypeClassName;
|
||||
class TypeDefinition;
|
||||
class Builtin;
|
||||
/// @}
|
||||
|
||||
class VariableScope;
|
||||
|
@ -115,6 +115,7 @@ public:
|
||||
virtual bool visit(TypeClassInstantiation& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TypeDefinition& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TypeClassName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Builtin& _node) { return visitNode(_node); }
|
||||
/// @}
|
||||
|
||||
virtual void endVisit(SourceUnit& _node) { endVisitNode(_node); }
|
||||
@ -178,6 +179,7 @@ public:
|
||||
virtual void endVisit(TypeClassInstantiation& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TypeDefinition& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TypeClassName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Builtin& _node) { endVisitNode(_node); }
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
@ -263,6 +265,7 @@ public:
|
||||
virtual bool visit(TypeClassInstantiation const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TypeDefinition const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(TypeClassName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Builtin const& _node) { return visitNode(_node); }
|
||||
/// @}
|
||||
|
||||
virtual void endVisit(SourceUnit const& _node) { endVisitNode(_node); }
|
||||
@ -326,6 +329,7 @@ public:
|
||||
virtual void endVisit(TypeClassInstantiation const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TypeDefinition const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(TypeClassName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Builtin const& _node) { endVisitNode(_node); }
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
|
@ -1128,6 +1128,18 @@ void TypeClassName::accept(ASTConstVisitor& _visitor) const
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void Builtin::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
_visitor.visit(*this);
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void Builtin::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
_visitor.visit(*this);
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
/// @}
|
||||
|
||||
}
|
||||
|
@ -125,22 +125,6 @@ TypeInference::TypeInference(Analysis& _analysis):
|
||||
defineBinaryCompareOperator(BuiltinClass::LessOrEqual, Token::LessThanOrEqual, "leq");
|
||||
defineBinaryCompareOperator(BuiltinClass::Greater, Token::GreaterThan, "gt");
|
||||
defineBinaryCompareOperator(BuiltinClass::GreaterOrEqual, Token::GreaterThanOrEqual, "geq");
|
||||
|
||||
{
|
||||
auto [members, newlyInserted] = annotation().members.emplace(m_typeSystem.constructor(PrimitiveType::Bool), std::map<std::string, TypeMember>{});
|
||||
solAssert(newlyInserted);
|
||||
members->second.emplace("abs", TypeMember{helper.functionType(m_wordType, m_boolType)});
|
||||
members->second.emplace("rep", TypeMember{helper.functionType(m_boolType, m_wordType)});
|
||||
}
|
||||
{
|
||||
Type first = m_typeSystem.freshTypeVariable({});
|
||||
Type second = m_typeSystem.freshTypeVariable({});
|
||||
Type pairType = m_typeSystem.type(PrimitiveType::Pair, {first, second});
|
||||
auto [members, newlyInserted] = annotation().members.emplace(m_typeSystem.constructor(PrimitiveType::Pair), std::map<std::string, TypeMember>{});
|
||||
solAssert(newlyInserted);
|
||||
members->second.emplace("first", TypeMember{helper.functionType(pairType, first)});
|
||||
members->second.emplace("second", TypeMember{helper.functionType(pairType, second)});
|
||||
}
|
||||
}
|
||||
|
||||
bool TypeInference::analyze(SourceUnit const& _sourceUnit)
|
||||
@ -307,48 +291,6 @@ bool TypeInference::visit(InlineAssembly const& _inlineAssembly)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeInference::visit(ElementaryTypeNameExpression const& _expression)
|
||||
{
|
||||
auto& expressionAnnotation = annotation(_expression);
|
||||
solAssert(!expressionAnnotation.type);
|
||||
|
||||
switch (m_expressionContext)
|
||||
{
|
||||
case ExpressionContext::Term:
|
||||
case ExpressionContext::Type:
|
||||
if (auto constructor = m_analysis.annotation<TypeRegistration>(_expression).typeConstructor)
|
||||
{
|
||||
std::vector<Type> arguments;
|
||||
std::generate_n(std::back_inserter(arguments), m_typeSystem.constructorInfo(*constructor).arguments(), [&]() {
|
||||
return m_typeSystem.freshTypeVariable({});
|
||||
});
|
||||
// TODO: get rid of the distinction (assign a function on unit for the empty case)? Ambiguity?
|
||||
if (arguments.empty() || m_expressionContext == ExpressionContext::Term)
|
||||
expressionAnnotation.type = m_typeSystem.type(*constructor, arguments);
|
||||
else
|
||||
{
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
expressionAnnotation.type =
|
||||
helper.typeFunctionType(
|
||||
helper.tupleType(arguments),
|
||||
m_typeSystem.type(*constructor, arguments)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorReporter.typeError(4107_error, _expression.location(), "No type constructor registered for elementary type name.");
|
||||
expressionAnnotation.type = m_typeSystem.freshTypeVariable({});
|
||||
}
|
||||
break;
|
||||
case ExpressionContext::Sort:
|
||||
m_errorReporter.typeError(2024_error, _expression.location(), "Elementary type name expression not supported in sort context.");
|
||||
expressionAnnotation.type = m_typeSystem.freshTypeVariable({});
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeInference::visit(BinaryOperation const& _binaryOperation)
|
||||
{
|
||||
auto& operationAnnotation = annotation(_binaryOperation);
|
||||
@ -825,6 +767,8 @@ void TypeInference::endVisit(MemberAccess const& _memberAccess)
|
||||
|
||||
bool TypeInference::visit(TypeDefinition const& _typeDefinition)
|
||||
{
|
||||
bool isBuiltIn = dynamic_cast<Builtin const*>(_typeDefinition.typeExpression());
|
||||
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
auto& typeDefinitionAnnotation = annotation(_typeDefinition);
|
||||
if (typeDefinitionAnnotation.type)
|
||||
@ -833,14 +777,6 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
|
||||
if (_typeDefinition.arguments())
|
||||
_typeDefinition.arguments()->accept(*this);
|
||||
|
||||
std::optional<Type> underlyingType;
|
||||
if (_typeDefinition.typeExpression())
|
||||
{
|
||||
ScopedSaveAndRestore expressionContext{m_expressionContext, ExpressionContext::Type};
|
||||
_typeDefinition.typeExpression()->accept(*this);
|
||||
underlyingType = annotation(*_typeDefinition.typeExpression()).type;
|
||||
}
|
||||
|
||||
std::vector<Type> arguments;
|
||||
if (_typeDefinition.arguments())
|
||||
for (size_t i = 0; i < _typeDefinition.arguments()->parameters().size(); ++i)
|
||||
@ -852,6 +788,19 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
|
||||
else
|
||||
typeDefinitionAnnotation.type = helper.typeFunctionType(helper.tupleType(arguments), definedType);
|
||||
|
||||
std::optional<Type> underlyingType;
|
||||
|
||||
if (isBuiltIn)
|
||||
// TODO: This special case should eventually become user-definable.
|
||||
underlyingType = m_wordType;
|
||||
else if (_typeDefinition.typeExpression())
|
||||
{
|
||||
ScopedSaveAndRestore expressionContext{m_expressionContext, ExpressionContext::Type};
|
||||
_typeDefinition.typeExpression()->accept(*this);
|
||||
|
||||
underlyingType = annotation(*_typeDefinition.typeExpression()).type;
|
||||
}
|
||||
|
||||
TypeConstructor constructor = typeConstructor(&_typeDefinition);
|
||||
auto [members, newlyInserted] = annotation().members.emplace(constructor, std::map<std::string, TypeMember>{});
|
||||
solAssert(newlyInserted, fmt::format("Members of type '{}' are already defined.", m_typeSystem.constructorInfo(constructor).name));
|
||||
@ -860,6 +809,15 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
|
||||
members->second.emplace("abs", TypeMember{helper.functionType(*underlyingType, definedType)});
|
||||
members->second.emplace("rep", TypeMember{helper.functionType(definedType, *underlyingType)});
|
||||
}
|
||||
|
||||
if (helper.isPrimitiveType(definedType, PrimitiveType::Pair))
|
||||
{
|
||||
solAssert(isBuiltIn);
|
||||
solAssert(arguments.size() == 2);
|
||||
members->second.emplace("first", TypeMember{helper.functionType(definedType, arguments[0])});
|
||||
members->second.emplace("second", TypeMember{helper.functionType(definedType, arguments[1])});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,6 @@ public:
|
||||
|
||||
bool visit(MemberAccess const& _memberAccess) override;
|
||||
void endVisit(MemberAccess const& _memberAccess) override;
|
||||
bool visit(ElementaryTypeNameExpression const& _expression) override;
|
||||
|
||||
bool visit(TypeClassDefinition const& _typeClassDefinition) override;
|
||||
bool visit(TypeClassInstantiation const& _typeClassInstantiation) override;
|
||||
|
@ -56,32 +56,30 @@ bool TypeRegistration::visit(TypeClassDefinition const& _typeClassDefinition)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TypeRegistration::visit(ElementaryTypeName const& _typeName)
|
||||
bool TypeRegistration::visit(Builtin const& _builtin)
|
||||
{
|
||||
if (annotation(_typeName).typeConstructor)
|
||||
if (annotation(_builtin).typeConstructor)
|
||||
return false;
|
||||
annotation(_typeName).typeConstructor = [&]() -> std::optional<TypeConstructor> {
|
||||
switch (_typeName.typeName().token())
|
||||
{
|
||||
case Token::Void:
|
||||
return m_typeSystem.constructor(PrimitiveType::Void);
|
||||
case Token::Fun:
|
||||
return m_typeSystem.constructor(PrimitiveType::Function);
|
||||
case Token::Unit:
|
||||
return m_typeSystem.constructor(PrimitiveType::Unit);
|
||||
case Token::Pair:
|
||||
return m_typeSystem.constructor(PrimitiveType::Pair);
|
||||
case Token::Word:
|
||||
return m_typeSystem.constructor(PrimitiveType::Word);
|
||||
case Token::Integer:
|
||||
return m_typeSystem.constructor(PrimitiveType::Integer);
|
||||
case Token::Bool:
|
||||
return m_typeSystem.constructor(PrimitiveType::Bool);
|
||||
default:
|
||||
m_errorReporter.fatalTypeError(7758_error, _typeName.location(), "Expected primitive type.");
|
||||
|
||||
auto primitiveType = [&](std::string _name) -> std::optional<PrimitiveType> {
|
||||
if (_name == "void") return PrimitiveType::Void;
|
||||
if (_name == "fun") return PrimitiveType::Function;
|
||||
if (_name == "unit") return PrimitiveType::Unit;
|
||||
if (_name == "pair") return PrimitiveType::Pair;
|
||||
if (_name == "word") return PrimitiveType::Word;
|
||||
if (_name == "integer") return PrimitiveType::Integer;
|
||||
if (_name == "bool") return PrimitiveType::Bool;
|
||||
return std::nullopt;
|
||||
}
|
||||
}();
|
||||
}(_builtin.nameParameter());
|
||||
|
||||
if (!primitiveType.has_value())
|
||||
m_errorReporter.fatalTypeError(
|
||||
7758_error,
|
||||
_builtin.location(),
|
||||
"Expected the name of a built-in primitive type."
|
||||
);
|
||||
|
||||
annotation(_builtin).typeConstructor = m_typeSystem.constructor(primitiveType.value());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -165,15 +163,41 @@ bool TypeRegistration::visit(TypeClassInstantiation const& _typeClassInstantiati
|
||||
|
||||
bool TypeRegistration::visit(TypeDefinition const& _typeDefinition)
|
||||
{
|
||||
if (annotation(_typeDefinition).typeConstructor)
|
||||
return false;
|
||||
return !annotation(_typeDefinition).typeConstructor.has_value();
|
||||
}
|
||||
|
||||
void TypeRegistration::endVisit(TypeDefinition const& _typeDefinition)
|
||||
{
|
||||
if (annotation(_typeDefinition).typeConstructor.has_value())
|
||||
return;
|
||||
|
||||
if (auto const* builtin = dynamic_cast<Builtin const*>(_typeDefinition.typeExpression()))
|
||||
{
|
||||
auto [previousDefinitionIt, inserted] = annotation().builtinTypeDefinitions.try_emplace(
|
||||
builtin->nameParameter(),
|
||||
&_typeDefinition
|
||||
);
|
||||
|
||||
if (inserted)
|
||||
annotation(_typeDefinition).typeConstructor = annotation(*builtin).typeConstructor;
|
||||
else
|
||||
{
|
||||
auto const& [builtinName, previousDefinition] = *previousDefinitionIt;
|
||||
m_errorReporter.typeError(
|
||||
9609_error,
|
||||
_typeDefinition.location(),
|
||||
SecondarySourceLocation{}.append("Previous definition:", previousDefinition->location()),
|
||||
"Duplicate builtin type definition."
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
annotation(_typeDefinition).typeConstructor = m_typeSystem.declareTypeConstructor(
|
||||
_typeDefinition.name(),
|
||||
"t_" + *_typeDefinition.annotation().canonicalName + "_" + util::toString(_typeDefinition.id()),
|
||||
_typeDefinition.arguments() ? _typeDefinition.arguments()->parameters().size() : 0,
|
||||
&_typeDefinition
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
TypeRegistration::Annotation& TypeRegistration::annotation(ASTNode const& _node)
|
||||
|
@ -35,13 +35,14 @@ public:
|
||||
{
|
||||
// For type class definitions.
|
||||
TypeClassInstantiations instantiations;
|
||||
// For type definitions, type class definitions, type names and type name expressions.
|
||||
// For builtins, type definitions, type class definitions, type names and type name expressions.
|
||||
std::optional<TypeConstructor> typeConstructor;
|
||||
};
|
||||
struct GlobalAnnotation
|
||||
{
|
||||
std::map<PrimitiveClass, TypeClassInstantiations> primitiveClassInstantiations;
|
||||
std::map<BuiltinClass, TypeClassInstantiations> builtinClassInstantiations;
|
||||
std::map<std::string, TypeDefinition const*> builtinTypeDefinitions;
|
||||
};
|
||||
TypeRegistration(Analysis& _analysis);
|
||||
|
||||
@ -50,9 +51,10 @@ private:
|
||||
bool visit(TypeClassDefinition const& _typeClassDefinition) override;
|
||||
bool visit(TypeClassInstantiation const& _typeClassInstantiation) override;
|
||||
bool visit(TypeDefinition const& _typeDefinition) override;
|
||||
void endVisit(TypeDefinition const& _typeDefinition) override;
|
||||
bool visit(UserDefinedTypeName const& _typeName) override;
|
||||
void endVisit(ElementaryTypeNameExpression const& _typeName) override;
|
||||
bool visit(ElementaryTypeName const& _typeName) override;
|
||||
bool visit(Builtin const& _builtin) override;
|
||||
Annotation& annotation(ASTNode const& _node);
|
||||
GlobalAnnotation& annotation();
|
||||
|
||||
|
@ -66,7 +66,7 @@ std::optional<TypeConstructor> experimental::typeConstructorFromToken(Analysis c
|
||||
return typeSystem.builtinConstructor(BuiltinType::Pair);
|
||||
case Token::Word:
|
||||
return typeSystem.builtinConstructor(BuiltinType::Word);
|
||||
case Token::Integer:
|
||||
case Token::IntegerType:
|
||||
return typeSystem.builtinConstructor(BuiltinType::Integer);
|
||||
case Token::Bool:
|
||||
return typeSystem.builtinConstructor(BuiltinType::Bool);
|
||||
@ -224,6 +224,14 @@ bool TypeSystemHelpers::isTypeConstant(Type _type) const
|
||||
}, _type);
|
||||
}
|
||||
|
||||
bool TypeSystemHelpers::isPrimitiveType(Type _type, PrimitiveType _primitiveType) const
|
||||
{
|
||||
if (!isTypeConstant(_type))
|
||||
return false;
|
||||
auto constructor = std::get<0>(destTypeConstant(_type));
|
||||
return constructor == typeSystem.constructor(_primitiveType);
|
||||
}
|
||||
|
||||
experimental::Type TypeSystemHelpers::functionType(experimental::Type _argType, experimental::Type _resultType) const
|
||||
{
|
||||
return typeSystem.type(PrimitiveType::Function, {_argType, _resultType});
|
||||
@ -239,10 +247,7 @@ std::tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destFuncti
|
||||
|
||||
bool TypeSystemHelpers::isFunctionType(Type _type) const
|
||||
{
|
||||
if (!isTypeConstant(_type))
|
||||
return false;
|
||||
auto constructor = std::get<0>(destTypeConstant(_type));
|
||||
return constructor == typeSystem.constructor(PrimitiveType::Function);
|
||||
return isPrimitiveType(_type, PrimitiveType::Function);
|
||||
}
|
||||
|
||||
experimental::Type TypeSystemHelpers::typeFunctionType(experimental::Type _argType, experimental::Type _resultType) const
|
||||
@ -260,10 +265,7 @@ std::tuple<experimental::Type, experimental::Type> TypeSystemHelpers::destTypeFu
|
||||
|
||||
bool TypeSystemHelpers::isTypeFunctionType(Type _type) const
|
||||
{
|
||||
if (!isTypeConstant(_type))
|
||||
return false;
|
||||
auto constructor = std::get<0>(destTypeConstant(_type));
|
||||
return constructor == typeSystem.constructor(PrimitiveType::TypeFunction);
|
||||
return isPrimitiveType(_type, PrimitiveType::TypeFunction);
|
||||
}
|
||||
|
||||
std::vector<experimental::Type> TypeEnvironmentHelpers::typeVars(Type _type) const
|
||||
|
@ -35,6 +35,7 @@ struct TypeSystemHelpers
|
||||
TypeSystem const& typeSystem;
|
||||
std::tuple<TypeConstructor, std::vector<Type>> destTypeConstant(Type _type) const;
|
||||
bool isTypeConstant(Type _type) const;
|
||||
bool isPrimitiveType(Type _type, PrimitiveType _primitiveType) const;
|
||||
Type tupleType(std::vector<Type> _elements) const;
|
||||
std::vector<Type> destTupleType(Type _tupleType) const;
|
||||
Type sumType(std::vector<Type> _elements) const;
|
||||
|
@ -1831,7 +1831,22 @@ ASTPointer<TypeDefinition> Parser::parseTypeDefinition()
|
||||
if (m_scanner->currentToken() == Token::Assign)
|
||||
{
|
||||
expectToken(Token::Assign);
|
||||
|
||||
if (m_scanner->currentToken() != Token::Builtin)
|
||||
expression = parseExpression();
|
||||
else
|
||||
{
|
||||
expectToken(Token::Builtin);
|
||||
expectToken(Token::LParen);
|
||||
|
||||
expression = nodeFactory.createNode<Builtin>(
|
||||
std::make_shared<std::string>(m_scanner->currentLiteral()),
|
||||
m_scanner->currentLocation()
|
||||
);
|
||||
|
||||
expectToken(Token::StringLiteral);
|
||||
expectToken(Token::RParen);
|
||||
}
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
expectToken(Token::Semicolon);
|
||||
|
@ -1,5 +1,9 @@
|
||||
pragma experimental solidity;
|
||||
|
||||
type word = __builtin("word");
|
||||
type bool = __builtin("bool");
|
||||
type integer = __builtin("integer");
|
||||
|
||||
type uint256 = word;
|
||||
|
||||
instantiation uint256: + {
|
||||
@ -34,7 +38,7 @@ instantiation word: * {
|
||||
}
|
||||
}
|
||||
|
||||
instantiation word: integer {
|
||||
instantiation word: Integer {
|
||||
function fromInteger(x:integer) -> word {
|
||||
//x + x;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
pragma experimental solidity;
|
||||
|
||||
type word = __builtin("word");
|
||||
type bool = __builtin("bool");
|
||||
|
||||
type Cat = word;
|
||||
type Dog = word;
|
||||
|
||||
@ -59,7 +62,6 @@ contract C {
|
||||
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ====
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// () -> 1, 0
|
||||
|
@ -0,0 +1,90 @@
|
||||
pragma experimental solidity;
|
||||
|
||||
type void = __builtin("void");
|
||||
|
||||
type bool = __builtin("bool");
|
||||
type word = __builtin("word");
|
||||
type integer = __builtin("integer");
|
||||
type unit = __builtin("unit");
|
||||
|
||||
type fun(T, U) = __builtin("fun");
|
||||
type pair(T, U) = __builtin("pair");
|
||||
|
||||
contract C {
|
||||
fallback() external {
|
||||
let v: void;
|
||||
|
||||
let b: bool;
|
||||
bool.abs(bool.rep(b));
|
||||
|
||||
let w: word;
|
||||
let i: integer;
|
||||
let u: unit;
|
||||
|
||||
let f: fun(word, bool);
|
||||
b = f(w);
|
||||
|
||||
let p: pair(bool, word);
|
||||
pair.first(p);
|
||||
pair.second(p);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
// Info 4164: (31-61): Inferred type: void
|
||||
// Info 4164: (63-93): Inferred type: bool
|
||||
// Info 4164: (94-124): Inferred type: word
|
||||
// Info 4164: (125-161): Inferred type: integer
|
||||
// Info 4164: (162-192): Inferred type: ()
|
||||
// Info 4164: (194-228): Inferred type: tfun(('u:type, 'v:type), 'u:type -> 'v:type)
|
||||
// Info 4164: (202-208): Inferred type: ('s:type, 't:type)
|
||||
// Info 4164: (203-204): Inferred type: 's:type
|
||||
// Info 4164: (206-207): Inferred type: 't:type
|
||||
// Info 4164: (229-265): Inferred type: tfun(('y:type, 'z:type), ('y:type, 'z:type))
|
||||
// Info 4164: (238-244): Inferred type: ('w:type, 'x:type)
|
||||
// Info 4164: (239-240): Inferred type: 'w:type
|
||||
// Info 4164: (242-243): Inferred type: 'x:type
|
||||
// Info 4164: (284-584): Inferred type: () -> ()
|
||||
// Info 4164: (292-294): Inferred type: ()
|
||||
// Info 4164: (318-325): Inferred type: void
|
||||
// Info 4164: (321-325): Inferred type: void
|
||||
// Info 4164: (340-347): Inferred type: bool
|
||||
// Info 4164: (343-347): Inferred type: bool
|
||||
// Info 4164: (357-378): Inferred type: bool
|
||||
// Info 4164: (357-365): Inferred type: word -> bool
|
||||
// Info 4164: (357-361): Inferred type: bool
|
||||
// Info 4164: (366-377): Inferred type: word
|
||||
// Info 4164: (366-374): Inferred type: bool -> word
|
||||
// Info 4164: (366-370): Inferred type: bool
|
||||
// Info 4164: (375-376): Inferred type: bool
|
||||
// Info 4164: (393-400): Inferred type: word
|
||||
// Info 4164: (396-400): Inferred type: word
|
||||
// Info 4164: (414-424): Inferred type: integer
|
||||
// Info 4164: (417-424): Inferred type: integer
|
||||
// Info 4164: (438-445): Inferred type: ()
|
||||
// Info 4164: (441-445): Inferred type: ()
|
||||
// Info 4164: (460-478): Inferred type: word -> bool
|
||||
// Info 4164: (463-478): Inferred type: word -> bool
|
||||
// Info 4164: (463-466): Inferred type: tfun((word, bool), word -> bool)
|
||||
// Info 4164: (467-471): Inferred type: word
|
||||
// Info 4164: (473-477): Inferred type: bool
|
||||
// Info 4164: (488-496): Inferred type: bool
|
||||
// Info 4164: (488-489): Inferred type: bool
|
||||
// Info 4164: (492-496): Inferred type: bool
|
||||
// Info 4164: (492-493): Inferred type: word -> bool
|
||||
// Info 4164: (494-495): Inferred type: word
|
||||
// Info 4164: (511-530): Inferred type: (bool, word)
|
||||
// Info 4164: (514-530): Inferred type: (bool, word)
|
||||
// Info 4164: (514-518): Inferred type: tfun((bool, word), (bool, word))
|
||||
// Info 4164: (519-523): Inferred type: bool
|
||||
// Info 4164: (525-529): Inferred type: word
|
||||
// Info 4164: (540-553): Inferred type: bool
|
||||
// Info 4164: (540-550): Inferred type: (bool, word) -> bool
|
||||
// Info 4164: (540-544): Inferred type: ('cb:type, 'cc:type)
|
||||
// Info 4164: (551-552): Inferred type: (bool, word)
|
||||
// Info 4164: (563-577): Inferred type: word
|
||||
// Info 4164: (563-574): Inferred type: (bool, word) -> word
|
||||
// Info 4164: (563-567): Inferred type: ('ci:type, 'cj:type)
|
||||
// Info 4164: (575-576): Inferred type: (bool, word)
|
@ -0,0 +1,17 @@
|
||||
pragma experimental solidity;
|
||||
|
||||
type void1 = __builtin("void");
|
||||
type void2 = __builtin("void");
|
||||
|
||||
type word1 = __builtin("word");
|
||||
type word2 = __builtin("word");
|
||||
|
||||
type fun1(T, U) = __builtin("fun");
|
||||
type fun2(T, U) = __builtin("fun");
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
// TypeError 9609: (63-94): Duplicate builtin type definition.
|
||||
// TypeError 9609: (128-159): Duplicate builtin type definition.
|
||||
// TypeError 9609: (197-232): Duplicate builtin type definition.
|
@ -0,0 +1,8 @@
|
||||
pragma experimental solidity;
|
||||
|
||||
type someUnknownType = __builtin("someUnknownType");
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
// TypeError 7758: (31-81): Expected the name of a built-in primitive type.
|
Loading…
Reference in New Issue
Block a user