A categorical programming language
Revision | 8fa9e079783349f7a06efab4512c30b44b05f46a (tree) |
---|---|
Time | 2024-10-25 15:03:35 |
Author | Corbin <cds@corb...> |
Commiter | Corbin |
Use regexes to parse inject/project/nats/ords.
@@ -2,6 +2,7 @@ import math | ||
2 | 2 | |
3 | 3 | from rpython.rlib.objectmodel import specialize |
4 | 4 | # from rpython.rlib.rbigint import rbigint |
5 | +from rpython.rlib.rsre import rsre_re as re | |
5 | 6 | |
6 | 7 | from cammylib.elements import F, N, thePoint, theTrue, theFalse |
7 | 8 |
@@ -479,53 +480,54 @@ class Nat(Arrow): | ||
479 | 480 | def compileCAM(self, compiler): compiler.quote(N(self.n)) |
480 | 481 | def types(self, cs): return cs.concrete("1"), cs.concrete("N") |
481 | 482 | |
483 | +RE_INJECT = re.compile("^i(\d+)o(\d+)$") | |
484 | +RE_PROJECT = re.compile("^p(\d+)o(\d+)$") | |
485 | +RE_NAT = re.compile("^n(\d+)(o(\d+))?$") | |
486 | + | |
482 | 487 | def buildUnary(name): |
483 | 488 | if name in unaryFunctors: return unaryFunctors[name] |
484 | - elif name.startswith("i"): | |
485 | - o = name[1:] | |
486 | - # XXX regex instead? | |
489 | + elif RE_INJECT.match(name): | |
490 | + m = RE_INJECT.match(name) | |
487 | 491 | try: |
488 | - ok, on = o.split("o", 1) | |
489 | - k = int(ok) | |
490 | - n = int(on) | |
492 | + k = int(m.group(1)) | |
493 | + n = int(m.group(2)) | |
491 | 494 | if n < 2: |
492 | 495 | raise BuildProblem("The smallest ordinal is 2, not %d" % n) |
493 | 496 | if not (0 <= k < n): |
494 | 497 | raise BuildProblem("Invalid ordinal index: %d of %d" % (k, n)) |
495 | 498 | return Inject(k, n) |
496 | - except ValueError: raise BuildProblem("Invalid ordinal pair: " + o) | |
497 | - elif name.startswith("p"): | |
498 | - o = name[1:] | |
499 | - # XXX regex instead? | |
499 | + except ValueError: raise BuildProblem("Invalid ordinal pair: " + name) | |
500 | + elif RE_PROJECT.match(name): | |
501 | + m = RE_PROJECT.match(name) | |
500 | 502 | try: |
501 | - ok, on = o.split("o", 1) | |
502 | - k = int(ok) | |
503 | - n = int(on) | |
503 | + k = int(m.group(1)) | |
504 | + n = int(m.group(2)) | |
504 | 505 | if n < 2: |
505 | 506 | raise BuildProblem("The smallest ordinal is 2, not %d" % n) |
506 | 507 | if not (0 <= k < n): |
507 | 508 | raise BuildProblem("Invalid ordinal index: %d of %d" % (k, n)) |
508 | 509 | return Project(k, n) |
509 | - except ValueError: raise BuildProblem("Invalid ordinal pair: " + o) | |
510 | - elif name.startswith("n"): | |
511 | - if "o" in name: | |
512 | - ok, on = name[1:].split("o", 1) | |
513 | - k = int(ok) | |
514 | - n = int(on) | |
510 | + except ValueError: raise BuildProblem("Invalid ordinal pair: " + name) | |
511 | + elif RE_NAT.match(name): | |
512 | + m = RE_NAT.match(name) | |
513 | + if m.group(2) is None: | |
514 | + try: return Nat(int(m.group(1))) | |
515 | + except ValueError: | |
516 | + raise BuildProblem("Invalid natural number: " + name) | |
517 | + else: | |
518 | + k = int(m.group(1)) | |
519 | + n = int(m.group(3)) | |
515 | 520 | if n < 2: |
516 | 521 | raise BuildProblem("The smallest ordinal is 2, not %d" % n) |
517 | 522 | if not (0 <= k < n): |
518 | 523 | raise BuildProblem("Invalid ordinal index: %d of %d" % (k, n)) |
519 | 524 | return Ord(k, n) |
520 | - k = name[1:] | |
521 | - try: return Nat(int(k)) | |
522 | - except ValueError: raise BuildProblem("Invalid natural number: " + k) | |
523 | 525 | else: |
524 | 526 | raise BuildProblem("Invalid unary functor: " + name) |
525 | 527 | |
526 | 528 | def buildCompound(name, args): |
527 | 529 | if name == "comp" and len(args) >= 2: return Comp(args) |
528 | - elif name == "tuple" and len(args) >= 2: return Tuple(args) | |
530 | + elif name in ("pair", "tuple") and len(args) >= 2: return Tuple(args) | |
529 | 531 | elif name == "case" and len(args) >= 2: return Case(args) |
530 | 532 | elif name == "curry" and len(args) == 1: |
531 | 533 | return Curry(args[0]) |
@@ -141,7 +141,7 @@ termOps = [ | ||
141 | 141 | ] |
142 | 142 | print "CAM: Created %d term ops" % len(termOps) |
143 | 143 | |
144 | -HAVE_PARAMS = QUOTE, CUR, GOTO, CALL, GOTORIGHT, GOTOTAG, PROJECT, SLICETUPLE | |
144 | +HAVE_PARAMS = QUOTE, CUR, GOTO, CALL, GOTORIGHT, GOTOTAG, INJECT, PROJECT, SLICETUPLE | |
145 | 145 | LABEL_PARAM = CUR, GOTO, CALL, GOTORIGHT, GOTOTAG |
146 | 146 | assert set(LABEL_PARAM) < set(HAVE_PARAMS), "implementation error" |
147 | 147 | def hasParam(op): return op in HAVE_PARAMS |
@@ -153,6 +153,9 @@ | ||
153 | 153 | * Need promotion Ord(X) -> N |
154 | 154 | * prom = (opr zero succ) : Ord(X) -> N |
155 | 155 | * Jet it! |
156 | + * Need conversion to sums Ord(X) -> 1 + 1 + ... | |
157 | + * Mostly need a good name | |
158 | + * Internal bytecode is makeTag, yields a term op | |
156 | 159 | * Need fractions Ord(X) -> F |
157 | 160 | * Could do it if given compile-time cardinality Ord(X) -> N |
158 | 161 | * card : Ord(X) -> N |
@@ -537,5 +540,5 @@ | ||
537 | 540 | * Current big refactor |
538 | 541 | * Inject and project |
539 | 542 | * Bytecodes could be term ops, but term ops can't take params! |
540 | - * Regexes might give us a simpler and more portable specification of | |
541 | - acceptable syntax | |
543 | + * This actually needs to get fixed so that we can use inject/project | |
544 | + to replace fst/snd/left/right |