ZeScript гэта невялікі, просты, які ўбудоўваецца, і струменевай-скрыптовая мова з C-падобны сінтаксіс. Гэта пабочны прадукт пры пошуку мову сцэнарыяў для ZeGraph. З шматлікіх выдатных моў там, Lua і C-Talk былі выкарыстаныя. Абодва маюць свае заслугі, але не маюць магчымасці, якія робяць гэта натуральна назваць функцыямі або ўжываць аператараў да аб'ектаў карыстальнікаў. Напрыклад, пераазначэння аператараў для карыстацкіх аб'ектаў быў абмежаваны ў Lua, і пакуль яшчэ можа быць зроблена ў C-Talk, ён не мае механізму Lua для выкліку функцый, што яны з'яўляюцца метадамі аб'екта карыстальніка.
ZeScript лёгкі і хуткі - усё выкананыя, уключаючы стандартныя бібліятэкі, складае каля 500 К. мова просты ў вывучэнні таксама, асабліва для тых, хто з вопытам C.
ZeScript лёгка пашырыць. Крыніц для дынамічных бібліятэк з EXPAT ( expat.cpp ), SQLITE ( sqlite.cpp ), MySQL ( mysql.cpp ), NetCDF ( netcdf.cpp ), HDF ( hdf.cpp ), а wxWidget ( wdget.cpp ) кажуць самі за сябе. Вы можаце не толькі дадаць прымітыўных функцый для карыстацкіх аб'ектаў, вы можаце таксама прызначыць прымітыўныя функцыі па-новаму вызначыць аператара паводзін для карыстацкіх аб'ектаў. Зыходны код для бібліятэкі матрыца паказвае, як зрабіць аператары працуюць на дадзеных масіў сімвалаў, кароткія, цэлага, якія плавалі і двойчы, і паказана, як вызначыць __get і __set функцый для доступу да матрыцы каштоўнасцяў праз доступ да масіву выразаў ZeScript.
ZeScript падтрымлівае прымітыўных тыпаў аб'ект Null, Boolean, цэлыя, сапраўдныя радкі, Хэш-масіў, і карыстальнік. Пасля тых, структураваны тып аб'екта, т. е. класа, могуць быць вызначаны для інкапсуляцыі зменных прымітыўных аб'ектаў і функцый сцэнараў.
ZeScript выкарыстоўвае re2c сфармаваць яе маркерам сканер, у выніку хуткага разбору скрыпту.
ZeScript зменныя з'яўляюцца дынамічнымі і ствараюцца або абнаўляюцца задання. Тып аб'екта, які ўяўляе пераменная можа быць нулявым, лагічныя, цэлыя, сапраўдныя радкі, Хэш-масіў, клас або аб'ект карыстальніка. Аб'ект карыстальніка змяшчае паказальнік створаныя прымітыўнай функцыі карыстальніка. Напрыклад,
/************************************************* ***** * Як і C, ўтрыманне паміж / * і * / з'яўляюцца каментарамі * І доўга каментары, як гэты, можа быць прадоўжаны * На некалькі радкоў. * * Як паказана ніжэй, любая рэч пасля / / становіцца * Адзін каментар. ************************************************** ****/ = 135 / / цэлае тыпу = 0x07FF / / шаснаццатковае эквівалента 2047 = 135,0; / / У цяперашні час рэальны тып б = TRUE; / / б гэта лагічны тып з = няпраўду; / / з-лагічны тып D = E = F = NULL; / / г, д, е ўстаноўлены на нулявой S = "Я люблю ZeScript."; / / С радковага тыпу
Выраз павінна сканчацца падабенства-калонка ";".
Унутрана лагічнае сапраўднага эквівалентна цэламу ліку ад 1 і ілжывых 0. Рэальнае падвойнае лік з якая плавае і цэлы лік 64-біт. Радкі, гэта значыць тэкст паміж парай "або" знакі, могуць утрымліваць сімвалы C бегчы. У "радок у двукоссях \" можа выкарыстоўвацца для ўключэння 'у радок, але ў тым ліку "не патрабуюць экранавання. Тое ж самае ставіцца да "двукоссях. Так як \ выкарыстоўваецца для ўцёкаў, яна павінна быць прадстаўлена ў выглядзе \ \ у радок. Радок можа займаць некалькі радкоў, але такая доўгая радок не павінна перавышаць 8 Кб.
Хэш-масіва, створанага аператарам [] змяшчае калекцыю пар ключ-значэнне, з якіх ключавым з'яўляецца радок, і значэнне можа быць аб'ект любога тыпу.
a = ["name"="Jiye Zeng", "Age"=5]; //, is used to separate array items
Калі ключ не паказаны, радок эквівалент пазіцыі індэкса, лічачы ад нуля, будзе выкарыстоўвацца, напрыклад,
= [1, 3, 5]; / / Гэтак жа, як = ["0" = 1, "1" = 3, "2" = 5];Заўважым, што ["імя "=...,...] гэта не тое ж самае імя [=...,...]: той час як" імя "ў былым з'яўляецца радок, імя ў апошні зменнай, якія могуць прадстаўляць радок або любы іншы тып аб'екта.
Выразы прысвойвання устанаўлівае або вызначае зменную. Злева ад "=" атрымае копію правоў, калі права з'яўляецца адным з відаў нулявы, лагічнага, цэлага, рэальнай, радок або масіў, і атрымаць спасылку на права на клас і, калі карыстач уводзіць __copy функцыя вызначана для класа або зарэгістраваны як прымітыўная функцыя для аб'екта карыстальніка. У гэтым выпадку, __copy функцыя будзе выклікана з карыстачом або аб'ект класа ў якасці першага параметру і аб'ект у выніку правага выразы ў якасці другога параметру.
Выраз стварэння масіва могуць быць выкарыстаны для некалькіх прысвойвання:
[a, b, c] = [1, 2, 3]; // a=1, b=2, c=3 [a, b, c] = [1, 2]; // a=1, b=2, c=null [a, b, c] = [1, "a"=2, 3]; // a=1, b=null, c=3 [a, b, c] = 1; // a=1, b=1, c=1
Прызначэнне на некалькі зменных працуе наступным чынам:
Гэтая функцыя прадастаўляе зручны спосаб атрымання некалькіх значэнняў вяртаецца ў выглядзе масіва з функцыі.
Выразаў expr.expr і выраз [выраз] называюцца доступу масіва ці доступу да сябра.
Аб'екты ў масіве могуць быць устаноўлены або будуць атрыманы праз свае ключы, напрыклад,
a.addr = "123-стрыт"; / / абнавіць ці ўсталяваць пару ключ-значэнне з масіва ["Адрас"] = "123-стрыт", / / тое ж, што і вышэй Коммерсанта = a.addr / / б цяпер "123-стрыт" Коммерсанта = ["адрас"]; / / тое ж, што і вышэй
Калі ключ элемента цэлы лік, радок эквівалент цэлага выкарыстоўваецца ў якасці ключа, напрыклад,
= [1, 3, 5]; / / Стварэнне масіва Коммерсанта = [0]; / / б змяшчае 1 [1] = 10; / / цяпер змяшчае [1, 10, 5]
Доступ да масіву вяртае нуль, калі масіў не мае ключа.
Калі масіў утрымоўвае толькі лікавыя значэння і ўсе ключы пазіцыйнай, то гэта будзе разглядацца як набор лікаў аператараў і функцый, напрыклад,
= [1, 2,1, 3,5, 5]; + +; / / Масіва ў цяперашні час мае [2, 3.1, 4.5, 6]; Коммерсанта = грэх (); / / б-масіў змяшчае [граху (2), грэх (3,1), грэх (4,5), грэх (6)]
Некалькі ключоў, таксама дапушчальныя ў атрымання і ўстаноўкі значэнняў:
= [10, 11, 12, 13, "прывітанне"]; / / ствараем масіў Коммерсанта = [1,4]; / / б становіцца масіў, які змяшчае [11, "прывітанне"] [0,1] = [100200]; / / цяпер змяшчае [100,200,12,13, "прывітанне"] [2] = б; / / цяпер змяшчае [100200, [11, "прывітанне"], 13, "прывітанне"]
Шматразовае прызначэнне да элементаў масіва працуе наступным чынам:
Выраз доступу да масіву [...] можа быць выкарыстана для атрымання і ўсталёўкі радок знакаў, напрыклад,
S = "ABCDEFG"; / / ствараем радок = З [1]; / / зьмяшчае "B" з [0] = / / Зараз з зьмяшчае "BBCDEFG" B = S [1,3]; / / У "BD"; з [1,3] = ""; / / цяпер з зьмяшчае "BACAEFG" з [1,3] = "XYZ"; / / цяпер з зьмяшчае "BXCYEFG" з [5] = 90; / / цяпер з зьмяшчае "BXCYEZG";
Доступ падрадок праз выраз доступу масіў працуе наступным чынам:
Для аб'екта карыстальніка, выраз
a = user.member;
Будзе тэлефанаваць __get прымітыўная функцыя зарэгістраваных для гэтага карыстальніка тыпу з аб'екта карыстальніка ў якасці першага параметру і радкі аб'екта "сябра" ў якасці другога параметру. І
user.member = выраз;
Будзе тэлефанаваць __set прымітыўныя функцыі з аб'ектам карыстальніка ў якасці першага параметру, радок аб'ект "сябра" ў якасці другога параметру, і аб'ект у выніку правага выразы ў якасці трэцяга параметру.
Акрамя таго,
= Карыстальнік [EXR,...];
Будзе тэлефанаваць __get прымітыўныя функцыі з аб'ектам карыстальніка ў якасці першага параметру варта аб'ектаў у выніку выразы ўнутры []. І
Карыстальнік [выраз,...] = выраз;
Будзе тэлефанаваць __set прымітыўныя функцыі з аб'ектам карыстальніка ў якасці першага параметру варта аб'ектаў у выніку выразы ўнутры [], а аб'ект з правага выразы ў якасці апошняга параметру.
І * можа выкарыстоўвацца ўнутры [], каб прадстаўляць нулявыя. Гэта значыць і [я, *] эквівалентна і [я, нулявы]. Звернецеся да API спасылкі для атрымання дадатковай інфармацыі.
Дыяпазон выразы, такія як: бы альбо: B: C, вырабляе масіў з двух або трох лічбаў, напрыклад,
r1 = 1:10; / / r1 з'яўляецца [1, 10] r2 = 1:10:2; // r2 is [1, 10, 2]
Калі дыяпазон выраз выкарыстоўваецца ў стварэнні масіва, то гэта азначае для запаўнення масіва з нумарамі ад першага чысла на другое. Прырашчэнне кроку роўная 1 для: бы выгляд і трэці нумар: Ь: з формай. Напрыклад,
a = [1:11]; // a is [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
І калі такі выраз выкарыстоўваецца як індэкс ў атрыманні доступу да элементаў масіва, радкі, і аб'ект карыстальніка, гэта значыць, каб атрымаць элементы з нумарамі ад першага чысла на другое з крокам трэці, і ўсё лікі, у выніку дыяпазон выраз павінна быць цэлымі лікамі. Нулявым ці *, могуць быць выкарыстаны для замены второго ліку для абазначэння апошняга азначніка. Напрыклад,
b = a[0:*:2]; // b is [1, 3, 5, 7, 9, 11]
Дыяпазон выраз можа выглядаць як правы аперанд варыянт выразы:
= B> C? б +1: В + С;
Гэта эквівалентна
калі (б> с)
= Коммерсанта + 1;
яшчэ
= В + С;
У дадатак да сваіх нармальным вынікам, калі аперанд цэлае або рэчыўны, аператара распаўсюджваецца на нуль, радок і масіў наступным чынам:
Для аб'екта класа, клас павінен вызначаць "__ дадаць", каб прыняць аператара, і для аб'екта карыстальніка, аператара функцыя павінна апрацоўваць аператара, калі аператар, як чакаецца, праца над карыстачом тыпу.
ZeScript падтрымлівае тры цыкла структур (у той час, рабіць, па):
n = 0;
while (n >= 0) {
n++;
if (n == 50) continue; // skip this number
if (n > 100) break; // jump out of the loop
csv(n);
}
/////////////////////////////////////
n = 0;
do {
n++;
if (n == 50) continue; // skip this number
if (n > 100) break; // jump out of the loop
csv(n);
} while (n >= 0);
/////////////////////////////////////
for (i = 0; i < 100; i++) {
if (i == 10) continue; // Skip the rest when i=0
csv(i);
}
І тры кіравання / перанакіраванне структур (калі, камутатар, перайсці):
a = 1;
b = 2;
c = 3;
/////////////////////////////////////
if (a > 0) {
csv(a);
// more expressions may follow.
}
/////////////////////////////////////
if (a > b) csv(a); // {} is optional if there is only one expression
else csv(b); // after "if" or "else".
/////////////////////////////////////
if (a > b) {
csv(b);
}
else if (a > c) {
csv(c);
}
else {
csv(a);
}
/////////////////////////////////////
switch (flag) {
case C1:
csv(C1);
break;
case C2:
csv(C2);
goto 100;
default:
csv("default");
}
case 100:
....
Аргумент выключальнік і выразаў пасля справы і перайсці павінна вызначаць лік ці радок. Выпадку знакі, дзе выключальнік пачынае выкананне ў адпаведнасці са значэннем перамыкача аргумент. Выраз па змаўчанні з'яўляецца абавязковым ўнутры перамыкача блока.
Выпадку таксама можа быць выкарыстаны ў функцыі або модуля для перанакіравання перайсці. Выраз перайсці вышэй зробіць выкананне скачкоў у выпадку 100.
ZeScript код ў файл уключае ў сябе модуль. Вы можаце вызначаць зменныя і функцыі ў модулі. Модуль можа імпартаваць іншыя модулі для доступу да функцыі, вызначаныя ў іх, напрыклад,
////////// hello.zs //////////////////
n = 100;
Функцыя прывітанне (а, бы, у)
{
csv(a, b, c, n, "Hello!");
}
////////// main module ///////////////
import hello;
hello(1, 2, 3); // call function in hello.zs
Імпарт каманда працуе як макрас ўключыць у C. Паколькі ён апрацоўваецца ZeScript падчас кампіляцыі, ён можа быць размешчаны ў любым месцы скрыпту. Вы таксама можаце выкарыстоўваць імпарт (), каб загрузіць модуль дынамічна. Хоць імпартаванага модуля, каманда імпарту захоўваецца на працягу ўсяго існавання імпарцёрам, імпартавана модуль, функцыю імпарту выдаляецца пры яго вяртанні зменнай з вобласці бачнасці.
Калі модуль імя любога аператара знакаў, імя модуля павінна быць у двукоссях. Напрыклад,
import "hellor.zs"; // import hello.zs import "my-module/say-hello"; // імпарт сказаць-hello.zs ў маім-модуль падкаталог
Імпарт шукае скрыпт файлы ў бягучай дырэкторыі, а затым у падкаталогах Бібліятэка, CLS, або CGI; ці іншых уключаючы падкаталогі ўнутры ў ZeScript віртуальнай машыне.
Як паказана вышэй, функцыя аб'яўлена ключавым словам "функцыі", а затым імя функцыі, аргументы ў дужках (), і выразы у {}. Аргумент можа мець значэнне па змаўчанні. Калі значэнне па змаўчанні аргументу не ўстаноўлены, нулявы мяркуецца няяўна. У выкліку функцыі, параметры перадаюцца аргументы ў адпаведных пазіцыях, але калі заданне выраз выкарыстоўваецца, у выніку аб'ект права будзе ўсталяваная на аргумент, што мае тое ж імя, што і левая.
функцыя f1(a, b=1, c=2.1, d="hi!", e=[1, 2, 3])
{
csv(a, b, c, d, e);
}
f1(); // call f1 with no argument
// output: null, 1, 2.000000, hi!, [0=1, 1=2, 2=3]
f1(a=1, 2, e="Hi!", d=[1, 2, 3]); // call f1 with positional and assignment arguments
// output: 1, 2, 2.000000, [0=1, 1=2, 2=3], Hi!
Аб'екты Null, Boolean, цэлыя, сапраўдныя і струннага перадаюцца функцыі па значэнні; і аб'ектаў масіва, клас, і карыстач перадаюцца па спасылцы.
Выклік функцыі сцэнара итеративно дапускаецца:
функцыя Ack(m, n)
{
if (m == 0) {
return n + 1;
}
if (n == 0) {
return Ack(m - 1, 1);
}
return Ack(m-1, Ack(m, n - 1));
}
csv(Ack(3, 4));
Функцыя можа быць аб'яўлена ўнутры іншай функцыі. У гэтым выпадку ўсярэдзіне функцыі можа атрымаць доступ да прыватнай зменныя бацькоўскай функцыі. Напрыклад,
функцыя f(a, b)
{
a += 10;
// more expressions here
ff(); // call function defined internally
function ff()
{
csv(a, b); // access variable of parent function
}
}
У пэўным сэнсе, модуль як ананімную функцыю.
Прымітыўныя функцыі дынамічнай бібліятэкі можа быць загружаны ў глабальнай табліцы прымітыўныя функцыі ZeScript любым модулем. Напрыклад:
load("my.dll"); // load primitive functions in my.dll
hello(); // suppose hello() is a primitive function in my.dll
Прымітыўныя функцыі папярэднічаюць функцый сцэнарыя пры выкліку функцыі. Гэта значыць, калі загружаецца прымітыўных мае тое ж імя, як функцыі сцэнара, прымітыўная функцыя будзе выкарыстоўвацца.
Выраз:
object.method(...);
выклікае функцыю, якая належыць аб'ект.
Калі аб'ект тыпу класа (больш дыскусій пазней), скрыпт функцыю з імем метад павінен быць абвешчаны ў класе.
Калі аб'ект любога іншага тыпу, прымітыўная функцыя з імем метаду, павінны быць зарэгістраваныя для дадзенага тыпу (гл. Даведнік па API ) і бібліятэку, якая змяшчае функцыі павінны быць загружаны. Прымітыўная функцыя заўсёды будзеце атрымліваць аб'ект у якасці першага параметру. Таму што вы можаце выкарыстоўваць тое ж імя функцыі для розных тыпаў аб'ектаў, выраз, як і выклік метадаў класа ў C + +.
ZeScript укараніла механізмы для выкліку функцыі скрыпту ад прымітыўнай функцыі. Глядзіце API спасылкі для дэталяў.
Клас ўяўляе сабой структураваны аб'ект, абвешчаны на ўзроўні модуля і павінен быць створаны перад выкарыстаннем. Клас, як адмысловы модуль ў тым, што на ўзроўні класа зменныя даступныя ўнутры функцый, але абаронены ад функцый іншых модуляў або класаў. Розніца ў тым, што кожны асобнік класа мае свой уласны кантэкст зменнай у той час як модуль мае толькі адну зменную кантэкст.
Вельмі Асаблівасцю класа ZeScript ў тым, што аператар-функцыі могуць быць вызначаны для апрацоўкі такога выразы, як В +. Напрыклад,
class Point {
cx = 0; // initialize class level variables
cy = 0;
cz = 0;
function set(x, y, z)
{
::cx = x; ::cy = y; ::cz = z;
}
function add(x, y, z)
{
cx += x; cy += y; cz += z;
}
function csv()
{
csv(cx, cy, cz);
}
// this is a operator function for +
function __add(a, b)
{
c = new Point;
c.cx = a.cx + b.cx;
c.cy = a.cy + b.cy;
c.cz = a.cz + b.cz;
return c;
}
}
a = new Point; // create a point
a.set(10, 10, 10); // call a's function
b = new Point;
b.cx += 5; // access b's variable directly
c = a + b; // because a is a class, call a's
// operator function for "+".
// c is now a class object.
c.csv();
Для бінарных аператараў, Z-скрыпт званкоў аператару функцыі больш высокага рангу ў парадку нулявы, лагічнага, цэлага, рэальнай, радкі, масівы, клас, і карыстальнік. У прыведзеным вышэй прыкладзе, калі гэты лік і б клас, Ь 'ы __add () функцыя будзе выклікана з б у якасці першага аргументу, а ў якасці другога.
Клас можа перавызначыць аператар-функцый пералічаныя ніжэй:
__neg(a) <==> -a __not(a) <==> !a __cmpl(a) <==> ~a __incr(a) <==> a++ __decr(a) <==> a-- __mul(a,b) <==> a + b __add(a,b) <==> a + b __div(a,b) <==> a - b __div2(a,b) <==> b - a __mod(a,b) <==> a % b __mod2(a,b) <==> b % a __sub(a,b) <==> a - b __sub2(a,b) <==> b - a __le(a,b) <==> a <= b __lt(a,b) <==> a < b __ge(a,b) <==> a >= b __gt(a,b) <==> a > b __eq(a,b) <==> a == b __ne(a,b) <==> a != b __and(a,b) <==> a & b __or(a,b) <==> a | b __xor(a,b) <==> a ^ b __nn(a,b) <==> a && b __oo(a,b) <==> a || b __rsh(a,b) <==> a >> b __lsh(a,b) <==> a << b __mul_eq(a,b) <==> a *= b __div_eq(a,b) <==> a /= b __mod_eq(a,b) <==> a %= b __add_eq(a,b) <==> a += b __sub_eq(a,b) <==> a -= b __rsh_eq(a,b) <==> a >>= b __lsh_eq(a,b) <==> a <<= b __and_eq(a,b) <==> a &= b __or_eq(a,b) <==> a |= b __xor_eq(a,b) <==> a ^= b
Усе аператары ZeScript можа быць перагледжаны, каб дзейнічаць на любых тыпах аб'ектаў карыстальнікаў. Калі ласка, звярніцеся да старонцы API і зыходныя коды для матрыцы бібліятэкі аб тым, як гэтага дамагчыся.
load("matrix.dll");
A = matrix("double", 10, 10); // 10x10 double matrix
A.fill(1, 1); // A contains numbers from 1 to 100
A *= 10; // A contains numbers from 10 to 1000;
A += 1; // A contains numbers from 11 to 1001;Зменнай, вызначанай у модулі даступная толькі выразы, функцыі і класы, абвешчаныя ў гэтым модулі; зменнай, вызначанай у класе даступны толькі для выказвання і функцыі, вызначаныя ў гэтым класе, і зменнай, вызначанай у функцыі, даступныя толькі для выразаў і функцый, абвешчаных у гэтай функцыі.
Кожны модуль мае свой уласны кантэкст зменнай, кожны асобнік класа мае ўласную зменную кантэкст, і кожная функцыя выконваецца ў сваёй уласнай зменнай кантэксту.
Калі выраз спрабуе атрымаць значэнне з зменнай, ён пачынае шукаць у функцыі, класа ці модуля, які адносіцца да зменнай, а затым, калі не атрымалася, пачынае шукаць у гаспадара функцыі або класа. Але калі:: аператар выкарыстоўваецца, пачатковы пошук пачынаецца ў гаспадара.
Калі выраз спрабуе ўсталяваць значэнне зменнай і зменнай не існуе ў функцыі, класа ці модуля, што выраз належыць, новая пераменная будзе вызначацца на мясцовым узроўні. Але калі:: аператар выкарыстоўваецца выраз спрабуе знайсці зменную ўладальніка функцыі або класа, які вызначае зменную і задаць ёй значэнне.
Наступны прыклад паказвае канцэпцыю бачнасці зменнай:
a = 0;
b = 0;
function f()
{
a = 10;
::a = 100;
csv(a, b, ::a);
ff();
function ff()
{
a = 1;
::b = -1;
csv(a, ::a, ::b);
}
}
csv(a, b);
f();
csv(a, b);
У выпадку выкарыстання ZeScript ў серверы, яна не можа быць пажадана, каб дазволіць любому ZeScript памылка часу выканання, каб перапыніць службы сервера. Паспрабуй злавіць асаблівасцю ZeScript можа быць выкарыстаны, каб злавіць і працэс паведамленні пра памылку, напрыклад,
try {
a++;
...
}
catch (error) {
cgi_error(error)
}
addpath break case catch class continue default do else false for function goto if import new null return switch true try while
Выкарыстоўвайце + +, а = + 1, *= б а = а + б, і так далей для павышэння эфектыўнасці. Паспрабуйце паўторна выкарыстоўваць імёны зменных, так што ўспаміны, выдзеленых на нявыкарыстаных пераменная будзе неадкладна вызвалены.