Design.md @master — view markup · raw · history · blame
Castile Design Notes
(These are the original notes from the original README.)
Unlike most of my programming languages, there is nothing that could really be described as innovative or experimental or even particularly unusual about Castile. It is not a particularly comfortable programming experience, often forcing the programmer to be explicit and verbose.
Castile's influences might include:
C: Most of Castile's syntax follows C, but it is generally more permissive (semicolons are optional, types of local variables and return types for functions do not have to be declared, etc.) It has a type system (where
structs are the only types with name equivalence) which can be applied statically. It has function values, but not closures.
Rust: There is a union type, to which values must be explicitly promoted (with
as) and extracted (with
typecase ... is.) This is like Rust's
Enum, which is (to quote its tutorial) "much like the 'tagged union' pattern in C, but with better static guarantees." Along with structs, this provides something similar to algebraic data typing, as seen in languages such as Haskell, Scala, etc.
Eightebed: A few years back I realized that pointers that can assume a null value are really a variant type, like Haskell's
Maybe. Of course, in most languages with pointers, the property of being null isn't captured by the type; you can go ahead and dereference a pointer in C or Java, whether it's valid or not. In Castile, this is captured with a union type which includes
Python: The first time a local variable is assigned counts as its declaration as a local.
Ruby: The last expression in a function body is the return value of that function; no explicit
returnis needed there. (But unlike Ruby, and more like Pascal or linted C, all other expressions in statement position within a block must have void type.)
Erlang (or any other purely functional language): There are no language-level pointers; sharing, if it happens at all, must be orchestrated by the implementation. Global variables and function arguments are not mutable, and neither are the fields of structs. (But unlike Erlang, local variables are mutable.)
Some lines of research underneath all this are, if all we have is a relatively crude language, but we make it typesafe and give it a slightly nicer type system, does it suffice to make programming tolerable? Do tolerable ways of managing memory without a full garbage collector present themselves? Does having a simple compiler which can be target many backends provide any advantages?
One area where the Castile implementation is not entirely unremarkable is that the typechecker is not required to be run. Unchecked Castile is technically a different language from Castile; there are Castile programs which would result in an error, where the Unchecked Castile program would not (because it never executes the part of the program with a bad type.) However, Unchecked Castile programs should be otherwise well-behaved; any attempt to execute code which would have resulted in a type failure, will result in a crash. Note, however, that this only applies to the evaluator, not any of the compiler backends. Compiling Unchecked Castile will simply not work (the backend will crash when it can't see any types.)