StaDyn is an object-oriented general-purpose programming language for the .NET platform that uniquely supports both static and dynamic typing. Its compiler performs type reconstruction, flow-sensitive typing, union and intersection types, and method specialization to detect type errors at compile time and optimize code. Introduced in 2007 as a modification of C# 3.0, StaDyn extends type inference by allowing var
as a type with flow-sensitive checks, enabling type-safe duck typing, while also supporting a more flexible dynamic
type. Designed by Francisco Ortin from the University of Oviedo and implemented by the Computational Reflection group, StaDyn combines the advantages of static and dynamic typing, reflected in its name—a portmanteau of “static” and “dynamic.”
Code samples
Variables with different types
Just like dynamic languages, variables may hold different types in the same scope:
using System; class Program { public static void Main() { Console.Write("Number: "); var age = Console.In.ReadLine(); Console.WriteLine("Digits: " + age.Length); age = Convert.ToInt32(age); age++; Console.WriteLine("Happy birthday, you are " + age + " years old now."); int length = age.Length; // * Compiler error } }The age variable is first inferred as string, so it is safe to get its Length property. Then, it holds an integer, so age++ is a valid expression. The compiler detects an error in the last line, since Length is no longer provided by age.
The generated code does not use a single Object variable to represent age, but two different variables whose types are string and int. This is achieved with a modification of the algorithm to compute the SSA form.4 This makes the generated code to be more efficient, since runtime type conversions are not required.
Flow-sensitive types
var and dynamic variables can hold flow-sensitive types:
using System; class Program { public static void Main(String[] args) { var exception; if (args.Length > 0) exception = new ApplicationException("An application exception."); else exception = new SystemException("A system exception."); Console.WriteLine(exception.Message); } }It is safe to get the Message property from exception because both ApplicationException and SystemException provide that property. Otherwise, a compiler error is shown. In this way, StaDyn provides a type-safe static duck-typing system.
In the following program:
using System; class Program { public static void Main(String[] args) { var exception; switch (args.Length) { case 0: exception = new ApplicationException("An application exception."); break; case 1: exception = new SystemException("A system exception."); break; default: exception = "This is not an exception."; break; } Console.WriteLine(exception.Message); // * Compiler error with var, but not with dynamic Console.WriteLine(exception.Unknown); // * Compiler error } }The Message property is not provided by String, so a compiler error is shown for exception.Message. However, if we declare exception as dynamic, the previous program is accepted by the compiler. dynamic is more lenient than var, following the flavor of dynamic languages. However, static type checking is still performed. This is shown in the last line of code, where the compiler shows an error for exception.Unknown even if exception is declared as dynamic. This is because neither of the three possible types (ApplicationException, SystemException and String) supports the Unknown message.5
Although dynamic and var types can be used explicitly to obtain safer or more lenient type checking, the dynamism of single var references can also be modified with command-line options, XML configuration files and a plugin for Visual Studio.6
Type inference of fields
var and dynamic types can be used as object fields:
class Wrapper { private var attribute; public Wrapper(var attribute) { this.attribute = attribute; } public var get() { return attribute; } public void set(var attribute) { this.attribute = attribute; } } class Test { public static void Main() { string aString; int aInt; Wrapper wrapper = new Wrapper("Hello"); aString = wrapper.get(); aInt = wrapper.get(); // * Compiler error wrapper.set(3); aString = wrapper.get(); // * Compiler error aInt = wrapper.get(); } }The Wrapper class can wrap any type. Each time we call the set method, the type of attribute is inferred as the type of the argument. Each object has a potentially different type of attribute, so its type is stored for every single instance rather than for the whole class. In this way, the two lines indicated in the code above report compilation errors. A type-based alias analysis algorithm is implemented to support this behavior.7
Constraint-based types
Let's analyze the following method:
public static var upper(var parameter) { return parameter.ToUpper(); }The type of parameter and the function return value are inferred by the compiler. To that aim, a constraint is added to the type of the upper method: the argument must provide a ToUpper method with no parameters. At each invocation, the constraint will be checked. Additionally, the return type of upper will be inferred as the return type of the corresponding ToUpper method implemented by the argument.8
The programmer may use either var or dynamic to declare parameter, changing the way type checking is performed upon method invocation. Let's assume that the argument passed to upper holds a flow-sensitive type (e.g., the ApplicationException, SystemException or String exception variable in the code above). With var, all the possible types of the argument must provide ToUpper; with dynamic, at least one type must provide ToUpper.
Runtime performance
The type information gathered by StaDyn is used to perform significant optimizations in the generated code: 9 the number of type inspections and type casts are reduced, reflection is avoided, frequent types are cached, and methods with constraints are specialized. The point of all the optimizations is to reduce the number of type-checking operations performed at runtime, which is the main performance penalty of most dynamic languages. Many of those type checks are undertaken earlier by the StaDyn compiler. A detailed evaluation of the runtime performance of StaDyn is detailed in.10
See also
External links
References
Francisco Ortin; Miguel Garcia; Sean McSweeney (2019). "Rule-based program specialization to optimize gradually typed code". Knowledge-Based Systems. 179: 145–173. doi:10.1016/j.knosys.2019.05.013. hdl:10651/53505. S2CID 182002303. /wiki/Doi_(identifier) ↩
"Francisco Ortin". uniovi.es. Retrieved May 17, 2022. https://reflection.uniovi.es/ortin/ ↩
"Computational Reflection Research Group". uniovi.es. Retrieved May 17, 2022. https://reflection.uniovi.es/ ↩
Jose Quiroga; Francisco Ortin (2017). "SSA Transformations to Facilitate Type Inference in Dynamically Typed Code". The Computer Journal. doi:10.1093/comjnl/bxw108. hdl:10651/53507. /wiki/Doi_(identifier) ↩
Francisco Ortin; Miguel Garcia (2011). "Union and intersection types to support both dynamic and static typing". Information Processing Letters. 111 (6): 278–286. doi:10.1016/j.ipl.2010.12.006. hdl:10651/8732. /wiki/Doi_(identifier) ↩
Francisco Ortin; Francisco Morero; Anton Morant (2014). "Static type information to improve the IDE features of hybrid dynamically and statically typed languages". Journal of Visual Languages & Computing. 25 (4): 346–362. doi:10.1016/j.jvlc.2014.04.002. hdl:10651/28429. /wiki/Doi_(identifier) ↩
Francisco Ortin; Daniel Zapico; J.B.G. Perez-Schofield; Miguel Garcia (2010). "Including both static and dynamic typing in the same programming language". IET Software. 4 (4): 268. doi:10.1049/iet-sen.2009.0070. hdl:10651/9769. /wiki/Doi_(identifier) ↩
Francisco Ortin (2011). "Type Inference to Optimize a Hybrid Statically and Dynamically Typed Language". The Computer Journal. 54 (11): 1901–1924. doi:10.1093/comjnl/bxr067. hdl:10651/11411. /wiki/Doi_(identifier) ↩
Miguel Garcia; Francisco Ortin; Jose Quiroga (2016). "Design and implementation of an efficient hybrid dynamic and static typing language". Software: Practice and Experience. 46 (2): 199–226. doi:10.1002/spe.2291. hdl:10651/29465. S2CID 2065468. /wiki/Doi_(identifier) ↩
Francisco Ortin; Miguel Garcia; Sean McSweeney (2019). "Rule-based program specialization to optimize gradually typed code". Knowledge-Based Systems. 179: 145–173. doi:10.1016/j.knosys.2019.05.013. hdl:10651/53505. S2CID 182002303. /wiki/Doi_(identifier) ↩