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(libsolidity)
|
||||
add_subdirectory(libsolc)
|
||||
add_subdirectory(libstdlib)
|
||||
add_subdirectory(tools)
|
||||
|
||||
if (NOT EMSCRIPTEN)
|
||||
|
@ -59,6 +59,8 @@
|
||||
#include <libsolidity/codegen/ir/Common.h>
|
||||
#include <libsolidity/codegen/ir/IRGenerator.h>
|
||||
|
||||
#include <libstdlib/stdlib.h>
|
||||
|
||||
#include <libyul/YulString.h>
|
||||
#include <libyul/AsmPrinter.h>
|
||||
#include <libyul/AsmJsonConverter.h>
|
||||
@ -95,6 +97,7 @@ using namespace std;
|
||||
using namespace solidity;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::stdlib;
|
||||
|
||||
using solidity::util::errinfo_comment;
|
||||
|
||||
@ -369,6 +372,15 @@ bool CompilerStack::parse()
|
||||
for (auto const& import: ASTNode::filteredNodes<ImportDirective>(source.ast->nodes()))
|
||||
{
|
||||
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.
|
||||
// We first have to apply remappings before we can store the actual absolute path
|
||||
|
@ -271,9 +271,9 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
||||
SourceLocation unitAliasLocation{};
|
||||
ImportDirective::SymbolAliasList symbolAliases;
|
||||
|
||||
if (m_scanner->currentToken() == Token::StringLiteral)
|
||||
if (isQuotedPath() || isStdlibPath())
|
||||
{
|
||||
path = getLiteralAndAdvance();
|
||||
path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
|
||||
if (m_scanner->currentToken() == Token::As)
|
||||
{
|
||||
advance();
|
||||
@ -315,9 +315,9 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
||||
if (m_scanner->currentToken() != Token::Identifier || m_scanner->currentLiteral() != "from")
|
||||
fatalParserError(8208_error, "Expected \"from\".");
|
||||
advance();
|
||||
if (m_scanner->currentToken() != Token::StringLiteral)
|
||||
if (!isQuotedPath() && !isStdlibPath())
|
||||
fatalParserError(6845_error, "Expected import path.");
|
||||
path = getLiteralAndAdvance();
|
||||
path = isQuotedPath() ? getLiteralAndAdvance() : getStdlibImportPathAndAdvance();
|
||||
}
|
||||
if (path->empty())
|
||||
fatalParserError(6326_error, "Import path cannot be empty.");
|
||||
@ -2486,4 +2486,25 @@ ASTPointer<ASTString> Parser::getLiteralAndAdvance()
|
||||
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();
|
||||
///@}
|
||||
|
||||
bool isQuotedPath() const;
|
||||
bool isStdlibPath() const;
|
||||
|
||||
ASTPointer<ASTString> getStdlibImportPathAndAdvance();
|
||||
|
||||
/// Creates an empty ParameterList at the current location (used if parameters can be omitted).
|
||||
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
|
||||
# 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
|
||||
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)"
|
||||
echo "Looking at ${NSOURCES} .sol files..."
|
||||
|
@ -110,7 +110,7 @@ do
|
||||
SOL_FILES+=("$line")
|
||||
done < <(
|
||||
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/semanticTests" |
|
||||
# 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;
|
||||
if (SourceLocation const* location = currentError->sourceLocation())
|
||||
{
|
||||
locationStart = location->start;
|
||||
locationEnd = location->end;
|
||||
solAssert(location->sourceName, "");
|
||||
sourceName = *location->sourceName;
|
||||
solAssert(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)
|
||||
if(m_sources.sources.count(sourceName) == 1)
|
||||
{
|
||||
solAssert(location->start >= preambleSize, "");
|
||||
locationStart = location->start - preambleSize;
|
||||
}
|
||||
if (location->end != -1)
|
||||
{
|
||||
solAssert(location->end >= preambleSize, "");
|
||||
locationEnd = location->end - preambleSize;
|
||||
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, "");
|
||||
locationStart = location->start - preambleSize;
|
||||
}
|
||||
if (location->end != -1)
|
||||
{
|
||||
solAssert(location->end >= preambleSize, "");
|
||||
locationEnd = location->end - preambleSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
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