Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add print builtin #2818

Merged
merged 3 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions vyper/ast/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,19 @@ def __eq__(self, other):
def __repr__(self):
cls = type(self)
class_repr = f"{cls.__module__}.{cls.__qualname__}"
return f"{class_repr}:\n{self._annotated_source}"

source_annotation = annotate_source_code(
@property
def _annotated_source(self):
# return source with context / line/col info
return annotate_source_code(
self.full_source_code,
self.lineno,
self.col_offset,
context_lines=VYPER_ERROR_CONTEXT_LINES,
line_numbers=VYPER_ERROR_LINE_NUMBERS,
)

return f"{class_repr}:\n{source_annotation}"

@property
def description(self):
"""
Expand Down
44 changes: 44 additions & 0 deletions vyper/builtin_functions/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
SArrayType,
StringType,
TupleType,
get_type_for_exact_size,
is_base_type,
is_bytes_m_type,
parse_integer_typeinfo,
Expand Down Expand Up @@ -86,9 +87,11 @@
DECIMAL_DIVISOR,
MemoryPositions,
SizeLimits,
abi_method_id,
bytes_to_int,
fourbytes_to_int,
keccak256,
vyper_warn,
)

from .signatures import Optional, validate_inputs
Expand Down Expand Up @@ -1867,6 +1870,46 @@ def build_IR(self, expr, args, kwargs, context):
return IRnode("~empty", typ=output_type)


class Print(_SimpleBuiltinFunction):
_id = "print"
_inputs = [("arg", "*")]

_warned = False

def fetch_call_return(self, node):
if not self._warned:
vyper_warn("`print` should only be used for debugging!\n" + node._annotated_source)
self._warned = True

validate_call_args(node, 1)
return None

@validate_inputs
def build_IR(self, expr, args, kwargs, context):
args = [Expr(arg, context).ir_node for arg in expr.args]
args_tuple_t = TupleType([x.typ for x in args])
args_as_tuple = IRnode.from_list(["multi"] + [x for x in args], typ=args_tuple_t)
args_abi_t = args_tuple_t.abi_type
# create a signature like "log(uint256)"
sig = "log" + "(" + ",".join([arg.typ.abi_type.selector_name() for arg in args]) + ")"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be log (built in keyword) or should it be print?

method_id = abi_method_id(sig)

buflen = 32 + args_abi_t.size_bound()

# 32 bytes extra space for the method id
buf = context.new_internal_variable(get_type_for_exact_size(buflen))

ret = ["seq"]
ret.append(["mstore", buf, method_id])
encode = abi_encode(buf + 32, args_as_tuple, context, buflen, returns_len=True)

# debug address that tooling uses
CONSOLE_ADDRESS = 0x000000000000000000636F6E736F6C652E6C6F67
ret.append(["staticcall", "gas", CONSOLE_ADDRESS, buf + 28, encode, 0, 0])

return IRnode.from_list(ret, annotation="print:" + sig)


class ABIEncode(_SimpleBuiltinFunction):
_id = "_abi_encode" # TODO prettier to rename this to abi.encode
# signature: *, ensure_tuple=<literal_bool> -> Bytes[<calculated len>]
Expand Down Expand Up @@ -2046,6 +2089,7 @@ def build_IR(self, expr, context):

STMT_DISPATCH_TABLE = {
"send": Send(),
"print": Print(),
"selfdestruct": SelfDestruct(),
"raw_call": RawCall(),
"raw_log": RawLog(),
Expand Down
5 changes: 5 additions & 0 deletions vyper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ def trace(n=5, out=sys.stderr):
print("END TRACE", file=out)


# print a warning
def vyper_warn(msg, prefix="Warning: ", file_=sys.stderr):
print(f"{prefix}{msg}", file=file_)


# converts a signature like Func(bool,uint256,address) to its 4 byte method ID
# TODO replace manual calculations in codebase with this
def abi_method_id(method_sig):
Expand Down