📜 ⬆️ ⬇️

From MUMPS to MSH

In the previous article I tried to tell the people about the merits of such a little-known programming language like MUMPS. But along with his merits, he also has disadvantages about which I would like to share in this article. Some commentators who bothered to look at this language by the way paid attention to them. In addition, I want to suggest ways to address these shortcomings in the new MSH language.

The first impression that MUMPS makes is that it is archaic. It was created quite a long time ago and being enshrined in the standard has changed little compared with its 2nd edition. In the MUMPS community, there is quite a strong rejection of changes to this language. But in implementations they are trying to introduce extensions to compensate for its shortcomings, although it is sometimes extremely unfortunate. But despite its flaws, the MUMPS ideology is very productive.
By and large, the main drawback of this language is the lack of objects and an event processing system. It is not object oriented. First, the reason, as always, lies in its history. At the time of its creation, object programming was not common. The language was immediately standardized, which prevented its fundamental change. Secondly, the inclusion in the language of objects is hampered by the absence of variables in the declaration language.
In short, objects need to be added to the language. In addition, I believe that a modern high-level programming language must necessarily include an advanced event handling system. Of all the languages ​​I know, only the assembler has event handling tools. Event processing methodology is widely used in programming practice, both in visual libraries (Delphi, GTK, and in others), and for building operating systems. Library-level operating systems have various event handling facilities. Event handling in MUMPS is extremely undeveloped and in fact comes down to error handling, although the ZTRAP team can create a custom event.
As a starting point for creating the MSH language, I didn’t take MUMPS by accident. This is the perfect language. He is in some sense perfect. There are no contradictions, unnecessary constructions. A small but powerful library of built-in functions of the language. Incredible language flexibility.
The main, but not the only advantage of this language is the organization and management of data. Description of the data is missing. Therefore, any variable can appear in different forms, depending on the context. In one context, it can be interpreted as a string, in the other as a number. The structure of any variable is a tree, but the variable can be simple. A variable can be located both in RAM and on any block device, even on another continent.
Presentation of data, both in RAM and on external media, is almost the same and therefore the data can be processed by the same means of the language. The language has an advanced data integrity system. That is, it is a fully functional distributed database. Specific implementations also have data logging and duplication systems. The language has built-in multitasking with synchronization tools. Indirect syntax and the Xecute command allow you to handle external commands coming from outside the program.

The first drawback is eliminated very simply. Since the language is fundamentally absent declarative, the declarative part of the description of the object is discarded and only the implementation of the object remains in the form of a standard module. And the point syntax is added to the language to refer to the properties of the objects. The name of the public property of the object is associated with the entry point in the module. To organize inheritance, we introduce an additional Extend command, in the arguments of which we enumerate all the ancestors of this class.
But the event-handling system must be fully developed. For this, event handling commands have been added to the MSH language:

1. EventCall - the command binds the processing program to the event,
2. EventWait - the team is waiting for the occurrence of a given event,
3. EventDelete - the command deletes the event,
4. EventTrap - the command generates an event.
')
These commands should be enough to handle events. Events can be systemic, they are those generated by the external environment. For example, asynchronous opening of the device or RunTime errors in the program. Events can also be generated by an application using the EventTrap command, then this is a custom event. The required parameters are passed to the event-handling program as arguments.

The remaining changes in the MSH language in comparison with MUMPS are not so fundamental, but nevertheless they should improve its capabilities.
Let's start with the localization of data. MUMPS adopted its own terminology for the designation of data scopes. Analogue of MUMPS globals in other programming languages ​​are data located in databases. The analogue of the MUMPS locales in the C language are global and automatic variables. By default, all MUMPS variables are global variables in C terminology. To create automatic variables using the terminology of C in MUMPS, there is a New command in two forms. The first form corresponds roughly to the declaration of variables in the C language. All variables listed in this command become automatic variables until the end of the subroutine. The second form of the New command in C has no analogues. This is the so-called exclusive form of the New command. In this case, all variables not listed in this command become automatic in the sense of C until the end of the execution of the subroutine. There are no concepts of global and automatic variables in MUMPS, they are all called locales. This state of affairs in MUMPS always strained me. It is inconvenient to include the New command in each routine to protect the variables. Therefore, I decided to abandon this method of data localization.
There are several variable scope areas in MSH.
1. Variables localized within a subroutine call,
2. Variables localized inside the job,
3. Variables localized within the application,
4. Variables located on external devices.

