Skip to content
This repository has been archived by the owner on Jul 16, 2023. It is now read-only.

Commit

Permalink
hide implementations in compiled code
Browse files Browse the repository at this point in the history
  • Loading branch information
rjdbcm committed Nov 7, 2021
1 parent 60efb49 commit ac6ead4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 56 deletions.
36 changes: 18 additions & 18 deletions Aspidites/parser/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,47 @@ def cvt_arith_expr(tks):
substr = ['!', '**', '//', '/', '%']
while any([s in expr for s in substr]):
if "!" in expr:
expr = "Maybe(SafeFactorial, " + expr.replace('!', '', 1) + end
expr = "__maybe(__safeFactorial, " + expr.replace('!', '', 1) + end
if expr.count(end) > 1:
expr = "Maybe(SafeFactorial, " + expr
expr = "__maybe(__safeFactorial, " + expr
continue
elif "**" in expr:
a, op, b = expr.partition('**')
expr = a + op + b.replace('**', end, 1) + sep
expr = "Maybe(SafeExp, " + expr.replace("**", sep, 1) + end
expr = "__maybe(__safeExp, " + expr.replace("**", sep, 1) + end
if expr.count(end) > 1:
expr = "Maybe(SafeExp, " + expr
expr = "__maybe(__safeExp, " + expr
continue
elif "//" in expr:
a, op, b = expr.partition('//')
expr = a + op + b.replace('//', end, 1) + sep
expr = "Maybe(SafeFloorDiv, " + expr.replace("//", sep, 1) + end
expr = "__maybe(__safeFloorDiv, " + expr.replace("//", sep, 1) + end
if expr.count(end) > 1:
expr = "Maybe(SafeFloorDiv, " + expr
expr = "__maybe(__safeFloorDiv, " + expr
continue
elif "/" in expr:
a, op, b = expr.partition('/')
expr = a + op + b.replace('/', end + sep, 1)
expr = "Maybe(SafeDiv, " + expr.replace("/", sep, 1) + end
expr = "__maybe(__safeDiv, " + expr.replace("/", sep, 1) + end
if expr.count(end) > 1:
expr = "Maybe(SafeDiv, " + expr
expr = "__maybe(__safeDiv, " + expr
continue
elif "%" in expr:
a, op, b = expr.partition('%')
expr = a + op + b.replace('%', end, 1) + sep
expr = "Maybe(SafeMod, " + expr.replace("%", sep, 1) + end
expr = "__maybe(__safeMod, " + expr.replace("%", sep, 1) + end
if expr.count(end) > 1:
expr = "Maybe(SafeMod, " + expr
expr = "__maybe(__safeMod, " + expr
continue
# TODO Unary ops don't get caught during parsing.
elif '-' in expr and expr.count('-') % 2 == 0:
expr = "Maybe(SafeUnaryAdd, " + expr.replace("+", '') + end
expr = "__maybe(__safeUnaryAdd, " + expr.replace("+", '') + end
continue
elif '-' in expr and expr.count('-') % 2 == 1:
expr = "Maybe(SafeUnarySub, " + expr.replace("-", '') + end
expr = "__maybe(__safeUnarySub, " + expr.replace("-", '') + end
continue
elif '+' in expr:
expr = "Maybe(SafeUnaryAdd, " + expr.replace("+", '') + end
expr = "__maybe(__safeUnaryAdd, " + expr.replace("+", '') + end
continue
return expr

Expand Down Expand Up @@ -103,7 +103,7 @@ def cvt_dict(t):
else: # integer key
t[i] = f"{key}: {val}"
s = f'{", ".join(t)}'.encode('UTF-8')
return f"pmap({{{s.decode('UTF-8')}}})"
return f"__pmap({{{s.decode('UTF-8')}}})"


def cvt_list(t):
Expand All @@ -115,7 +115,7 @@ def cvt_list(t):
else: # integer key
t[i] = int(v)
s = f'{", ".join(t)}'.encode('UTF-8')
return f"pvector([{s.decode('UTF-8')}])"
return f"__pvector([{s.decode('UTF-8')}])"


def cvt_list_index(t):
Expand All @@ -135,7 +135,7 @@ def cvt_set(t):
else: # integer key
t[i] = int(v)
s = f'{", ".join(t)}'.encode('UTF-8')
return f"pset({{{s.decode('UTF-8')}}})"
return f"__pset({{{s.decode('UTF-8')}}})"


def cvt_contract_assign(t):
Expand Down Expand Up @@ -165,8 +165,8 @@ def swap_val_to_idx(lst: list, val, idx: int) -> list:


