<?xml version="1.0" encoding="UTF-8"?>
<TEI xml:space="preserve" xmlns="http://www.tei-c.org/ns/1.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.tei-c.org/ns/1.0 https://raw.githubusercontent.com/kermitt2/grobid/master/grobid-home/schemas/xsd/Grobid.xsd"
 xmlns:xlink="http://www.w3.org/1999/xlink">
	<teiHeader xml:lang="en">
		<fileDesc>
			<titleStmt>
				<title level="a" type="main">Runtime type collecting and transpilation to a static language</title>
			</titleStmt>
			<publicationStmt>
				<publisher/>
				<availability status="unknown"><licence/></availability>
			</publicationStmt>
			<sourceDesc>
				<biblStruct>
					<analytic>
						<author>
							<persName><forename type="first">Pavel</forename><surname>Krivanek</surname></persName>
							<affiliation key="aff0">
								<orgName type="department">Nidea s.r.o</orgName>
								<address>
									<addrLine>Smejkalova 1033/136, 00</addrLine>
									<postCode>616</postCode>
									<settlement>Brno Zabovresky</settlement>
									<country>Czechia</country>
								</address>
							</affiliation>
						</author>
						<author>
							<persName><forename type="first">Richard</forename><surname>Uttner</surname></persName>
							<affiliation key="aff1">
								<orgName type="institution">Projector Software GmbH</orgName>
								<address>
									<addrLine>Mathildenstr. 34</addrLine>
									<postCode>72072</postCode>
									<settlement>Tübingen</settlement>
									<country key="DE">Germany</country>
								</address>
							</affiliation>
						</author>
						<title level="a" type="main">Runtime type collecting and transpilation to a static language</title>
					</analytic>
					<monogr>
						<idno type="ISSN">1613-0073</idno>
					</monogr>
					<idno type="MD5">C01FC39F67C55329B0AC3AE4FB150A16</idno>
				</biblStruct>
			</sourceDesc>
		</fileDesc>
		<encodingDesc>
			<appInfo>
				<application version="0.7.2" ident="GROBID" when="2025-04-23T18:09+0000">
					<desc>GROBID - A machine learning software for extracting information from scholarly documents</desc>
					<ref target="https://github.com/kermitt2/grobid"/>
				</application>
			</appInfo>
		</encodingDesc>
		<profileDesc>
			<textClass>
				<keywords>
					<term>Pharo</term>
					<term>static typing</term>
					<term>type annotations</term>
					<term>runtime type collection</term>
					<term>transpilation</term>
					<term>IWST *</term>
				</keywords>
			</textClass>
			<abstract>