And as in MSH, as in MUMPS, there is no declaration of variables, to delimit the areas of visibility, we had to use the only known and proven method of the ancient BASIC by the variable prefix.
Variables localized within the application have the prefix %%.
Variables localized within the job have the prefix%.
Variables located on external devices have the prefix ^.
All other variables are localized within the subroutine call.
This allowed us to exclude the wonderful New team.

Now about the data structure. In MUMPS, one data structure for locales and globals is a tree. Variables can be indexed and non-indexed. But in the globals there is such a thing as a shortened link. Abbreviated link greatly complicates both the understanding of the program and its debugging. In addition, if an abbreviated reference is used in a subroutine, such a subroutine cannot be used to process local variables, which violates the integrity of the MUMPS language. Therefore, there is no abbreviated link in MSH. So that the MUMPS language does not lose flexibility, it contains such a very dubious construction as indirect syntax. Which allows you to use as a variable name another variable in which the name of the first variable is located. It sounds somewhat clumsy, but equally uncomfortable to use it. This construction of the language causes many complaints, so this construction is excluded in MSH. And in order not to lose the flexibility of the language, it was decided to abandon the name of the variable and leave only the index. The first index is interpreted as a variable name. Of course, the wooden data structure is very versatile. But it is certainly not optimal for access speed for simple, not indexed variables. Therefore, one more data structure has been added to MSH - a one-dimensional data array.

Let us turn to the commands of the language.
Arguments are separated from the command by a space. In MUMPS there are 2 types of syntactically different commands. In commands of the first type, the next command is separated from the previous one by a space. In these commands, spaces are significant and extra spaces are not allowed. Their presence leads to syntax errors. If there are no arguments in the command, then the command is followed by 2 spaces. Commands of the second type are completed with the end of the line. There are 3 such commands: For, If, Else. In fact, these commands are used in a block with other commands and therefore their syntax is different. In addition, these commands, unlike the commands of the first type, do not have the conditions for their execution. All this together leads to the fact that writing visual programs is inconvenient.
MSH uses a slightly different syntax strategy.
First, the end character of the command is entered; The space is stored as a separator between the command and the arguments, but their number now does not matter.
Second, the concept of block commands is introduced. A command of this type is the beginning of a block, and the end of a block is an End command. The command execution condition applies to all commands. The syntax becomes more uniform.
Lock commands.
In MUMPS, the lock command is used in 2 forms: for locking and unlocking. In MSH, the lock command is divided into read lock, write lock and unlock. In addition, system functions are used for timeout locks. Locks are mainly used to synchronize processes and synchronize access to data in different tasks. In MSH, synchronization of access to data on external devices and application-level data is performed at the language level and do not require additional use of lock commands.
The If command has become a block one and must be completed with either Else or End. This command has no arguments, and the condition for executing the command applies to the whole block. The Else command is used with the If command and can also have a run condition. Then this command becomes the ElseIf command. The Else command is block and must be completed with either the Else command or the End command. The Else team has no arguments.
Another block command is the For command. This command implements a loop. In terms of content, the For MSH command is close to the for command of the C language. The C command has 3 arguments. 1st argument loop initialization. In MSH, this argument is excluded from the For command. The necessary initialization of variables is performed before the loop with the Set command. The 2nd argument in C sets the end condition of the loop. In MSH, the end-of-cycle condition has been moved to the condition for executing the For and End commands. This made it possible to exclude the while loop commands and do while commands, since the loop command with no arguments implements these loops. The 3rd argument in the for C command. Changing the loop parameters is an argument to the For command in MSH.
In connection with the cycles in MUMPS there is one uncomfortable feature. Inside the loop, it can be completed using the Quit command. But the trouble is that the same command is used to complete the subprogram, and it is impossible to complete the subprogram within the loop. In MSH, the Break command is used as a loop termination command, and the Return command is used to complete the subroutine. Quit command is excluded.
The programming experience in MUMPS showed me that in 90% of cases the For command is used to organize tree traversal. And this is not the most convenient team. It requires additional requests for data. Therefore, 3 iterator commands and a tree traversal system function are introduced in MSH.
1. Next command - traversing one level of the tree from beginning to end,
2. Back command - traversal of one level of the tree from the end to the beginning,
3. Query command — traversing a tree node to its full depth.

