System Design¶
Philosophy¶
Padmini follows the principles of the tradition as much as possible, but we break with the traditional model of rule selection, since doing so greatly simplifies the program.
Data Types¶
Padmini’s main data structure is the Prakriya
, which models the
derivation state. Its most important data is a list of Term
objects,
each of which contains a string of sounds and any metadata associated with
those sounds. For detail, see the Core API page.
Filters and Operators¶
We model a rule as having two parts: a filter that checks if the rule can
apply, and an operation that makes the necessary change. Filters and
operations are allowed to work on Prakriya
objects, directly, but
usually they work on a Term
object instead. For example, most rules
are written in the following format:
if filter(term):
op(term)
Filters might be actual Python functions, but they are usually simple
expressions that take advantage of Term
’s rich API:
if term.antya == 'a':
op(prakriya)
Operations, meanwhile, are usually standardized functions from the
operations
module. By centralizing operation code in one place,
we make it easy to refactor or modify operation behavior across the system if
future needs demand it.
To better illustrate the points above, here is an example of a simple rule from Padmini. This rule creates verbs like tasthau and jagau:
if prev.antya == "A" and tin.u == "Ral":
op.upadesha("7.1.34", p, tin, "O")
Here the rule uses upadesha()
to replace the upadeśa
value of the final tiṅ suffix.
Creating a Prakriyā¶
Generally, Padmini groups related rules into functions and related functions
into modules. Then the main Padmini code just calls these functions one after
another. For example, here is a version of the subanta()
function with
comments removed:
def subanta(pratipadika: str, linga: str, tags=None, options=None) -> Prakriya:
p = Prakriya.make()
p.add_tags(*(tags or []))
p.set_options(options or {})
pratipadika_karya.run(p, pratipadika, linga)
sup_karya.run(p)
samjna.pratipadika_samjna(p)
ac_sandhi.sup_sandhi_before_angasya(p)
angasya.run_remainder(p)
ac_sandhi.sup_sandhi_after_angasya(p)
ac_sandhi.run_common(p)
tripadi.run(p)
return p
Roughly, this function has two steps. First, we create the prakriyā and add any metadata associated with the derivation. Then, we apply functions one after another until the derivation is complete.