Skip to content

Commit

Permalink
annotations and error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kus committed Feb 27, 2020
1 parent 93ea967 commit d57586f
Show file tree
Hide file tree
Showing 8 changed files with 537 additions and 322 deletions.
169 changes: 76 additions & 93 deletions pytezos/repl/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,20 @@
from pytezos.crypto import blake2b_32, Key
from pytezos.repl.control import instruction
from pytezos.repl.stack import Stack
from pytezos.repl.types import assert_type, Int, Nat, Timestamp, Mutez, Option, Pair, Bool, Bytes, Key, Signature, \
KeyHash
from pytezos.repl.parser import assert_comparable, assert_expr_equal


def dispatch_type_map(a, b, mapping):
assert (type(a), type(b)) in mapping, \
f'unsupported argument types {type(a).__name__} and {type(b).__name__}'
return mapping[(type(a), type(b))]


def assert_equal_types(a, b):
assert type(a) == type(b), f'different types {type(a).__name__} and {type(b).__name__}'
from pytezos.repl.types import assert_stack_type, Int, Nat, Timestamp, Mutez, Option, Pair, Bool, Bytes, Key, \
Signature, KeyHash, dispatch_type_map


@instruction('ABS')
def do_abs(stack: Stack, prim, args):
def do_abs(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Int)
res = Nat(abs(top.value))
stack.ins(res)
assert_stack_type(top, Int)
res = Nat(abs(int(top)))
return stack.ins(res, annots=annots)


@instruction('ADD')
def do_add(stack: Stack, prim, args):
def do_add(stack: Stack, prim, args, annots):
a, b = stack.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Nat,
Expand All @@ -38,26 +27,19 @@ def do_add(stack: Stack, prim, args):
(Int, Timestamp): Timestamp,
(Mutez, Mutez): Mutez
})
res = res_type(a.value + b.value)
stack.ins(res)
res = res_type(int(a) + int(b))
return stack.ins(res, annots=annots)


@instruction('COMPARE')
def do_compare(stack: Stack, prim, args):
def do_compare(stack: Stack, prim, args, annots):
a, b = stack.pop2()
assert_expr_equal(a.type_expr, b.type_expr)
assert_comparable(a.type_expr)
if a.value > b.value:
res = Int(1)
elif a.value < b.value:
res = Int(-1)
else:
res = Int(0)
stack.ins(res)
res = Int(a.__cmp__(b))
return stack.ins(res, annots=annots)


@instruction('EDIV')
def do_ediv(stack: Stack, prim, args):
def do_ediv(stack: Stack, prim, args, annots):
a, b = stack.pop2()
q_type, r_type = dispatch_type_map(a, b, {
(Nat, Nat): (Nat, Nat),
Expand All @@ -67,21 +49,21 @@ def do_ediv(stack: Stack, prim, args):
(Mutez, Nat): (Mutez, Mutez),
(Mutez, Mutez): (Nat, Mutez)
})
if b.value == 0:
if int(b) == 0:
res = Option.none(Pair.new(q_type(), r_type()).type_expr)
else:
q, r = divmod(a.value, b.value)
q, r = divmod(int(a), int(b))
if r < 0:
r += abs(b.value)
r += abs(int(b))
q += 1
res = Option.some(Pair.new(q_type(q), r_type(r)))
stack.ins(res)
return stack.ins(res, annots=annots)


@instruction(['EQ', 'GE', 'GT', 'LE', 'LT', 'NEQ'])
def do_eq(stack: Stack, prim, args):
def do_eq(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Int)
assert_stack_type(top, Int)
handlers = {
'EQ': lambda x: x == 0,
'GE': lambda x: x >= 0,
Expand All @@ -90,44 +72,44 @@ def do_eq(stack: Stack, prim, args):
'LT': lambda x: x < 0,
'NEQ': lambda x: x != 0
}
res = Bool(handlers[prim](top.value))
stack.ins(res)
res = Bool(handlers[prim](int(top)))
return stack.ins(res, annots=annots)


@instruction('INT')
def do_int(stack: Stack, prim, args):
def do_int(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Nat)
res = Int(top.value)
stack.ins(res)
assert_stack_type(top, Nat)
res = Int(int(top))
return stack.ins(res, annots=annots)


@instruction('ISNAT')
def do_is_nat(stack: Stack, prim, args):
def do_is_nat(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Int)
if top.value >= 0:
res = Option.some(Nat(top.value))
assert_stack_type(top, Int)
if int(top) >= 0:
res = Option.some(Nat(int(top)))
else:
res = Option.none(Nat().type_expr)
stack.ins(res)
return stack.ins(res, annots=annots)


