Skip to content

Commit

Permalink
Gut NullType from codebase
Browse files Browse the repository at this point in the history
Just use LLLnode with value == None
  • Loading branch information
charles-cooper committed Nov 12, 2019
1 parent 08d5df7 commit 5a09d40
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 72 deletions.
8 changes: 0 additions & 8 deletions tests/parser/types/test_node_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@
ByteArrayType,
ListType,
MappingType,
NullType,
StructType,
TupleType,
canonicalize_type,
get_size_of_type,
)


def test_null_type():
node1 = NullType()
node2 = NullType()

assert node1 == node2


def test_bytearray_node_type():

node1 = ByteArrayType(12)
Expand Down
5 changes: 2 additions & 3 deletions vyper/functions/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
ByteArrayLike,
ByteArrayType,
ListType,
NullType,
StringType,
TupleType,
are_units_compatible,
Expand Down Expand Up @@ -1260,8 +1259,8 @@ def sqrt(expr, args, kwargs, context):
def clear(expr, context):
if len(expr.args) != 1:
raise ParserException('function expects two parameters.', expr)
output_type = context.parse_type(expr.args[0], expr.args[0].value.id)
return LLLnode(None, typ=NullType(output_type), pos=getpos(expr))
output_type = context.parse_type(expr.args[0], expr.args[0])
return LLLnode(None, typ=output_type, pos=getpos(expr))


dispatch_table = {
Expand Down
3 changes: 1 addition & 2 deletions vyper/parser/expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
ContractType,
ListType,
MappingType,
NullType,
StringType,
StructType,
TupleType,
Expand Down Expand Up @@ -755,7 +754,7 @@ def compare(self):
left = Expr.parse_value_expr(self.expr.left, self.context)
right = Expr.parse_value_expr(self.expr.comparators[0], self.context)

if isinstance(right.typ, NullType):
if right.value is None:
raise InvalidLiteralException(
'Comparison to None is not allowed, compare against a default value.',
self.expr,
Expand Down
4 changes: 2 additions & 2 deletions vyper/parser/lll_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from vyper.types import (
BaseType,
NodeType,
NullType,
ceil32,
)
from vyper.utils import (
Expand Down Expand Up @@ -213,7 +212,8 @@ def __init__(self,
self.gas = sum([arg.gas for arg in self.args]) + 30
if self.value == 'if_unchecked':
self.gas = self.args[0].gas + self.args[1].gas + 17
elif self.value is None and isinstance(self.typ, NullType):
elif self.value is None:
# TODO revisit this
self.valency = 1
self.gas = 5
else:
Expand Down
50 changes: 18 additions & 32 deletions vyper/parser/parser_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
ByteArrayType,
ListType,
MappingType,
NullType,
StringType,
StructType,
TupleLike,
Expand Down Expand Up @@ -86,7 +85,7 @@ def get_original_if_0_prefixed(expr, context):

# Copies byte array
def make_byte_array_copier(destination, source, pos=None):
if not isinstance(source.typ, (ByteArrayLike, NullType)):
if not isinstance(source.typ, ByteArrayLike):
btype = 'byte array' if isinstance(destination.typ, ByteArrayType) else 'string'
raise TypeMismatchException(f"Can only set a {btype} to another {btype}", pos)
if isinstance(source.typ, ByteArrayLike) and source.typ.maxlen > destination.typ.maxlen:
Expand All @@ -107,7 +106,7 @@ def make_byte_array_copier(destination, source, pos=None):

pos_node = LLLnode.from_list('_pos', typ=source.typ, location=source.location)
# Get the length
if isinstance(source.typ, NullType):
if source.value is None:
length = 1
elif source.location == "memory":
length = ['add', ['mload', '_pos'], 32]
Expand All @@ -127,10 +126,10 @@ def make_byte_array_copier(destination, source, pos=None):
location=destination.location,
)
# Maximum theoretical length
max_length = 32 if isinstance(source.typ, NullType) else source.typ.maxlen + 32
max_length = 32 if source.value is None else source.typ.maxlen + 32
return LLLnode.from_list([
'with', '_pos',
0 if isinstance(source.typ, NullType) else source,
0 if source.value is None else source,
make_byte_slice_copier(destination, pos_node, length, max_length, pos=pos)
], typ=None)

Expand All @@ -152,7 +151,7 @@ def make_byte_slice_copier(destination, source, length, max_length, pos=None):
]
], typ=None, annotation=f'copy byte slice dest: {str(destination)}')
# special case: rhs is zero
if isinstance(source.typ, NullType):
if source.value is None:
return mzero(destination, max_length)
# Copy over data
if source.location == "memory":
Expand Down Expand Up @@ -393,7 +392,7 @@ def base_type_conversion(orig, frm, to, pos, in_function_call=False):
raise InvalidLiteralException(
f"Function calls require explicit unit definitions on calls, expected {to}", pos
)
if not isinstance(frm, (BaseType, NullType)) or not isinstance(to, BaseType):
if not isinstance(frm, BaseType) or not isinstance(to, BaseType):
raise TypeMismatchException(
f"Base type conversion from or to non-base type: {frm} {to}", pos
)
Expand All @@ -406,13 +405,6 @@ def base_type_conversion(orig, frm, to, pos, in_function_call=False):
['mul', orig, DECIMAL_DIVISOR],
typ=BaseType('decimal', to.unit, to.positional),
)
elif isinstance(frm, NullType):
if to.typ not in ('int128', 'bool', 'uint256', 'address', 'bytes32', 'decimal'):
# This is only to future proof the use of base_type_conversion.
raise TypeMismatchException( # pragma: no cover
f"Cannot convert null-type object to type {to}", pos
)
return LLLnode.from_list(0, typ=to)
# Integer literal conversion.
elif (frm.typ, to.typ, frm.is_literal) == ('int128', 'uint256', True):
return LLLnode(orig.value, orig.args, typ=to, add_gas_estimate=orig.add_gas_estimate)
Expand Down Expand Up @@ -522,9 +514,6 @@ def pack_arguments(signature, args, context, stmt_expr, return_placeholder=True)