<div xmlns="http://www.tei-c.org/ns/1.0"><p>This study delves into incorporating static typing into Pharo, a dynamic language derived from Smalltalk. Utilizing Pharo's pragmas, it introduces type annotations at both method and class levels, drawing from Strongtalk's approach but without altering Pharo's grammar. A novel experiment detailed here involves annotating Pharo code using these annotations and runtime type collection, then transpiling it to C#, highlighting the syntactic and conceptual adaptations required. Despite the complexities, the experiment successfully translates Pharo code into compilable C# code, underscoring Pharo's potential for optional static typing. The exploration also suggests future directions, including improved type inference, while reassessing static typing's role in error detection.</p></div>
			</abstract>
		</profileDesc>
	</teiHeader>
	<text xml:lang="en">
		<body>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="1.">Introduction</head><p>Pharo, as a descendant of the Smalltalk programming language, benefits from the flexibility and expressiveness provided by strong dynamic typing. However, static type checking offers advantages such as error detection, facilitation of code refactoring and documentation. Additionally, a JIT compiler can utilize it or static typing can be used for transpiling code into other languages.</p><p>In the context of integrating static typing into dynamically typed languages, Strongtalk <ref type="bibr" target="#b0">[1]</ref> is a notable example, enhancing Smalltalk-80 with optional static type annotations to improve performance and robustness. However, Strongtalk required significant grammar changes. Figure <ref type="figure" target="#fig_0">1</ref> illustrates an example of Strongtalk code. Pharo, unlike Smalltalk-80, has pragmas similar to those introduced by Strongtalk, allowing for type annotations without modifying its grammar.</p><p>We performed a limited experiment in which we introduced type annotations in the form of pragmas <ref type="bibr" target="#b1">[2]</ref> into Pharo, used runtime type collecting to annotate existing Pharo code, and then transpiled it into a static programming language.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.">Type Annotations</head><p>Type annotations are categorized into two types: method-level and class-level.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.1.">Method-level Type Annotations</head><p>Method-level type annotations describe the types of:</p><p>• Method return value • Arguments • Temporary variables • Block arguments</p><p>• Block temporary variables Besides the type information, the method-level annotations include:</p><p>• Information on whether the return value of a given block is supposed to be used Figure <ref type="figure" target="#fig_1">2</ref> shows the alternative to the Strongtalk code written using type annotating pragmas. Method-level type annotations for block arguments and block temporary variables have one problem -the names of these entities may be the same in multiple blocks. A typical example is a method with several blocks where each of them uses the block argument named each. We used two strategies to solve this problem. The first requires each block argument and temporary variable in the scope of a method to have a distinct name, which means that before adding type annotations to the code, every method that does not pass this rule needs to be refactored. The second strategy involves adding a block identification into the annotating pragma. We used a prefix that denotes the block order in the method: &lt;blockArg: #_1_each type: #Integer&gt; &lt;blockArg: #_2_each type: #Point&gt; The latter approach avoids refactoring but complicates readability and further code modifications. Therefore, we preferred using unique names within the method's lexical scope.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="2.2.">Class-level Type Annotations</head><p>Class-level type annotations are used for type descriptions of instance variables (more generally, slots) and other class elements, and we placed them into special methods named _slotTypes. Like the method-level type annotations, they include pragmas.  Given the commonality of UndefinedObject as an alternative type, we offer a shortcut for it expressed as two colons. Here we would rather have preferred a question mark, but were limited by Pharo's symbol parsing. Type descriptions for block closures are the most complex. They describe the types of all arguments and the return type of the block. Blocks need not have arguments or return values, so these parts can be omitted. These block type annotations are useful when describing argument types or variables holding the block. However, Pharo code containing block literals does not indicate if the return value (the result of the last expression) is to be used, as in select:, or ignored, as in do:. Thus, the method with such a block can contain a pragma specifying this information, which is important in some cases like code translation.</p><p>&lt;block: 1 returnsValue: false&gt; An example of such a method is described in the following chapter. We developed a simple system to regenerate type annotations while allowing programmers to manually modify them without losing these changes. Each automatically generated type annotation pragma includes an additional argument named generated: with true as the default value.</p><p>&lt;arg: #anObject type: Object generated: true&gt; When generating type annotations, the system creates only new pragmas or those with generated: true.</p><p>Other popular dynamically typed languages often implement type annotations by extending the language syntax and standardizing existing language features such as function annotations (Python 3 <ref type="bibr" target="#b2">[3]</ref>), using existing grammar constructs like special forms (Common Lisp <ref type="bibr" target="#b3">[4]</ref>), or creating a new language derived from the original one (TypeScript <ref type="bibr" target="#b4">[5]</ref> derived from ECMAScript).</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="3.">Runtime Type Collecting</head><p>Annotating existing Pharo code with types is a laborious task. Previous attempts, such as RoelTyper <ref type="bibr" target="#b5">[6]</ref>, resolved a relatively low number of types. Thus, we explored an alternative approach leveraging advances in Pharo's reflectivity infrastructure.</p><p>We collect runtime type information automatically during program execution by inserting watchpoints and generate type annotations in post-processing. This method requires most of the existing code to be executed in a manner providing relevant type information. Fortunately, in Pharo, the test-driven style of development is very popular, so projects with a high test coverage ratio are not unlikely. Ideally, runtime type collecting requires 100% code coverage with relevant tests.</p><p>Our technical solution involves installing various Metalinks <ref type="bibr" target="#b6">[7]</ref> into each method to resolve types. Metalinks in Pharo allow developers to attach additional behavior and metadata to methods dynamically at runtime, enabling fine-grained control and non-intrusive modification of method execution. For instance, to detect method argument types, a Metalink is installed at the method's beginning. For temporary variable types, a Metalink is installed at all assignments to the variable within the method. Method return types are detected by wrapping the entire method execution with a Metalink.</p><p>Each Metalink has an associated object describing the collected types. Each invocation of the Metalink updates this collection with the current types of values written into variables. After executing all relevant code, the collected type information is post-processed and written as type pragmas described above.</p><p>This straightforward process is hindered by technical limitations in Pharo's Metalinks implementation, such as incorrect handling of some Metalink combinations. For example, Metalinks for method return values need to be installed as standalone and require additional code execution.</p><p>Block closure literals require special treatment. Resolving their arguments is not significantly different from resolving the method argument types; however, handling return values poses a significant challenge. As mentioned above, in Pharo, the return value of a block evaluation is the result of the last expression. The block itself does not provide any information about whether this resulting value is actually meaningful and will be used. If the block is not constructed with the intent to use its return value, the type provided by runtime collecting can produce an arbitrary value, which does not help in describing the block type information because the actual expected return type is void. Consider the following code:</p><formula xml:id="formula_0">self critical: [ logFileStream ifNotNil: [ logFileStream close. logFileStream := nil ]. ]</formula><p>For the outermost block closure, the argument of the method critical:, we cannot be sure at the first glance how the method critical: actually handles the block. We may assume it evaluates the block, but we do not know if it only evaluates it and throws the result away or processes it further. This information is required when we, for example, try to translate this code into a different language that must explicitly specify a return statement for anonymous functions replacing the block. Always returning the result type of the last statement is not possible because the value may sometimes vary significantly. Moreover, in Pharo, the usage of a block return value is sometimes depending on the actual context.</p><p>We addressed this issue by returning a special proxy object instead of the actual block result value. When we detect during type collecting that the variable or argument type is a block, we construct a custom block closure of a custom class inheriting from the standard FullBlockClosure class, set it up based on the original closure, and swap their identities using standard become:. Thus, we ensure that we can handle standard evaluation messages of this block like value, value: etc. These custom methods, when called, perform the standard block evaluation and wrap the returned result in a custom proxy object. When a message is sent to the proxy or if it is assigned to a variable -which needs to be resolved by some installed Metalink -the block is marked as a block returning a value of the given result type. The proxy is then replaced by the actual result object (using become:, again), so this mechanism is performed at most once.</p><p>The type collecting process can be executed several times on a given code: As the type collector always starts reading all available type annotations, it will merge the new collected annotations with the existing ones if they are marked for regeneration.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.">Translation into a Static Language</head><p>Our experiment aimed to explore the possibility of transpiling parts of an existing business application from Pharo to C# for architectural reasons, leveraging existing C# libraries and code while benefiting from Pharo's unique features. C# has several properties that facilitate the transpiling of Pharo code, notably being a class-based object-oriented language with automatic memory management based on garbage collection. Additionally, C#'s optional named arguments make the translation of Pharo keywords easier than it would normally be for C-syntax based languages, thus keeping the output code closer to its original source. Modern versions of C# support anonymous functions and some other language properties similar to Pharo.</p><p>However, C# has significant lexical, syntactical, and semantic differences from Pharo, particularly in expressions and control structures. Its class metamodel also differs notably. The C# grammar, being quite complicated, suggests that the direct transpiling of grammatically simpler Pharo code to C# should be straightforward, at least from a syntactic perspective. Unfortunately, this is only partially true. While in Pharo, practically everything is a message call or an assignment, constructs that are easy to transpile, some C# language features introduce difficulties, such as: Each of these issues presents its own challenges and potential solutions. In some cases, we decided to limit constructs allowed in the transpiled Pharo code, so we must admit that we are able to transpile only a subset of the Pharo language.</p><formula xml:id="formula_1">•</formula><p>We aimed to generate readable, maintainable C# code with a direct relation to the original Pharo code. On the other hand, we wanted the Pharo code to be the main source of information. The C# code was repeatedly generated from it while the Pharo code was still being modified and improved.</p><p>The transpilation process itself is not innovative. We start with Pharo code AST. Using a transpiling visitor, we generate a new abstract syntax tree for a C# subset (because we do not need all C# features) and finally, using another visitor, we generate C# code by visiting these nodes. The generated C# code uses a small supporting library providing equivalents to Pharo standard library along with other utility functions.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.1.">Messages</head><p>Pharo unary messages are straightforward to translate into C#. They simply follow standard dot notation and skip the this keyword if possible. All message names are modified to use the regular C# customary to start with uppercase letter. So Binary message sends are interpreted as operators for common messages like +, &lt; and so on. Some binary messages need to be reinterpreted, such as = as Equals().</p><p>Keyword messages are generally hard to translate into other languages if readability shall be preserved. Fortunately, with C# optional named arguments, this task is manageable with only small limitations.</p><p>As an example, let us choose a keyword message chooseFrom:title: with two keyword parts. The method header with argument names looks like: chooseFrom: aList title: aString When transpiling to C#, we can keep the first argument name (aList) unchanged. We rename every other argument to match the corresponding keyword part name, aString to title in our case. The original argument name is mentioned as a comment and in the beginning of the method. Then, we define the new variable with the same name as it was in Pharo and assign it from the the argument name we created. Thus the original argument name can be used inside of the method without further change, as shown in the following example: This approach proves its utility when we perform a method call of this message with some arguments, as it closely resembles the message calls as done in the original Pharo code:</p><p>ChooseFrom(someList, title: actualTitle);</p><p>However, this approach has some small limitations. Keyword part names need to be distinct so it may require renaming of some methods (like with:with:) before transpiling. The reason behind is that C# uses named arguments primarily to support different order of arguments. We created a simple non-GUI tool in form of specialized class-side methods to detect such cases in advance.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.2.">Non-local returns</head><p>In Pharo, when a return statement is used inside a block closure, it causes program flow to exit from the whole method, not only from a given closure. In C#, anonymous methods, also called lambda expressions, are the closest corresponding construct to Pharo blocks. The main difference in behaviour is that a return statement in C# only exits the execution of the current anonymous function, not the method where it is defined.</p><p>The difference in usage of non-local returns in Pharo and in C# stems from the fact that Pharo uses combination of message sends and block closures for constructs that are expressed using special grammar control structures in C#, like if-statements.</p><p>Well-known Pharo methods such as ifTrue:, ifFalse:, ifNil:, ifEmpty:, whileTrue:, and do: are translated directly into corresponding C# statements which use regular code blocks {…} instead of lambdas. So the statement</p><formula xml:id="formula_2">aBoolean ifTrue: [ self doSomeAction. ^ 0 ]</formula><p>is translated into if (aBoolean) { DoSomeAction; return 0; } Non-local returns that cannot be translated into statements are currently forbidden by our transpiler. We have a small non-GUI tool to detect such cases in the code. The other alternative, which generates slower code but is more general and does not require so many code modifications, is to use exceptions.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.3.">Expressions</head><p>Pharo does not have any limits on structure of expressions. So instead of aBoolean in the example above, another complex expression containing statement-like message can be used. This is not true for C#. Some simple C# statements like if-else statement or null checks have an alternative expression syntax. For example, the ternary expressions (?:) or the null-coalescing operators (??). The transpiling visitor marks the AST subtrees that need to be expressions and tries to use these alternatives. If this is not possible, it reports an error. In that case, the Pharo code needs to be rewritten.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.4.">Object construction mechanisms</head><p>Pharo usually instantiates a class by sending a message to it. Such message then directly or indirectly invokes a VM primitive that creates an object. C# does not have the concept of metaclasses. For objects construction, the operator new is used. During building of the object, its constructors are called.</p><p>When the C# object is created, it sometimes requires generic type information, for example:</p><p>new Dictionary&lt;string, int&gt;()&gt;;</p><p>Pharo does not provide such information; the equivalent expression is simply Dictionary new. Our transpiler needs this information so it expects that the created object is assigned to some variable, which is usually the correct assumption. If the new message is on the right side of an assignment, the transpiler can derive generic types from the type annotations belonging to the variable the new object is assigned to.</p><p>If this mechanism cannot be used, an error is reported. In such case, the solution is to create an additional temporary variable with type annotation and assign the new object during creation to it.</p><p>The base C# class that is used as the root class for classes generated by the transpiler always calls the Initialize method from its constructor to automatically mimic default Pharo behavior.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.5.">Cascade</head><p>Cascade is a heavily used Pharo construct that does not have a corresponding equivalent in C#. To translate a cascade, we need to first create a temporary variable with a unique name and assign the base cascade object to it. This variable needs to be typed in C#, but fortunately, automatic type inference is sufficient in most cases. Because this assignment is a statement in C# but in Pharo, the cascade is a general expression, there are additional complications in deciding where to and how to evaluate the generated statement. The resultant code then looks, for example, like this: var cascade = new Dictionary&lt;string&gt;&lt;string&gt;(); cascade.At("uid", put: uid); cascade.At("label", put: label); return cascade; Moreover, cascades may be embedded. We pay special attention to their evaluation order.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.6.">Metaclasses and polymorphism</head><p>The metaclasses concept in Pharo is very powerful and heavily used, but does not have a direct mapping to C#. In Pharo, class-side methods often play a role of object constructing methods, and they are polymorphic. We translate them into static methods in C# calling specially generated constructors. We do not allow overrides because C# does not support static methods polymorphism. Moreover, C# does not support polymorphism of constructors.</p><p>The only more regular solution that could address this issue and allow to transpile more Pharo code without need to adopt the code-base in advance, is to create a real object playing the role of the class. This solution would break the direct relation between original transpiled code and, as a consequence, lead to new issues. However, we plan to explore this approach in future development, as we expect it to be the best way to avoid large refactorings.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="4.7.">Other complications</head><p>While traits in Pharo and interfaces in C# are comparable, traits in Pharo are stateful <ref type="bibr" target="#b7">[8]</ref> such that they can contain slots. As such slots cannot be translated into C#, we do not support stateful traits in our transpiler.</p><p>A surprising complication stems from the way how C# handles the nullability of primitive value types like int. For such types, the nullability means that they are wrapped in an additional structure that keeps information whether the value is set or not. If not, the actual value is set to the default value, not null. This makes general implementation of some trivial Pharo collection messages generally impossible (messages of type Dictionary &gt;&gt; atOrNil:).</p><p>We tried to mimic many Pharo standard library methods using extension methods in C#. When it was not possible because of C# limitations, like in the case of some Object extensions, we used static methods in ECMAScript style (PharoObject.IsInteger(anObject)).</p><p>The difference between Pharo and C# in zero array indexing proved to be not a real problem because it was handled by extension methods we created to follow the Pharo collections API.</p><p>Unlike Pharo, C# has a wide set of reserved keywords that can cause name collisions with the existing Pharo code. C# has a way how to handle special names (using the @ sign). However, as we encountered some problems with them, we rather changed the Pharo code in advance manually or using refactorings to avoid names that are C# keywords, which was trivial.</p><p>For Associations, we first tried to use C# pairs, but later switched to an own C# class which was easier to handle in all use cases we needed.</p><p>In relatively rare cases when the generated C# code required type casting, we introduced the Pharo message castAs: #TypeName which does nothing in Pharo but adds a casting operator to the C# code. In cases of several messages, we created own application specific hooks performing certain casting operations, mainly for casting to return types of called methods. Thus we could get around some complications, and even more important, avoid that C# performs unnecessary single element casts for big collections, resulting in significant runtime overhead.</p></div>