MUMPS lacks such a useful command as Case. In MSH, it was added to Pascal notation, which seemed to me more successful than in C. In this case, the selection variable can be of any type. Case MSH is a block command and ends with an End command. Labels inside the command are localized inside the block.

There is no such thing as a constant in MUMPS, and this thing is very useful, so the Const command has been added to MSH.

To organize inheritance in MSH, use the Extend command.
In addition, the Include command is taken from C and allows you to link the program text from different pieces.

In MSH, the system for transferring parameters to subroutines and functions has been changed. In MUMPS, entry points to a subroutine and labels are distinguished by the fact that entry points sometimes have a list of formal parameters. But to call a subroutine for any label, and possibly for a label + offset does not interfere with anything, though it will not be possible to transfer the parameters in this case. That is, in general, the label from the entry point may be no different. This approach is somewhat not logical and ugly. In addition, the list of actual parameters fixes their number, which is not good. In C, we were forced to add the ability to transfer a variable number of actual parameters using crutches. I acted differently in MSH. There is no list of formal parameters in MSH. Subprograms and functions are accessed by labels in the module with the transfer of actual parameters in the traditional form. The actual parameters of the subroutine fall into a special array of arguments, the number of which is stored in the zero element of the array.

In addition, some operations have been added, the most significant of which is the selection operation in the syntax of the C language.

All this was done in order to create a modern, reliable, flexible programming language for information systems.

Next, I give a formal description of this language.
MSH Language Description
Content
1. Introduction
Purpose.
2. Language vocabulary
Alphabet
Comments
3. Operations
4. Constants
5. Variables
6. Expressions
7. Teams
8. Functions
9. Predefined properties.
10. Lists.
11. Module structure.
12. Objects.
13. Conclusion.

1. Introduction
purpose
Objective: - Reduce the maintenance time of the software life cycle.

Reducing development time is achieved by the following means:
- The language must be syntactically simple, concise and minimally possible.
- Language constructions should be unambiguous and not allow unusual use.
-A set of language commands should be sufficient to support all modern programming models.
- The language should be as flexible as possible. It is achieved by the absence of declaration of variables.

Reducing debugging time is achieved by the following means:
-Easy and clear programs.
-Minimum possible errors in the program.
-Programs must contain a minimum of lines.

Reducing the maintenance time is achieved by the following means:
-The reliability of the language.
-The language must have the means to ensure the integrity of the data.
-Minimum possible errors in the program.

None of the modern languages ​​is consistent with the goal. Now there is a large selection of different languages, each of which contains any ideas. But there are not so many ideas. I will try to use the most valuable ideas in the language.
To achieve maximum flexibility, a language must have certain properties; in particular, it should not be declarative. All declarative languages ​​immediately lose flexibility. Programs on them immediately swell in volume. The declarations of the variables themselves have no other meaning besides the help of the translator. The language should be focused on data manipulation and not contain tools for building dialogues with users. Tools building dialogues with the user must provide a specialized language HTML. The language should be focused on web development.
The language that best meets the goal is the MUMPS programming language. We take it as a basis. The last standard of this language is the standard of 1995. It will be the starting point.

2. Language vocabulary

Alphabet
The alphabet is a character set in UTF-8 encoding.

Comments
single line comment //
multiline comment / * * /

When describing a language, optional parameters are placed inside brackets <>

3. Operations
Operands can be any variables, constants and functions.
Unary operations:
'-' unary minus Sign of a negative number.
Result: Arithmetic type.
'~' NO logical operation
Result: integer 0 or 1
Binary operations:
Operations can be 1-2 character.
Arithmetic operations: Result Arithmetic type
'+' plus
'-' minus
'*' multiply
'**' exponentiation
'/' division
'\' division in the whole Result integer
'#' module numbers Result integer
Logical operations: Result integer 0 or 1
'&' operation AND
'|' operation OR
Comparison Operations: Result is an integer 0 or 1
'>' more
'<' less
'==' equals
'~ =' is not equal
'~>' no more
'~ <' no less
'> =' is greater than or equal to
'<=' is less than or equal to
'<>' is not equal
String operations: Result string of characters
'_' string concatenation
'_>' line follows
'_ <' line contains