def cvt_clos_call(t):
return "Maybe" + t[0][1] + t[0][0] + sep + sep.join(t[0][2:-1]) + t[0][-1]
return "__maybe" + t[0][1] + t[0][0] + sep + sep.join(t[0][2:-1]) + t[0][-1]


def cvt_func_call(t):
return "Maybe" + t[0][1] + t[0][0] + sep + sep.join(t[0][2:-1]) + t[0][-1] + lit_lparen + lit_rparen
return "__maybe" + t[0][1] + t[0][0] + sep + sep.join(t[0][2:-1]) + t[0][-1] + lit_lparen + lit_rparen
2 changes: 1 addition & 1 deletion Aspidites/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
func_decl = Group(
Optional(OneOrMore(bool_pragmas) | OneOrMore(pragmas)) +
private_def_decl + identifier + def_args + _contract_expression).setParseAction(
lambda t: "\n@contract()\n" + "".join(*t) + lit_colon)
lambda t: "\n@__contract()\n" + "".join(*t) + lit_colon)
func_decl.setName('function declaration')
comment_line = (Combine(Regex(r"`(?:[^`\n\r\\]|(?:``)|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "`").setParseAction(
lambda t: t[0]).setParseAction(cvt_comment_line))
Expand Down
4 changes: 2 additions & 2 deletions Aspidites/parser/reserved.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
lparen, rparen, lbrack, rbrack, lbrace, rbrace, colon, comma = map(Suppress, "()[]{}:,")
lit_lparen, lit_rparen, lit_lbrack, lit_rbrack, lit_lbrace, lit_rbrace, lit_colon, lit_comma = map(str, "()[]{}:,")
bool_literal = oneOf("True False", asKeyword=True).setParseAction(lambda t: t[0] == "True").setName('boolean literal')
nullit = oneOf("/0 ø Ø").setParseAction(replaceWith("Undefined()")).setName('nullity')
nullit = oneOf("/0 ø Ø").setParseAction(replaceWith("__undefined()")).setName('nullity')
signop = Literal("+") | Literal("-")
multop = Literal("*") | oneOf("/ //") | Literal("%") | Literal("@")
plusop = Literal("+") | Literal("-")
Expand Down Expand Up @@ -82,6 +82,6 @@
break_stmt = Literal("<%>").setParseAction(replaceWith('break')).setName('break trigram')
if_cond = Literal('<?>').setParseAction(replaceWith('if ')).setName('conditional trigram')
respects = Keyword("->").setParseAction(lambda t: ":").setName('contract assignment')
imposes = Keyword("<-").setParseAction(lambda t: "new_contract").setName('contract imposition')
imposes = Keyword("<-").setParseAction(lambda t: "__new_contract").setName('contract imposition')
struct_main = Keyword("main:").setParseAction(replaceWith('if __name__ == "__main__":'))

22 changes: 10 additions & 12 deletions Aspidites/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,13 @@
longdoublecomplex, longlong, complex, float as cfloat)
from Aspidites._vendor.pyrsistent import (
pset,
pmap,
pvector,
pset as __pset,
pmap as __pmap,
pvector as __pvector,
s, v, m
)
from Aspidites.woma import *
from Aspidites._vendor import (
F,
take,
drop,
takelast,
Expand Down Expand Up @@ -227,19 +226,18 @@
match as __match,
_,
)
from Aspidites.monads import Maybe, Surely
from Aspidites.math import Undefined, SafeDiv, SafeExp, SafeMod, SafeFloorDiv, SafeUnaryAdd, SafeUnarySub, SafeFactorial
from Aspidites._vendor.contracts import contract, new_contract
from Aspidites._vendor.RestrictedPython import safe_builtins
safe_builtins['F'] = F
safe_builtins['print'] = print
from Aspidites.monads import Maybe as __maybe, Surely as __surely
from Aspidites.math import Undefined as __undefined, SafeDiv as __safeDiv, SafeExp as __safeExp, SafeMod as __safeMod, SafeFloorDiv as __safeFloorDiv, SafeUnaryAdd as __safeUnaryAdd, SafeUnarySub as __safeUnarySub, SafeFactorial as __safeFactorial
from Aspidites._vendor.contracts import contract as __contract, new_contract as __new_contract
from Aspidites._vendor.RestrictedPython import safe_builtins as __safe_builtins
__safe_builtins['print'] = print
from Aspidites._vendor.RestrictedPython import compile_restricted as compile
safe_builtins['compile'] = compile
__safe_builtins['compile'] = compile
# DECLARATIONS TO ALLOW CONTRACTS TO TYPE CHECK #
procedure: None
coroutine: Generator
number: Any
globals().update(dict(__builtins__=safe_builtins)) # add all imports to globals
globals().update(dict(__builtins__=__pmap(__safe_builtins))) # add all imports to globals
$code
Expand Down
46 changes: 23 additions & 23 deletions Aspidites/tests/test_aspidites.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import hypothesis
import pytest as pt
from hypothesis import given, assume, strategies as st
from Aspidites._vendor.contracts import contract
from Aspidites._vendor.contracts import contract as __contract

try:
from numpy import inf, nan, isinf, isnan
Expand All @@ -19,8 +19,8 @@
from ..__main__ import get_cy_kwargs, main
from ..parser.parser import parse_module, func_def, arith_expr, list_item, collection_trigrams
from ..templates import woma_template
from ..monads import Maybe, Surely
from ..math import SafeFloorDiv, SafeMod, SafeDiv, SafeExp, Undefined, SafeFactorial, SafeUnarySub, SafeUnaryAdd
from ..monads import Maybe as __maybe, Surely
from ..math import Undefined as __undefined, SafeDiv as __safeDiv, SafeExp as __safeExp, SafeMod as __safeMod, SafeFloorDiv as __safeFloorDiv, SafeUnaryAdd as __safeUnaryAdd, SafeUnarySub as __safeUnarySub, SafeFactorial as __safeFactorial
from ..compiler import Compiler, CompilerArgs

docker = os.getenv("ASPIDITES_DOCKER_BUILD")
Expand Down Expand Up @@ -106,7 +106,7 @@ def test_parse_func_def(w, x, y, z):
def test_parse_literals(v, x, y):
assert ''.join(list_item.parseString(f"'{v}'")) == f"'{v}'"
assert ''.join(list_item.parseString(f'"{v}"')) == f'"{v}"'
assert ''.join(list_item.parseString('/0')) == 'Undefined()'
assert ''.join(list_item.parseString('/0')) == '__undefined()'
assert ''.join(list_item.parseString('True')) == 'True'
assert ''.join(list_item.parseString('False')) == 'False'
assert ''.join(list_item.parseString(f'{x}.{y}')) == f'{x}.{y}'
Expand All @@ -118,7 +118,7 @@ def test_parse_literals(v, x, y):
st.integers(),
st.integers(min_value=0))
def test_set_remove(v, x, y):
assert ''.join(collection_trigrams.parseString(f"{{{y},{x}}}[*]{y}")) == f"pset({{{y}, {x}}}).remove({y})"
assert ''.join(collection_trigrams.parseString(f"{{{y},{x}}}[*]{y}")) == f"__pset({{{y}, {x}}}).remove({y})"


# @hypothesis.settings(deadline=None)
Expand All @@ -139,9 +139,9 @@ def test_set_remove(v, x, y):
st.integers(min_value=0))
def test_parse_collections(t, u, v, w, x, y):
assert ''.join(list_item.parseString(f"{{'a': ({y}+5), '{w}': 8, '{v}': True, {x}: None, 'd': 6**2*5+3}}")) \
== f"pmap({{'a': ({y}+5), '{w}': 8, '{v}': True, {x}: None, 'd': Maybe(SafeExp, 6, 2*5+3, )()}})"
assert ''.join(list_item.parseString(f"{{'{v}', '{w}'}}")) == f"pset({{'{v}', '{w}'}})"
assert ''.join(list_item.parseString(f"[{u}, 4, 6, {x}, {y}]")) == f"pvector([pvector({u}), 4, 6, {x}, {y}])"
== f"__pmap({{'a': ({y}+5), '{w}': 8, '{v}': True, {x}: None, 'd': __maybe(__safeExp, 6, 2*5+3, )()}})"
assert ''.join(list_item.parseString(f"{{'{v}', '{w}'}}")) == f"__pset({{'{v}', '{w}'}})"
assert ''.join(list_item.parseString(f"[{u}, 4, 6, {x}, {y}]")) == f"__pvector([__pvector({u}), 4, 6, {x}, {y}])"


@hypothesis.settings(deadline=None)
Expand All @@ -151,20 +151,20 @@ def test_parse_collections(t, u, v, w, x, y):
st.integers(min_value=0))
def test_parse_evolvers(w, x, y, z):
assert ''.join(list_item.parseString("{'a': (3+5), 'b': 8, 'c': True, 4: None, 'd': 6**2*5+3}...")) \
== "pmap({'a': (3+5), 'b': 8, 'c': True, 4: None, 'd': Maybe(SafeExp, 6, 2*5+3, )()}).evolver()"
assert ''.join(list_item.parseString("{'a', 'b', 'c'}...")) == "pset({'a', 'b', 'c'}).evolver()"
assert ''.join(list_item.parseString("[2, 4, 6, 8, 10]...")) == "pvector([2, 4, 6, 8, 10]).evolver()"
== "__pmap({'a': (3+5), 'b': 8, 'c': True, 4: None, 'd': __maybe(__safeExp, 6, 2*5+3, )()}).evolver()"
assert ''.join(list_item.parseString("{'a', 'b', 'c'}...")) == "__pset({'a', 'b', 'c'}).evolver()"
assert ''.join(list_item.parseString("[2, 4, 6, 8, 10]...")) == "__pvector([2, 4, 6, 8, 10]).evolver()"


# TODO Stacking unary operators onto their respective positive/negative operands does not parse safely
# line 105, in test_parse_arith
# assert eval(stmt) == eval(''.join(arith_expr.parseString(stmt)))
# AssertionError: assert 1 == -1
# + where 1 = eval('--1-0//-1')
# + and -1 = eval('Maybe(SafeFloorDiv, --1-0, -1)()')
# + where 'Maybe(SafeFloorDiv, --1-0, -1)()' = <built-in method join of str object at 0x1033f0030>((['Maybe(SafeFloorDiv, --1-0, -1)()'], {}))
# + and -1 = eval('__maybe(__safeFloorDiv, --1-0, -1)()')
# + where '__maybe(__safeFloorDiv, --1-0, -1)()' = <built-in method join of str object at 0x1033f0030>((['__maybe(__safeFloorDiv, --1-0, -1)()'], {}))
# + where <built-in method join of str object at 0x1033f0030> = ''.join
# + and (['Maybe(SafeFloorDiv, --1-0, -1)()'], {}) = <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)>('--1-0//-1')
# + and (['__maybe(__safeFloorDiv, --1-0, -1)()'], {}) = <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)>('--1-0//-1')
# + where <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)> = arith_expr.parseString
#
# Falsifying example: test_parse_arith(
Expand All @@ -174,12 +174,12 @@ def test_parse_evolvers(w, x, y, z):
# TODO Stacking division and floor division does not parse safely
# line 120, in test_parse_arith
# assert eval(stmt) == eval(''.join(arith_expr.parseString(stmt)))
# AssertionError: assert -1.0 == Undefined(None, (), {})
# AssertionError: assert -1.0 == __undefined(None, (), {})
# + where -1.0 = eval('-1/1//1')
# + and Undefined(None, (), {}) = eval('Maybe(SafeDiv, Maybe(SafeFloorDiv, -1, 1, 1)())()')
# + where 'Maybe(SafeDiv, Maybe(SafeFloorDiv, -1, 1, 1)())()' = <built-in method join of str object at 0x10ac04030>((['Maybe(SafeDiv, Maybe(SafeFloorDiv, -1, 1, 1)())()'], {}))
# + and __undefined(None, (), {}) = eval('__maybe(__safeDiv, __maybe(__safeFloorDiv, -1, 1, 1)())()')
# + where '__maybe(__safeDiv, __maybe(__safeFloorDiv, -1, 1, 1)())()' = <built-in method join of str object at 0x10ac04030>((['__maybe(__safeDiv, __maybe(__safeFloorDiv, -1, 1, 1)())()'], {}))
# + where <built-in method join of str object at 0x10ac04030> = ''.join
# + and (['Maybe(SafeDiv, Maybe(SafeFloorDiv, -1, 1, 1)())()'], {}) = <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)>('-1/1//1')
# + and (['__maybe(__safeDiv, __maybe(__safeFloorDiv, -1, 1, 1)())()'], {}) = <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)>('-1/1//1')
# + where <bound method ParserElement.parseString of Combine:(Forward: bitwise operator term)> = arith_expr.parseString
@hypothesis.settings(deadline=None)
@hypothesis.given(st.integers(min_value=1, max_value=255), # exponent
Expand Down Expand Up @@ -243,14 +243,14 @@ def test_compile_to_shared_object(inject_config):
Add(x=6.5, y=12)

assert [1, 2, 3] == [i for i in Yield123()]
assert Maybe(Add, 6.5, 12)() == Undefined()
assert __maybe(Add, 6.5, 12)() == __undefined()
assert x() == 6
assert y() == Undefined()
assert nullity == Undefined()
assert y() == __undefined()
assert nullity == __undefined()
assert z == 9
assert Add(x=3, y=2) == 5
assert val() == Undefined()
assert div_by_zero == Undefined()
assert val() == __undefined()
assert div_by_zero == __undefined()

#
# def teardown_function():
Expand Down

0 comments on commit ac6ead4

Please sign in to comment.