# Create an x=y statement, where the types may be compound
def make_setter(left, right, location, pos, in_function_call=False):
if isinstance(right.typ, NullType):
if right.typ.typ is not None and right.typ.typ != left.typ:
raise TypeMismatchException('attempt to clear {left.typ} but provided {right.typ.typ}')
# Basic types
if isinstance(left.typ, BaseType):
right = base_type_conversion(
Expand All @@ -542,6 +531,8 @@ def make_setter(left, right, location, pos, in_function_call=False):
f"Number out of range for {left.typ}: {right.value}",
pos
)
if right.value is None:
right.value = 0
if location == 'storage':
return LLLnode.from_list(['sstore', left, right], typ=None)
elif location == 'memory':
Expand All @@ -557,20 +548,14 @@ def make_setter(left, right, location, pos, in_function_call=False):
# Cannot do something like [a, b, c] = [1, 2, 3]
if left.value == "multi":
raise Exception("Target of set statement must be a single item")
if not isinstance(right.typ, (ListType, NullType)):
if not isinstance(right.typ, ListType):
raise TypeMismatchException(
f"Setter type mismatch: left side is array, right side is {right.typ}", pos
f"Setter type mismatch: left side is {left.typ}, right side is {right.typ}", pos
)
left_token = LLLnode.from_list('_L', typ=left.typ, location=left.location)
if left.location == "storage":
left = LLLnode.from_list(['sha3_32', left], typ=left.typ, location="storage_prehashed")
left_token.location = "storage_prehashed"
# Type checks
if not isinstance(right.typ, NullType):
if not isinstance(right.typ, ListType):
raise TypeMismatchException("Left side is array, right side is not", pos)
if left.typ.count != right.typ.count:
raise TypeMismatchException("Mismatched number of elements", pos)
# If the right side is a literal
if right.value == "multi":
if len(right.args) != left.typ.count:
Expand All @@ -584,7 +569,7 @@ def make_setter(left, right, location, pos, in_function_call=False):
array_bounds_check=False,
), right.args[i], location, pos=pos))
return LLLnode.from_list(['with', '_L', left, ['seq'] + subs], typ=None)
elif isinstance(right.typ, NullType):
elif right.value is None:
if left.location == 'memory':
return mzero(left, get_size_of_type(left.typ))