Bitwise string operations:
'_ &' operation AND
'_ |' operation OR
'_ ^' exclusive operation OR
'_ ~' operation is NOT

Selection operation:
'?' - almost corresponds to the standard of the C language.
ExpYcl? ExpTrue: expFalse
expYcl selection condition,
expTrue-expression assigned when the condition
expFalse expression assigned when the condition is not met.

Built-in operations have the form of operations with the prefix `
Arg1 `name Arg2

4. Constants
Constants consist of name and value. Name is an identifier. Constant value
There are any number of alphanumeric characters in any languages. The constant value can be in quotes or in double quotes.In this case, any characters may appear inside the quotes.
Example of constant values: 123 ABC 15Ngsh '75 & 56 + "()" "" wq ^ erNG ""
5. Variables
There are no variable declarations in the language. A variable occurs when it is assigned a value. When accessing an undefined variable, an empty string is returned.
Variables can be both in RAM and in external memory. Variables in external memory have a prefix ^.
For example: ^ abc [15, gh8,42] abc- global name.

Variables in memory are separated by scope and storage structure.
1. Globali. Variables residing on external devices. The prefix of these variables is ^.
2. Task variables. They are common to all programs in the Job job. These variables have the prefix%
3. The remaining variables. They are visible only inside the Do block.
4. Pseudo-arrays. They have the prefix @.

The storage structure may be as follows:
1. Tree structure. Such variables appear as an arbitrary index structure enclosed in square brackets. Indices are separated by commas. Any index can be of any type. Number, string, etc. For example: ldb [abc, 125,5,9]
Indices in variables can be arbitrary expressions.
The name can use the predefined constant this. In this case, the closed properties of the object are addressed. Such a call is possible only inside a call to a method or property of an object.
For example:
[% this] .Age

2. The structure of a solid array.
This structure has one integer index. All elements of the array are located in a row. This structure is used for quick access to data.
The array index follows the $ sign.
For example: $ 25
Array indexing starts at 1. The zero element of the array is a service element and contains the index of the last element. Iterators ignore this item.

3. Pseudo-arrays.
Service information is transferred to them. Appeal to them corresponds to the appeal to the array.
The list of pseudo-arrays: the
prefix @ - the values ​​of the arguments passed to the function, the
prefix do @ the stack of subroutine calls for the current job, the
prefix job @ the stack of job calls for the application,
data prefix @ Do data block stack,
ind @ prefix index Do block block.

6. Expressions
Expressions are a combination of operands and operations. Operands can be expressions, then they are enclosed in brackets. Variable types are arbitrary. The result of the operation is uniquely determined by the operation. There are no priorities for operations.

7. Commands
Arguments in different teams may be different. The argument can consist of subfields separated either by a symbol = or a symbol:
For further explanations, we adopt the following conventions:
exp - prefix denoting expression
expYcl - expression defining the condition for executing the command
ref - prefix denoting a reference to a variable.
Prog - link to the program in the form .expLabel [expArg <, expArg>]
expMod - the expression whose value is the name of the module
expLabel - the expression whose value is a label in the module
expArg - whose expression is an argument. The argument is passed by value.

Time intervals are specified in microseconds 10e-6 seconds.

Declarative commands:
Extend, Constant, Include.
Declarative commands have the format:
CMD Arg <, Arg>;
CMD - command code.
Arg is a command argument.
Declarative commands are executed at the time of translation as they appear in the program source code. Their execution does not depend on the progress of the program.

Team Extend (Ext).
The command arguments are the ancestors of this module. The command is used to organize inheritance.
Extend expParent <, expParent>;
expParent- constant parent name for this module. As can be seen from the syntax, multiple inheritance takes place. The priority of choosing a parent is determined by the order in the inheritance list. The earlier the parent is found, the higher its priority.

