aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp9
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp2
-rw-r--r--libsolidity/inlineasm/AsmData.h17
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp34
-rw-r--r--libsolidity/inlineasm/AsmParser.h1
-rw-r--r--libsolidity/inlineasm/AsmPrinter.cpp33
-rw-r--r--libsolidity/inlineasm/AsmPrinter.h2
-rw-r--r--libsolidity/inlineasm/AsmScope.cpp8
-rw-r--r--libsolidity/inlineasm/AsmScope.h17
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp16
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.h3
-rw-r--r--test/libjulia/Parser.cpp26
12 files changed, 123 insertions, 45 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index dad05a78..590f9ad6 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -184,7 +184,7 @@ bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
int const stackHeight = m_stackHeight;
bool success = boost::apply_visitor(*this, *_varDecl.value);
solAssert(m_stackHeight - stackHeight == 1, "Invalid value size.");
- boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.name)).active = true;
+ boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.variable.name)).active = true;
m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
return success;
}
@@ -193,7 +193,7 @@ bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
{
Scope& bodyScope = scope(&_funDef.body);
for (auto const& var: _funDef.arguments + _funDef.returns)
- boost::get<Scope::Variable>(bodyScope.identifiers.at(var)).active = true;
+ boost::get<Scope::Variable>(bodyScope.identifiers.at(var.name)).active = true;
int const stackHeight = m_stackHeight;
m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();
@@ -232,8 +232,9 @@ bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
},
[&](Scope::Function const& _fun)
{
- arguments = _fun.arguments;
- returns = _fun.returns;
+ /// TODO: compare types too
+ arguments = _fun.arguments.size();
+ returns = _fun.returns.size();
}
)))
{
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index c19667b4..137a70f5 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -204,7 +204,7 @@ public:
int height = m_state.assembly.deposit();
boost::apply_visitor(*this, *_varDecl.value);
expectDeposit(1, height);
- auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.name));
+ auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.variable.name));
var.stackHeight = height;
var.active = true;
}
diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h
index d61b5803..363873ab 100644
--- a/libsolidity/inlineasm/AsmData.h
+++ b/libsolidity/inlineasm/AsmData.h
@@ -33,12 +33,17 @@ namespace solidity
namespace assembly
{
+using Type = std::string;
+
+struct TypedName { SourceLocation location; std::string name; Type type; };
+using TypedNameList = std::vector<TypedName>;
+
/// What follows are the AST nodes for assembly.
/// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; };
/// Literal number or string (up to 32 bytes)
-struct Literal { SourceLocation location; bool isNumber; std::string value; };
+struct Literal { SourceLocation location; bool isNumber; std::string value; Type type; };
/// External / internal identifier or label reference
struct Identifier { SourceLocation location; std::string name; };
struct FunctionalInstruction;
@@ -52,18 +57,18 @@ struct FunctionDefinition;
struct FunctionCall;
struct Block;
using Statement = boost::variant<Instruction, Literal, Label, Assignment, Identifier, FunctionalAssignment, FunctionCall, FunctionalInstruction, VariableDeclaration, FunctionDefinition, Block>;
-/// Functional assignment ("x := mload(20)", expects push-1-expression on the right hand
+/// Functional assignment ("x := mload(20:u256)", expects push-1-expression on the right hand
/// side and requires x to occupy exactly one stack slot.
struct FunctionalAssignment { SourceLocation location; Identifier variableName; std::shared_ptr<Statement> value; };
-/// Functional instruction, e.g. "mul(mload(20), add(2, x))"
+/// Functional instruction, e.g. "mul(mload(20:u256), add(2:u256, x))"
struct FunctionalInstruction { SourceLocation location; Instruction instruction; std::vector<Statement> arguments; };
struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; };
-/// Block-scope variable declaration ("let x := mload(20)"), non-hoisted
-struct VariableDeclaration { SourceLocation location; std::string name; std::shared_ptr<Statement> value; };
+/// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted
+struct VariableDeclaration { SourceLocation location; TypedName variable; std::shared_ptr<Statement> value; };
/// Block that creates a scope (frees declared stack variables)
struct Block { SourceLocation location; std::vector<Statement> statements; };
/// Function definition ("function f(a, b) -> (d, e) { ... }")
-struct FunctionDefinition { SourceLocation location; std::string name; std::vector<std::string> arguments; std::vector<std::string> returns; Block body; };
+struct FunctionDefinition { SourceLocation location; std::string name; TypedNameList arguments; TypedNameList returns; Block body; };
struct LocationExtractor: boost::static_visitor<SourceLocation>
{
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index d9b0b3e0..7ecad5ea 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -201,16 +201,26 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
}
else
ret = Identifier{location(), literal};
+ m_scanner->next();
break;
}
case Token::StringLiteral:
case Token::Number:
{
- ret = Literal{
+ Literal literal{
location(),
m_scanner->currentToken() == Token::Number,
- m_scanner->currentLiteral()
+ m_scanner->currentLiteral(),
+ ""
};
+ m_scanner->next();
+ if (m_julia)
+ {
+ expectToken(Token::Colon);
+ literal.location.end = endPosition();
+ literal.type = expectAsmIdentifier();
+ }
+ ret = std::move(literal);
break;
}
default:
@@ -220,7 +230,6 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
"Expected elementary inline assembly operation."
);
}
- m_scanner->next();
return ret;
}
@@ -228,7 +237,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
expectToken(Token::Let);
- varDecl.name = expectAsmIdentifier();
+ varDecl.variable = parseTypedName();
expectToken(Token::Colon);
expectToken(Token::Assign);
varDecl.value.reset(new Statement(parseExpression()));
@@ -244,7 +253,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
expectToken(Token::LParen);
while (m_scanner->currentToken() != Token::RParen)
{
- funDef.arguments.push_back(expectAsmIdentifier());
+ funDef.arguments.emplace_back(parseTypedName());
if (m_scanner->currentToken() == Token::RParen)
break;
expectToken(Token::Comma);
@@ -256,7 +265,7 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition()
expectToken(Token::GreaterThan);
while (true)
{
- funDef.returns.push_back(expectAsmIdentifier());
+ funDef.returns.emplace_back(parseTypedName());
if (m_scanner->currentToken() == Token::LBrace)
break;
expectToken(Token::Comma);
@@ -335,6 +344,19 @@ assembly::Statement Parser::parseFunctionalInstruction(assembly::Statement&& _in
return {};
}
+TypedName Parser::parseTypedName()
+{
+ TypedName typedName = createWithLocation<TypedName>();
+ typedName.name = expectAsmIdentifier();
+ if (m_julia)
+ {
+ expectToken(Token::Colon);
+ typedName.location.end = endPosition();
+ typedName.type = expectAsmIdentifier();
+ }
+ return typedName;
+}
+
string Parser::expectAsmIdentifier()
{
string name = m_scanner->currentLiteral();
diff --git a/libsolidity/inlineasm/AsmParser.h b/libsolidity/inlineasm/AsmParser.h
index c55fd2ac..addc1725 100644
--- a/libsolidity/inlineasm/AsmParser.h
+++ b/libsolidity/inlineasm/AsmParser.h
@@ -69,6 +69,7 @@ protected:
VariableDeclaration parseVariableDeclaration();
FunctionDefinition parseFunctionDefinition();
Statement parseFunctionalInstruction(Statement&& _instruction);
+ TypedName parseTypedName();
std::string expectAsmIdentifier();
private:
diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp
index 4a6f975d..f3b66aee 100644
--- a/libsolidity/inlineasm/AsmPrinter.cpp
+++ b/libsolidity/inlineasm/AsmPrinter.cpp
@@ -47,7 +47,7 @@ string AsmPrinter::operator()(assembly::Instruction const& _instruction)
string AsmPrinter::operator()(assembly::Literal const& _literal)
{
if (_literal.isNumber)
- return _literal.value;
+ return _literal.value + appendTypeName(_literal.type);
string out;
for (char c: _literal.value)
if (c == '\\')
@@ -74,7 +74,7 @@ string AsmPrinter::operator()(assembly::Literal const& _literal)
}
else
out += c;
- return "\"" + out + "\"";
+ return "\"" + out + "\"" + appendTypeName(_literal.type);
}
string AsmPrinter::operator()(assembly::Identifier const& _identifier)
@@ -113,14 +113,30 @@ string AsmPrinter::operator()(assembly::FunctionalAssignment const& _functionalA
string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDeclaration)
{
- return "let " + _variableDeclaration.name + " := " + boost::apply_visitor(*this, *_variableDeclaration.value);
+ return "let " + _variableDeclaration.variable.name + appendTypeName(_variableDeclaration.variable.type) + " := " + boost::apply_visitor(*this, *_variableDeclaration.value);
}
string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition)
{
- string out = "function " + _functionDefinition.name + "(" + boost::algorithm::join(_functionDefinition.arguments, ", ") + ")";
+ string out = "function " + _functionDefinition.name + "(";
+ out += boost::algorithm::join(
+ _functionDefinition.arguments | boost::adaptors::transformed(
+ [this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
+ ),
+ ", "
+ );
+ out += ")";
if (!_functionDefinition.returns.empty())
- out += " -> " + boost::algorithm::join(_functionDefinition.returns, ", ");
+ {
+ out += " -> ";
+ out += boost::algorithm::join(
+ _functionDefinition.returns | boost::adaptors::transformed(
+ [this](TypedName argument) { return argument.name + appendTypeName(argument.type); }
+ ),
+ ", "
+ );
+ }
+
return out + "\n" + (*this)(_functionDefinition.body);
}
@@ -145,3 +161,10 @@ string AsmPrinter::operator()(Block const& _block)
boost::replace_all(body, "\n", "\n ");
return "{\n " + body + "\n}";
}
+
+string AsmPrinter::appendTypeName(std::string const& _type)
+{
+ if (m_julia)
+ return ":" + _type;
+ return "";
+}
diff --git a/libsolidity/inlineasm/AsmPrinter.h b/libsolidity/inlineasm/AsmPrinter.h
index 038c6d85..282fd7e3 100644
--- a/libsolidity/inlineasm/AsmPrinter.h
+++ b/libsolidity/inlineasm/AsmPrinter.h
@@ -60,6 +60,8 @@ public:
std::string operator()(assembly::Block const& _block);
private:
+ std::string appendTypeName(std::string const& _type);
+
bool m_julia = false;
};
diff --git a/libsolidity/inlineasm/AsmScope.cpp b/libsolidity/inlineasm/AsmScope.cpp
index 609dca16..e3f4615a 100644
--- a/libsolidity/inlineasm/AsmScope.cpp
+++ b/libsolidity/inlineasm/AsmScope.cpp
@@ -32,15 +32,17 @@ bool Scope::registerLabel(string const& _name)
return true;
}
-bool Scope::registerVariable(string const& _name)
+bool Scope::registerVariable(string const& _name, JuliaType const& _type)
{
if (exists(_name))
return false;
- identifiers[_name] = Variable();
+ Variable variable;
+ variable.type = _type;
+ identifiers[_name] = variable;
return true;
}
-bool Scope::registerFunction(string const& _name, size_t _arguments, size_t _returns)
+bool Scope::registerFunction(string const& _name, std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns)
{
if (exists(_name))
return false;
diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h
index b70bee67..dd45613d 100644
--- a/libsolidity/inlineasm/AsmScope.h
+++ b/libsolidity/inlineasm/AsmScope.h
@@ -61,6 +61,8 @@ struct GenericVisitor<>: public boost::static_visitor<> {
struct Scope
{
+ using JuliaType = std::string;
+
struct Variable
{
/// Used during code generation to store the stack height. @todo move there.
@@ -68,6 +70,7 @@ struct Scope
/// Used during analysis to check whether we already passed the declaration inside the block.
/// @todo move there.
bool active = false;
+ JuliaType type;
};
struct Label
@@ -78,18 +81,22 @@ struct Scope
struct Function
{
- Function(size_t _arguments, size_t _returns): arguments(_arguments), returns(_returns) {}
- size_t arguments = 0;
- size_t returns = 0;
+ Function(std::vector<JuliaType> const& _arguments, std::vector<JuliaType> const& _returns): arguments(_arguments), returns(_returns) {}
+ std::vector<JuliaType> arguments;
+ std::vector<JuliaType> returns;
};
using Identifier = boost::variant<Variable, Label, Function>;
using Visitor = GenericVisitor<Variable const, Label const, Function const>;
using NonconstVisitor = GenericVisitor<Variable, Label, Function>;
- bool registerVariable(std::string const& _name);
+ bool registerVariable(std::string const& _name, JuliaType const& _type);
bool registerLabel(std::string const& _name);
- bool registerFunction(std::string const& _name, size_t _arguments, size_t _returns);
+ bool registerFunction(
+ std::string const& _name,
+ std::vector<JuliaType> const& _arguments,
+ std::vector<JuliaType> const& _returns
+ );
/// Looks up the identifier in this or super scopes and returns a valid pointer if found
/// or a nullptr if not found. Variable lookups up across function boundaries will fail, as
diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp
index 4a651388..eb10dbb3 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.cpp
+++ b/libsolidity/inlineasm/AsmScopeFiller.cpp
@@ -59,13 +59,19 @@ bool ScopeFiller::operator()(Label const& _item)
bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl)
{
- return registerVariable(_varDecl.name, _varDecl.location, *m_currentScope);
+ return registerVariable(_varDecl.variable, _varDecl.location, *m_currentScope);
}
bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef)
{
bool success = true;
- if (!m_currentScope->registerFunction(_funDef.name, _funDef.arguments.size(), _funDef.returns.size()))
+ vector<Scope::JuliaType> arguments;
+ for (auto const& _argument: _funDef.arguments)
+ arguments.push_back(_argument.type);
+ vector<Scope::JuliaType> returns;
+ for (auto const& _return: _funDef.returns)
+ returns.push_back(_return.type);
+ if (!m_currentScope->registerFunction(_funDef.name, arguments, returns))
{
//@TODO secondary location
m_errors.push_back(make_shared<Error>(
@@ -102,14 +108,14 @@ bool ScopeFiller::operator()(Block const& _block)
return success;
}
-bool ScopeFiller::registerVariable(string const& _name, SourceLocation const& _location, Scope& _scope)
+bool ScopeFiller::registerVariable(TypedName const& _name, SourceLocation const& _location, Scope& _scope)
{
- if (!_scope.registerVariable(_name))
+ if (!_scope.registerVariable(_name.name, _name.type))
{
//@TODO secondary location
m_errors.push_back(make_shared<Error>(
Error::Type::DeclarationError,
- "Variable name " + _name + " already taken in this scope.",
+ "Variable name " + _name.name + " already taken in this scope.",
_location
));
return false;
diff --git a/libsolidity/inlineasm/AsmScopeFiller.h b/libsolidity/inlineasm/AsmScopeFiller.h
index bb62948b..61428eea 100644
--- a/libsolidity/inlineasm/AsmScopeFiller.h
+++ b/libsolidity/inlineasm/AsmScopeFiller.h
@@ -34,6 +34,7 @@ namespace solidity
namespace assembly
{
+struct TypedName;
struct Literal;
struct Block;
struct Label;
@@ -72,7 +73,7 @@ public:
private:
bool registerVariable(
- std::string const& _name,
+ TypedName const& _name,
SourceLocation const& _location,
Scope& _scope
);
diff --git a/test/libjulia/Parser.cpp b/test/libjulia/Parser.cpp
index 11820c01..c401f57b 100644
--- a/test/libjulia/Parser.cpp
+++ b/test/libjulia/Parser.cpp
@@ -117,12 +117,12 @@ BOOST_AUTO_TEST_CASE(smoke_test)
BOOST_AUTO_TEST_CASE(vardecl)
{
- BOOST_CHECK(successParse("{ let x := 7 }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 7:u256 }"));
}
BOOST_AUTO_TEST_CASE(assignment)
{
- BOOST_CHECK(successParse("{ let x := 2 let y := x }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 2:u256 let y:u256 := x }"));
}
BOOST_AUTO_TEST_CASE(function_call)
@@ -132,27 +132,27 @@ BOOST_AUTO_TEST_CASE(function_call)
BOOST_AUTO_TEST_CASE(vardecl_complex)
{
- BOOST_CHECK(successParse("{ let y := 2 let x := add(7, mul(6, y)) }"));
+ BOOST_CHECK(successParse("{ let y:u256 := 2:u256 let x:u256 := add(7:u256, mul(6:u256, y)) }"));
}
BOOST_AUTO_TEST_CASE(blocks)
{
- BOOST_CHECK(successParse("{ let x := 7 { let y := 3 } { let z := 2 } }"));
+ BOOST_CHECK(successParse("{ let x:u256 := 7:u256 { let y:u256 := 3:u256 } { let z:u256 := 2:u256 } }"));
}
BOOST_AUTO_TEST_CASE(function_definitions)
{
- BOOST_CHECK(successParse("{ function f() { } function g(a) -> x { } }"));
+ BOOST_CHECK(successParse("{ function f() { } function g(a:u256) -> x:u256 { } }"));
}
BOOST_AUTO_TEST_CASE(function_definitions_multiple_args)
{
- BOOST_CHECK(successParse("{ function f(a, d) { } function g(a, d) -> x, y { } }"));
+ BOOST_CHECK(successParse("{ function f(a:u256, d:u256) { } function g(a:u256, d:u256) -> x:u256, y:u256 { } }"));
}
BOOST_AUTO_TEST_CASE(function_calls)
{
- BOOST_CHECK(successParse("{ function f(a) -> b {} function g(a, b, c) {} function x() { g(1, 2, f(mul(2, 3))) x() } }"));
+ BOOST_CHECK(successParse("{ function f(a:u256) -> b:u256 {} function g(a:u256, b:u256, c:u256) {} function x() { g(1:u256, 2:u256, f(mul(2:u256, 3:u256))) x() } }"));
}
BOOST_AUTO_TEST_CASE(label)
@@ -167,12 +167,12 @@ BOOST_AUTO_TEST_CASE(instructions)
BOOST_AUTO_TEST_CASE(push)
{
- CHECK_ERROR("{ 0x42 }", ParserError, "Call or assignment expected.");
+ CHECK_ERROR("{ 0x42:u256 }", ParserError, "Call or assignment expected.");
}
BOOST_AUTO_TEST_CASE(assign_from_stack)
{
- CHECK_ERROR("{ =: x }", ParserError, "Literal or identifier expected.");
+ CHECK_ERROR("{ =: x:u256 }", ParserError, "Literal or identifier expected.");
}
BOOST_AUTO_TEST_CASE(empty_call)
@@ -180,6 +180,14 @@ BOOST_AUTO_TEST_CASE(empty_call)
CHECK_ERROR("{ () }", ParserError, "Literal or identifier expected.");
}
+BOOST_AUTO_TEST_CASE(lacking_types)
+{
+ CHECK_ERROR("{ let x := 1:u256 }", ParserError, "Expected token Identifier got 'Assign'");
+ CHECK_ERROR("{ let x:u256 := 1 }", ParserError, "Expected token Colon got 'RBrace'");
+ CHECK_ERROR("{ function f(a) {} }", ParserError, "Expected token Colon got 'RParen'");
+ CHECK_ERROR("{ function f(a:u256) -> b {} }", ParserError, "Expected token Colon got 'LBrace'");
+}
+
BOOST_AUTO_TEST_SUITE_END()
}