def test_braces(self): self.assertEqual(lex('[a, 1]'), [Term(Tag('['), None, None, None), Term(Tag('IDENTIFIER'), 'a', None, None), Term(Tag(','), None, None, None), Term(Tag('.int.'), 1, None, None), Term(Tag(']'), None, None, None)])
def test_holes(self): self.assertEqual(lex('${'), [Term(Tag('${'), None, None, None)]) self.assertEqual(lex('$blee'), [Term(Tag('DOLLAR_IDENT'), "blee", None, None)]) self.assertEqual(lex('@{'), [Term(Tag('@{'), None, None, None)]) self.assertEqual(lex('@fred'), [Term(Tag('AT_IDENT'), "fred", None, None)]) self.assertEqual(lex('@_fred'), [Term(Tag('AT_IDENT'), "_fred", None, None)]) self.assertEqual(lex('@_'), [Term(Tag('AT_IDENT'), "_", None, None)]) self.assertEqual(lex('$0'), [Term(Tag('$'), None, None, None), Term(Tag(".int."), 0, None, None)]) self.assertEqual(lex('@1'), [Term(Tag('@'), None, None, None), Term(Tag(".int."), 1, None, None)])
def test_dedent(self): self.assertEqual(lex(SIMPLE_DEDENT), [Term(Tag('EOL'), None, None, None), Term(Tag('IDENTIFIER'), "foo", None, None), Term(Tag(':'), None, None, None), Term(Tag('EOL'), None, None, None), Term(Tag('INDENT'), None, None, None), Term(Tag('IDENTIFIER'), "baz", None, None), Term(Tag('DEDENT'), None, None, None), Term(Tag('EOL'), None, None, None), Term(Tag('IDENTIFIER'), "blee", None, None), Term(Tag('EOL'), None, None, None)])
def test_arrow(self): self.assertEqual(lex(ARROW_INDENT), [Term(Tag('EOL'), None, None, None), Term(Tag('IDENTIFIER'), "foo", None, None), Term(Tag('->'), None, None, None), Term(Tag('EOL'), None, None, None), Term(Tag('INDENT'), None, None, None), Term(Tag('IDENTIFIER'), "baz", None, None), Term(Tag('DEDENT'), None, None, None), Term(Tag('EOL'), None, None, None), Term(Tag('EOL'), None, None, None)])
def _substitute(self, map): candidate = self.functor._substitute(map)[0] args = tuple( itertools.chain.from_iterable( a._substitute(map) for a in self.args)) term = Term(candidate.tag, candidate.data, args) return [term]
def makeTerm(t, args=None): if isinstance(t, Term): if t.data is not None: if not args: return t else: raise ValueError("Literal terms can't have arguments") return Term(t.asFunctor(), None, args and tuple(args))
def rule_unknown_term(self): tt, _ = self.rule_anything() oldInput = self.input self.input = InputStream.fromIterable(tt.args) newargs, e = self.many(self.rule_transform) self.end() self.input = oldInput return Term(tt.tag, None, tuple(coerceToTerm(a) for a in newargs)), e
def generate_Predicate(self, out, term, debugname=None): """ Generate a call to self.pred(lambda: expr). """ fname = self._newThunkFor(out, "pred", Term(Tag("Action"), None, [term], None)) return self._expr(out, "pred", "self.pred(%s)" %(fname,), debugname)
def _coerce(self, spec): if isinstance(spec, Term): newf = coerceToQuasiMatch(spec.withoutArgs(), self.functor.isFunctorHole, self.tag) if newf is None: return None return Term(newf.asFunctor(), None, spec.args) else: return coerceToQuasiMatch(spec, self.functor.isFunctorHole, self.tag)
def coerceToQuasiMatch(val, isFunctorHole, tag): if isFunctorHole: if val is None: result = Term(Tag("null"), None, None) elif isinstance(val, Term): if len(val.args) != 0: return None else: result = val elif isinstance(val, basestring): result = Term(Tag(val), None, None) elif isinstance(val, bool): result = Term(Tag(["false", "true"][val]), None, None) else: return None else: result = coerceToTerm(val) if tag is not None and result.tag != tag: return None return result
def primary(self, atom, trailers): """ Re-nest a series of trailers on an atom. """ if trailers: # Ugh. This trickery is necessary because Terms are hard to unpack # and repack. for term in trailers: repacked = (atom,) + term.args[1:] atom = Term(term.tag, term.data, repacked) return atom
def test_zap(self): self.assertEqual(lex('1 >'), [Term(Tag('.int.'), 1, None, None), Term(Tag('>'), None, None, None)]) self.assertEqual(lex('1 >='), [Term(Tag('.int.'), 1, None, None), Term(Tag('>='), None, None, None)]) self.assertEqual(lex('1 >>='), [Term(Tag('.int.'), 1, None, None), Term(Tag('>>='), None, None, None)])
def convertInfix(self, maxPrec): leftAssociative = set( ['+', '-', '>>', '<<', '/', '*', '//', '%', '%%']) selfAssociative = set(['|', '&']) lhs, err = self.rule_prefix() output = [lhs] opstack = [] while True: opTok, _ = self.input.head() op = opTok.tag.name if op not in OPERATORS: break nextPrec = OPERATORS[op][0] if nextPrec > maxPrec: break self.input = self.input.tail() self.rule_br() if opstack and (opstack[-1][0] < nextPrec or op in leftAssociative and opstack[-1][0] <= nextPrec or op in selfAssociative and opstack[-1][2] == op): prec, nodeName, opname = opstack.pop() rhs = output.pop() lhs = output.pop() output.append(Term(Tag(nodeName), None, (lhs, rhs), None)) opstack.append(OPERATORS[op] + (op, )) if op in ['=~', '!~']: nextTok, err = self.rule_pattern() else: nextTok, err = self.rule_prefix() output.append(nextTok) while opstack: prec, nodeName, opname = opstack.pop() rhs = output.pop() lhs = output.pop() output.append(Term(Tag(nodeName), None, (lhs, rhs), None)) assert len(output) == 1 return output[0], err
def test_simpleTerm(self): """ Kernel syntax for terms is parsed properly. """ parse = self.getParser("baseTerm") self.assertEqual(parse("x"), Term(Tag("x"), None, None)) self.assertEqual(parse("x()"), Term(Tag("x"), None, [])) self.assertEqual(parse("x(1)"), Term(Tag("x"), None, (Term(Tag(".int."), 1, None), ))) self.assertEqual( parse("x(1, 2)"), Term(Tag("x"), None, (Term(Tag(".int."), 1, None), Term(Tag(".int."), 2, None)))) self.assertEqual(parse("1"), Term(Tag(".int."), 1, None)) self.assertEqual(parse('"1"'), Term(Tag(".String."), "1", None)) self.assertRaises(ValueError, parse, "'x'(x)") self.assertRaises(ValueError, parse, '3.14(1)') self.assertRaises(ValueError, parse, '"foo"(x)') self.assertRaises(ValueError, parse, "1(2)")
def test_literal(self): """ Literals are parsed to literal terms. """ parse = self.getParser("literal") self.assertEqual(parse('"foo bar"'), Term(Tag('.String.'), "foo bar", None, None)) self.assertEqual(parse("'x'"), Term(Tag('.char.'), 'x', None, None)) self.assertEqual(parse("0xDECAFC0FFEEBAD"), Term(Tag('.int.'), 0xDECAFC0FFEEBAD, None, None)) self.assertEqual(parse("0755"), Term(Tag('.int.'), 0o755, None, None)) self.assertEqual(parse("3.14159E17"), Term(Tag('.float64.'), 3.14159E17, None, None)) self.assertEqual(parse("1e9"), Term(Tag('.float64.'), 1e9, None, None)) self.assertEqual(parse("0"), Term(Tag(".int."), 0, None, None)) self.assertEqual(parse("7"), Term(Tag(".int."), 7, None, None)) self.assertEqual(parse("-1"), Term(Tag(".int."), -1, None, None)) self.assertEqual(parse("-3.14"), Term(Tag('.float64.'), -3.14, None, None)) self.assertEqual(parse("3_000"), Term(Tag('.int.'), 3000, None, None)) self.assertEqual(parse("0.91"), Term(Tag('.float64.'), 0.91, None, None)) self.assertEqual(parse("3e-2"), Term(Tag('.float64.'), 3e-2, None, None)) self.assertEqual(parse("'\\n'"), Term(Tag('.char.'), character("\n"), None, None)) self.assertEqual(parse('"foo\\nbar"'), Term(Tag('.String.'), "foo\nbar", None, None)) self.assertEqual(parse("'\\u0061'"), Term(Tag('.char.'), character("a"), None, None)) self.assertEqual(parse('"z\141p"'), Term(Tag('.String.'), "zap", None, None)) self.assertEqual(parse('"x\41"'), Term(Tag('.String.'), "x!", None, None)) self.assertEqual(parse('"foo\\\nbar"'), Term(Tag('.String.'), "foobar", None, None))
def backpatch(self, fromIdx, toIdx): old = self.instrs[fromIdx] self.instrs[fromIdx] = Term(old.tag, None, [coerceToTerm(toIdx)])
def generate_Object(self, out, ctx, node): #XXX replace this gubbish with proper destructuring doc, nameNode, script = node.args doc = doc.data guard = script.args[1] if nameNode.tag.name == 'IgnorePattern': name = "_" nameNode = Term(nameNode.tag, None, (guard, ), nameNode.span) selfName = ctx.layout.gensym("ignore") else: name = nameNode.args[0].args[0].data nameNode = Term(nameNode.tag, None, (nameNode.args[0], guard), nameNode.span) selfName = ctx.layout.addNoun(name, nameNode) implements = script.args[2].args if guard.tag.name != "null": implements = (guard, ) + implements scriptname = "_m_%s_Script" % (selfName, ) ss = scope(node) used = ss.namesUsed() fields = [ ctx.layout.getBinding(n) for n in used - ctx.layout.outer.outers ] if nameNode.tag.name != 'IgnorePattern': selfBinding = ctx.layout.getBinding(name) if nameNode.tag.name in ('FinalPattern', 'IgnorePattern'): paramNames = self._collectSlots(fields) else: paramNames = [selfName] + self._collectSlots(fields) fields = [selfBinding] fields += [ ctx.layout.getBinding(n) for n in used - ctx.layout.outer.outers ] methods = script.args[3].args matchers = script.args[4].args verbs = [meth.args[1].data for meth in methods] methGuards = [ "%r: %s" % (meth.args[1].data, self._generate(out, ctx, meth.args[3])) for meth in methods if meth.args[3].tag.name != 'null' ] if methGuards: paramNames.insert(0, '{%s}' % ', '.join(methGuards)) if implements: paramNames.insert( 0, '[%s]' % ', '.join( [self._generate(out, ctx, iface) for iface in implements])) val = "%s(%s)" % (scriptname, ", ".join(paramNames)) selfName = self._generatePattern(out, ctx, None, val, nameNode, True) frame = FrameScopeLayout(fields, verbs, selfName, nameNode, '%s$%s' % (ctx.layout.frame.fqnPrefix, name)) matcherNames = [ctx.layout.gensym("matcher") for _ in matchers] classOut, cflush = ctx.classWriter() classOut.writeln("class %s(_monte.MonteObject):" % (scriptname, )) classBodyOut = classOut.indent() classBodyOut.writeln( "_m_fqn = '%s$%s'" % (ctx.layout.frame.fqnPrefix, name.encode('string-escape'))) if not any([methods, matchers, fields, doc, implements]): classBodyOut.writeln("pass") if matcherNames: classBodyOut.writeln('_m_matcherNames = %r' % (matcherNames, )) if doc: classBodyOut.writeln('"""') for ln in doc.splitlines(): classBodyOut.writeln(ln) classBodyOut.writeln('"""') fnames = () if any([fields, implements, methGuards]): initOut = classBodyOut.indent() fnames = sorted([f.name for f in fields]) pyfnames = [mangleIdent(n) + "_slot" for n in fnames] initParams = pyfnames if methGuards: initParams = ["_m_methodGuards"] + initParams if implements: initParams = ["_m_auditors"] + initParams classBodyOut.writeln("def __init__(%s, %s):" % (selfName, ', '.join(initParams))) if implements: initOut.writeln(selfName + "._m_audit(_m_auditors)") if methGuards: initOut.writeln(selfName + "._m_guardMethods(_m_methodGuards)") for name, pyname in zip(fnames, pyfnames): initOut.writeln("_monte.MonteObject._m_install(%s, '%s', %s)" % (selfName, mangleIdent(name), pyname)) initOut.writeln("") metacontext = False for meth in methods: methctx = ctx.with_(layout=ScopeLayout(None, frame, ctx.layout.outer), mode=VALUE) mdoc = meth.args[0].data verb = meth.args[1].data params = meth.args[2].args methGuard = meth.args[3] body = meth.args[4] methOut = classBodyOut.indent() paramOut, flush = methOut.delay() paramNames = [ self._generatePatternForParam(paramOut, methctx, None, p) for p in params ] classBodyOut.writeln( "def %s(%s):" % (mangleIdent(verb), ', '.join([selfName] + paramNames))) if mdoc: methOut.writeln('"""') for ln in mdoc.splitlines(): methOut.writeln(ln) methOut.writeln('"""') flush() rvar = self._generate(methOut, methctx, body) if methGuard.tag.name != 'null': rvar = "%s._m_guardForMethod(%r).coerce(%s, _monte.throw)" % ( selfName, verb, rvar) methOut.writeln("return " + rvar + "\n") metacontext = metacontext or methctx.layout.metaContextExpr for matcherName, mtch in zip(matcherNames, matchers): mtchctx = ctx.with_(layout=ScopeLayout(None, frame, ctx.layout.outer), mode=VALUE) patt = mtch.args[0] body = mtch.args[1] matcherNames.append(matcherName) classBodyOut.writeln("def %s(%s, _m_message):" % (matcherName, selfName)) mtchOut = classBodyOut.indent() self._generatePattern(mtchOut, mtchctx, '_monte.matcherFail', "_m_message", patt) rvar = self._generate(mtchOut, mtchctx, body) mtchOut.writeln("return " + rvar + "\n") metacontext = metacontext or mtchctx.layout.metaContextExpr if implements or metacontext: classBodyOut.writeln( '_m_objectExpr = "%s"\n' % node._unparse().encode('zlib').encode('base64').replace( '\n', '')) cflush() if ctx.mode != FX_ONLY: return selfName
def Bag(args): return Term(Tag(".bag."), None, tuple(args))
def leafTag(tagName, span): """ Create a token with no data. """ return Term(Tag(tagName), None, None, span)
def test_caret(self): self.assertEqual(lex('^'), [Term(Tag('^'), None, None, None)]) self.assertEqual(lex('^='), [Term(Tag('^='), None, None, None)])
def leafInternal(tag, data): return Term(tag, data, None)
def Attr(k, v): return Term(Tag(".attr."), None, (k, v))
def LabelledBag(f, arg): return Term(f.asFunctor(), None, (arg, ))
def test_crunch(self): self.assertEqual(lex('<'), [Term(Tag('<'), None, None, None)]) self.assertEqual(lex('<-'), [Term(Tag('<-'), None, None, None)]) self.assertEqual(lex('<='), [Term(Tag('<='), None, None, None)]) self.assertEqual(lex('<<='), [Term(Tag('<<='), None, None, None)]) self.assertEqual(lex('<=>'), [Term(Tag('<=>'), None, None, None)])
def composite(tagName, data, span): """ Create a token with a name and data. """ return Term(Tag(tagName), data, None, span)
def test_minus(self): self.assertEqual(lex('-'), [Term(Tag('-'), None, None, None)]) self.assertEqual(lex('-='), [Term(Tag('-='), None, None, None)]) self.assertEqual(lex('-> {'), [Term(Tag('->'), None, None, None), Term(Tag('{'), None, None, None)])
def test_plus(self): self.assertEqual(lex('+'), [Term(Tag('+'), None, None, None)]) self.assertEqual(lex('+='), [Term(Tag('+='), None, None, None)])
def test_colon(self): self.assertEqual(lex(':x'), [Term(Tag(':'), None, None, None), Term(Tag('IDENTIFIER'), 'x', None, None)]) self.assertEqual(lex(':='), [Term(Tag(':='), None, None, None)]) self.assertEqual(lex('::'), [Term(Tag('::'), None, None, None)])
def _substitute(self, map): return [Term(self.tag, self.data, None)]
def Tuple(args): return Term(Tag(".tuple."), None, tuple(args))