Team Constant (Const).
Constant nameConst = valConst <, nameConst = valConst>;
nameConst- the name of a constant is an identifier and its length must not exceed 18 bytes,
valConst is the value of a constant. May consist of alphanumeric characters or any characters enclosed in quotes or double quotes.

Include command.
Include fileName <, fileName>;
fileName- the name of the inserted file. This command will be replaced by the contents of the listed files.

Execution commands:
Break, Back, Back1, Copy, Do, Else, End, Case, Loop, GoTo, If, Job, KiLL, LockW, LockR, LockUn, Move, Next, Next1, Query, Query1, Return, Set, TimeOut , Transaction, EventTrap, EventCall, EventWait, EventDelete, Open, Close, Write, Read.

Commands consist of:
- command code,
- optional command execution condition,
- mandatory space,
- optional arguments listed separated by commas.
The end of the command is marked with a semicolon. The command code is not case sensitive and can be abbreviated. The full command code can be expanded with any number of Latin characters or numbers. For example, the End command may be written as EndIf. The same applies to other teams.
The command execution condition is separated from the command code by? If the result of evaluating the execution condition is 0, then the command is not executed. If the result of evaluating the execution condition is not 0, then the command is executed.
Cmd <? ExpYcl> <Arg1 <, ArgN >>;

The command for evaluating the expression Set.
Set (S) - has the form:
Set <? ExpYcl> ref = exp <, ref = exp>;
S <? ExpYcl> ref = exp <, ref = exp>;
the variable ref is assigned the value of exp.

The command to delete data Kill.
Team KiLL (K).
Kill <? ExpYcl> ref <, ref>;
K <? ExpYcl> ref <, ref>;
The command deletes the descendants of the ref node and the node itself and the properties of the object.
There are also modifications of this command.
Deletes the data in the ref node.
KillD <? ExpYcl> ref <, ref>; KD <? ExpYcl> ref <, ref>;
Removes the children of the ref node.
KillN <? ExpYcl> ref <, ref>; KN <? ExpYcl> ref <, ref>;
Removes the properties of the ref node object.
KillP <? ExpYcl> ref <, ref>; KP <? ExpYcl> ref <, ref>;
Combinations of postfixes are possible. For example, it
deletes the data and properties of the ref node object.
KillDP <? ExpYcl> ref <, ref>; KP <? ExpYcl> ref <, ref>;
Removes data and descendants of the ref node.
KillDN<?expYcl> ref <,ref>; KN <?expYcl> ref <,ref>;

:
refFrom refTo
Copy<?expYcl> refTo=refFrom <,refTo=refFrom>;
refFrom refTo
Move<?expYcl> refTo=refFrom <,refTo=refFrom>;

.
LockW (LW).
LockW<?expYcl> expID <,expID>;
LW<?expYcl> expID <,expID>;
expID.

LockR (LR).
LockR<?expYcl> expID <,expID>;
LR<?expYcl> expID<,expID>;
expID.

LockUn (LU).
LockUn<?expYcl> expID <,expID>;
LU<?expYcl> expID <,expID>;
expID.

.

TimeOut .
TimeOut<?expYcl> expTime<,expTime>;
expTime — .

GOTO (G) .
GOTO<?expYcl> expMod.expLabel; G<?expYcl> expMod.expLabel;
.
GOTO<?expYcl> expLabel; G<?expYcl> expLabel;
expMod — .
expLabel — .

Do.
.
Do<?expYcl> <expMod.>expLabel< [<arg <,arg> >] >< ,<expMod.>expLabel< [<arg <,arg> > ] > >;

Job (J).
. Run Do.
Job<?expYcl> ref=<expMod.>expLabel< [<arg <,arg>> ] >< ,ref=<expMod.>expLabel< [<arg <,arg>> ] >;
ref- .

Return (Re) .
Return<?expYcl> expRet;
Re<?expYcl> expRet;
expRet- .

.
. END;

If (I).
If Else End. If End Else.

Else Else. Else Else End.
.
If?expYcl; I?expYcl;

Else<?expYcl;> E<?expYcl>;

