Slice 語言定義
在這里,我們提供Slice語言乍炉。 Slice(Specification Language for Ice)是一種將對象接口與其實(shí)現(xiàn)分離的基本抽象機(jī)制绢片。Slice在客戶端和服務(wù)器之間建立一個(gè)描述應(yīng)用程序使用的類型和對象接口的合同。該描述與實(shí)現(xiàn)語言無關(guān)恩急,因此客戶端是否以與服務(wù)器相同的語言編寫并不重要杉畜。
即使盡管Slice是一個(gè)首字母縮略詞,它的發(fā)音是一個(gè)音節(jié)衷恭,像a slice of bread
Slice定義是由編譯器為特定的實(shí)現(xiàn)語言編譯的此叠。編譯器將與語言無關(guān)的定義轉(zhuǎn)換為特定語言的類型定義和api。開發(fā)人員使用這些類型和API來提供應(yīng)用程序功能并與Ice進(jìn)行交互随珠,用于各種實(shí)現(xiàn)語言的翻譯算法被稱為語言映射灭袁。目前,Ice定義了C ++窗看,Java茸歧,C#,Python显沈,Objective-C软瞎,Ruby和PHP的語言映射。
因?yàn)镾lice描述的是接口和類型(但不是實(shí)現(xiàn))拉讯,它是純粹的聲明性語言;不能在Slice中編寫可執(zhí)行的語句涤浇。
Slice定義側(cè)重于對象接口,這些接口支持的操作以及可能由操作引發(fā)的異常魔慷。此外只锭,Slice還提供了對象持久化的特性。這需要相當(dāng)多的支持機(jī)制院尔;特別是蜻展,大部分的Slice內(nèi)容都涉及到數(shù)據(jù)類型的定義喉誊。這是因?yàn)橹挥性赟lice中定義了類型,才能在客戶端和服務(wù)器之間交換數(shù)據(jù)纵顾。您不能在客戶端和服務(wù)器之間交換任意的C ++數(shù)據(jù)伍茄,因?yàn)樗鼤茐腎ce的語言獨(dú)立性。但是施逾,您總是可以創(chuàng)建一個(gè)Slice類型的定義幻林,它對應(yīng)于您想要發(fā)送的c++數(shù)據(jù),然后可以傳輸Slice類型音念。
Slice 語言的作用如圖
Slice 源文件 Slice Source Files
文件命名
包含Slice定義的文件必須以 .ice結(jié)尾沪饺。例如,clock.ice是一個(gè)有效的文件名闷愤。其他文件擴(kuò)展被編譯器拒絕整葡。
對于不區(qū)分大小寫的文件系統(tǒng)(如DOS),可以將文件擴(kuò)展名寫成大寫或小寫讥脐,因此Clock.ICE是合法的等恐。對于區(qū)分大小寫的文件系統(tǒng)(如Unix)乒疏,Clock.ICE是非法的。(擴(kuò)展必須是小寫的。)
文件格式
Slice是一種自由格式的語言膀篮,因此你可以使用空格账忘、橫向和縱向制表符晃洒、換行符安排你的代碼布局垒玲。Slice中語義和定義的布局沒有關(guān)聯(lián)。
Slice文件可以是ASCII文本文件岖免,或者在每個(gè)文件的開頭用字節(jié)順序標(biāo)記(BOM)使用utf - 8字符編碼岳颇。但是,Slice標(biāo)識符僅限于ASCII字母和數(shù)字;非ASCII字母只能出現(xiàn)在注釋和字符串文字中颅湘。
預(yù)處理
Slice支持與c++相同的預(yù)處理指令话侧,因此您可以使用諸如# include和宏定義之類的指令。但是闯参,Slice許可證#只包含在文件開頭的指令瞻鹏,在任何切片定義之前。
如果你使用# include指令鹿寨,那么保護(hù)他們新博,以防止雙重包含文件是一個(gè)好主意:
用#pragma也可以得到相同的結(jié)果
檢測Ice 版本
在在Ice 3.5中,Slice編譯器定義了預(yù)處理器宏__ICE_VERSION__释移,可以用來實(shí)現(xiàn)Ice版本的兼容
檢測Slice編譯器
在Ice 3.5中叭披,每個(gè)Slice編譯器定義它自己的宏寥殖,這樣您就可以為某些語言映射定制您的Slice代碼玩讳。下面的宏由各自的編譯器定義:
例如 .NET開發(fā)人員可能會選擇避免對結(jié)構(gòu)成員使用默認(rèn)值涩蜘,因?yàn)槟J(rèn)值的存在會改變結(jié)構(gòu)到類的結(jié)構(gòu)的c#映射:
詞法規(guī)則 Lexical Rules
注釋(支持c和c++兩種風(fēng)格的注釋)
關(guān)鍵字
Slice使用一些關(guān)鍵字,必須用小寫字母拼寫熏纯。例如同诫,class和dictionary是關(guān)鍵字,必須這樣拼寫樟澜。這個(gè)小寫規(guī)則有兩個(gè)例外:Object和LocalObject是關(guān)鍵字误窖,必須大寫。
標(biāo)識符
標(biāo)識符以字母字符開頭秩贰,后面跟著任意數(shù)量的字母字符或數(shù)字霹俺。在標(biāo)識符中也允許有以下限制:
標(biāo)識符不能以下劃線開始或結(jié)束
標(biāo)識符不能包含多個(gè)連續(xù)下劃線
標(biāo)識符get_account_name是合法的,但這些是非法的 _account毒费、account_或get__account丙唧。
Slice標(biāo)識符僅限于字母字符的ASCII范圍,不能包含非英語字母觅玻,如?想际。(支持非ascii標(biāo)識符將使將Slice映射到缺少該特性支持的目標(biāo)語言非常困難。)
大小寫敏感
標(biāo)識符是大小寫不敏感的溪厘,但是必須保持拼寫一致胡本。例如TimeOfDay和TIMEOFDAY在同一個(gè)命名空間中是一樣的。但是畸悬,Slice強(qiáng)制拼寫一致侧甫。一旦你定義了一個(gè)標(biāo)識符之后,你必須自始至終的拼寫這個(gè)標(biāo)識符的大小寫蹋宦,否則闺骚,編譯器會認(rèn)為這是非法的標(biāo)識符。這條規(guī)則之所以存在妆档,是因?yàn)檫@樣就允許Slice可以映射到大小寫敏感的語言也能映射到大小寫不敏感的語言僻爽。
是關(guān)鍵字的標(biāo)識符
你可以使用其他語言的關(guān)鍵字來定義Slice標(biāo)示符,例如贾惦,switch可以用來作為Slice標(biāo)識符胸梆,但是也是Java和 C plus plus 的關(guān)鍵字。Slice語言映射中針對每一種語言都定義了映射規(guī)則來處理這樣的標(biāo)識符须板。例如碰镜,Slice把switch映射為 C plus plus 的_cpp_stitch和Java的_switch。但不建議這樣使用习瑰,您應(yīng)該至少嘗試避免常見的關(guān)鍵字绪颖。Slice標(biāo)識符如self、import和while絕對不是一個(gè)好主意甜奄。
轉(zhuǎn)義的標(biāo)識符
可以使用Slice關(guān)鍵字作為標(biāo)識符柠横,通過使用反斜杠來預(yù)先確定關(guān)鍵字:(但也不推薦這樣使用窃款,應(yīng)盡量避免)
保留的標(biāo)識符
Slice將Ice以及以Ice開始的所有標(biāo)識符作為保留的標(biāo)識符。例如牍氛,Icecream將會被認(rèn)為是非法的標(biāo)識符晨继。
同時(shí),Slice還將以以下標(biāo)識符為后綴的標(biāo)識符視為保留的標(biāo)識符:
Helper
Hodler
Prx
Ptr
保留它們搬俊,主要是為了防止在生成代碼時(shí)發(fā)生沖突紊扬。
模塊Modules
Slice提供模塊來保持整體結(jié)構(gòu)的條理性
模塊是強(qiáng)制性的,所有定義必須在模塊中 Modules are Mandatory
在全局范圍內(nèi)的定義是被禁止的唉擂,因?yàn)樗鼈儠?dǎo)致一些實(shí)現(xiàn)語言(例如Python餐屎,它沒有真正的全局作用域)的問題。
重啟模塊 Reopening Modules
模塊可以重新開放:
重新打開的模塊對于更大的項(xiàng)目是有用的:它們允許您在多個(gè)不同的源文件中分割一個(gè)模塊的內(nèi)容玩祟。這樣做的好處是啤挎,當(dāng)開發(fā)人員對模塊的一部分進(jìn)行更改時(shí),只有依賴于更改部分的文件需要重新編譯(而不是必須重新編譯使用該模塊的所有文件)卵凑。
模塊的映射 Module Mapping
模塊映射到每個(gè)編程語言中相應(yīng)的范圍構(gòu)造庆聘。(例如,對于c++和c#勺卢,Slice模塊映射到命名空間伙判,而對于Java,它們映射到包黑忱。)這允許您使用適當(dāng)?shù)腸++使用或Java導(dǎo)入聲明宴抚,以避免在源代碼中使用過多的標(biāo)識符。
Ice 模塊 The Ice Module
Ice運(yùn)行時(shí)的api甫煞,除了少數(shù)無法用Ice表達(dá)的特定語言的調(diào)用菇曲,都是在Ice模塊中定義的。換句話說抚吠,大部分的Ice API實(shí)際上表示為Slice定義常潮。這樣做的好處是,Slice定義就足以為所有受支持的語言定義Ice運(yùn)行時(shí)間的API楷力。然后喊式,各自的語言映射規(guī)則確定每個(gè)實(shí)現(xiàn)語言的每個(gè)Ice API的確切形狀。
基本數(shù)據(jù)類型 Basic Types
Slice中內(nèi)置了一些基本數(shù)據(jù)類型
所有基本類型(除了byte類型)在服務(wù)器和客戶端之間傳遞時(shí)萧朝,數(shù)據(jù)類型都根據(jù)實(shí)際情況在變化岔留。例如:一個(gè)long類型的值在從一臺little-endian機(jī)器傳遞到bit-endian機(jī)器時(shí)會發(fā)生位變換。類似的检柬,string在從EBCDIC發(fā)往ASCII時(shí)也是進(jìn)行翻譯的献联,也許string的字符的尺寸也發(fā)生了變化,因?yàn)椴皇撬械臋C(jī)器都使用8位的字符。實(shí)際上里逆,這些變化對于程序員來說都是透明的进胯,而且會嚴(yán)格按照需要來變化。
整數(shù)類形(integer types)
Slice提供了如下的整數(shù)類型:
short运悲,16位
int,32位
long项钮,64位
不過班眯,這些類型在某些機(jī)器上會映射到更寬的原生類型。需要注意的是那些無符號類型Slice并沒有提供烁巫。因?yàn)闊o符號類型影射到那些沒有原生的無符號類型的語言相當(dāng)困難署隘,例如Java。
浮點(diǎn)數(shù)類型(floating-point types)
浮點(diǎn)數(shù)類型遵循IEEE的規(guī)范亚隙。如果一個(gè)實(shí)現(xiàn)語言么有支持IEEE的浮點(diǎn)數(shù)格式磁餐,Ice運(yùn)行時(shí)會將浮點(diǎn)數(shù)值轉(zhuǎn)換為原生浮點(diǎn)數(shù)表示。
字符串(strings)
Slice字符串使用Unicode字符集阿弃。唯一的不能出現(xiàn)在字符串中的字符就是零字符诊霹。
Slice沒有null字符串的概念。這是因?yàn)閚ull字符串很難映射到不直接支持null字符串概念的語言上渣淳,例如Python脾还。不要設(shè)計(jì)依靠一個(gè)null字符串來表示“不在那里”的語義的接口。如果你需要表示可選的串入愧,可以通過使用類鄙漏,字符串的序列,或者一個(gè)空的字符串來表示null字符串棺蛛。
布爾類型(booleans)
布爾類型的值只能由false和true怔蚌。如果語言映射時(shí)有原生布爾類型,語言映射就會使用該類型旁赊。
Byte類型(bytes)
Slice定義byte是一個(gè)至少8位的桦踊,在地址空間中傳遞時(shí)保證不會發(fā)生變化的類型。保證不發(fā)生變化就允許交換二進(jìn)制數(shù)據(jù)终畅,而這些數(shù)據(jù)不會被篆改钞钙。其他的Slice類型都會在傳遞過程中會被改變表達(dá)形式。
自定義數(shù)據(jù)類型 User-Defined Types
枚舉(Enumerations)
這個(gè)定義引入了一個(gè)名為水果的類型声离,它本身就是一種新的類型芒炼。Slice保證枚舉器的值從左到右增長,默認(rèn)情況下术徊,第一個(gè)枚舉器的值為0本刽,后續(xù)枚舉器的值順序遞增。
Slice枚舉器符號進(jìn)入封閉命名空間范圍,因此以下是非法的:
下面的示例展示了如何從不同的范圍引用枚舉器
Slice不允許空的枚舉子寓。
自定義枚舉器值 Custom Enumerator Values?
Slice允許你為枚舉器分配自定義值
自定義值必須是唯一的和非負(fù)的暗挑,并且可以引用整數(shù)類型的Slice常量。如果沒有為枚舉器指定自定義值斜友,那么它的值就是大于前面的枚舉器的值炸裆。在上面的例子中,橙色的值為8鲜屏。
枚舉值的最大值與int的最大值(2(31次方)- 1)相同烹看。
Slice不需要將自定義枚舉值聲明為遞增順序:
但是注意,當(dāng)聲明順序和枚舉器的數(shù)值次序之間不一致時(shí)洛史,比較操作的行為可能會因語言映射而有所不同惯殊。因此推薦在自定義枚舉值時(shí)也按照遞增順序排列
結(jié)構(gòu)(Structures)
Slice支持包含一個(gè)或多個(gè)任意類型的命名成員的結(jié)構(gòu),包括用戶定義的復(fù)雜類型也殖。例如:
結(jié)構(gòu)中不能出現(xiàn)結(jié)構(gòu)定義土思,例如下面的代碼是錯誤的:
這條規(guī)則適用于一般情況:類型定義不能嵌套(除了用于支持嵌套的模塊)。這條規(guī)則的原因是嵌套類型定義可能難以實(shí)現(xiàn)一些目標(biāo)語言忆嗜,即使是可實(shí)現(xiàn)的己儒,極大地使范圍解析規(guī)則復(fù)雜化。對于規(guī)范語言捆毫,例如Slice址愿,嵌套的類型定義是不必要的——您可以始終將上面的定義寫如下(這也是風(fēng)格上的清潔):
您可以為具有以下類型的數(shù)據(jù)成員指定一個(gè)默認(rèn)值:
An integral type (byte, short, int, long)
?A floating point type (float or double)?
string?
bool
enum
序列(Sequeces)
序列是可變長度的元素集合
一個(gè)序列可以是空的——也就是說,它可以不包含任何元素冻璃,或者它可以將任何數(shù)量的元素都保存到平臺的內(nèi)存限制中响谓。
序列可以包含本身序列的元素。這種安排允許你創(chuàng)建列表的列表:
序列用于建模各種集合省艳,如向量娘纷、列表、隊(duì)列跋炕、集合赖晶、包或樹。(取決于應(yīng)用程序來決定順序是否重要;通過丟棄順序辐烂,序列充當(dāng)一個(gè)集合或包遏插。)
使用序列來定義model中的可選字段。
字典(Dictionaries)
字典是一個(gè)從鍵類型到值類型的映射纠修。
例如:
上面的定義創(chuàng)建了一個(gè)名為employeemap的字典胳嘲,它達(dá)到了從employee編號到一個(gè)包含有employee詳細(xì)信息的結(jié)構(gòu)的映射。
字典key和value的允許類型
字典的關(guān)鍵類型不需要是整數(shù)類型扣草。例如了牛,我們可以用下面的定義來翻譯一周的日子:
服務(wù)器實(shí)現(xiàn)將負(fù)責(zé)初始化該映射颜屠,并與鍵值對monday - montag、tuesday - dienstag等進(jìn)行初始化鹰祸。
字典的值類型可以是任何類型的甫窟。但是,字典的關(guān)鍵類型僅限于以下類型之一:
Integral types (byte, short, int, long, bool)?
string
?enum?
Structures containing only data members of legal key types
其他復(fù)雜類型蛙婴,如字典和浮點(diǎn)類型(float和double)不能用作鍵類型粗井。復(fù)雜類型是不允許的,因?yàn)樗鼈兪棺值涞恼Z言映射變得更加復(fù)雜街图,并且浮點(diǎn)類型是不允許的浇衬,因?yàn)榭鐧C(jī)器邊界的值的具象變化會導(dǎo)致定義不明確的等式語義。
常量 Constants and Literals
Slice 允許你用以下類型定義常量
An integral type (bool, byte, short, int, long)?
A floating point type (float or double)
string?
enum
布爾常量
boolean常量只能用true和false的關(guān)鍵詞來初始化台夺。(你不能用0和1來表示false和true径玖。)
整形常量
整數(shù)常量可以用十進(jìn)制痴脾、八進(jìn)制或十六進(jìn)制表示颤介。
請注意,如果將byte解釋為一個(gè)數(shù)字而不是一個(gè)位模式赞赖,您可能會得到不同語言的不同結(jié)果滚朵。例如,對于c++前域,byte映射到unsigned char辕近,而對于Java,byte映射到byte匿垄,這是一個(gè)符號類型移宅。
注意,后綴表示long且無符號的常量(l,L,u,U, used by C++)是非法的:
整數(shù)的值必須在其常量類型的范圍內(nèi)椿疗,如內(nèi)置的基本類型表中所示;否則編譯器將發(fā)出診斷漏峰。
浮點(diǎn)型常量
浮點(diǎn)常數(shù)使用 C++ 的語法,只是你不能使用 l 或 L 后綴以指示擴(kuò)展的浮點(diǎn)常數(shù);然而届榄,f 和 F 則是合法的 (但被忽略)浅乔。
浮點(diǎn)常量必須在常量類型的范圍內(nèi)(float或double);否則,編譯器會發(fā)出診斷铝条。
字符型常量
字符串文本支持與c++相同的轉(zhuǎn)義序列
請注意靖苇,Slice沒有空字符串的概念
Null字符串根本不存在于Slice中,在Ice平臺中的任何地方都不能作為一個(gè)字符串的合法值班缰。這個(gè)決定的原因是贤壁,在許多編程語言中都不存在null字符串。
除了C和c++之外埠忘,許多語言使用字節(jié)數(shù)組作為內(nèi)部字符串表示芯砸。在這種語言中萧芙,null字符串不存在(并且很難映射)。
常數(shù)表達(dá)式
常數(shù)定義也可以指另一個(gè)常數(shù)假丧。對于兩個(gè)常量來說双揪,具有相同的Slice類型并不是必需的,但是現(xiàn)有常量的值必須與定義的常量類型一致
DEFAULT_SIZE常量是合法的包帚,因?yàn)樗哂信cSIZE相同的類型渔期,并且SHORT_SIZE是合法的,因?yàn)镾IZE(500)的值在Slice short類型的范圍內(nèi)渴邦。但是疯趟,BYTE_SIZE是非法的,因?yàn)镾IZE的值超出了byte類型的范圍谋梭。