<div xmlns="http://www.tei-c.org/ns/1.0"><head n="5.">Results and Further Development</head><p>In our limited experiment, we were able to convert several packages of a real-life business application into about 20,000 lines of compilable and working C# code. While the Pharo code required some modifications to make it translatable to the target language, the amount of required changes was relatively low. Because the automatically generated code was compilable by the C# compiler, it means that the same task could theoretically be done without any translation to C#. This proves that Pharo can easily play the role of a language with optional static typing.</p><p>Our experiences during this experiment suggested several directions for further improvements. Combining runtime type collecting with type inference in the style of RoelTyper <ref type="bibr" target="#b5">[6]</ref> would be a significant advantage for transpiling code with low code coverage. It showed us that, at least in the case of C#, it would make sense not to maintain such a tight correspondence between the input and output code and to handle constructs like metaclasses and non-local returns in more a verbose and less readable but more general way. We would like to try translation into other languages, such as TypeScript, as well.</p><p>One interesting outcome of this experiment was our curiosity about whether static annotation would reveal any serious type errors in the existing code. At least in this case, the result was negative. We have encountered, of course, many reported type errors during compilation, but all of them were related to the C# narrow interpretation of types, even if the Pharo code had valid semantics.</p><p>Even though we did not detect bugs in the Pharo code, runtime errors were still common even for the code that was successfully compiled. Most of them, however, were related to some limitations of the translation process or to bugs therein. This suggests that while static typing brings some advantages, its role in error detection for well-designed dynamically typed code should not be overestimated.</p><p>The transpiler is publicly available at https://github.com/pavel-krivanek/Pharo-CSharp under MIT lincense.</p></div><figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_0"><head>Figure 1 :</head><label>1</label><figDesc>Figure 1: An example code in Strongtalk with type annotations for a method argument, a method return value, a temporary variable and a block argument. occurrencesOf: o &lt;arg: #o type: Object&gt; &lt;returns: #Integer&gt; &lt;var: #c type: #Integer&gt; &lt;blockArg: #e type: #Object generated: true&gt; | c | c := 0. self do: [ :e | e = o ifTrue:[ c := c + 1 ]]. ^c</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_1"><head>Figure 2 :</head><label>2</label><figDesc>Figure 2: An example Pharo code with type annotations for a method argument, a method return value, a temporary variable and a block argument.</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_2"><head></head><label></label><figDesc>&lt;var: #temp type: #Symbol::&gt; Complex types use literal arrays comprising the type class name, additional symbols such as of, key or value describing the purpose of the subsequent type description, and embedded type descriptions. #(Array of Symbol) #(Dictionary of Symbol keys Object) #(Association key Symbol value Number) #(Array of (Number String)) #(Array of (Array of String))</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_3"><head></head><label></label><figDesc>returning Integer) #(FullBlockClosure:: returning Integer) #(FullBlockClosure arguments #(String Object) returning Integer)</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_4"><head></head><label></label><figDesc>The absence of non-local returns • A notable difference between statements and expressions • Different object construction mechanisms • The absence of metaclasses and cascade • Missing polymorphism of constructors and static methods • Only stateless interfaces • The presence of primitive non-object types • Limited extension methods • A wide set of reserved words</figDesc></figure>
<figure xmlns="http://www.tei-c.org/ns/1.0" xml:id="fig_6"><head></head><label></label><figDesc>public long ChooseFrom(object aList, string title /* aString */ ) { var aString = title; … }</figDesc></figure>
		</body>
		<back>
			<div type="references">

				<listBibl>