END;
Else ElseIf, Else.
If :
If?expYcl;
comand…
< Else?expYcl; comand… >
< Else; comand… >
End;

Case.
. Pascal.
.
Case End.
<comandElse...>.

Case<?expYcl> expLabel;
<comandElse...>
Label: comand…
<Label: comand...>
End;

Try.
Try . .
Try<?expYcl> <Prog [arg<,arg>] >;
comand…
End;
. . , .

Transaction(Tr).
Transaction . . Job Job . End . =0, . . .
Transaction<?expYcl>;
comand…
End ;

.
Loop (L).
. . Loop 0 . End 0 .

Loop<?expYclFor>;
comand…
End<?expYclEnd>;

L<?expYclFor>;
comand…
End<?expYclEnd>;

expYclFor — .
expYclEnd — .

.
. .
* Next, Back Query. Next1, Back1 Query1:
. $$2 [[3]] $2 [3] . .
.

Next (N).
Next<?expYclEnd> refY<,refSaveInd>;
comand…
End;
N<?expYclEnd> refY<,refSaveInd>;
comand…
End;

refY — . .
RefSaveInd — . . .
, ':'
Next [4:],$1

Back (Ba).
Back<?expYclEnd> refY<,refSaveInd>;
comand…
End;
Ba<?expYclEnd> refY<,refSaveInd>;
comand…
End;

refY — .
RefSaveInd — . . .

Query (Q).
Query .
Query<?expYclEnd> refY<,refSaveInd>;
comand…
End;
Q<?expYclEnd> refY<,refSaveInd>;
comand…
End;

refY — .
RefSaveInd — . . .

.

.
Next1 (N1) .
Next1<?expYclEnd> refY,refSaveInd;

Back1 (B1) .
Back1<?expYclEnd> refY,refSaveInd;

refY — .
RefSaveInd — . . .

Query1 (Q1) .
Query1<?expYclEnd> refY,refSaveInd;

refY — .
RefSaveInd — . . .

Break (Br).
Break<?expYclFor>; Br<?expYclFor>;

.
EventTrap (EvT).
EventTrap<?expYcl> expName<(arg1<,argN> )> <,expName<(arg1<,argN> )>
EvT<?expYcl> expName<(arg1<,argN> )> <,expName<(arg1<,argN> )>
expName — . 18 .
arg — .
. .
.
.
, .

.
EventCall (EvC).
EventCall<?expYcl> expName=Prog<,expName=Prog>
EvC<?expYcl> expName=Prog<,expName=Prog>
expName — .
Prog — .
.

EventWait (EvW).
EventWait<?expYcl> expName<,expName>
EvW<?expYcl> expName<,expName>
. EventTrap. EventWait .

EventDelete(EvD).
EventDelete<?expYcl> expName<,expName>
EvD<?expYcl> expName<,expName>

.

. sys. EventTrap . usr.

:
sysJobEnd — , . .

.
EventTrap. . 1- . , . 2- , , .
sysRead — . 2- .
EventTrap .
sysOpenReadClose — .
EventTrap .

.
:
Write<?expYcl> pathFile;
pathFile — .
.

:
Read<?expYcl> pathFile;
pathFile — .
.

8. .
. . . . sys.
. !..

.
.
%Query(refArrInd,<expMod.>expLabel)
refArrInd – ,
expMod.expLabel – .
.

.
%LockR(exp,time)— ,
%LockW(exp,time)— ,
%LockSt(exp)—

exp —
18 .
18
:time - TimeOut (usleep)
ref=
0-
<0-
>0 —№ . .

Ini
%ReadIni(expFile,refYZL)
%WriteIni(expFile,refYZL)
%WriteIni(OUT,refYZL)
%WriteIni(WWW,refYZL)

%ReadTxt(expFile,refYZL)
%WriteTxt(expFile,refYZL)
%WriteTxt(OUT,refYZL)
%WriteTxt(WWW,refYZL)
expFile-
refYZL — .
:
OUT —
WWW —

.
%ReadDir(expFile,refYZL)
expFile-
refYZL — .

.
%ReadDirR(expFile,refYZL)
expFile-
refYZL — .

.
%CreateDir(expFile)
expFile-

