©2014 Shintaro Hosoai
Xtext & Xtend
Documents
細合 晋太郎
2014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Xtext
2014/3/31 SEA関西プロセス分科会 2
©2014 Shintaro Hosoai
Xtext構造
grammar org.eclipse.xtext.example.fowlerdsl.Statemachine with
org.eclipse.xtext.common.Terminals
generate statemachine "http://www.eclipse.org/xtext/example/fowlerdsl/Statemachine"
Statemachine :
{Statemachine}
('events'
events+=Event+
'end')?
('resetEvents'
resetEvents+=[Event]+
'end')?
('commands'
commands+=Command+
'end')?
states+=State*;
terminal MYID:
'A''0'..'9';
言語名宣言と言語Mixin
言語モデル宣言
Parser Rule/言語構造定義
lexis/語彙定義
初めのうちは,上二つは自動生成ままで利用するのがよい
Event:
name=ID;
...
©2014 Shintaro Hosoai
DSL Mixin
• DSL Mixinを行うにはWith句にDSL名を指定する.
grammar DSL名 with ベースDSL名
• デフォルトのDSL
org.eclipse.xtext.common.Terminals
IDやINT,STRING等のTerminalが定義されている.
• Xbase
org.eclipse.xtext.xbase.Xbase
Jvm統合に必要な各種要素が定義されている.
• 自前DSLをMixinするには,以下のようにwith句にDSL名を
指定
42014/3/31 SEA関西プロセス分科会
grammar my.SuperGrammar
generate super "http://my.org/super"
...
RuleA : "a" stuff=RuleB;
RuleB : "{" name=ID "}";
grammar my.SubGrammar with my.SuperGrammar
...
ベースDSL
子DSL
©2014 Shintaro Hosoai
Parser Rules
• 定義名:~‘;’までが一つのルールとなる.
• この定義名のモデルが生成される(Returnsを
指定しない場合,Returnsで指定したモデルを
割り当てることも出来る.)
52014/3/31 SEA関西プロセス分科会
State:
'state' name=ID
('actions' '{' actions+=[Command]+ '}')?
transitions+=Transition*
'end';
Transition:
event=[Event] '=>' state=[State];
DSL定義
©2014 Shintaro Hosoai
語彙
• ’’で区切った部分は語彙として定義される
62014/3/31 SEA関西プロセス分科会
State:
'state' name=ID
('actions' '{' actions+=[Command]+ '}')?
transitions+=Transition*
'end';
DSL定義
state myState
actions { myCommand1 myCommand2 }
event2 => myState2
event3 => myState3
end
DSL例
©2014 Shintaro Hosoai
変数
• 変数は,属性として生成される.
• 割り当てに応じて
=:単体,
+=:EList
• として生成される
72014/3/31 SEA関西プロセス分科会
State:
'state' name=ID
('actions' '{' actions+=[Command]+ '}')?
transitions+=Transition*
'end';
Transition:
event=[Event] '=>' state=[State];
DSL定義
State
name : ID
actions : List<Command>
transitions:List<Transition>
Transition
event : Event
state : State
©2014 Shintaro Hosoai
数量子
• ():グループ
• * :0回以上
• + :1回以上
• ? :0または1
• Terminal 限定
• . :任意の一文字
• ! :否定.!(‘A’|’B’|’C’)なら ABC以外の文字が
マッチ.
• -> : Until, ‘/*’ -> ‘*/’ なら*/が来るまでスキップさ
れる
• .. :範囲値.‘A’..’D’ ならABCD,数値も可
Unicodeの並びで範囲指定しているらし
い.
このため日本語を指定することも可能.
82014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Type Reference
State:
'state' name=ID
('actions' '{' actions+=[Command]+ '}')?
transitions+=Transition*
'end';
state myState
actions { myCommand1 myCommand2 }
event2 => myState2
event3 => myState3
end
Transition:
event=[Event] '=>' state=[State];
DSL定義
DSL例
[]で指定した要素はnameによりで
インスタンスを参照する.
このため参照されるRuleにはname=ID
を持つ必要がある.
例ではState,Event,Commandは参照可
Transitionはname=IDを持たないので,
参照出来ない.
割り当てに用いることが出来るのは,
・Terminal Rule (ex: ID)
・Parser Rule (ex: Transition)
・Parser Ruleの実体への参照(ex: [Command])
©2014 Shintaro Hosoai
Terminal
• 任意の語彙の作成
• terminal 語彙名 :
定義;
• 例えば,アルファベットから始まる英数字の羅
列
• terminal MyID :
(‘a’..’z’|’A’..’Z’)(‘a’..’z’|’A’..’Z’|’0’..’9’)*;
102014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Xtend
2014/3/31 SEA関西プロセス分科会 11
©2014 Shintaro Hosoai
こんにちはXtend!
• Xtendの記法はJavaによく似ています.
• メソッド定義はdefキーワードで行います.
•class HelloWorld {
def static void main(String[] args) {
println("Hello World")
}
}
// Generated Java Source Code
import org.eclipse.xtext.xbase.lib.InputOutput;
public class HelloWorld {
public static void main(final String[] args) {
InputOutput.<String>println("Hello World");
}
}
自動生成
生成されたJavaコード
Xtendコード
記述したXtendコードはセーブ
タイミングで自動的にJavaコー
に変換されます.
©2014 Shintaro Hosoai
Xtendの特徴
• Extension methods
• Lambda Expression
• Active Annotations
• Operator overloading
• Powerful switch expressions
• Multiple dispatch
• Template expressions
• No statement
• Properties
• Type inference
• Full support for Java generics
• Translate to Java (not bytecode)
©2014 Shintaro Hosoai
Classes and Members
package com.acme
import java.util.List
class MyClass {
String name
new(String name) {
this.name = name
}
def String first(List<String> elements) {
elements.get(0)
}
}
セミコロンは不要(あってもよ
い)
コンストラクタはnewキーワードで定義
クラス内で自身のコンストラクタ呼び出しは
this().
親コンストラクタはsuper() (Javaと同じ)
メソッドはdefキー
ワードで定義
デフォルトはpublic. protected,
package, privateを指定可能
extends, implementsの使い方は
Javaと同じ
©2014 Shintaro Hosoai
Field(1)
• 変数宣言の方法は3つ
• Javaと同じ型名 変数名
メソッド内の定義には使えない.var/valを利用する
こと
• var 変数名 :動的型.型推論で適切な型が振られ
る
• val 定数名 :定数宣言.こちらも明確な型指定は
行わず,初回代入時の型に応じて決まる.
• アクセス指示子はデフォルトでPrivate
©2014 Shintaro Hosoai
Field(2)
• getter/setterの自動呼出し
• FooクラスにsetHoge(), getHoge()定義されている場
合.
• val foo = new Foo
• foo.hoge : getHoge()が呼ばれる
• foo.hoge = “aaa”:setHoge(“aaa”)が呼ばれる
• getter/setterの自動生成
• @Property
• Type variable
• とすることで,自動的にGetter/Setterが生成される
162014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Field(3)
• this
• Javaと同じ.省略可
• it:
省略可能になる変数,Lambdaと組合わせるといいら
しい
• val it = new Person
• name = “Horst” : it.setName()が呼ばれる
• クラス変数,クラスメソッドへのアクセス
• MyClass::myField
• MyClass::myMethod()
172014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Expression
• Xtendの構文はすべて式です.メソッド呼び出
しはもちろん,ブロック,各種制御構文,メ
ソッド定義もすべて値を返します.
• 関数型もあります
• val toUpperCaseFunction = [String s |
s.toUpperCase]
↑String.toUpperCaseメソッドを
toUpperCaseFunctionという変数に代入
182014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Operators(1)
• 一覧は演算子とオーバーライド章を参照
• 等価・比較演算子
• ==, != : equals()で比較.文字列比較はこれ
で
• ===, !== : 従来のJavaの比較演算子.Reference
• >, <, >=, <= : Javaと同じ.Comparable
• 算術演算:
+, -, *, /, %, **.Javaと同じだが,Primitive Type以外に
もオーバーライドして利用可
• Elvis Operator: null-safe feature call
• val salutation = person.firstName ?: ‘Sir/Madam’
• personがNullでもぬるぽにならない.’Sir/Madam’が
代入される
192014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Operators(2)
• With Operator:オブジェクトの属性に簡単代入
• var person = new Person => [
firstName = “Shintaro”
lastName = “Hosoai”
address = new Address => [
city = “Fukuoka”
]
]
• Range Operator : 範囲値作成
• 0..10 → 012345678910
• Pair Operator : ペア値作成(簡易Hash?)
• val nameAndAge = ‘Homer’ -> 42
202014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
制御構文:IF
• if (cond) {
• expression
• }else{
• elseExpression
• }
• ifも式として用いる事ができます.
• var name = if (firstName!=null)
firstName+’ ’+lastName else lastName
• var name = if (str.length>1) str : elseを省略する
とelse nullと見なされます(nullが返る)
212014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
制御構文:switch
switch myString {
case myString.length > 5 : “a long string”
case ‘some’ : “It’s some string”.
default : “It’s another short string”
}
• caseに条件文が使えます.break句は不要です.
Stringの比較が行えます.
222014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
制御構文:switch:Type Guard
def something(Object o){
switch o {
String : o.substring(3)
Integer case o > 10 : o.toString
default : “not match”
}
}
型で条件分岐できます.(instanceof)
型にマッチした後にさらにCaseで条件を加える
事ができます.マッチした時点で自動的にCast
されています.
232014/3/31 SEA関西プロセス分科会
このOはIntegerに
Castされている
このOはStringに
Castされている
©2014 Shintaro Hosoai
制御構文:for
• Xtendのforはjava5の拡張Forのみです.従来の
for(int a=0; a<10;a++)といった書き方はできませ
ん.
(Range記法と組み合わせる事で同様の事はで
きます)
for ( Type variable : arrayOrIterable){
expressions.
}
型宣言や{}は省略可です.適切な型が選択さ
れます.ex) List<String>ならStringの変数となる.
for(variable : arrayOrIterable) expression
242014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
制御構文:for Rangeとの組み合わ
せ
• 1~10までループしたい場合どうするの?
for (i : 1 ..10)
print i
10..1で逆順も可能
Range Operations
• 0..10 → 012345678910
• 0..<10 → 0123456789
• 10>..0 → 9876543210
• 0 .. hoge.length といった表記も可
252014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Methods(1)
• メソッド宣言はdefで行う.デフォルトのアク
セス指示子はpublic. protected, package, private指
定可.
• 返り値の型は省略可能.またReturnも省略可
能,一番最後の式の値が返る.
• staticでクラスメソッドとすることも出来る
(Javaと同じ)
• 抽象メソッド
• 抽象クラスやインターフェイス内で,Bodyの
無いメソッド定義は,抽象メソッドとなる.
abstract class MyAbstractClass() {
def String abstractMethod() // no body
}
©2014 Shintaro Hosoai
Methods(2)
• オーバーライドはdefの代わりにoverrideキー
ワードを用いて明示する.
• Exception
• Javaと同様
• Generic
• Javaと同様
• Method Call
• Javaと同様.引数がない場合は()省略可能
override String second(List<String> elements) {
elements.get(1)
}
©2014 Shintaro Hosoai
Lambda(1)
• [ Type variable | expression]
• 以下,JavaとXtendのLambdaの実装比較
Java
final JTextField textField = new JTextField();
textFeild.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
textField.text=“Something happend”);
}});
Xtend
val textField = new JTextField
textField.addActionListener([ActionEvent e |
textField.text = “Something happned”
])
282014/3/31 SEA関西プロセス分科会
これも省略可
©2014 Shintaro Hosoai
Lambda(2)
• [a, b | a.length – b.length] <二引数の関数の場合
• 変数への代入も可能
• val myFunction = [Type a | a.doAnything()]
• コレクションにももちろん利用可能
• 予め便利なメソッド群がExtension Methodとして追
加されている
• forEach((T)=>void Procedure) : void
• map((T)=>R Transformation) : List<R>
• filter((T)=> Boolean Predicate) : Iteratable<T>
• findFirst((T)=>Boolean Predicate): T
• reduce((T,T)=> T function): T
• などなど.
292014/3/31 SEA関西プロセス分科会
©2014 Shintaro Hosoai
Dispatch Methods(1)
• Javaはコンパイル時の型に基づいて,メソッド
呼び出しを決定する.このため,動的に
Dispatchできない
左図のような構造で,Dispatcher
に
MyInterface a = MyClass1();
Dispatcher.dispatch(a);
とすると,呼び出しは不
定となる
(コンパイルできない)
• 言語AST(Abstract Syntax Tree)へのアクセスは,
このようなDispatch Methodが多用される
MyInterface
MyClass1 MyClass2
Dispatcher
dispatch(MyClass1 a)
dispatch(MyClass2 b)
©2014 Shintaro Hosoai
Dispatch Methods(2)
• Xtendではdispatch
キーワードを付与する
ことで,Dispatch Method
として定義できる
• 次のようなXtext定義を
行った際などは,dispatch
を指定するとよい
class DispatchSample {
def doGenerate(){
val expressions = new
ArrayList<Expression>
expressions.add(new Add)
expressions.add(new Sub)
expressions.add(new Mul)
expressions.add(new Div)
for(e : expressions){
genExpression(e);
}
}
dispatch def genExpression(Add a)''''''
dispatch def genExpression(Sub a)''''''
dispatch def genExpression(Mul a)''''''
dispatch def genExpression(Div a)''''''
}
interface Expression{}
class Add implements Expression{}
class Sub implements Expression{}
class Mul implements Expression{}
class Div implements Expression{}
Expression :
Add | Sub | Mul | Div;
Add : ...;
Sub : ...;
Mul : ...;
Div : ...;
実際にはDSL
のパーサがこ
のようにモデ
ルを詰めて渡
してくる
Xtextで
生成
される
AST
©2014 Shintaro Hosoai
Extension Methods
• クラスにメソッドを(仮想的に)付け加える
• たとえば.StringにtoFirstUpper()メソッドを加
えたり
• 第一引数を対象の型にしたメソッドはExtension
Methodとして呼び出せる
• def extensionCall(String str, Hoge any){
• str.doSomething()
• }
• “hello”.extensionCall(hogeAny) ←呼び出す時は左
辺のオブジェクトが第一引数として渡される.
©2014 Shintaro Hosoai
Extension Imports/Provider
• Xtendには,モデル操作等の便利なユーティリ
ティメソッドがExtension Methodのライブラリ
として提供されている
• ObjectExtensions (src)
• IterableExtensions (src)
• MapExtensions (src)
• ListExtensions (src)
• CollectionExtensions (src)
• BooleanExtensions (src)
• IntegerExtensions (src)
• FunctionExtensions (src)
©2014 Shintaro Hosoai
Active Annotation
• @Property
• 属性に付与することで,private変数とgetter/setter
を生成する
• @Property
String name
• ->
private String _name;
String getName(){return _name;}
void setName(String name){this._name=name;}
• @Data
• クラスに付与することで,含まれる属性の
getter/setter, 属性設定を行うコンストラクタ等を生
成
©2014 Shintaro Hosoai
Annotation Type Declaration
annotation MyAnnotation {
String[] value
boolean isTricky = false
int[] lotteryNumbers = #[ 42, 137 ]
}
©2014 Shintaro Hosoai
Enum Type Declaration
• Javaと同じ?
enum MyColor {
GREEN,
BLUE,
RED
}
©2014 Shintaro Hosoai
演算子とオーバーライド(1)
• Xtendでは,演算子のオーバーライドが可能
• 演算子に対応するメソッドを定義すると,その
演算子が使われた際に対応するメソッドが呼ば
れる.
class OperatorOverwrite {
String name = “hoge”
def operator_plus(OperatorOverwrite e2){
this.name+"::"+e2.name
}
def static void main(String[] args) {
var op1 = new OperatorOverwrite;
var op2 = new OperatorOverwrite;
print(op1+op2)
}
}
+二項演算子の定義.
オーバーライドではある
がoverrideではなくdefで
定義する.
thisが左辺,引数が右辺.
ここでは自身と同じ型を
引数に取っているが,異
なる型でも可能.オー
バーロードも可.
+二項演算子の呼び出し
©2014 Shintaro Hosoai
演算子とオーバーライド(2)
演算子 対応メソッド名 演算子 対応メソッド名
! e1 e1.operator_not() e1 == e2 e1.operator_equals(e2)
- e1 e1.operator_minus() e1 != e2 e1.operator_notEquals(e2)
+ e1 e1.operator_plus() e1 === e2 e1.operator_tripleEquals(e2)
e1 + e2 e1.operator_plus(e2) e1 !== e2 e1.operator_tripleNotEquals(e2)
e1 – e2 e1.operator_minus(e2) e1 < e2 e1.operator_lessThan(e2)
e1 * e2 e1.operator_multiply(e2) e1 > e2 e1.operator_greaterThan(e2)
e1 / e2 e1.operator_divide(e2) e1 <= e2 e1.operator_lessEqualsThan(e2)
e1 % e2 e1.operator_modulo(e2) e1 >= e2 e1.operator_greaterEqualsThan(e2)
e1 ** e2 e1.operator_power(e2) e1 -> e2 e1.operator_mappedTo(e2)
e1 += e2 e1.operator_add(e2) e1 .. e2 e1.operator_upTo(e2)
e1 –= e2 e1.operator_remove(e2) e1 >.. e2 e1.operator_greaterThanDoubleDot(
e2)
e1 || e2 e1.operator_or(e2) e1 ..<e2 e1.operator_doubleDotLessThan(e2)
e1 && e2 e1.operator_and(e2)
©2014 Shintaro Hosoai
演算子とオーバーライド(3)
演算子 対応メソッド名 演算子 対応メソッド名
e1 => e2 e1.operator_equals(e2)
e1 <= e2 e1.operator_notEquals(e2) e1 >>> e2 e1.operator_greaterThan(e2)
e1 << e2 e1.operator_tripleEquals(e2) e1 <> e2 e1.operator_lessEqualsThan(e2)
e1 >> e2 e1.operator_tripleNotEquals(
e2)
e1 ?: e2 e1.operator_greaterEqualsThan(
e2)
e1 <<< e2 e1.operator_lessThan(e2) e1 <=> e2 e1.operator_mappedTo(e2)

