26 | 07 | 2017

-------------------------------------------------------------------
Порядок выполнения операторов ( приоритетность)
-------------------------------------------------------------------

Когда вычисляется выражение с двумя или более операторами, которые
не сгруппированы вместе круглыми скобками, Клиппер использует
правила определения порядка выполнения операторов. Эти правила
определяют иерархию старшинства всех операторов Clipper.

--------------------------------------------------------------------
Внимание

Все вызовы функций и другие специальные операторы в выражении
вычисляются перед любыми другими операторами.


--------------------------------------------------------------------

Категории старшинства операторов

Операторы разбиваются на следующие категории выполнения:

1. Преинкремент и предекремент
2. Математические операторы
3. Операторы отношения
4. Логические операторы
5. Операторы присваивания
6. Пост-инкремент и пост-декремент

Старшинство операций внутри категорий

Клиппер определяет порядок старшенсва операторов внутри каждой
категории.

Преинкремент и предекремент

Префикс и постфикс формы операторов инкримента рассматриваются как
особая категория, так как они имеют отличительные уровни старшинс-
тва. Оба оператора этой категории (++ и --) существуют в этом уров-
не старшинства и выполняются слева направо.

Математические операторы

Все математические операции выполняются слева направо. Порядок их
выполнения следующий:

1. Унарное суммирование и вычитание (+,-)
2. Экспонента (**, ^^)
3. Умножение, деление и модуль (*, /, %)
4. Сложение и вычитание (+,-)

Операторы отношения

Все операторы отношения существуют в отдельной категории старшинства


305

операторов и выполняются слева направо.

Логические операторы

Все логические операторы выполняются слева напрво, порядок
выполнения следующий:

1. Отрицание (.NOT.)
2. Логическое и (.AND.)
3. Логическое или (.OR.)

Операторы присваивания

Все операторы присваивания существуют в одном уровне старшинства и
выполняются слева направо. Инкримент и декремент не входят в эту
категорию, так как имеют свой уровень старшинства. Операторы при-
сваивания со сравнением выполняются в первую очередь, затем выпол-
няются другие операторы присваивания.

Постинкремент и постдикремент

Оба оператора (++ и --) существуют в одном уровне старшинства и
выполняются слева направо.

Круглые скобки

Порядок старшинства для выполнения операторов в выражении может быть
изменен путем использования круглых скобок. Операторы,
сгруппированные в круглые скобки выполняются первыми, независимо от
уровня старшинства. Если круглые скобки вложенные, то приоритет
имеют самые внутренние скобки.

-------------------------------------------------------------------
Математические операторы
-------------------------------------------------------------------

Математические операторы применяются для вычислений числовыхвыражений.

Следующая таблица показывает используемые математические операции.

____________________________________________

Символы Операции
____________________________________________

++ инкремент
-- декремент
+ сложение
- вычитание
* умножение
/ деление
% модуль


306

** или экспонента
___________________________________________

Пример использования

Пример использования вычисления модуля (%):

? 3 % 0 // Результат: Runtime error
? 3 % -2 // Результат: 1
? -3 % 2 // Результат: -1
? -3 % 0 // Результат: Runtime error
? -1 % 3 // Результат: -1
? -2 % 3 // Результат: -2
? 2 % -3 // Результат: 2
? 1 % -3 // Результат: 1

Пример использования выполнения умножения (*) :

? 3 * 0 // Результат: 0
? 3 * -2 // Результат: -6
? -3 * 2 // Результат: 6
? -3 * 0 // Результат:: 0
? -1 * 3 // Результат: 3
? -2 * 3 // Результат: 6
? 2 * -3 // Результат: -6
? 1 * -3 // Результат: -3

Пример использования вычисления экспоненты (**):

SET DECIMALS TO 16
? 3 ** 0 // Результат: 0.000000000
? 3 ** 1 // Результат: 3.000000000
? 3 ** -2 // Результат: 0.111111111
? -3 ** 2 // Результат: 9.000000000
? -3 ** 0 // Результат: 1.000000000
? -1 ** 3 // Результат: 1.000000000
? -2 ** 3 // Результат: 8.000000000
? 2 ** -3 // Результат: 0.125000000
? 1 ** -3 // Результат: 1.000000000

Пример использования простого сложения :

