On Mixing Static Typing, Dynamic Typing and Values

In the Cat language I found it neccessary to have primitives which have embedded values. For example store#N would place the value on the top of the main stack into the Nth position in the auxiliary stack. There are currently a couple of other primitives like this.

Upon examination, this syntax yields a limitation: you can't use an expression in place of N. For example: store#1 + 2 doesn't really make sense. This lead me to consider the notation: store<1 2 +>. This isn't perfect, but it has a certain familiarity which I am comfortable with. This also extends relatively nicely to primitives like: local<int>, which pushes a new integer onto the auxiliary stack.

When I step back and look at this differently, I am embedding compile-time expressions between angled brackets (lt; and >). This makes the language specification more complex because the semantics for compile-time code are necessarily different from those of run-time code. This leads me to ask the question, shouldn't I allow compile-time or type expressions to be expressed using precisely the same syntax as the rest of the language? In other words why not place types on the stack, and if a type-expression can be resolved at compile-time, then let the compiler do so.

The only problem that I can see is that some expressions are not resolvable at compile-time, but this would simply lead to dynamic type expressions. I can see people potentially getting confused about what expressions can be evaluated at compile-time, and which ones are evaluated at run-time, but does it really matter?

It seems to me at this point that freely intermixing static and dynamic typing and evaluation is the right thing to do, but I'd like some feedback and other points of view.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Taking the middle ground

Finally somebody looking at taking the middle ground between after all these years.

Humour aside, Harland, Gunn et el were looking at such things at the Uni of Glsagow and other places in the late 70's to the mid 80's. Unfortunately, most of the papers and other documents of that time are no longer available. I have tried to obtain the research materials from the original authors and in many cases the materials no longer exist in any physical or electronic form. Some of the published papers may still be available in libraries around the world.

Just realise that the above work ended up promoting the idea that first-class values should include types, functions, code, closures, environments etc, so that all these things could be directly manipulable within the computational system (lisp like). The end result was the idea that the programmer should be able to have direct control over all applicable values including such things as whether or not a function should evaluate it parameters strict or lazy (or in any other fashion that she/he might want), control what applicable environment for the function (static or dynamic) was to be applicable, etc. Every value belonged to one type only (no type hierarchy) and all values being manipulated carried their respective types with them at all times.

The times distinguished by compile, execution etc were not considered as being so important, do everything you can at compilation time, if it can't be decided, then do it at run time. At the point you knew the type information use it then to do the relevant checks.