All things to All people!
   
 


Type Checking and Syntax Verification

There are three important features that may turn off developers coming to moto from other embedded scripting languages. The necessity of these features is well understood to experienced C or Java developers but is often misunderstood or considered a hassle to many who come from the world of embedded scripting commonplace in web development. The features are as follows

  • Moto requires users to declare variables before they use them.
  • Moto requires users to specify the types of variables and (usually) explicitly cast variables from one type to another.
  • Moto does extensive syntactic and semantic checking of files before it interprets or compiles them.

Granted these sound more like hassles than features but as a developer for many years in other web scripting languages, let me give my perspective as to why they are so important:

1) Moto requires users to declare variables before they use them.

I spent over a year coding on a large commercial, Coldfusion based system. Coldfusion allows you to write code like the following pseudo code :

if(var is true)
   foo=bar
print foo
 

That might be fine except for what happens when var isn't true. In that case the above code will fail with an error because foo was never defined to be anything. One might think that this would be an obvious error to test for but consider the following

if(var ==1)
   mood="angry"
else if(var == 2)
   mood="sad"
else if(var ==3)
   mood="sick"
print mood
 

This code might work 99 out of 100 times but then on that 100th run var is set to yellow ... uh oh that's a crasher. Now of course the above code could be fixed by adding some default value for the variable mood, perhaps with a final else. But this denies a very fundamental principal about programmers and scripters alike. We are LAZY and we will not do something if we don't have to. By forcing us to to declare the variable 'mood' before using it, moto saves countless hours of bugfixing down the road (when var equals yellow). Moreover moto tells us right away that this might be a problem and that we need to fix it:

ex1.moto:4: Variable 'mood' not declared before used
ex1.moto:6: Variable 'mood' not declared before used
ex1.moto:8: Variable 'mood' not declared before used
ex1.moto:9: Variable 'mood' not declared before used
 

2) Moto requires users to specify the types of variables and (usually) explicitly cast variables from one type to another.

The same sort of example applies here. Consider a language where 'everthing is a string' until used otherwise. Coldfusion is like this. I might write a program like the following (notice the typo in the last else if, that's not a zero)

if(var =="1")
   mood="1"
else if(var == "2")
   mood="10"
else if(var =="3")
   mood="100"
else if(var =="4")
   mood="100O"
print mood + 1
 

Now lets suppose the case when var equals 4 occurs very rarely ... one out of every 50 times ... but on that 50th time I try adding an int to something that's not an int. Boom! The behavior is undefined. Maybe I'll get an error. Maybe the int will be implicitly cast to a string and I'll get 100O1. It depends on the language but it's almost never what you want. But again, unless every case is getting tested this bug is going to get by.

Think this example was a stretch ? What about when var equals 5 ? What happens then ? Something is bound to go wrong with the above code. It's just a matter of when.

A related issue that is just as common when 'including' a large number of files into the same page is the use of a variable with the same name to store different types!

Include 1:
   if (default not defined)
      default="happy"
Include 2:
   if(default not define)
      default=37
Page
   include (include1)
   include (include2)
   print default/12
 

And once again we have a runtime error!

In moto you have to declare the type of a variable before you use it. If default is an int you need to say:

$declare(int default)  

or just

${int default;}$  

You also need to be explicit about your operations. If you want to convert from a string to an int you need to say

${int i = atoi("12"); }$  

in moto you can say

${print "10" + "1"; }$  

and you'll get 101 or you can say

${print 10+1;}$  

and you'll get 11 but if you say

${print "10" + 1;}$  

you'll get

ex2.moto:1: Illegal binary operation: <String> + <int>  

3) Moto does extensive syntactic and semantic checking of files before it interprets or compiles them.

The reasoning presented so far really boils down to the following:

"Not forcing programmers to declare variables and their types before using them, or implicitly casting variables from one type to another, lets programmers make really common errors that are really hard to test for and only show up at runtime"

There is an important corollary to this:

"Runtime errors are bad."

Why are runtime errors bad ? Well, apart from being hardest type of error to test for, runtime errors are bad because you only get them one at a time! Consider the following piece of really bad code:

a= b+"12";
c= 18 + "c";
print c.length();
 

In some languages (names have been left out to protect the guilty) the programmer would type this, hit the page with his browser and get

error on line 1: b is undefined  

The programmer then goes and changes his program so it says

b="1"
a= b+"12";
c= 18 + "c";
print c.length();
 

hits reload on the browser and gets

error on line 3 : cant add an int to a string  

The programmer changes it again to

b="1";
a= b+"12";
c= 18 + "3";
print c.length();
 

hits reload again and gets

error on line 4 : can't get length() for an int  

That's three reloads because each time the programmer changed things there was oonly one error returned at a time. Try the same program in moto and you get:

ex3.moto:1: Variable 'b' not declared before used
ex3.moto:1: Illegal binary operation: <Object> + <String>
ex3.moto:1: Variable 'a' not declared before used
ex3.moto:2: Illegal binary operation: <int> + <String>
ex3.moto:2: Variable 'c' not declared before used
ex3.moto:3: Variable 'c' not declared before used
ex3.moto:3: No such method: Object::length()
 

All the errors all at once. In fact, using the moto command line tools you can find all the syntax and type casting errors in every page of an application all at once:

moto -v *.moto  

The dirty little secret is that these little extra hurdles actually make

1) Programmers more productive because they see more errors at one time!
2) Code less error prone because two of the most common errors programmers make can't happen!