at:tutorial:symbiosis
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
at:tutorial:symbiosis [2007/04/06 13:13] – jdedecker | at:tutorial:symbiosis [2009/04/23 09:24] – tvcutsem | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Symbiosis with Java ====== | ====== Symbiosis with Java ====== | ||
- | < | + | AmbientTalk |
- | AmbientTalk is fully implemented in Java and runs on top of the JVM. | + | The reverse, accessing |
- | The reverse, namely that AmbientTalk | + | This chapter explains how to program using this " |
- | This chapter explains how both sides of this symbiotic relationship between Java and AmbientTalk can be leveraged. The goal of this symbiotic relationship is to complement the advantages of both languages and to alleviate their disadvantages. | + | ===== Built-in Conversions ===== |
- | ===== Accessing | + | When AmbientTalk values and Java values cross language boundaries (e.g. when they are passed as arguments of or return values from a method that is invoked from the other language), these values are converted. AmbientTalk features a number of built-in conversions that maps AmbientTalk' |
- | ===== Creating | + | ^ Java value : type ^ AmbientTalk value ^ |
+ | | null: Object | nil | | ||
+ | | n: int | a number n | | ||
+ | | d: double | a fraction d | | ||
+ | | b: boolean | a boolean b | | ||
+ | | s: String | a text s | | ||
+ | | array: T[] | a table (of converted values) | | ||
+ | | e: Exception | an exception e | | ||
+ | | c: Class | class wrapper( c ) | | ||
+ | | o: ATObject | o | | ||
+ | | o: Type | java wrapper(o : Type) | | ||
- | ===== Using Java wrappers ===== | + | ^ AmbientTalk value ^ Java value : type ^ |
+ | | nil | null: Object | | ||
+ | | a number n | n: int | | ||
+ | | a fraction f | f: double | | ||
+ | | a boolean b | b: boolean | | ||
+ | | a text t | t: String | | ||
+ | | a table t | t: T[] | | ||
+ | | an exception exc | exc : Exception | | ||
+ | | a class wrapper( c ) | c : Class | | ||
+ | | a java wrapper(obj : Type) | obj : Type | | ||
+ | | any object o | AT wrapper (o) : I | | ||
- | ===== Overloading ===== | + | Note that non-native Java or AmbientTalk objects are represented in the other language by means of " |
- | ===== Symbionts ===== | + | In the last conversion rule of the second table, '' |
- | ===== Conversions | + | ===== Accessing Java from within AmbientTalk |
- | ===== Thread-Actor Symbiosis | + | ==== Accessing Java classes |
+ | |||
+ | Any class that can be loaded from the class path of the JVM running the AmbientTalk interpreter is accessible from within an AmbientTalk program. Classes are loaded by sending messages to a special object named '' | ||
+ | |||
+ | < | ||
+ | >def Vector := jlobby.java.util.Vector | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | A class is represented as a normal AmbientTalk object. All '' | ||
+ | |||
+ | < | ||
+ | If you want to load your own Java class make sure that the .class file is in the classpath of the JVM running AmbientTalk. By default, the iat script puts the at/ directory of the AmbientTalk distribution in the classpath. | ||
+ | </ | ||
+ | |||
+ | ==== Creating Java objects ==== | ||
+ | |||
+ | Java classes can be instantiated in AmbientTalk similar to how AmbientTalk objects are instantiated, | ||
+ | the Java constructor. Here is how to create a new vector in AmbientTalk: | ||
+ | |||
+ | < | ||
+ | >def aVector := Vector.new() | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | If the Java class defines multiple constructors, | ||
+ | |||
+ | < | ||
+ | >aVector := Vector.new(30) | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | ==== Invoking methods on Java objects ==== | ||
+ | |||
+ | Java objects are represented as AmbientTalk objects whose field and method slots correspond to '' | ||
+ | |||
+ | < | ||
+ | >1.to: 10 do: { |i| aVector.add(i) } | ||
+ | >> | ||
+ | > | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | When an AmbientTalk object sends a message to a wrapped Java object, the following algorithm is applied: | ||
+ | * if a message is sent to a wrapper for a **class** object, only static fields or methods of the Java class are considered. | ||
+ | * If the message is sent to an **instance** wrapper, only non-static fields or methods of the Java class of the wrapped object are considered. | ||
+ | * If the AmbientTalk selector uniquely identifies a method (i.e. no overloading on the method name is performed in Java), the matching method is invoked. All AmbientTalk arguments are converted to Java objects. This is done by wrapping them into Java objects in the case of custom objects or by converting them to native Java values if possible (e.g. for the different number types and strings). The Java return value is mapped back to an AmbientTalk value. | ||
+ | |||
+ | ==== Overloading ==== | ||
+ | |||
+ | In Java methods can be overloaded based on the number of arguments and the static types of the arguments. Invoking an overloaded method from within AmbientTalk requires special consideration because it does not have the notion of static types. | ||
+ | |||
+ | If the Java method is overloaded based on arity (i.e. each overloaded method takes a different number of arguments), the number of arguments in the AmbientTalk invocation can be used to identify a unique Java method. Hence, overloading based on arity does not require special attention from the AmbientTalk programmer. If the Java method is overloaded based solely on argument types, the interpreter may derive that the actual arguments can only be converted from AmbientTalk to the appropriate Java types for one of the matching overloaded signatures. Again, if only one match remains, the unique match is invoked. In the remaining case in which the actual AmbientTalk arguments satisfy more than one overloaded method signature, the symbiotic invocation fails with a runtime exception. It is then the AmbientTalk programmer' | ||
+ | |||
+ | Selection of the correct overloaded method is done using a special '' | ||
+ | |||
+ | < | ||
+ | >def remove := aVector.& | ||
+ | >>< | ||
+ | > | ||
+ | >>1 | ||
+ | > | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | In the example above the expression '' | ||
+ | |||
+ | < | ||
+ | > | ||
+ | >> | ||
+ | > | ||
+ | >>< | ||
+ | </ | ||
+ | |||
+ | ===== Accessing AmbientTalk from within Java ===== | ||
+ | |||
+ | ==== Invoking AmbientTalk methods in Java ==== | ||
+ | |||
+ | Besides calling Java methods from within AmbientTalk it is also possible to call AmbientTalk methods from within Java. To illustrate this consider the code snippet shown below. | ||
+ | |||
+ | < | ||
+ | def SymbiosisDemo := jlobby.at.tutorial.SymbiosisDemo; | ||
+ | |||
+ | def showSymbiosis() { | ||
+ | def javaDemo := SymbiosisDemo.new(); | ||
+ | |||
+ | def atObject := object: { | ||
+ | def ping() { | ||
+ | system.println(" | ||
+ | javaDemo.run2(self); | ||
+ | }; | ||
+ | def pong() { | ||
+ | system.println(" | ||
+ | 42 | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | javaDemo.run(atObject); | ||
+ | }; | ||
+ | |||
+ | self | ||
+ | </ | ||
+ | |||
+ | When an AmbientTalk object is passed as an argument to a Java method expecting an object of an interface type, the AmbientTalk object will appear to Java objects as a regular Java object implementing that interface. | ||
+ | |||
+ | < | ||
+ | package at.tutorial; | ||
+ | |||
+ | public class SymbiosisDemo { | ||
+ | public interface PingPong { | ||
+ | public int ping(); | ||
+ | public int pong(); | ||
+ | } | ||
+ | |||
+ | public int run(PingPong pp) { | ||
+ | return pp.ping(); | ||
+ | } | ||
+ | |||
+ | public int run2(PingPong pp) { | ||
+ | return pp.pong(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | If Java invokes a method declared in an interface with an overloaded method signature, all overloaded invocations are transformed into the same method invocation on the AmbientTalk object. In other words, the AmbientTalk object does not take the types into consideration. However, if the Java method is overloaded based on arity, the AmbientTalk programmer can take this into account in the parameter list of the corresponding AmbientTalk method, by means of a variable-argument list or optional parameters. Otherwise, the Java invocation may fail because of an arity mismatch. | ||
+ | |||
+ | < | ||
+ | >def test := / | ||
+ | > | ||
+ | ping! | ||
+ | pong! | ||
+ | >> | ||
+ | </ | ||
+ | |||
+ | ==== Starting an AmbientTalk interpreter from Java ==== | ||
+ | |||
+ | So far, the examples have illustrated how to reuse Java code from within AmbientTalk. They have shown how to access Java classes, instantiate them and invoke methods on the resulting objects. Moreover, | ||
+ | |||
+ | Embedding AmbientTalk in an application, | ||
+ | |||
+ | Once an instance of an EmbeddableAmbientTalk subclass is created, the AmbientTalk VM can be started by sending it the '' | ||
+ | |||
+ | < | ||
+ | EmbeddableAmbientTalk vm = new MyEmbeddableAmbientTalk(); | ||
+ | vm.initialize( | ||
+ | NATParser.parse( | ||
+ | initFile.getName(), | ||
+ | Evaluator.loadContentOfFile(initFile)), | ||
+ | new SharedActorField[] { | ||
+ | vm.computeSystemObject(arguments), | ||
+ | vm.computeWorkingDirectory(), | ||
+ | vm.computeObjectPath(objectPath) }, | ||
+ | " | ||
+ | </ | ||
+ | The code excerpt also illustrates that the EmbeddableAmbientTalk class provides methods to create definitions for fields such as '' | ||
+ | |||
+ | Once the virtual machine is properly initialized, | ||
+ | |||
+ | < | ||
+ | public interface Controller { | ||
+ | public void executeEvent(ApplicationEvent evt); | ||
+ | public void executeEventWithoutUndo(ApplicationEvent evt); | ||
+ | public void undo(); | ||
+ | } | ||
+ | ... | ||
+ | private Controller controller = | ||
+ | (Controller) vm.evalAndWrap( | ||
+ | Evaluator.loadContentsOfFile(" | ||
+ | Controller.class); | ||
+ | </ | ||
+ | |||
+ | The corresponding AmbientTalk code should then return an object which implements the three methods to modify the model, and can be used to detect other reachable controllers with which it can exchange ApplicationEvents. | ||
+ | |||
+ | < | ||
+ | When starting an AmbientTalk virtual machine from a Java application, | ||
+ | </ |
at/tutorial/symbiosis.txt · Last modified: 2013/05/17 20:25 by tvcutsem