<biblStruct xml:id="b0">
	<analytic>
		<title level="a" type="main">Strongtalk: Typechecking Smalltalk in a production environment</title>
		<author>
			<persName><forename type="first">G</forename><surname>Bracha</surname></persName>
		</author>
		<author>
			<persName><forename type="first">D</forename><surname>Griswold</surname></persName>
		</author>
		<idno type="DOI">10.1145/165854.165893</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 8th International Conference on Object-Oriented Programming Systems, Languages, and Applications (OOPSLA &apos;93)</title>
				<meeting>the 8th International Conference on Object-Oriented Programming Systems, Languages, and Applications (OOPSLA &apos;93)<address><addrLine>New York, NY, USA</addrLine></address></meeting>
		<imprint>
			<publisher>ACM Press</publisher>
			<date type="published" when="1993">1993</date>
			<biblScope unit="page" from="215" to="230" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b1">
	<analytic>
		<title level="a" type="main">Pragmas: Literal Messages as Powerful Method Annotations</title>
		<author>
			<persName><forename type="first">S</forename><surname>Ducasse</surname></persName>
		</author>
		<author>
			<persName><forename type="first">E</forename><surname>Miranda</surname></persName>
		</author>
		<author>
			<persName><forename type="first">A</forename><surname>Plantec</surname></persName>
		</author>
		<idno type="DOI">10.1145/2991041.2991050</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 11th International Workshop on Smalltalk Technologies (IWST 2016)</title>
				<meeting>the 11th International Workshop on Smalltalk Technologies (IWST 2016)<address><addrLine>New York, NY, USA</addrLine></address></meeting>
		<imprint>
			<publisher>ACM Press</publisher>
			<date type="published" when="2016">2016</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b2">
	<analytic>
		<title level="a" type="main">The evolution of type annotations in Python: An empirical study</title>
		<author>
			<persName><forename type="first">L</forename><surname>Di Grazia</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Pradel</surname></persName>
		</author>
		<idno type="DOI">10.1145/3540250.3549114</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 30th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE 2022)</title>
				<meeting>the 30th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE 2022)<address><addrLine>New York, NY, USA</addrLine></address></meeting>
		<imprint>
			<publisher>ACM Press</publisher>
			<date type="published" when="2022">2022</date>
			<biblScope unit="page" from="209" to="220" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b3">
	<monogr>
		<title level="m" type="main">Common Lisp: The Language</title>
		<author>
			<persName><forename type="first">G</forename><forename type="middle">L</forename><surname>Steele</surname><genName>Jr</genName></persName>
		</author>
		<imprint>
			<date type="published" when="1990">1990</date>
			<publisher>Digital Press</publisher>
		</imprint>
	</monogr>
	<note>2nd ed.</note>
