Definitions infer stack effects.

At start-up defs that DON'T type check are permitted (so you can use e.g.
loop, map, etc.) in the definitions "source", but then the user-facing
inscribe command only allows you to define new commands that DO
type-check.  The ideal solution here is to get inference working for the
loopy words.  (In the meantime you can select and execute their
definition text directly.  That's not (yet!) type-checked.)
This commit is contained in:
Simon Forman 2018-07-17 20:52:57 -07:00
parent c9f405fbe9
commit 7607ca7650
3 changed files with 47 additions and 84 deletions

View File

@ -23,7 +23,7 @@ from inspect import getdoc
from joy.joy import run
from joy.parser import Symbol
from joy.utils.stack import stack_to_string
from joy.utils.polytypes import type_check
from joy.utils.types import type_check
def is_numerical(s):

View File

@ -236,6 +236,7 @@ codireco == cons dip rest cons
make_generator == [codireco] ccons
ifte == [nullary not] dipd branch
'''
#
#
# ifte == [nullary] dipd swap branch
# genrec == [[genrec] cons cons cons cons] nullary swons concat ifte
@ -365,17 +366,20 @@ class DefinitionWrapper(object):
class_.add_def(definition, dictionary)
@classmethod
def add_def(class_, definition, dictionary):
def add_def(class_, definition, dictionary, fail_fails=False):
'''
Add the definition to the dictionary.
'''
F = class_.parse_definition(definition)
try:
#print F._body
# print F.name, F._body
secs = infer(*F._body)
except JoyTypeError:
pass
print F.name, '==', expression_to_string(F.body), ' --failed to infer stack effect.'
if fail_fails:
print 'Function not inscribed.'
return
else:
FUNCTIONS[F.name] = SymbolJoyType(F.name, secs, _SYM_NUMS())
dictionary[F.name] = F
@ -405,7 +409,7 @@ def inscribe_(stack, expression, dictionary):
the definitions.txt resource.
'''
definition, stack = stack
DefinitionWrapper.add_def(definition, dictionary)
DefinitionWrapper.add_def(definition, dictionary, fail_fails=True)
return stack, expression, dictionary
@ -652,6 +656,7 @@ def reverse(S):
@inscribe
@combinator_effect(_COMB_NUMS(), s7, s6)
@SimpleFunctionWrapper
def concat_(S):
'''Concatinate the two lists on the top of the stack.
@ -982,7 +987,7 @@ def infra(stack, expression, dictionary):
@inscribe
@combinator_effect(_COMB_NUMS(), s7, s6, s5, s4)
#@combinator_effect(_COMB_NUMS(), s7, s6, s5, s4)
@FunctionWrapper
def genrec(stack, expression, dictionary):
'''
@ -1396,7 +1401,7 @@ def times(stack, expression, dictionary):
@inscribe
@combinator_effect(_COMB_NUMS(), b1, s6)
#@combinator_effect(_COMB_NUMS(), b1, s6)
@FunctionWrapper
def loop(stack, expression, dictionary):
'''

View File

@ -1,58 +1,15 @@
# -*- coding: utf_8
'''
Multiple Stack Effects
By adjusting the machinery in types.py to handles lists of stack effect comments
we can capture more information about the type signatures of some functions,
and we can introduce a kind of Kleene Star or sequence type that can stand for
an unbounded sequence of other types.
'''
import sys
import joy.library
from joy.parser import Symbol, text_to_expression
from joy.utils.stack import (
concat as CONCAT,
expression_to_string,
list_to_stack,
)
average =
# sum_ =
# product =
# min_ = max_ = [(((Ns[1], s1), s0), (n0, s0))]
# flatten = [(((Ss[1], s1), s0), (s2, s0))]
return {
name.rstrip('_'): stack_effect
for name, stack_effect in locals().iteritems()
}
FUNCTIONS.update({
name: SymbolJoyType(name, stack_effect, i)
for i, (name, stack_effect) in enumerate(defs().iteritems())
})
FUNCTIONS.update({
combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
for i, combo in enumerate((
joy.library.concat_,
joy.library._dictionary['disenstacken'],
joy.library.x,
))
})
def branch_true(stack, expression, dictionary):
(then, (else_, (flag, stack))) = stack
return stack, CONCAT(then, expression), dictionary
def branch_false(stack, expression, dictionary):
(then, (else_, (flag, stack))) = stack
return stack, CONCAT(else_, expression), dictionary
FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
pop = FUNCTIONS['pop']
def loop_true(stack, expression, dictionary):
@ -70,41 +27,42 @@ def loop_false(stack, expression, dictionary):
FUNCTIONS['loop'] = CombinatorJoyType('loop', [loop_two_true, loop_true, loop_false], 101)
joy.library.add_aliases(FUNCTIONS, joy.library.ALIASES)
def set_expectations_of_definition(cjt):
if len(cjt.stack_effects) != 1:
raise ValueError
defi = cjt.stack_effects[0]
if not isinstance(defi, joy.library.DefinitionWrapper):
raise ValueError
F = infer_expression(defi.body)
assert len(F) == 1, repr(F)
fi, fo = F[0]
cjt.expect = fi
def set_expectations():
# joy.library.add_aliases(FUNCTIONS, joy.library.ALIASES)
# def set_expectations_of_definition(cjt):
# if len(cjt.stack_effects) != 1:
# raise ValueError
# defi = cjt.stack_effects[0]
# if not isinstance(defi, joy.library.DefinitionWrapper):
# raise ValueError
# F = infer_expression(defi.body)
# assert len(F) == 1, repr(F)
# fi, fo = F[0]
# cjt.expect = fi
average =
loop.expect = s6, (b1, s5)
# i.expect = nullary.expect = x.expect = s7, s6
# dip.expect = dupdip.expect = s8, (a8, s7)
# dipd.expect = s8, (a8, (a7, s7))
# dipdd.expect = s8, (a8, (a7, (a6, s7)))
concat_.expect = s8, (s7, s6)
# b.expect = infra.expect = s8, (s7, s6)
# set_expectations_of_definition(unary)
# set_expectations_of_definition(binary)
# set_expectations_of_definition(ternary)
# set_expectations_of_definition(quoted)
# set_expectations_of_definition(unquoted)
# set_expectations_of_definition(enstacken)
disenstacken.expect = (As[1], s1), s0
scope = globals().copy()
scope.update(FUNCTIONS)
eval(set_expectations.func_code, scope)
del scope
joy.library._dictionary['disenstacken'],
# scope = globals().copy()
# scope.update(FUNCTIONS)
# eval(set_expectations.func_code, scope)
# del scope