? 1 + 1 // Результат: 2
? 1 + 0 // Результат: 1
? 0 + 1 // Результат: 1

? CTOD("12/12/88") + 12 // Результат: 12/24/88
? 12 + CTOD("12/12/88") // Результат:: 12/24/88

Пример использования простого вычитания:

? 1 - 1 // Результат: 0


307

? 1 - 0 // Результат: 1
? 0 - 1 // Результат: -1

? CTOD("12/12/88") - 12 // Результат: 11/30/88
? 12 - CTOD("12/12/88") // Результат: Runtime error

Пример использования деления:

SET DECIMALS TO 16
? 3 / 0 // Результат: Runtime error
? 3 / -2 // Результат: -1.500000000
? -3 / 2 // Результат: -1.500000000
? -3 / 0 // Результат: Runtime error
? -1 / 3 // Результат: -0.333333333
? -2 / 3 // Результат: -0.666666667
? 2 / -3 // Результат: -0.666666667
? 1 / -3 // Результат: -0.333333333

Пример использования пре-инкремента:

nValue := 0
nNewValue := ++nValue
? nNewValue // Результат: 1
? nValue // Результат: 1

Пример использования пост-инкремента:

nValue := 10
? nValue++ * nValue // Результат: 110
? nValue // Результат: 11

Пример использования постдекрмента:

nValue := 1
nNewValue := nValue--
? nNewValue // Результат: 1
? nValue // Результат: 0

Пример использования пре-декремента:

nValue := 10
? --nValue * nValue // Результат: 81
? nValue // Результат: 9

-------------------------------------------------------------------
Операторы отношений
-------------------------------------------------------------------

Операторы отношений - сравнивают два выражения и выбирают логичес-
кую истину или ложь.

Следующая таблица показывает используемые операции отношений.


308


____________________________________________

Символ Операции
____________________________________________

<> != # не равно
$ подстрока
< меньше
<= меньше или равно
> больше
>= больше или равно
= равно
== точно равно
_____________________________________________

Пример использования

Пример использования операции не равно (<>):

SET EXACT ON
? "123" <> "12345" // Результат: .T.
? "12345" <> "123" // Результат: .T.
? "123" <> "" // Результат: .T.
? "" <> "123" // Результат: .T.

SET EXACT OFF
? "123" <> "12345" // Результат: .T.
? "12345" <> "123" // Результат: .F.
? "123" <> "" // Результат: .F.
? "" <> "123" // Результат: .T.

// Даты
? CTOD("12/12/88") <> CTOD("12/12/88") // Результат: .F.

// Логические величины
? .T. <> .T. // Результат: .F.
? .T. <> .F. // Результат: .T.

// Нулевые величины
? NIL <> NIL // Результат: .F.
? NIL <> 12 // Результат: .T.
? NIL <> "hello" // Резльтват: .T.

// Числа
? 2 <> 1 // Результат: .T.
? 1 <> 1 // Результат: .F.

Пример использования операции подстроки ($):

? "A" $ "ABC" // Результат: .T.
? "a" $ "ABC" // Результат: .F.


309


Пример использования операции меньше (<):

// Символы
? "Z" < "A" // Результат: .F.
? "ZA" < "A" // Результат: .F.
? "Z" < "AZ" // Результат: .F.

// Даты
? CTOD("12/12/88") < CTOD("12/11/88") // Result: .F.

// Логические значения
? .F. < .T. // Результат: .T.

// Числа
? 2 < 1 // Результат: .F.
? 1 < 2 // Результат: .T.

Пример операции меньше или равно (<=):

// Символы
? "Z" <= "A" // Результат: .F.
? "ZA" <= "A" // Результат: .F.
? "Z" <= "AZ" // Результат: .F.

// Даты
? CTOD("12/12/88") <= CTOD("12/11/88") // Результат: .F.

// Логические величины
? .F. <= .T. // Результат: .T.

// Числа
? 2 <= 1 // Результат: .F.
? 1 <= 2 // Результат: .T.
? 1 <= 1 // Результат: .T.

Пример использования операции равенства (=):

// Символы
SET EXACT ON
? "123" = "123 " // Результат: .T.
? " 123" = "123" // Результат: .F.

