mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Experimental standard library
Change import syntax and cover with tests
This commit is contained in:
parent
f1d2eda795
commit
47969adf91
@ -140,6 +140,7 @@ add_subdirectory(libevmasm)
|
|||||||
add_subdirectory(libyul)
|
add_subdirectory(libyul)
|
||||||
add_subdirectory(libsolidity)
|
add_subdirectory(libsolidity)
|
||||||
add_subdirectory(libsolc)
|
add_subdirectory(libsolc)
|
||||||
|
add_subdirectory(libstdlib)
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
|
|
||||||
if (NOT EMSCRIPTEN)
|
if (NOT EMSCRIPTEN)
|
||||||
|
@ -59,6 +59,8 @@
|
|||||||
#include <libsolidity/codegen/ir/Common.h>
|
#include <libsolidity/codegen/ir/Common.h>
|
||||||
#include <libsolidity/codegen/ir/IRGenerator.h>
|
#include <libsolidity/codegen/ir/IRGenerator.h>
|
||||||
|
|
||||||
|
#include <libstdlib/stdlib.h>
|
||||||
|
|
||||||
#include <libyul/YulString.h>
|
#include <libyul/YulString.h>
|
||||||
#include <libyul/AsmPrinter.h>
|
#include <libyul/AsmPrinter.h>
|
||||||
#include <libyul/AsmJsonConverter.h>
|
#include <libyul/AsmJsonConverter.h>
|
||||||
@ -95,6 +97,7 @@ using namespace std;
|
|||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
|
using namespace solidity::stdlib;
|
||||||
|
|
||||||
using solidity::util::errinfo_comment;
|
using solidity::util::errinfo_comment;
|
||||||
|
|
||||||
@ -369,6 +372,15 @@ bool CompilerStack::parse()
|
|||||||
for (auto const& import: ASTNode::filteredNodes<ImportDirective>(source.ast->nodes()))
|
for (auto const& import: ASTNode::filteredNodes<ImportDirective>(source.ast->nodes()))
|
||||||
{
|
{
|
||||||
solAssert(!import->path().empty(), "Import path cannot be empty.");
|
solAssert(!import->path().empty(), "Import path cannot be empty.");
|
||||||
|
// Check whether the import directive is for the standard library,
|
||||||
|
// and if yes, add specified file to source units to be parsed.
|
||||||
|
auto it = stdlib::sources.find(import->path());
|
||||||
|
if (it != stdlib::sources.end())
|
||||||
|
{
|
||||||
|
auto [name, content] = *it;
|
||||||
|
m_sources[name].charStream = make_unique<CharStream>(content, name);
|
||||||
|
sourcesToParse.push_back(name);
|
||||||
|
}
|
||||||
|
|
||||||
// The current value of `path` is the absolute path as seen from this source file.
|
// The current value of `path` is the absolute path as seen from this source file.
|
||||||
// We first have to apply remappings before we can store the actual absolute path
|
// We first have to apply remappings before we can store the actual absolute path
|
||||||
|
@ -271,9 +271,9 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
|||||||
SourceLocation unitAliasLocation{};
|
SourceLocation unitAliasLocation{};
|
||||||
ImportDirective::SymbolAliasList symbolAliases;
|
ImportDirective::SymbolAliasList symbolAliases;
|
||||||
|
|
||||||
if (m_scanner->currentToken() == Token::StringLiteral)
|
if (isQuotedPath() || isStdlibPath())
|
||||||
{
|
{
|
||||||
path = getLiteralAndAdvance();
|
path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
|
||||||
if (m_scanner->currentToken() == Token::As)
|
if (m_scanner->currentToken() == Token::As)
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
@ -315,9 +315,9 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
|||||||
if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from")
|
if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from")
|
||||||
fatalParserError(8208_error, "Expected \"from\".");
|
fatalParserError(8208_error, "Expected \"from\".");
|
||||||
advance();
|
advance();
|
||||||
if (m_scanner->currentToken() != Token::StringLiteral)
|
if (!isQuotedPath() && !isStdlibPath())
|
||||||
fatalParserError(6845_error, "Expected import path.");
|
fatalParserError(6845_error, "Expected import path.");
|
||||||
path = getLiteralAndAdvance();
|
path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
|
||||||
}
|
}
|
||||||
if (path->empty())
|
if (path->empty())
|
||||||
fatalParserError(6326_error, "Import path cannot be empty.");
|
fatalParserError(6326_error, "Import path cannot be empty.");
|
||||||
@ -2486,4 +2486,25 @@ ASTPointer<ASTString> Parser::getLiteralAndAdvance()
|
|||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::isQuotedPath() const
|
||||||
|
{
|
||||||
|
return m_scanner->currentToken() == Token::StringLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::isStdlibPath() const
|
||||||
|
{
|
||||||
|
return m_experimentalSolidityEnabledInCurrentSourceUnit
|
||||||
|
&& m_scanner->currentToken() == Token::Identifier
|
||||||
|
&& m_scanner->currentLiteral() == "std";
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPointer<ASTString> Parser::getStdlibImportPathAndAdvance()
|
||||||
|
{
|
||||||
|
ASTPointer<ASTString> std = expectIdentifierToken();
|
||||||
|
if (m_scanner->currentToken() == Token::Period)
|
||||||
|
advance();
|
||||||
|
ASTPointer<ASTString> library = expectIdentifierToken();
|
||||||
|
return make_shared<ASTString>(*std + "." + *library);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,11 @@ private:
|
|||||||
ASTPointer<ASTString> getLiteralAndAdvance();
|
ASTPointer<ASTString> getLiteralAndAdvance();
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
bool isQuotedPath() const;
|
||||||
|
bool isStdlibPath() const;
|
||||||
|
|
||||||
|
ASTPointer<ASTString> getStdlibImportPathAndAdvance();
|
||||||
|
|
||||||
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
|
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
|
||||||
ASTPointer<ParameterList> createEmptyParameterList();
|
ASTPointer<ParameterList> createEmptyParameterList();
|
||||||
|
|
||||||
|
18
libstdlib/CMakeLists.txt
Normal file
18
libstdlib/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# This will re-generate the headers if any file within src was modified.
|
||||||
|
set_directory_properties(PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/stdlib/src/)
|
||||||
|
|
||||||
|
set(STDLIB stub)
|
||||||
|
set(GENERATED_STDLIB_HEADERS)
|
||||||
|
foreach(src IN LISTS STDLIB)
|
||||||
|
set(STDLIB_FILE ${CMAKE_SOURCE_DIR}/libstdlib/src/${src}.sol)
|
||||||
|
file(READ ${STDLIB_FILE} STDLIB_FILE_CONTENT HEX)
|
||||||
|
string(REGEX MATCHALL ".." STDLIB_FILE_CONTENT "${STDLIB_FILE_CONTENT}")
|
||||||
|
list(REMOVE_ITEM STDLIB_FILE_CONTENT "0d")
|
||||||
|
string(REGEX REPLACE ";" ",\n\t0x" STDLIB_FILE_CONTENT "${STDLIB_FILE_CONTENT}")
|
||||||
|
set(STDLIB_FILE_CONTENT "0x${STDLIB_FILE_CONTENT}")
|
||||||
|
set(STDLIB_FILE_NAME ${src})
|
||||||
|
configure_file("${CMAKE_SOURCE_DIR}/libstdlib/stdlib.src.h.in" ${CMAKE_BINARY_DIR}/include/libstdlib/${src}.h NEWLINE_STYLE LF @ONLY)
|
||||||
|
list(APPEND GENERATED_STDLIB_HEADERS ${CMAKE_BINARY_DIR}/include/libstdlib/${src}.h)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
configure_file("${CMAKE_SOURCE_DIR}/libstdlib/stdlib.h.in" ${CMAKE_BINARY_DIR}/include/libstdlib/stdlib.h NEWLINE_STYLE LF @ONLY)
|
9
libstdlib/src/stub.sol
Normal file
9
libstdlib/src/stub.sol
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
pragma solidity >=0.0;
|
||||||
|
|
||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
function identity(uint256 x) pure returns (uint256)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
15
libstdlib/stdlib.h.in
Normal file
15
libstdlib/stdlib.h.in
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "libstdlib/stub.h"
|
||||||
|
|
||||||
|
namespace solidity::stdlib
|
||||||
|
{
|
||||||
|
|
||||||
|
static std::map<std::string, std::string> sources = {
|
||||||
|
{ "std.stub", stub }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace solidity::stdlib
|
13
libstdlib/stdlib.src.h.in
Normal file
13
libstdlib/stdlib.src.h.in
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// The generation of this file is defined in stdlib/CMakeLists.txt.
|
||||||
|
// This file was generated by using the content of stdlib/src/@STDLIB_FILE_NAME@.sol.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace solidity::stdlib
|
||||||
|
{
|
||||||
|
|
||||||
|
static char const @STDLIB_FILE_NAME@[] = {
|
||||||
|
@STDLIB_FILE_CONTENT@, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace solidity::stdlib
|
@ -209,7 +209,7 @@ esac
|
|||||||
# boost_filesystem_bug specifically tests a local fix for a boost::filesystem
|
# boost_filesystem_bug specifically tests a local fix for a boost::filesystem
|
||||||
# bug. Since the test involves a malformed path, there is no point in running
|
# bug. Since the test involves a malformed path, there is no point in running
|
||||||
# tests on it. See https://github.com/boostorg/filesystem/issues/176
|
# tests on it. See https://github.com/boostorg/filesystem/issues/176
|
||||||
IMPORT_TEST_FILES=$(find "${TEST_DIRS[@]}" -name "*.sol" -and -not -name "boost_filesystem_bug.sol")
|
IMPORT_TEST_FILES=$(find "${TEST_DIRS[@]}" -name "*.sol" -and -not -name "boost_filesystem_bug.sol" -not -path "*/experimental/*")
|
||||||
|
|
||||||
NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)"
|
NSOURCES="$(echo "${IMPORT_TEST_FILES}" | wc -l)"
|
||||||
echo "Looking at ${NSOURCES} .sol files..."
|
echo "Looking at ${NSOURCES} .sol files..."
|
||||||
|
@ -110,7 +110,7 @@ do
|
|||||||
SOL_FILES+=("$line")
|
SOL_FILES+=("$line")
|
||||||
done < <(
|
done < <(
|
||||||
grep --include "*.sol" -riL -E \
|
grep --include "*.sol" -riL -E \
|
||||||
"^\/\/ (Syntax|Type|Declaration)Error|^\/\/ ParserError (1684|2837|3716|3997|5333|6275|6281|6933|7319|8185|7637)|^==== Source:" \
|
"^\/\/ (Syntax|Type|Declaration)Error|^\/\/ ParserError (1684|2837|3716|3997|5333|6275|6281|6933|7319|8185|7637)|^==== Source:|^pragma experimental solidity;" \
|
||||||
"${ROOT_DIR}/test/libsolidity/syntaxTests" \
|
"${ROOT_DIR}/test/libsolidity/syntaxTests" \
|
||||||
"${ROOT_DIR}/test/libsolidity/semanticTests" |
|
"${ROOT_DIR}/test/libsolidity/semanticTests" |
|
||||||
# Skipping the unicode tests as I couldn't adapt the lexical grammar to recursively counting RLO/LRO/PDF's.
|
# Skipping the unicode tests as I couldn't adapt the lexical grammar to recursively counting RLO/LRO/PDF's.
|
||||||
|
@ -123,25 +123,28 @@ void SyntaxTest::filterObtainedErrors()
|
|||||||
string sourceName;
|
string sourceName;
|
||||||
if (SourceLocation const* location = currentError->sourceLocation())
|
if (SourceLocation const* location = currentError->sourceLocation())
|
||||||
{
|
{
|
||||||
|
locationStart = location->start;
|
||||||
|
locationEnd = location->end;
|
||||||
solAssert(location->sourceName, "");
|
solAssert(location->sourceName, "");
|
||||||
sourceName = *location->sourceName;
|
sourceName = *location->sourceName;
|
||||||
solAssert(m_sources.sources.count(sourceName) == 1, "");
|
if(m_sources.sources.count(sourceName) == 1)
|
||||||
|
|
||||||
int preambleSize =
|
|
||||||
static_cast<int>(compiler().charStream(sourceName).size()) -
|
|
||||||
static_cast<int>(m_sources.sources[sourceName].size());
|
|
||||||
solAssert(preambleSize >= 0, "");
|
|
||||||
|
|
||||||
// ignore the version & license pragma inserted by the testing tool when calculating locations.
|
|
||||||
if (location->start != -1)
|
|
||||||
{
|
{
|
||||||
solAssert(location->start >= preambleSize, "");
|
int preambleSize =
|
||||||
locationStart = location->start - preambleSize;
|
static_cast<int>(compiler().charStream(sourceName).size()) -
|
||||||
}
|
static_cast<int>(m_sources.sources[sourceName].size());
|
||||||
if (location->end != -1)
|
solAssert(preambleSize >= 0, "");
|
||||||
{
|
|
||||||
solAssert(location->end >= preambleSize, "");
|
// ignore the version & license pragma inserted by the testing tool when calculating locations.
|
||||||
locationEnd = location->end - preambleSize;
|
if (location->start != -1)
|
||||||
|
{
|
||||||
|
solAssert(location->start >= preambleSize, "");
|
||||||
|
locationStart = location->start - preambleSize;
|
||||||
|
}
|
||||||
|
if (location->end != -1)
|
||||||
|
{
|
||||||
|
solAssert(location->end >= preambleSize, "");
|
||||||
|
locationEnd = location->end - preambleSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_errorList.emplace_back(SyntaxTestError{
|
m_errorList.emplace_back(SyntaxTestError{
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
import std.stub;
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=constantinople
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,8 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
import std.stub as stub;
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=constantinople
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,8 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
import { identity } from std.stub;
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=constantinople
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,8 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
import * as stub from std.stub;
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=constantinople
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (std.stub:63-92): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,3 @@
|
|||||||
|
import std.stub;
|
||||||
|
// ----
|
||||||
|
// ParserError 9478: (7-10): Expected string literal (path), "*" or alias list.
|
@ -0,0 +1,3 @@
|
|||||||
|
import { identity } from std.stub;
|
||||||
|
// ----
|
||||||
|
// ParserError 6845: (25-28): Expected import path.
|
Loading…
Reference in New Issue
Block a user