diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 871e67772..1072f6d6b 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -349,7 +349,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::NonExperimentalEnd && tok < Token::ExperimentalEnd); + tok == Token::Return || tok == Token::Type || tok == Token::Bool || (tok > Token::NonExperimentalEnd && tok < Token::ExperimentalEnd); } constexpr bool isExperimentalSolidityOnlyKeyword(Token tok) { diff --git a/libsolidity/analysis/experimental/TypeInference.cpp b/libsolidity/analysis/experimental/TypeInference.cpp index 6dc8cc973..f1fd5e93a 100644 --- a/libsolidity/analysis/experimental/TypeInference.cpp +++ b/libsolidity/analysis/experimental/TypeInference.cpp @@ -48,6 +48,7 @@ m_typeSystem(_analysis.typeSystem()) m_wordType = m_typeSystem.type(BuiltinType::Word, {}); m_integerType = m_typeSystem.type(BuiltinType::Integer, {}); m_unitType = m_typeSystem.type(BuiltinType::Unit, {}); + m_boolType = m_typeSystem.type(BuiltinType::Bool, {}); m_env = &m_typeSystem.env(); } @@ -272,6 +273,9 @@ bool TypeInference::visit(ElementaryTypeNameExpression const& _expression) case Token::Unit: expressionAnnotation.type = helper.kindType(m_unitType); break; + case Token::Bool: + expressionAnnotation.type = helper.kindType(m_boolType); + break; case Token::Pair: { auto leftType = m_typeSystem.freshTypeVariable(false, {}); @@ -1055,7 +1059,6 @@ optional rationalValue(Literal const& _literal) bool TypeInference::visit(Literal const& _literal) { auto& literalAnnotation = annotation(_literal); - literalAnnotation.type = m_typeSystem.freshTypeVariable(false, {}); if (_literal.token() != Token::Number) { m_errorReporter.typeError(0000_error, _literal.location(), "Only number literals are supported."); @@ -1072,5 +1075,6 @@ bool TypeInference::visit(Literal const& _literal) m_errorReporter.typeError(0000_error, _literal.location(), "Only integers are supported."); return false; } + literalAnnotation.type = m_typeSystem.freshTypeVariable(false, Sort{{TypeClass{BuiltinClass::Integer}}}); return false; } diff --git a/libsolidity/analysis/experimental/TypeInference.h b/libsolidity/analysis/experimental/TypeInference.h index 1841b131a..afbea93e9 100644 --- a/libsolidity/analysis/experimental/TypeInference.h +++ b/libsolidity/analysis/experimental/TypeInference.h @@ -94,6 +94,7 @@ private: Type m_wordType; Type m_integerType; Type m_unitType; + Type m_boolType; std::optional m_currentFunctionType; Annotation& annotation(ASTNode const& _node); diff --git a/libsolidity/analysis/experimental/TypeRegistration.cpp b/libsolidity/analysis/experimental/TypeRegistration.cpp index 05d93a85d..4d95a8d27 100644 --- a/libsolidity/analysis/experimental/TypeRegistration.cpp +++ b/libsolidity/analysis/experimental/TypeRegistration.cpp @@ -41,7 +41,8 @@ m_typeSystem(_analysis.typeSystem()) {BuiltinType::Unit, "unit", 0}, {BuiltinType::Pair, "pair", 2}, {BuiltinType::Word, "word", 0}, - {BuiltinType::Integer, "integer", 0} + {BuiltinType::Integer, "integer", 0}, + {BuiltinType::Bool, "bool", 0} }) m_typeSystem.declareTypeConstructor(type, name, arity); @@ -80,6 +81,23 @@ m_typeSystem(_analysis.typeSystem()) defineBinaryMonoidalOperator(BuiltinClass::Mul, Token::Mul, "mul"); defineBinaryMonoidalOperator(BuiltinClass::Add, Token::Add, "add"); + + auto defineBinaryCompareOperator = [&](BuiltinClass _class, Token _token, std::string _name) { + declareBuiltinClass(_class, [&](Type _typeVar) -> MemberList { + return { + { + _name, + helper.functionType(helper.tupleType({_typeVar, _typeVar}), TypeConstant{BuiltinType::Bool, {}}) + } + }; + }); + annotation().operators[_token] = std::make_tuple(TypeClass{_class}, _name); + }; + defineBinaryCompareOperator(BuiltinClass::Equal, Token::Equal, "eq"); + defineBinaryCompareOperator(BuiltinClass::Less, Token::LessThan, "lt"); + defineBinaryCompareOperator(BuiltinClass::LessOrEqual, Token::LessThanOrEqual, "leq"); + defineBinaryCompareOperator(BuiltinClass::Greater, Token::GreaterThan, "gt"); + defineBinaryCompareOperator(BuiltinClass::GreaterOrEqual, Token::GreaterThanOrEqual, "geq"); } bool TypeRegistration::analyze(SourceUnit const& _sourceUnit) diff --git a/libsolidity/ast/experimental/Type.cpp b/libsolidity/ast/experimental/Type.cpp index 2d0a7dd40..487b97bb5 100644 --- a/libsolidity/ast/experimental/Type.cpp +++ b/libsolidity/ast/experimental/Type.cpp @@ -77,6 +77,16 @@ string TypeClass::toString() const return "*"; case BuiltinClass::Add: return "+"; + case BuiltinClass::Equal: + return "=="; + case BuiltinClass::Less: + return "<"; + case BuiltinClass::LessOrEqual: + return "<="; + case BuiltinClass::Greater: + return ">"; + case BuiltinClass::GreaterOrEqual: + return ">="; } solAssert(false); }, diff --git a/libsolidity/ast/experimental/Type.h b/libsolidity/ast/experimental/Type.h index f409efb60..4fb7e6c8d 100644 --- a/libsolidity/ast/experimental/Type.h +++ b/libsolidity/ast/experimental/Type.h @@ -47,6 +47,7 @@ enum class BuiltinType Unit, Pair, Word, + Bool, Integer }; @@ -75,7 +76,12 @@ enum class BuiltinClass Constraint, Integer, Mul, - Add + Add, + Equal, + Less, + LessOrEqual, + Greater, + GreaterOrEqual }; struct TypeClass diff --git a/libsolidity/ast/experimental/TypeSystem.cpp b/libsolidity/ast/experimental/TypeSystem.cpp index ffa01fa3c..751aa9864 100644 --- a/libsolidity/ast/experimental/TypeSystem.cpp +++ b/libsolidity/ast/experimental/TypeSystem.cpp @@ -85,6 +85,9 @@ std::string TypeEnvironment::canonicalTypeName(Type _type) const case BuiltinType::Word: stream << "word"; break; + case BuiltinType::Bool: + stream << "bool"; + break; case BuiltinType::Integer: stream << "integer"; break; diff --git a/libsolidity/ast/experimental/TypeSystemHelper.cpp b/libsolidity/ast/experimental/TypeSystemHelper.cpp index 44679e08e..cf0a92bd1 100644 --- a/libsolidity/ast/experimental/TypeSystemHelper.cpp +++ b/libsolidity/ast/experimental/TypeSystemHelper.cpp @@ -62,6 +62,8 @@ std::optional experimental::typeConstructorFromToken(langutil:: return BuiltinType::Word; case Token::Integer: return BuiltinType::Integer; + case Token::Bool: + return BuiltinType::Bool; default: return nullopt; } @@ -77,6 +79,16 @@ std::optional experimental::typeClassFromToken(langutil::Token _token return TypeClass{BuiltinClass::Mul}; case Token::Add: return TypeClass{BuiltinClass::Add}; + case Token::Equal: + return TypeClass{BuiltinClass::Equal}; + case Token::LessThan: + return TypeClass{BuiltinClass::Less}; + case Token::LessThanOrEqual: + return TypeClass{BuiltinClass::LessOrEqual}; + case Token::GreaterThan: + return TypeClass{BuiltinClass::Greater}; + case Token::GreaterThanOrEqual: + return TypeClass{BuiltinClass::GreaterOrEqual}; default: return nullopt; } diff --git a/test/libsolidity/semanticTests/experimental/stub.sol b/test/libsolidity/semanticTests/experimental/stub.sol index 16bc55137..7cbe94149 100644 --- a/test/libsolidity/semanticTests/experimental/stub.sol +++ b/test/libsolidity/semanticTests/experimental/stub.sol @@ -32,15 +32,28 @@ instantiation word: * { } } +instantiation word: integer { + function fromInteger(x:integer) -> y:word { + } +} + +instantiation word: == { + function eq(x, y) -> z:bool { + assembly { + x := eq(x, y) + } + } +} + contract C { fallback() external { let x : word; assembly { x := 0x10 } - let w: uint256 = uint256.abs(x); + let w = uint256.abs(x); w = w * w + w; - let y : word = 2; + let y : word; assembly { y := 2 } y = uint256.rep(w) * y; assembly {