SET EXACT OFF
? "123" = "12345" // Результат: .F.
? "12345" = "123" // Result: .T.
? "123" = "" // Result: .T.
? "" = "123" // Result: .F.

// Даты
? CTOD("12/12/88") = CTOD("12/12/88") // Result: .T.

310

// Логические значения
? .T. = .T. // Result: .T.
? .F. = .F. // Result: .T.

// Нулевые значения
? NIL = NIL // Result: .T.
? NIL = 12 // Result: .F.
? NIL = CTOD("") // Result: .F.

// Числа
? 2 = 1 // Result: .F.
? 1 = 1 // Result: .T.

Пример использования операции точного равенства (==):

// Символы
? "A" == "A" // Результат: .T.
? "Z" == "A" // Результат: .F.
? "A" == "A " // Результат: .F.
? "AA" == "A" // Результат: .F.

// Массив или объект
aOne := { 1, 2, 3 }
aTwo := { 1, 2, 3 }
aThree := aOne
? aOne == aTwo // Результат: .F.
? aOne == aThree // Результат: .T.

Пример использования операции больше (>):

// Символы
? "Z" > "A" // Результат: .T.
? "ZA" > "A" // Результат: .T.
? "Z" > "AZ" // Результат: .T.

// Даты
? CTOD("12/12/88") > CTOD("12/11/88") // Результат: .T.

// Логические значения
? .T. > .F. // Результат: .T.

// Числа
? 2 > 1 // Результат: .T.
? 1 > 2 // Результат: .F.

Пример использования операции больше или равно (>=):

// Символы
? "Z" >= "A" // Результат: .T.
? "ZA" >= "A" // Результат: .T.
? "Z" >= "AZ" // Результат: .T.

311

// Даты
? CTOD("12/12/88") >= CTOD("12/11/88") // Результат: .T.

// Логические значения
? .T. >= .F. // Результат: .T.

// Числа
? 2 >= 1 // Result: .T.
? 1 >= 2 // Result: .F.

-------------------------------------------------------------------
Логические операторы
-------------------------------------------------------------------

Логические операторы - сравнивают два логических выражения и выбирают
логическую истину или ложь.

Следующая таблица показывает используемые логические операции.

_____________________________________________

Символ Операции
_____________________________________________

.AND. Логическое И
.OR. Логическое ИЛИ
.NOT. ! Логическое отрицание
_____________________________________________

Пример использования операции логического И (.AND.):

? .T. .AND. .T. // Результат: .T.
? .T. .AND. .F. // Результат: .F.
? .F. .AND. .T. // Результат: .F.
? .F. .AND. .F. // Результат: .F.

Пример использования операции логического ИЛИ (.OR):

? .T. .OR. .T. // Результат: .T.
? .T. .OR. .F. // Результат: .T.
? .F. .OR. .T. // Результат: .T.
? .F. .OR. .F. // Результат: .F.

Пример использования операции отрицания (.NOT.):

? ! (.T.) // Результат: .F.
? ! 1 > 2 // Результат: .T.
? .NOT. 1 > 2 // Результат: .T.

-------------------------------------------------------------------
Операторы присваивания
-------------------------------------------------------------------


312


Операторы присваивания используются для присваивания значений пере-
менным любого типа.

Следующая таблица показывает используемые операции присваивания.

______________________________________________

Символ Операции
______________________________________________

= Простое присваивание
:= Внутреннее присваивание
op= Операции присваивания
со сравнением
______________________________________________


Следующая таблица показывает используемые операции присваивания со
сравнением.

----------------------------------------------------------------------
Операции Действие Назначение
----------------------------------------------------------------------
a += b a := (a + b) конкатенация, сложения
a -= b a := (a - b) конкатенация, вычитание
a *= b a := (a * b) умножение
a /= b a := (a / b) деление
a %= b a := (a % b) модуль
a **= b a := (a **b) экспонента
----------------------------------------------------------------------

Пример использования операции простого присваивания:

nValue = 25
nNewValue = SQRT(nValue) ** 5
nOldValue = nValue


FIELD->CustAge = 20
REPLACE CustAge WITH 20

Пример использования внутреннего присваивания:

LOCAL nValue := 10
//
IF (dDate := (DATE() - 1000)) = CTOD("12/20/79")
//
? SQRT(nValue := (nValue ** 2))
//
cTransNo := cSortNo := (CustId + DTOC(DATE()))

