archives

a logic of precedences. Suggestions

Hi, I'm new to programming language theory but like I suppose
everyone else around here I have some ideas about the theme.

Anyways I'm asking about an idea I have for my pet programming language.
It is a mixture of ml syntax, functional, in the future I'll implement a
static typesystem and ultimately add lazy evaluation, but now I'm trapp'd
with this kind of subsystem.

It is a precedence based logic. With it the programmer can
declare precedence and associavity.

Now, suppose we have the basic infix aritmetic 'operators' +, -, *, and div
like this:

+ a b / a + b, +:int->int->int.

We can declare their precedence with:

precedences { aritmetic := {+ - * div}, + = -, * = /, * > + }

or the more cute 'ladder syntax':

precedences { aritmetic := (* div) (+ -) }

I have developed a 'logic of precedences' that can deal with
relations ,= between symbols (function names) and/or classes of
symbols (like the previous aritmetic class) that I still have to refine
but right now it seems fine with pen and paper.

When a program or library grows you can still declare precedences without
the burden to cuantify levels explicitly, just declare relations.
Example, factorial:

! n / n !.
	precedences { ! > aritmetic }

I know that the emblematic languages like ocaml or haskell don't provide
such expresive feature. And they have limited levels of associativity. Why?
Do they envisioned that this feature is unimportant?

What do you think about this idea of declaring precedences with a 'logic system'?

The language will have types like disjoint sets (a la ocaml's but with
no restriction in the syntax of constructors). A sugaring feature is the
alternative type declaration called 'lexems' instead of 'type'. This mode
raises an invariant to the system that no function extern to the module
where it is declared will use a parameter of this type. So, they can be
safely used as lexems and data structures in DSLs.

With types declared as lexems, aplication modes of functions and precedence system
the if-then-else control structure can be coded like this (% is comments):

% control structures for if-then-else
lexemas iftest := { iftest(bool) }
lexemas elsesol x := { thensol(x) elsesol }

% declarations (not required but useful to see ugly types)
if / if : bool -> iftest bool.
then ifcont thenexp / ifcont then thenexp, then : iftest -> x -> elsesol x.
else thencont elseexp / thencont else elseexp, else : elsesol x -> x -> x.

% this declaration puts 'if' 'then' 'else' operators to a 'ifexp' class
% (classes of precedence are useful to handle DSLs or operators related
% as a whole). It reads as: "'if' has more precedence than 'then', and 'then'
% has more precedence than 'else'; all of then put on a class 'ifexp' whose
% precedence level is greater than the rest of functions, including default
% aplication level". It also raises the invariant that no other declaration 
% can mess with their relation nor merge between the 'ifexp' owned levels 
% so from this point of view the DSL is unaltered.
fixed_precedences { ifexp := if then else, ifexp > all, }

% if-then-else implementation (requires lazy evaluation, naturally)
if b = iftest(b).

then ifcont exp = ifcont
 con iftest(true) -> thensol(exp)
 con iftest(false) -> elsesol.

else branch elseexp = branch 
  con  thensol(x) -> x
  con  elsesol -> elseexp.