Skip to content

Commit

Permalink
Liberating qualifiers from the oppression of explicit tags.
Browse files Browse the repository at this point in the history
* Type qualifiers no longer need to use the "qualifier" keyword.
  Qualifier clauses are now implicitly identified.
* Experimenting with a "lookup" category that will let you lookup
  the categories related to any particular category.
  • Loading branch information
built committed Aug 5, 2011
1 parent 3611647 commit 2cde3a4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 26 deletions.
43 changes: 29 additions & 14 deletions interpreter/tools.py
Expand Up @@ -118,17 +118,30 @@ def is_qualifier(category):
def is_regex(context, category):
return [term for term in context.comprehend(category.name, "regex", "metadata") if term.name != context.name]

def is_metadata(category):
return "metadata" in category.contents

def is_transition(category):
return "transition" in category.contents

def is_relation(category):
return "__relation__" in category.name

def is_negated(category):
return "not" in category.contents

def pattern_terms(context, pattern):
# Things to filter out of a pattern expression before pattern matching:
#
# context
# pattern tag
# transition relation
# any metadata for the pattern expression
return [term for term in pattern.contents.values()
if term.name != context.name
and term.name != "pattern"
and ( (is_qualifier(term) or is_negated(term)) or not is_relation(term) ) ]
and not is_transition(term)
and not is_metadata(term) ]

def negated_terms(context, negated):
return [term for term in negated.contents.values()
Expand Down Expand Up @@ -157,15 +170,10 @@ def pattern(context, transition):
return None # This pains me. Falling through with null. TODO: Grace.

def dump_pattern(context, pattern):
print "-= PATTERN DUMP =-"
print "-= PATTERN DUMP: %s =-" % pattern.name

for term in pattern:
if is_qualifier(term):
qualified = qualified_type(context, term)

print "[%s]" % (qualified if qualified else 'EVERYTHING')
else:
print term.name
for term in pattern.contents.values():
print "%s ==> %s" % (term.name, term.terms)

print "-= ------------ =-"

Expand All @@ -177,11 +185,11 @@ def match(context, transition, expression):
pure_pattern = pattern_terms(context, pattern(context, transition))
expression_terms = [term for term in expression.contents.values() if term.name != context.name and "metadata" not in term.terms]
action_terms = set(no_relations(action(context, transition).terms)) - set([context.name, "action"])
literals = {term.name:None for term in pure_pattern if not is_qualifier(term) and not is_negated(term) and not is_regex(context, term)}
literals = {term.name:None for term in pure_pattern if not is_relation(term) and not is_negated(term) and not is_regex(context, term)}

regexes = {term.name:None for term in pure_pattern if is_regex(context, term)}

qualifieds = {term:[] for term in pure_pattern if is_qualifier(term)}
qualifieds = {term:[] for term in pure_pattern if is_relation(term) } # Let's assume by this point all useless relations are removed.

negateds = {x for x in names(list(chain.from_iterable([negated_terms(context, term) for term in pure_pattern if is_negated(term)]))) if "__relation__" not in x}

Expand All @@ -203,10 +211,10 @@ def match(context, transition, expression):
regexes[regex_term] = expression_term

for qualified_term in qualifieds.keys():
qualifying_set = set(term for term in qualified_term.contents.values() if term.name != context.name and "__relation__" not in term.name and term.name != "qualifier")
qualifying_set = set(term for term in qualified_term.contents.values() if term.name != context.name and "__relation__" not in term.name)
qualification = [expression_term.name] + list(names(qualifying_set))
relationship = [relation for relation in context.comprehend(*qualification) if relation.name != context.name]
if relationship and expression_term.name not in qualified_term.terms:
existing_relationship = [relation for relation in context.comprehend(*qualification) if relation.name != context.name]
if existing_relationship and expression_term.name not in qualified_term.terms:
qualifieds[qualified_term] += [expression_term]

# Don't return nulls, only real matches.
Expand Down Expand Up @@ -248,6 +256,13 @@ def evaluate(expression, context):
if context.comprehend("prelude", "loaded"):
printout(context, expression)
return
elif "lookup" in expression.terms:
terms = [term for term in expression.terms if term != "lookup" and term != '*' and "__relation__" not in term]
for result in context.comprehend(*terms):
for item in result.terms:
if "__relation__" not in item:
print item
return


def shorthand(name):
Expand Down
2 changes: 1 addition & 1 deletion prelude.w
@@ -1,7 +1,7 @@
# Set up some things so that we can be sane.

# Print to stdout
transition (pattern print (string qualifier)) (action STDOUT)
transition (pattern print (string)) (action STDOUT)

# Let the interpreter and built-ins know that the interpreter is loaded.
prelude loaded
18 changes: 9 additions & 9 deletions tests/pattern_tests.py
Expand Up @@ -52,11 +52,11 @@ def test_qualified_single_match(self):
root = Category('*')
evaluate(parse("AAA foo", root), root)

transition = parse("transition (pattern (AAA qualifier)) (action no_action)", root)
transition = parse("transition (pattern (AAA)) (action no_action)", root)
expression = parse("foo", root)
matches = match(root, transition, expression)

self.assertEqual(len(matches), 1, "Should have ONE match only.")
self.assertEqual(len(matches), 1, "Should have one match, and ONE match only.")

self.assertEqual(matches.pop().name, "foo")

Expand All @@ -67,7 +67,7 @@ def test_qualified_multiple_match(self):
evaluate(parse("AAA foo", root), root)
evaluate(parse("blarf bar", root), root)

transition = parse("transition (pattern (AAA qualifier) (blarf qualifier)) (action no_action)", root)
transition = parse("transition (pattern (AAA) (blarf)) (action no_action)", root)
expression = parse("foo bar", root)
matches = match(root, transition, expression)

Expand All @@ -81,7 +81,7 @@ def test_qualified_mismatch(self):
evaluate(parse("AAA foo", root), root)
evaluate(parse("blarf bar", root), root)

transition = parse("transition (pattern (AAA qualifier) (blarf qualifier)) (action no_action)", root)
transition = parse("transition (pattern (AAA) (blarf)) (action no_action)", root)
expression = parse("fizz binn", root)
matches = match(root, transition, expression)

Expand All @@ -93,7 +93,7 @@ def test_qualified_partial_match(self):
evaluate(parse("AAA foo", root), root)
evaluate(parse("blarf bar", root), root)

transition = parse("transition (pattern (AAA qualifier) (blarf qualifier)) (action no_action)", root)
transition = parse("transition (pattern (AAA) (blarf)) (action no_action)", root)
expression = parse("foo barney whoo hoo", root)
matches = match(root, transition, expression)

Expand All @@ -108,7 +108,7 @@ def test_mixed_match(self):
root = Category('*')
evaluate(parse("AAA foo", root), root)

transition = parse("transition (pattern bar (AAA qualifier)) (action no_action)", root)
transition = parse("transition (pattern bar (AAA)) (action no_action)", root)
expression = parse("foo bar", root)
matches = match(root, transition, expression)

Expand All @@ -120,7 +120,7 @@ def test_mixed_mismatch(self):
root = Category('*')
evaluate(parse("AAA foo", root), root)

transition = parse("transition (pattern bar (AAA qualifier)) (action no_action)", root)
transition = parse("transition (pattern bar (AAA)) (action no_action)", root)
expression = parse("fizz bin bar", root)
matches = match(root, transition, expression)

Expand All @@ -132,7 +132,7 @@ def test_mixed_craziness(self):
evaluate(parse("AAA foo", root), root)
evaluate(parse("blarf bar", root), root)

transition = parse("transition (pattern ninja (AAA qualifier) assassin (blarf qualifier) woot) (action no_action)", root)
transition = parse("transition (pattern ninja (AAA) assassin (blarf) woot) (action no_action)", root)
expression = parse("woot jibberish foo spiffy ninja bar assassin and other things as well", root)
matches = match(root, transition, expression)

Expand Down Expand Up @@ -180,7 +180,7 @@ def test_mixed_match(self):
root = Category('*')
# evaluate(parse("foo string", root), root)

transition = parse("transition (pattern print (string qualifier)) (action no_action)", root)
transition = parse("transition (pattern print (string)) (action no_action)", root)
expression = parse('print "foo"', root)
matches = match(root, transition, expression)

Expand Down
4 changes: 2 additions & 2 deletions tests/transition_tests.py
Expand Up @@ -45,7 +45,7 @@ def test_simplest_program(self):
evaluate(parse(term, root), root )

# Define a transition that detects when something enters "foo". That 'something' should be connected to "bar".
transition = "transition (pattern foo (* qualifier) ) (action bar)"
transition = "transition (pattern foo (*) ) (action bar)"
evaluate(parse(transition, root), root)

matches = root.comprehend("bar", "works")
Expand Down Expand Up @@ -84,7 +84,7 @@ def test_typed_transition(self):

# If you see a string, process it by putting it in the "processed" category.
# TODO: Get rid of the (not processed) negation when implicit negations are added.
transition = "transition (pattern (string qualifier)) (action processed)"
transition = "transition (pattern (string)) (action processed)"
evaluate(parse(transition, root), root)

matches = root.comprehend("example", "processed")
Expand Down

0 comments on commit 2cde3a4

Please sign in to comment.