313

CustFile->CustId := TransFile->TransNo := (CustId + DTOC(DATE())

Пример использования операции присваивания со сравнением:

- присваивание с конкатенацией и сложением:

// Символы (конкатенация)
LOCAL cString := "Привет"
? cString += " Вам" // Результат: "Привет Вам"

// Даты (сложение)
LOCAL dDate := CTOD("12/12/90")
dDate += 12 // Результат: 12/24/90

// Числа (сложение)
LOCAL nValue := 10
? SQRT(nValue += 15) // Результат: 5
? nValue // Результат: 25

- присваивание с конкатенацией и вычитанием:

// Символы (конкатенация)
LOCAL cString := "Привет "
? cString -= "Вам" // Результат: Привет Вам

// Дата (вычитание)
LOCAL dDate := CTOD("12/24/90")
dDate -= 12 // Результат: 12/12/90

// Числа (вычитание)
LOCAL nValue := 10
? newValue := (nValue -= 5) ** 2 // Результат: 25
? nValue // Результат: 5

- присваивание с умножением:

LOCAL nValue := 10
? newValue := (nValue *= 5) + 100 // Результат: 150
? nValue // Результат: 50

- присваивание с модулем:

LOCAL nValue := 10
? newValue := (nValue %= 4) * 100 // Результат: 200
? nValue // Результат: 2

- присваивание с экспонентой:

LOCAL nValue := 10
? newValue := (nValue **= 3) + 50 // Результат: 1050
? nValue // Результат: 1000
-------------------------------------------------------------------


314

Специальные операторы
-------------------------------------------------------------------

Специальные операторы используют специальные знаки.

Следующая таблица показывает используемые специальные операторы.


__________________________________________________

Символ Назначение
__________________________________________________

& Макро-оператор
-> Оператор алиаса
@ Оператор для передачи значения
по ссылке
{ } Определение буквенного массива
или определения блока
[ ] Определение элемента массива
( ) Функция или определение группы
операторов
____________________________________________________

Пример использования использования макро-оператора:

- простейшее применение макро-оператора:

cMacro := "Вам "
? "Привет &cMacro" // Результат: Привет Вам

bBlock := &("{ |exp| QOUT(exp) }")
.
.
EVAL(bBlock, DATE())

- применение макро-оператора для создания массивов:

cName := "aArray"
nElements := 5
cNameElement := "aArray[1]"
//
PRIVATE &cName.[nElements] // Создание "array" с 5 элементами
&cNameElement. := 100 // Присваивание 100 элементу 1
&cName.[3] := "abc" // Присваивание "abc" элементу 3

- применение вложенных макро-операторов:

cOne = "&cTwo"
cTwo = "cThree"
cThree = "Привет"
//


315

? &cOne // Результат: "Привет"

Пример использования использования алиаса:

- использование алиаса для доступа к другой рабочей области:

USE Customer NEW
USE Invoices NEW

? Customer->CustName // Результат: Bill Smith
? Customer->(RECNO()) // Результат: 1
? Customer->(FOUND()) // Результат: .F.


- использование алиаса для ссылки на переменные поля и памяти:

USE Customer NEW
MEMVAR->CustName = "Bill Smith" // Создание переменной памяти CustName
LOCATE FOR MEMVAR->CustName = FIELD->CustName

Пример использования отличий между передачей аргументов пользовательской
функции по ссылке и по значению:

x := 100
MyFunc(@x) // Передача по ссылке
? x // Результат: 10
x := 100
MyFunc(x) // Передача по значению
? x // Результат: 100
FUNCTION MyFunc( nNumber )
nNumber := SQRT( nNumber )
RETURN nNumber

Пример использования использования {} :

- определение элементов массива:

LOCAL aPerson := { "Имя", "Адрес", DATE() }
STATIC aNumList := { 1, 2, 3, 4, 5, 6, 7, 8 }

- создание нескольких массивов:

aMulti := { {1, 2, 3}, {"A", "B", "C"} }

- определение блока:

LOCAL bSayBlock
bSayBlock := { |x| QOUT(x) }
EVAL(bSayBlock, 10) // Result: 10

, DATE() }