Skip to content

Commit

Permalink
Refactor implementation of Tiger stdlib functions
Browse files Browse the repository at this point in the history
  • Loading branch information
iafisher committed Feb 9, 2019
1 parent 1185323 commit 5bb541c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
9 changes: 2 additions & 7 deletions hera/op.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from contextlib import suppress
from typing import Dict, List, Optional

from hera import stdlib
from hera.data import Constant, DataLabel, Location, Messages, Token
from hera.utils import format_int, from_u16, print_warning, to_u16, to_u32

Expand Down Expand Up @@ -936,13 +937,7 @@ class __EVAL(DebuggingOperation):
P = (STRING,)

def execute(self, vm):
# Rudimentary safeguard to make execution of malicious code harder. Users of
# hera-py should keep in mind that running arbitrary HERA code is no safer than
# running arbitrary code of any kind.
if "import" not in self.args[0]:
bytecode = compile(self.args[0], "<string>", "exec")
exec(bytecode, {}, {"vm": vm})

eval(self.args[0], {}, {"stdlib": stdlib, "vm": vm})
vm.pc += 1


Expand Down
49 changes: 43 additions & 6 deletions hera/stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,72 @@
"""


def tiger_printint_stack(vm):
print(vm.load_memory(vm.registers[14] + 3), end="")


def tiger_print_stack(vm):
addr = vm.load_memory(vm.registers[14] + 3)
n = vm.load_memory(addr)
for i in range(n):
print(chr(vm.load_memory(addr + i + 1)), end="")


def tiger_println_stack(vm):
addr = vm.load_memory(vm.registers[14] + 3)
n = vm.load_memory(addr)
for i in range(n):
print(chr(vm.load_memory(addr + i + 1)), end="")
print()


def tiger_exit(vm):
vm.halted = True


def tiger_div_stack(vm):
left = vm.load_memory(vm.registers[14] + 3)
right = vm.load_memory(vm.registers[14] + 4)
result = left // right if right != 0 else 0
vm.store_memory(vm.registers[14] + 3, result)


def tiger_mod_stack(vm):
left = vm.load_memory(vm.registers[14] + 3)
right = vm.load_memory(vm.registers[14] + 4)
result = left % right if right != 0 else 0
vm.store_memory(vm.registers[14] + 3, result)


# The standard library with parameters-on-the-stack functions.
TIGER_STDLIB_STACK = """
LABEL(printint)
__eval("print(vm.load_memory(vm.registers[14]+3), end='')")
__eval("stdlib.tiger_printint_stack(vm)")
RETURN(FP_alt, PC_ret)
LABEL(print)
__eval("addr = vm.load_memory(vm.registers[14]+3); n = vm.load_memory(addr)\\nfor i in range(n):\\n print(chr(vm.load_memory(addr+i+1)), end='')")
__eval("stdlib.tiger_print_stack(vm)")
RETURN(FP_alt, PC_ret)
LABEL(println)
__eval("addr = vm.load_memory(vm.registers[14]+3); n = vm.load_memory(addr)\\nfor i in range(n):\\n print(chr(vm.load_memory(addr+i+1)), end='')\\nprint()")
__eval("stdlib.tiger_println_stack(vm)")
RETURN(FP_alt, PC_ret)
LABEL(exit)
__eval("vm.pc = float('inf')")
__eval("stdlib.tiger_exit(vm)")
RETURN(FP_alt, PC_ret)
LABEL(div)
__eval("left = vm.load_memory(vm.registers[14]+3); right = vm.load_memory(vm.registers[14]+4); vm.store_memory(vm.registers[14]+3, left // right if right != 0 else 0)")
__eval("stdlib.tiger_div_stack(vm)")
RETURN(FP_alt, PC_ret)
LABEL(mod)
__eval("left = vm.load_memory(vm.registers[14]+3); right = vm.load_memory(vm.registers[14]+4); vm.store_memory(vm.registers[14]+3, left % right if right != 0 else 0)")
__eval("stdlib.tiger_mod_stack(vm)")
RETURN(FP_alt, PC_ret)
Expand Down
12 changes: 3 additions & 9 deletions test/test_exec/test_debug_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,12 @@ def test_println_increments_pc(vm):


def test___eval(vm):
helper(vm, '__eval("vm.registers[7] = 10")')
helper(vm, '__eval("stdlib.tiger_exit(vm)")')

assert vm.registers[7] == 10


def test___eval_cannot_import_anything(vm, capsys):
helper(vm, "__eval(\"import sys; sys.stdout.write('hi')\")")

assert capsys.readouterr().out == ""
assert vm.halted is True


def test___eval_increments_pc(vm):
helper(vm, '__eval("")')
helper(vm, '__eval("0")')

assert vm.pc == 1

0 comments on commit 5bb541c

Please sign in to comment.