Expand All @@ -595,7 +580,7 @@ def make_setter(left, right, location, pos, in_function_call=False):
LLLnode.from_list(i, typ='int128'),
pos=pos,
array_bounds_check=False,
), LLLnode.from_list(None, typ=NullType(left.typ)), location, pos=pos))
), LLLnode.from_list(None, typ=left.typ.subtype), location, pos=pos))
return LLLnode.from_list(['with', '_L', left, ['seq'] + subs], typ=None)
# If the right side is a variable
else:
Expand All @@ -621,7 +606,7 @@ def make_setter(left, right, location, pos, in_function_call=False):
elif isinstance(left.typ, (StructType, TupleType)):
if left.value == "multi" and isinstance(left.typ, StructType):
raise Exception("Target of set statement must be a single item")
if not isinstance(right.typ, NullType):
if right.value is not None:
if not isinstance(right.typ, left.typ.__class__):
raise TypeMismatchException(
f"Setter type mismatch: left side is {left.typ}, right side is {right.typ}",
Expand All @@ -630,6 +615,7 @@ def make_setter(left, right, location, pos, in_function_call=False):
if isinstance(left.typ, StructType):
for k in right.args:
if k.value is None:
raise CompilerPanic("Unreachable", pos)
raise InvalidLiteralException(
'Setting struct value to None is not allowed, use a default value.',
pos,
Expand Down Expand Up @@ -685,15 +671,15 @@ def make_setter(left, right, location, pos, in_function_call=False):
))
return LLLnode.from_list(['with', '_L', left, ['seq'] + subs], typ=None)
# If the right side is a null
elif isinstance(right.typ, NullType):
elif right.value is None:
if left.location == 'memory':
return mzero(left, get_size_of_type(left.typ))

subs = []
for typ, loc in zip(keyz, locations):
for key, loc in zip(keyz, locations):
subs.append(make_setter(
add_variable_offset(left_token, typ, pos=pos),
LLLnode.from_list(None, typ=NullType(typ)),
add_variable_offset(left_token, key, pos=pos),
LLLnode.from_list(None, typ=left.typ.members[key]),
loc,
pos=pos,
))
Expand Down
28 changes: 12 additions & 16 deletions vyper/parser/stmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
ContractType,
ListType,
NodeType,
NullType,
StructType,
TupleType,
get_size_of_type,
Expand Down Expand Up @@ -127,11 +126,7 @@ def _check_valid_assign(self, sub):
else:
raise TypeMismatchException('Invalid type, expected: bytes32', self.stmt)
elif isinstance(self.stmt.annotation, ast.Subscript):
check_typ = sub.typ
if isinstance(check_typ, NullType):
check_typ = check_typ.typ
good = isinstance(check_typ, (ListType, ByteArrayLike))
if not good:
if not isinstance(sub.typ, (ListType, ByteArrayLike)):
raise TypeMismatchException(
f'Invalid type, expected: {self.stmt.annotation.value.id},'
f' got: {sub.typ}', self.stmt
Expand Down Expand Up @@ -340,11 +335,12 @@ def _clear(self):
# Get target variable
target = self.get_target(self.stmt.args[0])

zero = LLLnode(None, typ=NullType(target.typ), pos=getpos(self.expr))
pos = getpos(self.stmt)

zero = LLLnode(None, typ=target.typ, pos=pos)

# Generate LLL node to set to zero
o = make_setter(target, zero, target.location, pos=getpos(self.stmt))
o.pos = getpos(self.stmt)
o = make_setter(target, zero, target.location, pos=pos)

return o

Expand All @@ -358,14 +354,14 @@ def call(self):
) and isinstance(self.stmt.func.value, ast.Name) and self.stmt.func.value.id == 'log'

if isinstance(self.stmt.func, ast.Name):
if self.stmt.func.id in stmt_dispatch_table:
if self.stmt.func.id == 'clear':
return self._clear()
else:
return stmt_dispatch_table[self.stmt.func.id](self.stmt, self.context)
elif self.stmt.func.id in dispatch_table:
funcname = self.stmt.func.id
if funcname == 'clear':
return self._clear()
if funcname in stmt_dispatch_table:
return stmt_dispatch_table[funcname](self.stmt, self.context)
elif funcname in dispatch_table:
raise StructureException(
f"Function {self.stmt.func.id} can not be called without being used.",
f"Function {funcname} can not be called without being used.",
self.stmt,
)
else:
Expand Down
9 changes: 0 additions & 9 deletions vyper/types/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,6 @@ def tuple_items(self):
return list(enumerate(self.members))


# Sentinel type to represent zeroing operations
class NullType(NodeType):
def __init__(self, typ=None):
self.typ = typ # optional type for typechecking

def eq(self, other):
return True


# Convert type into common form used in ABI
def canonicalize_type(t, is_indexed=False):
if isinstance(t, ByteArrayLike):
Expand Down

0 comments on commit 5a09d40

Please sign in to comment.