Xtext&Xtend documents

  • 1.
    ©2014 Shintaro Hosoai Xtext& Xtend Documents 細合 晋太郎 2014/3/31 SEA関西プロセス分科会
  • 2.
    ©2014 Shintaro Hosoai Xtext 2014/3/31SEA関西プロセス分科会 2
  • 3.
    ©2014 Shintaro Hosoai Xtext構造 grammarorg.eclipse.xtext.example.fowlerdsl.Statemachine with org.eclipse.xtext.common.Terminals generate statemachine "http://www.eclipse.org/xtext/example/fowlerdsl/Statemachine" Statemachine : {Statemachine} ('events' events+=Event+ 'end')? ('resetEvents' resetEvents+=[Event]+ 'end')? ('commands' commands+=Command+ 'end')? states+=State*; terminal MYID: 'A''0'..'9'; 言語名宣言と言語Mixin 言語モデル宣言 Parser Rule/言語構造定義 lexis/語彙定義 初めのうちは,上二つは自動生成ままで利用するのがよい Event: name=ID; ...
  • 4.
    ©2014 Shintaro Hosoai DSLMixin • DSL Mixinを行うにはWith句にDSL名を指定する. grammar DSL名 with ベースDSL名 • デフォルトのDSL org.eclipse.xtext.common.Terminals IDやINT,STRING等のTerminalが定義されている. • Xbase org.eclipse.xtext.xbase.Xbase Jvm統合に必要な各種要素が定義されている. • 自前DSLをMixinするには,以下のようにwith句にDSL名を 指定 42014/3/31 SEA関西プロセス分科会 grammar my.SuperGrammar generate super "http://my.org/super" ... RuleA : "a" stuff=RuleB; RuleB : "{" name=ID "}"; grammar my.SubGrammar with my.SuperGrammar ... ベースDSL 子DSL
  • 5.
    ©2014 Shintaro Hosoai ParserRules • 定義名:~‘;’までが一つのルールとなる. • この定義名のモデルが生成される(Returnsを 指定しない場合,Returnsで指定したモデルを 割り当てることも出来る.) 52014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; Transition: event=[Event] '=>' state=[State]; DSL定義
  • 6.
    ©2014 Shintaro Hosoai 語彙 •’’で区切った部分は語彙として定義される 62014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; DSL定義 state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3 end DSL例
  • 7.
    ©2014 Shintaro Hosoai 変数 •変数は,属性として生成される. • 割り当てに応じて =:単体, +=:EList • として生成される 72014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; Transition: event=[Event] '=>' state=[State]; DSL定義 State name : ID actions : List<Command> transitions:List<Transition> Transition event : Event state : State
  • 8.
    ©2014 Shintaro Hosoai 数量子 •():グループ • * :0回以上 • + :1回以上 • ? :0または1 • Terminal 限定 • . :任意の一文字 • ! :否定.!(‘A’|’B’|’C’)なら ABC以外の文字が マッチ. • -> : Until, ‘/*’ -> ‘*/’ なら*/が来るまでスキップさ れる • .. :範囲値.‘A’..’D’ ならABCD,数値も可 Unicodeの並びで範囲指定しているらし い. このため日本語を指定することも可能. 82014/3/31 SEA関西プロセス分科会
  • 9.
    ©2014 Shintaro Hosoai TypeReference State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3 end Transition: event=[Event] '=>' state=[State]; DSL定義 DSL例 []で指定した要素はnameによりで インスタンスを参照する. このため参照されるRuleにはname=ID を持つ必要がある. 例ではState,Event,Commandは参照可 Transitionはname=IDを持たないので, 参照出来ない. 割り当てに用いることが出来るのは, ・Terminal Rule (ex: ID) ・Parser Rule (ex: Transition) ・Parser Ruleの実体への参照(ex: [Command])
  • 10.
    ©2014 Shintaro Hosoai Terminal •任意の語彙の作成 • terminal 語彙名 : 定義; • 例えば,アルファベットから始まる英数字の羅 列 • terminal MyID : (‘a’..’z’|’A’..’Z’)(‘a’..’z’|’A’..’Z’|’0’..’9’)*; 102014/3/31 SEA関西プロセス分科会
  • 11.
    ©2014 Shintaro Hosoai Xtend 2014/3/31SEA関西プロセス分科会 11
  • 12.
    ©2014 Shintaro Hosoai こんにちはXtend! •Xtendの記法はJavaによく似ています. • メソッド定義はdefキーワードで行います. •class HelloWorld { def static void main(String[] args) { println("Hello World") } } // Generated Java Source Code import org.eclipse.xtext.xbase.lib.InputOutput; public class HelloWorld { public static void main(final String[] args) { InputOutput.<String>println("Hello World"); } } 自動生成 生成されたJavaコード Xtendコード 記述したXtendコードはセーブ タイミングで自動的にJavaコー に変換されます.
  • 13.
    ©2014 Shintaro Hosoai Xtendの特徴 •Extension methods • Lambda Expression • Active Annotations • Operator overloading • Powerful switch expressions • Multiple dispatch • Template expressions • No statement • Properties • Type inference • Full support for Java generics • Translate to Java (not bytecode)
  • 14.
    ©2014 Shintaro Hosoai Classesand Members package com.acme import java.util.List class MyClass { String name new(String name) { this.name = name } def String first(List<String> elements) { elements.get(0) } } セミコロンは不要(あってもよ い) コンストラクタはnewキーワードで定義 クラス内で自身のコンストラクタ呼び出しは this(). 親コンストラクタはsuper() (Javaと同じ) メソッドはdefキー ワードで定義 デフォルトはpublic. protected, package, privateを指定可能 extends, implementsの使い方は Javaと同じ
  • 15.
    ©2014 Shintaro Hosoai Field(1) •変数宣言の方法は3つ • Javaと同じ型名 変数名 メソッド内の定義には使えない.var/valを利用する こと • var 変数名 :動的型.型推論で適切な型が振られ る • val 定数名 :定数宣言.こちらも明確な型指定は 行わず,初回代入時の型に応じて決まる. • アクセス指示子はデフォルトでPrivate
  • 16.
    ©2014 Shintaro Hosoai Field(2) •getter/setterの自動呼出し • FooクラスにsetHoge(), getHoge()定義されている場 合. • val foo = new Foo • foo.hoge : getHoge()が呼ばれる • foo.hoge = “aaa”:setHoge(“aaa”)が呼ばれる • getter/setterの自動生成 • @Property • Type variable • とすることで,自動的にGetter/Setterが生成される 162014/3/31 SEA関西プロセス分科会
  • 17.
    ©2014 Shintaro Hosoai Field(3) •this • Javaと同じ.省略可 • it: 省略可能になる変数,Lambdaと組合わせるといいら しい • val it = new Person • name = “Horst” : it.setName()が呼ばれる • クラス変数,クラスメソッドへのアクセス • MyClass::myField • MyClass::myMethod() 172014/3/31 SEA関西プロセス分科会
  • 18.
    ©2014 Shintaro Hosoai Expression •Xtendの構文はすべて式です.メソッド呼び出 しはもちろん,ブロック,各種制御構文,メ ソッド定義もすべて値を返します. • 関数型もあります • val toUpperCaseFunction = [String s | s.toUpperCase] ↑String.toUpperCaseメソッドを toUpperCaseFunctionという変数に代入 182014/3/31 SEA関西プロセス分科会
  • 19.
    ©2014 Shintaro Hosoai Operators(1) •一覧は演算子とオーバーライド章を参照 • 等価・比較演算子 • ==, != : equals()で比較.文字列比較はこれ で • ===, !== : 従来のJavaの比較演算子.Reference • >, <, >=, <= : Javaと同じ.Comparable • 算術演算: +, -, *, /, %, **.Javaと同じだが,Primitive Type以外に もオーバーライドして利用可 • Elvis Operator: null-safe feature call • val salutation = person.firstName ?: ‘Sir/Madam’ • personがNullでもぬるぽにならない.’Sir/Madam’が 代入される 192014/3/31 SEA関西プロセス分科会
  • 20.
    ©2014 Shintaro Hosoai Operators(2) •With Operator:オブジェクトの属性に簡単代入 • var person = new Person => [ firstName = “Shintaro” lastName = “Hosoai” address = new Address => [ city = “Fukuoka” ] ] • Range Operator : 範囲値作成 • 0..10 → 012345678910 • Pair Operator : ペア値作成(簡易Hash?) • val nameAndAge = ‘Homer’ -> 42 202014/3/31 SEA関西プロセス分科会
  • 21.
    ©2014 Shintaro Hosoai 制御構文:IF •if (cond) { • expression • }else{ • elseExpression • } • ifも式として用いる事ができます. • var name = if (firstName!=null) firstName+’ ’+lastName else lastName • var name = if (str.length>1) str : elseを省略する とelse nullと見なされます(nullが返る) 212014/3/31 SEA関西プロセス分科会
  • 22.
    ©2014 Shintaro Hosoai 制御構文:switch switchmyString { case myString.length > 5 : “a long string” case ‘some’ : “It’s some string”. default : “It’s another short string” } • caseに条件文が使えます.break句は不要です. Stringの比較が行えます. 222014/3/31 SEA関西プロセス分科会
  • 23.
    ©2014 Shintaro Hosoai 制御構文:switch:TypeGuard def something(Object o){ switch o { String : o.substring(3) Integer case o > 10 : o.toString default : “not match” } } 型で条件分岐できます.(instanceof) 型にマッチした後にさらにCaseで条件を加える 事ができます.マッチした時点で自動的にCast されています. 232014/3/31 SEA関西プロセス分科会 このOはIntegerに Castされている このOはStringに Castされている
  • 24.
    ©2014 Shintaro Hosoai 制御構文:for •Xtendのforはjava5の拡張Forのみです.従来の for(int a=0; a<10;a++)といった書き方はできませ ん. (Range記法と組み合わせる事で同様の事はで きます) for ( Type variable : arrayOrIterable){ expressions. } 型宣言や{}は省略可です.適切な型が選択さ れます.ex) List<String>ならStringの変数となる. for(variable : arrayOrIterable) expression 242014/3/31 SEA関西プロセス分科会
  • 25.
    ©2014 Shintaro Hosoai 制御構文:forRangeとの組み合わ せ • 1~10までループしたい場合どうするの? for (i : 1 ..10) print i 10..1で逆順も可能 Range Operations • 0..10 → 012345678910 • 0..<10 → 0123456789 • 10>..0 → 9876543210 • 0 .. hoge.length といった表記も可 252014/3/31 SEA関西プロセス分科会
  • 26.
    ©2014 Shintaro Hosoai Methods(1) •メソッド宣言はdefで行う.デフォルトのアク セス指示子はpublic. protected, package, private指 定可. • 返り値の型は省略可能.またReturnも省略可 能,一番最後の式の値が返る. • staticでクラスメソッドとすることも出来る (Javaと同じ) • 抽象メソッド • 抽象クラスやインターフェイス内で,Bodyの 無いメソッド定義は,抽象メソッドとなる. abstract class MyAbstractClass() { def String abstractMethod() // no body }
  • 27.
    ©2014 Shintaro Hosoai Methods(2) •オーバーライドはdefの代わりにoverrideキー ワードを用いて明示する. • Exception • Javaと同様 • Generic • Javaと同様 • Method Call • Javaと同様.引数がない場合は()省略可能 override String second(List<String> elements) { elements.get(1) }
  • 28.
    ©2014 Shintaro Hosoai Lambda(1) •[ Type variable | expression] • 以下,JavaとXtendのLambdaの実装比較 Java final JTextField textField = new JTextField(); textFeild.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ textField.text=“Something happend”); }}); Xtend val textField = new JTextField textField.addActionListener([ActionEvent e | textField.text = “Something happned” ]) 282014/3/31 SEA関西プロセス分科会 これも省略可
  • 29.
    ©2014 Shintaro Hosoai Lambda(2) •[a, b | a.length – b.length] <二引数の関数の場合 • 変数への代入も可能 • val myFunction = [Type a | a.doAnything()] • コレクションにももちろん利用可能 • 予め便利なメソッド群がExtension Methodとして追 加されている • forEach((T)=>void Procedure) : void • map((T)=>R Transformation) : List<R> • filter((T)=> Boolean Predicate) : Iteratable<T> • findFirst((T)=>Boolean Predicate): T • reduce((T,T)=> T function): T • などなど. 292014/3/31 SEA関西プロセス分科会
  • 30.
    ©2014 Shintaro Hosoai DispatchMethods(1) • Javaはコンパイル時の型に基づいて,メソッド 呼び出しを決定する.このため,動的に Dispatchできない 左図のような構造で,Dispatcher に MyInterface a = MyClass1(); Dispatcher.dispatch(a); とすると,呼び出しは不 定となる (コンパイルできない) • 言語AST(Abstract Syntax Tree)へのアクセスは, このようなDispatch Methodが多用される MyInterface MyClass1 MyClass2 Dispatcher dispatch(MyClass1 a) dispatch(MyClass2 b)
  • 31.
    ©2014 Shintaro Hosoai DispatchMethods(2) • Xtendではdispatch キーワードを付与する ことで,Dispatch Method として定義できる • 次のようなXtext定義を 行った際などは,dispatch を指定するとよい class DispatchSample { def doGenerate(){ val expressions = new ArrayList<Expression> expressions.add(new Add) expressions.add(new Sub) expressions.add(new Mul) expressions.add(new Div) for(e : expressions){ genExpression(e); } } dispatch def genExpression(Add a)'''''' dispatch def genExpression(Sub a)'''''' dispatch def genExpression(Mul a)'''''' dispatch def genExpression(Div a)'''''' } interface Expression{} class Add implements Expression{} class Sub implements Expression{} class Mul implements Expression{} class Div implements Expression{} Expression : Add | Sub | Mul | Div; Add : ...; Sub : ...; Mul : ...; Div : ...; 実際にはDSL のパーサがこ のようにモデ ルを詰めて渡 してくる Xtextで 生成 される AST
  • 32.
    ©2014 Shintaro Hosoai ExtensionMethods • クラスにメソッドを(仮想的に)付け加える • たとえば.StringにtoFirstUpper()メソッドを加 えたり • 第一引数を対象の型にしたメソッドはExtension Methodとして呼び出せる • def extensionCall(String str, Hoge any){ • str.doSomething() • } • “hello”.extensionCall(hogeAny) ←呼び出す時は左 辺のオブジェクトが第一引数として渡される.
  • 33.
    ©2014 Shintaro Hosoai ExtensionImports/Provider • Xtendには,モデル操作等の便利なユーティリ ティメソッドがExtension Methodのライブラリ として提供されている • ObjectExtensions (src) • IterableExtensions (src) • MapExtensions (src) • ListExtensions (src) • CollectionExtensions (src) • BooleanExtensions (src) • IntegerExtensions (src) • FunctionExtensions (src)
  • 34.
    ©2014 Shintaro Hosoai ActiveAnnotation • @Property • 属性に付与することで,private変数とgetter/setter を生成する • @Property String name • -> private String _name; String getName(){return _name;} void setName(String name){this._name=name;} • @Data • クラスに付与することで,含まれる属性の getter/setter, 属性設定を行うコンストラクタ等を生 成
  • 35.
    ©2014 Shintaro Hosoai AnnotationType Declaration annotation MyAnnotation { String[] value boolean isTricky = false int[] lotteryNumbers = #[ 42, 137 ] }
  • 36.
    ©2014 Shintaro Hosoai EnumType Declaration • Javaと同じ? enum MyColor { GREEN, BLUE, RED }
  • 37.
    ©2014 Shintaro Hosoai 演算子とオーバーライド(1) •Xtendでは,演算子のオーバーライドが可能 • 演算子に対応するメソッドを定義すると,その 演算子が使われた際に対応するメソッドが呼ば れる. class OperatorOverwrite { String name = “hoge” def operator_plus(OperatorOverwrite e2){ this.name+"::"+e2.name } def static void main(String[] args) { var op1 = new OperatorOverwrite; var op2 = new OperatorOverwrite; print(op1+op2) } } +二項演算子の定義. オーバーライドではある がoverrideではなくdefで 定義する. thisが左辺,引数が右辺. ここでは自身と同じ型を 引数に取っているが,異 なる型でも可能.オー バーロードも可. +二項演算子の呼び出し
  • 38.
    ©2014 Shintaro Hosoai 演算子とオーバーライド(2) 演算子対応メソッド名 演算子 対応メソッド名 ! e1 e1.operator_not() e1 == e2 e1.operator_equals(e2) - e1 e1.operator_minus() e1 != e2 e1.operator_notEquals(e2) + e1 e1.operator_plus() e1 === e2 e1.operator_tripleEquals(e2) e1 + e2 e1.operator_plus(e2) e1 !== e2 e1.operator_tripleNotEquals(e2) e1 – e2 e1.operator_minus(e2) e1 < e2 e1.operator_lessThan(e2) e1 * e2 e1.operator_multiply(e2) e1 > e2 e1.operator_greaterThan(e2) e1 / e2 e1.operator_divide(e2) e1 <= e2 e1.operator_lessEqualsThan(e2) e1 % e2 e1.operator_modulo(e2) e1 >= e2 e1.operator_greaterEqualsThan(e2) e1 ** e2 e1.operator_power(e2) e1 -> e2 e1.operator_mappedTo(e2) e1 += e2 e1.operator_add(e2) e1 .. e2 e1.operator_upTo(e2) e1 –= e2 e1.operator_remove(e2) e1 >.. e2 e1.operator_greaterThanDoubleDot( e2) e1 || e2 e1.operator_or(e2) e1 ..<e2 e1.operator_doubleDotLessThan(e2) e1 && e2 e1.operator_and(e2)
  • 39.
    ©2014 Shintaro Hosoai 演算子とオーバーライド(3) 演算子対応メソッド名 演算子 対応メソッド名 e1 => e2 e1.operator_equals(e2) e1 <= e2 e1.operator_notEquals(e2) e1 >>> e2 e1.operator_greaterThan(e2) e1 << e2 e1.operator_tripleEquals(e2) e1 <> e2 e1.operator_lessEqualsThan(e2) e1 >> e2 e1.operator_tripleNotEquals( e2) e1 ?: e2 e1.operator_greaterEqualsThan( e2) e1 <<< e2 e1.operator_lessThan(e2) e1 <=> e2 e1.operator_mappedTo(e2)