Problem with typing function invocations


I am trying to create a language where the list of available functions is queried from a separate class. The language is standalone -- it does not extend base language or any other languages in MPS. I have created a FunctionInfo class which contains information about a function -- name, return type and types of formal parameters. This information is used in typing rule of the FunctionCall node which expresses the function call:

FunctionInfo info = FunctionInfo . getFunction ( call . name ) ;                                
if ( info == null ) {                                                                           
   // Function name and parameter count is checked by another rule.                             
   error " Unknown function: \" " + call . name + " \" " -> call ;                              
   return ;                                                                                     
typeof ( call ) :==: info . returnType ;                                                        
foreach ( node < Expression > arg : call . parameter ; node <  > paramType : info . paramTypes ) {
   typeof ( arg ) :==: paramType ;                                                              

Ideally, type of actual argument should be subtype of the type of the formal parameter, but here I'm using type equality to make it simpler. Additionally, I set the :==: operator for checking parameters to be "checking only" to ensure that the function call does not affect the types of the parameters.

I have created a simple expression language in which expressions can be either number literals, string literals or function calls. The supported functions are add (number addition), concat (string concatenation) and strlen (length of string) with the expected argument and return types. When typechecking an example program, all the errors are flagged correctly, but additionally it marks some correct expressions as incorrect:

concat ( " foo " ,  concat ( " foo " ,  " bar " ) ) 
add ( 10 ,  strlen ( concat ( " foo " ,  " bar " ) ) )

When I examine the program in node explorer, I can see that some nodes have quite funny types, for example string constant has somehow acquired NumberType.

I have read the documentation and looked at implementation of the base language and I cannot see what I am doing wrong. (or maybe it is bug in MPS?) I have attached the whole project so you can look at it.

Comment actions Permalink

Hello Margus,

You can fix the problem by using typeof(arg) :==: paramType.copy instead of typeof(arg) :==: paramType and doing the similar thing with returnType.



Comment actions Permalink


Thanks for the tip, this solved this particular problem.

However, it would be good to have documentation of the MPS type system, e.g. how exactly does the type info propagate. The current manual just mentions that it does propagate somehow. Sometimes this propagation gives a bit weird results. I'm also trying MPS on more complex language and it seems to me that if the DSL program has type errors, then the type system gets confused and gives invalid types to e.g. string literals (which derive their types from quite simple rules). Correct problems seem to work quite well.

Also, given the complexity of the MPS's type system, I would appreciate the "type debugger" feature which lets you select a node and shows, which are the equations that were used to derive the type of the node.

All the best,


Comment actions Permalink

hello Margus, your problem has happened because the same node (a node in collection in a field "paramTypes" which stores parameter types for your function) is used in every equation created for every call of your function.

so, according to equations you've written in an inference rule, the same node (a member of paramTypes collection) is stated to be equal to number type and to be equal to string type, which is type error, because no type can be string type and number type simultaneously. even more, every new equations which come from next function calls in your code will probably lead to type collision, since it is impossible for type to be number and string at the same time.

in other words, you have stated that all types which appear as types of actual arguments of the same formal parameter in all calls of your function are equal. which statement, being once broken, breaks everywhere.

quotations, to the contrary, create a new node each time they are evaluated, so quotations do not lead to the abovementioned problem. neither using inequalities does.

feature which lets you select a node and shows, which are the equations that were used to derive the type of the node.

try popup menu -> typesystem -> show rules which affect node's type.




Please sign in to leave a comment.