.
%DeleteDir(expFile)
expFile-

.
%DeleteFile(expFile)
expFile-

.

.
:
%Comp(pathFile);
pathFile — .
MSH mvm.
=0 :
_, , .

.
Do .
expMod.expLabel( <expArg <,expArg>> )
.expLabel( <expArg <,expArg>> )
expLabel( <expArg <,expArg>> )
expMod — .
ExpLabel — ( )
expArg — .

9. .
.
.
%this — .
%idJob — ID .
%idDo — ID Do.
%idDiv — -.
%statDo — .
%statData — .
%isTr- . .
%Key — .
%Data — .
%nameMod — .

.

.%type -
.%byte —
.%size —
.%stat — .
.

.
.
.
StartInd- .
Count — .

1. Count startInd. Count 1:
.%GetStr(startInd <,Count> )
: [j1,j2]=[i1,i2,i3].%GetStr(5,3)
2. startInd
.%CodeStr(startInd)
: [j1,j2]=[i1,i2,i3].%CodeStr (5)
3. Count
.%PopStr(Count )
: [j1,j2]=[i1,i2,i3].%PopStr(2)
4. startInd
.%InsStr(startInd)
: [i1,i2,i3].%InsStr(7)=[j1,j2]
$2=[i1,i2,i3].%InsStr(7,[j1,j2])
5. Count :
.%SetStr( startInd <,Count> )
: [i1,i2,i3].%SetStr(4,3)=[j1,j2]
6. Count startInd
.%DelStr( startInd <,Count> )
eg:
[j1,j2]=[i1,i2,i3].%DelStr(5,2)
7. startInd startInd :
.%FindStr( subStr<,startInd> )
: .
eg:
[j1,j2]=[i1,i2,i3].%FindStr(ABC,2)
8. charSource charRepl charRepl charSource :
.%ReplStr(charSource<,charRepl> )
eg:
[j1,j2]=[i1,i2,i3].%ReplStr( ABC,123)

.
Count 1.
1. Count startInd, Count Count=1:
.%GetField(delimiter,startInd <,Count> )
eg:
[j1,j2]=[i1,i2,i3].%GetField( ',',5,3
2. :
.%PushField(delimiter)
eg
[i1,i2,i3].%PushField('.')=[j1,j2]
3. Count Count Count=1:
.%PopField( delimiter<,Count> )
eg
[j1,j2]=[i1,i2,i3].%PopField('AB',2)
4.
.%InsField(delimiter,startInd)
eg:
[i1,i2,i3].%InsField('/',7)=['-',j1,j2]
5. Count startInd
.%SetField( delimiter,startInd <,Count> )
eg
[i1,i2,i3].%SetField('-',4,3)=[j1,j2]

6. Count startInd
.%DelField( delimiter,startInd <,Count> )
eg
[j1,j2]=[i1,i2,i3].%DelField('-',5,2)

10. .
. . .
c :
ref={exp<,exp>}
ref — .
exp — .
Query.

ref .
[ref]
. . :
[Af,[B,2],125,$1,5.6]
[B,2] $1 .

:
1. Count startInd
.%GetList(startInd <,Count> )
[j1,j2]=[i1,i2,i3].%GetList(5,3)
2.
.%PushList
eg
[i1,i2,i3].%PushList=[j1,j2]
3. Count
.%PopList(Count )
.%PopList — 1
eg
[j1,j2]=[i1,i2,i3].%PopList(2)
4. startInd
.%InsList(startInd)
eg
[i1,i2,i3].%InsList( 7)=[j1,j2]
5. Count startInd
.%SetList( startInd <,Count> )
eg
[i1,i2,i3].%SetList(4,3)=[j1,j2]
6. Count startInd
.%DelList(startInd <,Count> )
eg
[j1,j2]=[i1,i2,i3].%DelList(5,2)

11. .
. . . . . ';'.

12. .
() . 18 . . '.'. Extend. .TYPE (). () Org Arg.
:
Set [An,12].TYPE=Org; Arg :
[An,12].Arg=[An,12].Arg+1;

13. .
. . . .

: . Email: misha_shar53@mail.ru
.

Source: https://habr.com/ru/post/241369/


All Articles