</biblStruct>

<biblStruct xml:id="b4">
	<monogr>
		<title level="m" type="main">Programming TypeScript: Making Your JavaScript Applications Scale</title>
		<author>
			<persName><forename type="first">B</forename><surname>Cherny</surname></persName>
		</author>
		<imprint>
			<date type="published" when="2019">2019</date>
			<publisher>O&apos;Reilly Media</publisher>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b5">
	<analytic>
		<title level="a" type="main">Fast type reconstruction for dynamically typed programming languages</title>
		<author>
			<persName><forename type="first">F</forename><surname>Pluquet</surname></persName>
		</author>
		<author>
			<persName><forename type="first">A</forename><surname>Marot</surname></persName>
		</author>
		<author>
			<persName><forename type="first">R</forename><surname>Wuyts</surname></persName>
		</author>
		<idno type="DOI">10.1145/1640134.1640145</idno>
	</analytic>
	<monogr>
		<title level="m">Proceedings of the 5th Symposium on Dynamic Languages (DLS &apos;09)</title>
				<meeting>the 5th Symposium on Dynamic Languages (DLS &apos;09)<address><addrLine>New York, NY, USA</addrLine></address></meeting>
		<imprint>
			<publisher>ACM Press</publisher>
			<date type="published" when="2009">2009</date>
			<biblScope unit="page" from="69" to="78" />
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b6">
	<analytic>
		<title level="a" type="main">Sub-method, partial behavioral reflection with Reflectivity: Looking back on 10 years of use, The Art</title>
		<author>
			<persName><forename type="first">S</forename><surname>Costiou</surname></persName>
		</author>
		<author>
			<persName><forename type="first">V</forename><surname>Aranega</surname></persName>
		</author>
		<author>
			<persName><forename type="first">M</forename><surname>Denker</surname></persName>
		</author>
		<idno type="DOI">10.1145/3567512.3567517</idno>
	</analytic>
	<monogr>
		<title level="j">Science, and Engineering of Programming</title>
		<imprint>
			<biblScope unit="volume">4</biblScope>
			<date type="published" when="2020">2020</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b7">
	<analytic>
		<title level="a" type="main">A new modular implementation for stateful traits</title>
		<author>
			<persName><forename type="first">P</forename><surname>Tesone</surname></persName>
		</author>
		<author>
			<persName><forename type="first">S</forename><surname>Ducasse</surname></persName>
		</author>
		<author>
			<persName><forename type="first">G</forename><surname>Polito</surname></persName>
		</author>
		<author>
			<persName><forename type="first">L</forename><surname>Fabresse</surname></persName>
		</author>
		<author>
			<persName><forename type="first">N</forename><surname>Bouraqadi</surname></persName>
		</author>
		<idno>3167132.3167244</idno>
		<ptr target="https://doi.org/10.1145/" />
	</analytic>
	<monogr>
		<title level="j">Science of Computer Programming</title>
		<imprint>
			<biblScope unit="volume">195</biblScope>
			<date type="published" when="2020">2020</date>
		</imprint>
	</monogr>
</biblStruct>

<biblStruct xml:id="b8">
	<analytic>
		<title level="a" type="main">PharoJS: Transpiling Pharo classes to JS-ECMAScript 5 versus ECMAScript 6</title>
		<author>
			<persName><forename type="first">N</forename><surname>Bouraqadi</surname></persName>
		</author>
		<author>
			<persName><forename type="first">D</forename><surname>Mason</surname></persName>
		</author>
	</analytic>
	<monogr>
		<title level="m">presented at the International Workshop on Smalltalk Technologies</title>
				<meeting><address><addrLine>IWST</addrLine></address></meeting>
		<imprint>
			<date type="published" when="2023">2023. 2023</date>
		</imprint>
	</monogr>
</biblStruct>

				</listBibl>
			</div>
		</back>
	</text>
</TEI>