@instruction(['LSL', 'LSR'])
def do_lsl(stack: Stack, prim, args):
def do_lsl(stack: Stack, prim, args, annots):
a, b = stack.pop2()
assert_type(a, Nat)
assert_type(b, Nat)
assert_stack_type(a, Nat)
assert_stack_type(b, Nat)
handlers = {
'LSL': lambda x: x[0] << x[1],
'LSR': lambda x: x[0] >> x[1]
}
res = Nat(handlers[prim]((a.value, b.value)))
stack.ins(res)
res = Nat(handlers[prim]((int(a), int(b))))
return stack.ins(res, annots=annots)


@instruction('MUL')
def do_mul(stack: Stack, prim, args):
def do_mul(stack: Stack, prim, args, annots):
a, b = stack.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Nat,
Expand All @@ -137,20 +119,20 @@ def do_mul(stack: Stack, prim, args):
(Mutez, Nat): Mutez,
(Nat, Mutez): Mutez
})
res = res_type(a.value * b.value)
stack.ins(res)
res = res_type(int(a) * int(b))
return stack.ins(res, annots=annots)


@instruction('NEG')
def do_neg(stack: Stack, prim, args):
def do_neg(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, [Int, Nat])
res = Int(-top.value)
stack.ins(res)
assert_stack_type(top, [Int, Nat])
res = Int(-int(top))
return stack.ins(res, annots=annots)


@instruction('SUB')
def do_sub(stack: Stack, prim, args):
def do_sub(stack: Stack, prim, args, annots):
a, b = stack.pop2()
res_type = dispatch_type_map(a, b, {
(Nat, Nat): Int,
Expand All @@ -161,78 +143,79 @@ def do_sub(stack: Stack, prim, args):
(Timestamp, Timestamp): Int,
(Mutez, Mutez): Mutez
})
res = res_type(a.value - b.value)
stack.ins(res)
res = res_type(int(a) - int(b))
return stack.ins(res, annots=annots)


@instruction(['AND', 'OR', 'XOR'])
def do_and(stack: Stack, prim, args):
def do_and(stack: Stack, prim, args, annots):
a, b = stack.pop2()
assert_type(a, [Bool, Nat])
assert_equal_types(a, b)
val_type = dispatch_type_map(a, b, {
(Bool, Bool): bool,
(Nat, Nat): int
})
handlers = {
'AND': lambda x: x[0] & x[1],
'OR': lambda x: x[0] | x[1],
'XOR': lambda x: x[0] ^ x[1]
}
res_type = type(a)
res = res_type(handlers[prim]((a.value, b.value)))
stack.ins(res)
res = type(a)(handlers[prim]((val_type(a), val_type(b))))
return stack.ins(res, annots=annots)


@instruction('NOT')
def do_not(stack: Stack, prim, args):
def do_not(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, [Nat, Int, Bool])
assert_stack_type(top, [Nat, Int, Bool])
if type(top) in [Nat, Int]:
res = Int(~top.value)
res = Int(~int(top))
elif type(top) == Bool:
res = Bool(not top.value)
res = Bool(not bool(top))
else:
assert False
stack.ins(res)
return stack.ins(res, annots=annots)


@instruction('BLAKE2B')
def do_blake2b(stack: Stack, prim, args):
def do_blake2b(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Bytes)
res = Bytes(blake2b_32(top.value).digest())
stack.ins(res)
assert_stack_type(top, Bytes)
res = Bytes(blake2b_32(bytes(top)).digest())
return stack.ins(res, annots=annots)


@instruction('CHECK_SIGNATURE')
def do_check_sig(stack: Stack, prim, args):
def do_check_sig(stack: Stack, prim, args, annots):
pk, sig, msg = stack.pop3()
assert_type(pk, Key)
assert_type(sig, Signature)
assert_type(msg, Bytes)
key = Key.from_encoded_key(pk.value)
assert_stack_type(pk, Key)
assert_stack_type(sig, Signature)
assert_stack_type(msg, Bytes)
key = Key.from_encoded_key(str(pk))
try:
key.verify(signature=sig.value, message=msg.value)
key.verify(signature=str(sig), message=bytes(msg))
except:
res = Bool(False)
else:
res = Bool(True)
stack.ins(res)
return stack.ins(res, annots=annots)


@instruction('HASH_KEY')
def do_hash_key(stack: Stack, prim, args):
def do_hash_key(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Key)
key = Key.from_encoded_key(top.value)
assert_stack_type(top, Key)
key = Key.from_encoded_key(str(top))
res = KeyHash(key.public_key_hash())
stack.ins(res)
return stack.ins(res, annots=annots)


@instruction(['SHA256', 'SHA512'])
def do_sha(stack: Stack, prim, args):
def do_sha(stack: Stack, prim, args, annots):
top = stack.pop()
assert_type(top, Bytes)
assert_stack_type(top, Bytes)
handlers = {
'SHA256': lambda x: sha256(x).digest(),
'SHA512': lambda x: sha512(x).digest(),
}
res = Bytes(handlers[prim](top.value))
stack.ins(res)
res = Bytes(handlers[prim](bytes(top)))
return stack.ins(res, annots=annots)
Loading

0 comments on commit d57586f

Please sign in to comment.