Thursday, December 15, 2011

The power of dsl

When I started the samskritam-dsl project, one of my goals was to develop a domain-specific language that will allow to interact with the system using a natural syntax. Not just a programmer, but a samskritam pundit with a basic computer knowledge should be able to interact with the system. While that interaction is still a long way, I feel there are some foundations in place. The sandhi-s as described in ashtaadhyayI are very arithmetic like, yielding consistent results, so a program model should be able to simulate that.

For eg

assert 'a' + 'a' == 'A' //akaH savarNe dIrghaH sandhi


instead of

assert new Varna('a').add(new Varna('a').equals(new Varna('A')) == true


The former is obviously easier to understand as it follows mathematical conventions, instead of being bound by rigid programmatic syntaxes.

Static programming languages like Java just do not allow this kind of flexibility. But dynamic languages like Groovy/Ruby/Scala having special features for creating such constructs.

Let's go a step further than the above simple sandhi:

assert 'bhU' + 'sap' + 'tiG' == 'bhavati'  //bhU dhatu, kartari sap, prathama, parasmai-padam, eka vacanam, prathama purushaH


Is the above possible?

Before we answer that, does the above assert statement make sense at all? How do you know, or how do you make the computer know, that bhU is the dhaatu, sap is the vikaraNa pratyayaH, and tiG is the padam pratyayaH ? They are all straight strings and not objects. How do you tell the difference? Now lets say we rewrite the above assert slightly differently --

assert 'bhU'.dhatu + 'sap'.pratyaya + 'tiG'.pratyaya == 'bhavati'


Now, that reads better! A simple domain knowledge is now converted into a programmatic construct, yet it almost reads just like samskritam! As you read the sentence, it seems very natural. 

That, mon ami, er, mama mitrANi, is the power of dsl.

Here are the implementation details:

@Category(String)
class Samskritam {
  def getPratyaya() { return new Pratyaya(this) }
  def getDhatu() { return new Dhatu(this) }
  }
}

class Dhatu {
  def name
  
  Dhatu(String _name) { name = _name }
  
  @Override
  String plus(Pratyaya p) { name + ' ' + p.toString() }
  
  @Override
  String toString() { name }
}

class Pratyaya {
  String value
  String realValue
  
  Pratyaya(String _value) {
    value = _value
    realValue = value?.tasya_lopaH()
  }
  
  @Override
  String toString() { realValue }
}

So what sutram-s are involved here? Lets skim through the important ones -

bhU + shap -> p gets dropped due to halantyam; sh gets dropped due to lashaku ataddhite
bhU + a -> bhO + a; due to aad guNaH
bhO + a -> bhav; due to eco ayavaayaavaH
tiG -> the G gets dropped due to halantyam
bhav + a + ti -> bhavati
 
Here is the complete test case:

use (ch8.lang.Samskritam) {
  def a1 = 'bhU'.dhatu + 'shap'.pratyaya + 'tiG'.pratyaya
  def a2 = sandhi.apply(a1, sandhi.aad_guNaH)
  def padam = sandhi.apply(a2, sandhi.eco_ayavaayaavaH)
  assert padam == 'bhavati'
}
The sandhi methods aad_guNaH and eco_ayavaayaavaH also obediently follow Paninian technique of replace the varnas using respective rules. 

Once again, the full code is in github.com/vasya10/samskritam

No comments: