The SDL to CHILL Translator, sdl2chill, translates your SDL system into a semantically equivalent CHILL program ready for compilation and linking using ETRI CHILL or Samsung CHILL SDEs, as the case may be. In this chapter, the descriptions apply to both CHILL subsets, except where noted.
Please refer to the SDE documentation for descriptions of the respective CHILL compilation systems.
The translation from SDL to CHILL is based on a mapping scheme in which the basic concepts of SDL such as system structure, communication, behavior, actions and data are directly mapped into matching CHILL constructs of program structuring, concurrent processing, communication, actions and data. By this scheme SDL signals are mapped to CHILL signals and concurrency is implemented by utilizing the language inherent concurrency of CHILL as provided by the underlying operating system, CROS1.
The CHILL code generated from an SDL system, may be viewed as a CHILL module interfaced to via signals. This makes it easy to plug in an SDL system as an application program part anywhere in your CHILL software structure.
The application area for sdl2chill is development and maintenance of real-time application systems. By using sdl2chill, the CHILL program generated for your system will be efficient, reliable, easily readable and open for interfacing and interoperability with other software.
The application area for sdl2chill is development and maintenance of software for real-time application systems. sdl2chill has been implemented to maximize the user benefits of the ITU languages SDL and CHILL by combining the capabilities of SDT and CROS.
The CHILL program generated from your SDL specified system by using sdl2chill, will be efficient, reliable, easily readable and open for interfacing and interoperability with other software.
In this part of the manual, the usage of sdl2chill for generating application systems is described. When it comes to detailed information on the functionality and usage of the SDE tools and the SDT tools to be used together with sdl2chill, this is described in the respective SDE manuals for Samsung and ETRI CHILL and the Telelogic Tau User's Manual, respectively.
During development and the succeeding maintenance of your system, the combined functional power of SDT, sdl2chill and the CHILL SDE is fully available and you may conveniently design, generate, simulate, test and real-time test your application on a host computer before possibly recompiling, linking and downloading to dedicated target hardware.
Concurrent real-time execution, communication and timing as implemented by sdl2chill, are directly based on services provided by CROS.
The CHILL code generated by sdl2chill is prepared for distributed execution by support for CROS initial signal. This allows your programs to communicate by means of CHILL (and thus also SDL) signals in a distributed environment where programs may reside on different nodes in an heterogeneous network.
To facilitate generation of CHILL source code from SDL specifications or descriptions, the SDT Analyzer contains an SDL parser, an SDL semantic checker, and the sdl2chill translator.
To obtain an executable program that behaves according to an SDL description, you input the SDL description into the SDT Analyzer, which contains the sdl2chill translator, using the Make dialog in the Organizer (see Make). If the SDL description is syntactically and semantically correct a CHILL program and a Makefile2 is generated. This will presumably compile the program using the chosen CHILL compiler and link to form an executable program. See Figure 489.
As indicated above, sdl2chill contains two components:
sdl_support
, which implements run-time support for SDL constructs not mapped directly to in-line CHILL code. This applies e.g. to handling of the Charstring, Real, Time and Duration sorts.
Figure 489 : The production of a CHILL executable program
|
After running make
, a CHILL program generated by sdl2chill, can (just like any other executable program) be started from an operating system shell by typing the name of the file containing the executable program.
You can find more details on creating and executing a CHILL program in the following sections:
To create the CHILL source(s), use the SDT Analyzer and its built-in sdl2chill translator for creating a program expressed in CHILL source code. This operation is started from the Make dialog in the Organizer (see Make). The program may be partitioned to one or more CHILL compilation units.
There are two steps that you must take to create an executable CHILL program and run it from SDT. Both must be performed from the UNIX shell:
A CHILL program can only be generated for a complete SDL system. The CHILL source code that constitutes the program can, however, be partitioned to several compilation units (files). This means that a local change in an SDL unit, for example a process diagram, requires regeneration and recompilation of CHILL code for that unit only. For the other unchanged units the existing object files can then be reused in the link operation to form a new executable program.
Note: The Makefile includes all CHILL files in the current directory: the call format used by sdl2chill under UNIX is: chmf *.ch <#WITH directive files> |
By default, the SDE tool chmf will be invoked. This may be overridden using the environment variable CHMF
under UNIX. You may let this define a tool of your choice. The call used by sdl2chill is then:
$(CHMF) *.ch <#WITH directive files>
Post-processing the files to rename those containing #CODE for EDML to suffix "..ch
" is an example.
The files that are created during the generation phase will have the file names specified in Edit Separation dialog in the Generate menu in the Organizer. By default this is the name of the SDL unit.
File Extensions UNIX | |
---|---|
|
Compilation unit in CHILL source text form |
|
Object file |
|
Executable program |
|
Makefile (SDE dependent) |
The .ch
and .o
files are created for the system, and are also created for blocks and processes, depending on the separate generation scheme decided by the user. The file names will be the name of the units (system, block, or process) with the appropriate extension. For more information on generated files and file names see the section Selecting File Structure for Generated Code -- Directive #SEPARATE.
A CHILL program generated by sdl2chill can be started from an operating system shell by typing the name of the image file containing the executable program3.
Errors that may occur during code generation are internal errors, that is, errors due to not yet implemented features of SDL, and errors related to problems with open or close operations of files.
All the error messages are listed below, together with a short explanation. Some messages contain a"#" followed by a number which is used to indicate where information, specific of the error situation, can be found.
Feature of SDL not implemented: #1
The translator cannot yet handle this SDL feature. See the list of restrictions and implementation dependencies in the section Implementation Dependencies.
Cannot open outfile
A .ch
file cannot be opened.
WARNING! Unique name generation failed.
The scope structure is too deep.
#1 must be a unique name.
#1
is replaced by the name of an SDL unit. During code generation sdl2chill prefixes SDL name strings to make them unique. The prefixing algorithm and the limit for the length of the prefix, might make it impossible to generate a prefix, in which case this warning is issued. It is still possible to execute the generated program if the name, without prefix, is unique.
Node = nil in #1 Incorrect node type in #1. Nodetype: #2 Internal error in the PathStructure Line exceeded MaxLineLength
These four last errors are internal errors in sdl2chill. We would be pleased if you will report such errors to us.
sdl2chill implements your SDL system by mapping it to a semantically equivalent CHILL program. This means that when executing the generated program, it behaves according to the SDL system specification.
The translation from SDL to CHILL is based on a direct mapping scheme. The basic concepts of SDL such as system structure, communication, behavior, actions and data are directly mapped to matching CHILL constructs of program structuring, concurrent processing, communication, actions and data.
In the first parts of this section we describe the SDL to CHILL mapping as implemented by sdl2chill. The implementation is explained in terms of the CHILL and the ETRI/Samsung implementations of it. A good knowledge of these is required in order to understand the mapping details. As rationale and discussion of mapping alternatives are not needed in order to use sdl2chill, this is described in a separate technical document. CHILL source code is easy to read, and as a supplement to reading this section you are recommended to study the generated code for your own system(s).
The last part of this section describes how sdl2chill implements operators and literals in abstract data types. In the general case it is not considered feasible to derive the implementation of operators (and literals) from the axioms. sdl2chill therefore provides support for implementing the operators by user-written CHILL procedures. sdl2chill also offers a simple escape mechanism for types by means of which is it possible for the sdl2chill user to utilize CHILL modes and properties of modes otherwise not accessible from SDL.
Numerous examples are used to illustrate the run-time model and the SDL to CHILL mapping implemented by sdl2chill. In the examples, the prefixes, which can be added to names when they are translated to CHILL, are normally not shown. The prefixes are used to make sure that no name conflicts occur in the generated program. For more information about prefixes see Names and Prefixes in Generated Code.
sdl2chill maps an SDL system definition to an outermost CHILL module.
The CHILL code generated for a system may be partitioned to several compilation units. How this is facilitated is described in Selecting File Structure for Generated Code -- Directive #SEPARATE.
For the CHILL code to be compilable, sdl2chill also generates a context directive ("SPEC MODULE REMOTE"
below) to include a SDL support library (a.k.a. "sdl_support
").
SYSTEM My_System; ... ENDSYSTEM;
maps to:
SPEC MODULE REMOTE sdl_support; / /* GRANTs pervasively */ My_System: MODULE GRANT ALL; ... END My_System;
In sdl2chill a package will become a MODULE and the USE statements will become proper SEIZE statements.
The #CHILL-directive in packages is used to indicate that this package is an interface package between the environment (in CHILL) and the SDL system. The usage of this package is to access CHILL entities defined elsewhere from within the SDL system. During SDL analysis the SDL entities defined in the package are, of course, available. sdl2chill however does not translate them into CHILL, as they are available in the environment. Note that you should probably have #NAME directives on all entities, to get the proper names in the generated code. In this way signal definitions, type definitions, external procedures, and synonyms from the CHILL environment can be accessed. An ordinary global procedure can also be defined in a #CHILL package. This SDL implementation will not be used for the CHILL translation but can be used to simulate the behavior of the procedure in the SDT Simulator.
An #ENVIRONMENT and #WITH directive can be placed in a package, just as in a system, and will have the same meaning and use.
PACKAGE pack2; /*#CHILL*/ ...
sdl2chill maps the specifications contained in a block or in a block substructure to CHILL code without imposing any CHILL structure. The name string translation as described in Names and Prefixes in Generated Code, ensures proper name binding at the CHILL level.
BLOCK My_Block: ... ENDBLOCK;
maps to:
...
sdl2chill maps an SDL process definition to a CHILL process definition. The SDL process name and the formal parameters map to the CHILL process name and the formal parameter list respectively.
Creating the initial number of SDL process instances, if any, maps to a sequence of CHILL start actions executed by the CHILL imaginary outer process. The default value for initial number of processes is 1.
SELF maps to THIS. PARENT maps to an additional (implicit) formal parameter of PId sort for each process definition. OFFSPRING and SENDER map to process local CHILL locations to which values are assigned by in-line CHILL assignment actions.
PROCESS my_process (2, ); ... ENDPROCESS;
maps to:
my_process: PROCESS(parent INSTANCE); ... DCL offspring INSTANCE := NULL ,sender INSTANCE := NULL ; ... END my_process; ... DCL yAux_i INT; DO FOR yAux_i := 1 TO 2; START my_process(NULL); OD;
sdl2chill maps an SDL procedure definition to a CHILL procedure definition. This applies both to procedure definitions with state(s) and to procedure definitions without state(s). The SDL procedure name and the formal parameters map to the CHILL procedure name and the formal parameter list respectively.
Parameter passing for SDL in-parameters map on CHILL "pass by value" IN parameters, while SDL in/out-parameters are implemented by means of LOC.
Note: sdl2chill does not support calling an SDL procedure with an empty actual parameter. |
PROCEDURE My_Procedure; FPAR IN line_p PID, IN/OUT no Integer; RETURNS Integer; ... RETURN no; ENDPROCEDURE My_Procedure;
maps to:
... My_Procedure: PROC(line_p INSTANCE, no INT LOC)RETURNS(INT); ... END My_Procedure;
Procedures may be placed at any scope level in SDL-92. sdl2chill allows global procedures without state. Process local procedures may, of course, have state.
External procedures is a new feature in SDL-96, which is supported by sdl2chill. The identifier (no prefixing is performed) is automatically SEIZED, but it is the user's responsibility to make sure the identifier is visible in the generated CHILL code, e.g. via an #ENVIRONMENT directive, see Example 298 and Example 299.
Value returning procedures (SDL-92) are mapped in the obvious way as can be seen from the example.
MY_FILE: MODULE myProc: PROC(i INT)RETURNS(INT); ... END myProc; GRANT myProc; END MY_FILE;
System S; /*#ENVIRONMENT 'MY_FILE.sp' 'file1.sp' 'file2.sp'*/ ... Procedure myProc; Fpar i integer; Returns integer; External; ...
sdl2chill implements all process communication by means of CHILL signals. The channel definitions, signal route definitions and channel to signal route connection definitions of SDL all map to empty.
An SDL signal definition maps to a CHILL signal definition statement. The SDL signal name and the sort list map to the CHILL signal name and associated list of modes.
SIGNAL My_signal_1(INTEGER) ,My_signal_2;
maps to:
SIGNAL My_Signal_1 = (INT) ,My_Signal_2;
This mapping enables the CHILL inherent process communication and concurrency to be fully exploited by sdl2chill. The interface between the SDL system and its environment is mapped to a set of CHILL signals and connecting the generated program to other CHILL code thus becomes very easy.
CROS initial signals are supported, see Output.
An SDL variable definition maps to a CHILL location declaration local to the CHILL process. The SDL variable names and the sorts map to location names and modes respectively. Assignment (explicit or implicit) associated with the variable declaration map to reach-bound initialization or explicit assignment if the value mapping requires procedure call on the CHILL level.
DCL Line_Number INTEGER := 99 ,Line_P PID;
maps to:
DCL Line_Number INT := 99 ,Line_P INSTANCE := NULL;
The mapping of the transition associated with start (of the SDL process body) is shown by Example 302 below.
The states of an SDL process definition map into CHILL as follows:
START; task my_i := 0; NEXTSTATE s2; STATE s1; ... STATE s2; ... NEXTSTATE s1; ...
maps to:
... NEWMODE states = SET(start_state, s1, s2); DCL state states := start_state; DO WHILE TRUE; CASE state OF (start_state): my_i := 0; state := s2; GOTO SDL_next_state; (s1): ... (s2): ... state := s1; ESAC; SDL_next_state: ; ... OD;
Each signal for which input is specified in a state, maps to a signal receive alternative of the CHILL receive case action mapped from this state. See also Implicit Transition.
The values transported by CHILL signals are received in locations defined by the CHILL signal receive alternative.
The location to which the SDL expression SENDER is mapped, is directly updated by the receive case action.
SIGNAL My_Signal_1(INTEGER) ,My_Signal_2; ... DCL sum INTEGER; ... STATE s1; INPUT My_Signal_1(sum); ... INPUT My_Signal_2; ... NEXTSTATE s2; ...
maps to:
. .. SIGNAL My_Signal_1 = (INT) ,My_Signal_2; ... DCL sum INT; ... CASE state OF (s1): RECEIVE CASE NONPERSISTENT SET sender; (My_Signal_1 IN sum4): ... (My_Signal_2): ... state := s2; ESAC; ... ESAC;
A priori, the CHILL signals are persistent i.e. they are not consumed until explicitly received by a signal receive alternative. However, we use the ETRI/Samsung implementation defined "NONPERSISTENT
" clause on the receive case statement. Save maps on the implementation defined "EXCEPT <signallist>"-clause. See also Implicit Transition.
An SDL label maps to definition of a CHILL label. The connector name maps to the CHILL label name.
A transition maps to the CHILL action statement list of the signal receive alternative that is mapped from the input to which the transition is associated. See also Join.
Nextstate maps on assigning the set literal representing the specified nextstate to the CHILL location named state. The actual transfer of control is implemented by the enclosing case statement and loop statement. This is shown in Example 304.
Join maps to CHILL goto action. Connector name maps to label name. Join from a transition to any legal connector is supported.5
sdl2chill maps SDL stop to CHILL stop.
sdl2chill maps SDL return to CHILL return action.
The SDL semantics is that any signal (including timer signals) that is not explicitly saved or input in a state, shall be implicitly consumed when they are first in the input queue. The associated implicit transition is a nextstate action leading back to this state. The use of "NONPERSISTENT" gives this semantics, see Save.
process P1 (1, 1); signalset s1, s2, s3, s4; start; nextstate n1; state n1; input s1; nextstate n2; save s2; state n2; input s1; stop; input s2; stop; save*; state n3; input s4; nextstate n1; endprocess;
maps to:
P: PROCESS(parent INSTANCE); NEWMODE states = SET(start_state, n1, n2, n3); DCL offspring INSTANCE := NULL ,sender INSTANCE := NULL ,state states := start_state ; DO WHILE TRUE; CASE state OF (start_state): state := n1; GOTO SDL_next_state; (n1): RECEIVE CASE NONPERSISTENT SET sender; (s1): state := n2; GOTO SDL_next_state; (s3): GOTO SDL_next_state; /* Implicit transition */ (s4): GOTO SDL_next_state; /* Implicit transition */ ESAC; (n2): RECEIVE CASE NONPERSISTENT EXCEPT s3, s4 SET sender; (s1): STOP; (s2): STOP; ESAC; (n3): RECEIVE CASE NONPERSISTENT SET sender; (s4): state := n1; GOTO SDL_next_state; ESAC; ESAC; SDL_next_state: ; OD; END P
sdl2chill maps the assignment statements of a task body to CHILL assignment actions.
sdl2chill maps the create requests to CHILL start expressions.6 The result yielded by the start expression is assigned to the offspring location of the creating process.
If the process definitions of the creating process and the process to be created are mapped to different (separate) CHILL compilation units then an auxiliary proc location is introduced by sdl2chill (if necessary). This is done in order to avoid cycles in the compilation graph. The details are shown in the example below.
-- no modularization of the generated CHILL PROCESS My_Process_2 (0, ); FPAR line_p PID, subscriber_no INTEGER; ... ENDPROCESS My_Process_2; ... CREATE My_Process_2(P, I);
maps to:
... offspring := START My_Process_2(P, I, THIS);
-- full modularization of the generated CHILL PROCESS My_Process_2 (0, ); /*#PRIO 'PRIORITY 4' */ FPAR line_p PID, subscriber_no INTEGER; ... ENDPROCESS My_Process_2; ... CREATE My_Process_2(P, I);
maps to:
/* Compilation unit of the enclosing block */ NEWMODE par_My_Process_2 = PROC(INSTANCE, INT, INSTANCE) (INSTANCE); DCL var_My_Process_2 par_My_Process_2; /* Compilation unit of process definition */ proc_My_Process_2: PROC(line_p INSTANCE ,subscriber_no INT ,parent INSTANCE )(INSTANCE) DCL started_instance INSTANCE; started_instance := START My_Process_2(line_p ,subscriber_no ,parent) PRIORITY 4; RETURN started_instance; END; var_My_Process_2 = proc_My_Process_2; /* Compilation unit issuing create */ offspring := var_My_Process_2(P,I,THIS);
SDL procedure call maps to CHILL procedure call.
Value returning calls are mapped directly:
task localint := (call p) * (call p);
maps to:
localint := p()*p();
sdl2chill maps output and the associated signal parameters to a CHILL send action. CROS initial signals and broadcast can be generated with the #ALT directive, see CROS Initial Signals -- the #ALT Directive.
Note: Output without to (except if #ALT is used) or output with undefined actual parameters are not supported by sdl2chill. To denote the PId value of initially created processes, the translation directive #PIDLIT has been defined. By means of this directive, any specification relying on output without "to" may easily be adjusted to output with "to", see Identifying Initially Created Process Instances -- Directive #PIDLIT. If, in spite of this, you decide to use output without to, you will find that it maps to CHILL open send signal. As shown in the example below no error message is given, but thecomment /* TO ? */ is generated in the code to inform you that the CHILL open signal send, in the general case, may not properly implement the semantics of SDL output without to. In this case the generated program therefore may, or may not execute correctly. |
SIGNAL My_Signal_1(INTEGER) ,My_Signal_2; ... OUTPUT My_Signal_1(0) TO line_p; OUTPUT My_Signal_2 TO some_p; OUTPUT My_Signal_2 /*ALT 'IN node' */;
maps to:
SIGNAL My_Signal_1 = (INT) ,My_Signal_2; ... SEND My_Signal_1(0) TO line_p; SEND My_Signal_2 TO some_p; SEND My_Signal_2 IN node;
sdl2chill maps decision to CHILL if action as shown in the example below.
DECISION My_Integer - 1; (2): ... (4): ... (6): ... ENDDECISION;
maps to:
DCL yDcn_INT INT; ... yDcn_INT := My_Integer - 1; IF yDcn_INT = 2 THEN ... ELSIF yDcn_INT = 4 THEN ... ELSIF yDcn_INT = 6 THEN ... ELSE SDL_Error_Handler(SDL_DECISION_ERROR, "#SDTREF(SDL,/p/coins.spr(2),188(55,90),1)"); FI;
Note: The default exception handler in the |
SDL timers and the associated actions on timers are implemented by means of CROS. The mapping details are shown by Example 310 below.
TIMER T1(INTEGER), T2; ... SET (expiration_time, T1(3)); SET (NOW + 5, T2); RESET T1(3); TASK b := NOT ACTIVE(T2);
maps to:
[SYN _T1 INT = ...; SYN _T2 INT = ...;] /* CROS: must be supplied by user */ SIGNAL T1(INT), T2; DCL yAux_Int INT; ... yAux_Int:= 3; SDL_Set_Timer_With_Param(yTim_t1, expiration_time, _t1, SDL_PTR(-> yAux_Int), SIZE(INT)); SDL_Set_Timer(yTim_t2, (SDL_Time_Add (SDL_NOW() ,SDL_Duration_Lit(5,0) ), _t2); yAux_Int:= 3; SDL_Reset_Timer_With_Param( yTim_t1, SDL_PTR(-> yAux_Int)); b := NOT SDL_Active(yTim_t2);
sdl2chill supports a special subset which can be mapped directly to CHILL: A "provided true;
" can be present.
input TestSig; <action1>; provided true; <action2>;
maps to:
RECEIVE CASE SET <sender>; (TestSig): <action1>; ELSE <action2>; ESAC;
Note: Different priorities on the boolean expressions may be specified by rewriting the SDL: Use a decision inside the " |
An SDL synonym is implemented either by a CHILL location which is initialized at program start up, or as a CHILL synonym. The implementation using a location is chosen in case the expression defining the value of the synonym:
All other synonyms are translated into CHILL synonyms.
A synonym that maps to a location cannot be used in a range condition of a syntype because SDL range conditions are mapped to CHILL range modes and boundary values of CHILL range modes cannot be locations.
External synonyms can be used to parameterize an SDL system and thereby also a generated program. sdl2chill maps the definition of external synonyms on empty, this enables you to give values to external synonyms simply by using your own CHILL written definitions of these synonyms.
To give value to an external SDL synonym by means of CHILL written definitions, perform the following steps:
MY_FILE: MODULE SYN synonym1 INT = 255; DCL synonym2 BOOL := FALSE; GRANT synonym1, synonym2; END MY_FILE;
System S; /*#ENVIRONMENT 'MY_FILE.sp' 'file1.sp' 'file2.sp'*/
If you use this structure you can change the value of an external synonym merely by changing the corresponding CHILL data statements and recompiling the system.
In this section we first look at how sdl2chill translates the SDL predefined data types, see "SDL Predefined Types" below.
We then discuss how user-defined abstract data types are translated, see Translation of Sorts.
Next the possibility to include CHILL written procedures as implementation of the operators in abstract data types is presented, see User Defined Operators.
Last, in More about Abstract Data Types, we discuss more details about operators and the possibilities to include a CHILL written mode definition to represent an SDL sort.
Below is a table summarizing the SDL to CHILL mapping rules for the SDL predefined types and their operators (see SDL name/operator).
SDL name/operator | CHILL name/expression/operator |
---|---|
Boolean |
BOOL |
False, True |
FALSE, TRUE |
not |
NOT |
=, /= |
=, /= |
and |
AND |
or |
OR |
xor |
XOR |
=> |
<= |
Character |
CHAR |
NUL SOH ... |
SDL_NUL SDL_SOH ... (for all unprintable characters) |
'a' 'b' ... |
'a' 'b' ... (for all printable characters except ') |
'''' |
\' |
=, /= |
=, /= |
<, <=, >, >= |
<, <=, >, >= |
Chr, Num |
SDL_Chr(), SDL_Num() |
Charstring |
SDL_Charstring |
'aa' |
SDL_Charstring_Init(2, "aa") |
'"' |
\" |
= |
SDL_Charstring_Equal |
/= |
NOT SDL_Charstring_Equal |
MkString |
SDL_Charstring_MkString |
Length |
SDL_Charstring_Length |
First |
SDL_Charstring_First |
Last |
SDL_Charstring_Last |
// |
SDL_Charstring_Concat |
SubString |
SDL_Charstring_SubString |
Extract! |
SDL_Charstring_Extract |
Modify! |
SDL_Charstring_Modify |
Integer |
INT |
0, 1, 2,... |
same as in SDL |
+, - |
+, - |
* |
* |
REM, MOD |
REM, MOD1 |
/ |
/ |
=, /= |
=, /= |
<, <=, >, >= |
<, <=, >, >= |
Float |
SDL_Float |
Fix |
SDL_Fix |
Natural |
SDL_Natural |
Real |
SDL_Real |
0.0, ... |
SDL_Real_Lit(0, 0) |
- (monodic) |
SDL_Real_Neg |
+ |
SDL_Real_Add |
- (dyadic) |
SDL_Real_Sub |
* |
SDL_Real_Mul |
/ |
SDL_Real_Div |
=, /= |
SDL_Real_Equal, NOT SDL_Real_Equal |
< |
SDL_Real_Lss |
<= |
SDL_Real_Leq |
> |
SDL_Real_Gtr |
>= |
SDL_Real_Gte |
PId |
INSTANCE |
NULL |
NULL |
=, /= |
=, /= |
Duration |
SDL_Duration |
23.45 |
SDL_Duration_Lit(23, 450000000) |
+ |
SDL_Duration_Add |
- (monodic) |
SDL_Duration_Neg |
- (dyadic) |
SDL_Duration_Sub |
* |
SDL_Duration_Mul |
/ |
SDL_Duration_Div |
=, /= |
SDL_Duration_Equal NOT SDL_Duration_Equal |
> |
SDL_Duration_Gtr |
Time |
SDL_Time |
23.45 |
SDL_Time_Lit(23, 450000000) |
+ |
SDL_Time_Add |
- (result: Time) |
SDL_Time_Sub |
- (result: Duration) |
SDL_Time_Diff |
=, /= |
SDL_Time_Equal NOT SDL_Time_Equal |
< |
SDL_Time_Lss |
<= |
SDL_Time_Leq |
> |
SDL_Time_Gtr |
>= |
SDL_Time_Gte |
A small run-time8 library supporting the execution of programs generated by sdl2chill, has been implemented. This library is called SDL Support. It is delivered as part of sdl2chill and consists of auxiliary CHILL modes, synonyms and procedures used by sdl2chill. Interfacing to the library is of course, fully catered for by sdl2chill also when it comes to generating context directive and importing the applied names.
We will here briefly describe the modes, synonyms and procedures of sdl_support
used by sdl2chill to implement the SDL predefined types and the associated operators.
The listing below is extracted from source code of the library.
/* Copyright (c) 1996 Kvatro A/S ------------------------------------------------------------------------------- -- IDENTIFICATION -- sdl_support.ch -- -- ABSTRACT -- SDL Support (SDL) for Samsung/ETRI CHILL -- This module implements special run-time support for SDL. -- Run-time support is provided for the following SDL concepts: -- - TIMER -- - CHARACTER sort -- - CHARSTRING sort -- - REAL sort -- - DURATION sort -- - TIME sort -- - Error handling -- -- -- -- CVS LOG -- $Log: sdl_support.ch,v $ -- -- Revision 1.4 1996/09/26 12:23:02 bjornk -- Documentation baseline version -- -- Revision 1.3 1996/07/01 13:30:16 bjornk -- Initial release -- -- Revision 1.2 1996/06/14 13:17:26 bjornk -- Modified comment string -- -- Revision 1.1 1996/06/14 12:02:10 bjornk -- First version under CVS -- . -- ------------------------------------------------------------------------------- */ SPEC MODULE REMOTE cros; SPEC MODULE REMOTE libs; #include "math64.sp" Sdl_support: MODULE /* TIMER Z.100 (03/93) chapter 2.8, 5.4.4.1 and 5.4.4.5. */ GRANT SDL_Timer_Id ; GRANT SDL_set_timesig ; GRANT SDL_Now ; GRANT SDL_Set_Timer ; GRANT SDL_Reset_Timer ; GRANT SDL_Active_Timer ; GRANT SDL_Set_Timer_With_Param; GRANT SDL_Reset_Timer_With_Param; GRANT SDL_Active_Timer_With_Param; /* SDL CHARACTER SORT Z.100 (03/93) Annex D C.2 */ GRANT SDL_NUL ; GRANT SDL_SOH ; GRANT SDL_STX ; GRANT SDL_ETX ; GRANT SDL_EOT ; GRANT SDL_ENQ ; GRANT SDL_ACK ; GRANT SDL_BEL ; GRANT SDL_BS ; GRANT SDL_HT ; GRANT SDL_LF ; GRANT SDL_VT ; GRANT SDL_FF ; GRANT SDL_CR ; GRANT SDL_SO ; GRANT SDL_SI ; GRANT SDL_DLE ; GRANT SDL_DC1 ; GRANT SDL_DC2 ; GRANT SDL_DC3 ; GRANT SDL_DC4 ; GRANT SDL_NAK ; GRANT SDL_SYN ; GRANT SDL_ETB ; GRANT SDL_CAN ; GRANT SDL_EM ; GRANT SDL_SUB ; GRANT SDL_ESC ; GRANT SDL_IS4 ; GRANT SDL_IS3 ; GRANT SDL_IS2 ; GRANT SDL_IS1 ; GRANT SDL_DEL ; GRANT SDL_Charstring_max_length ; GRANT SDL_Charstring ; /* SDL CHARACTER SORT Z.100 (03/93) Annex D */ GRANT SDL_Num ; GRANT SDL_Chr ; /* SDL CHARSTRING SORT Z.100 (03/93) Annex D C.4 */ GRANT SDL_Charstring_Init ; GRANT SDL_Charstring_MkString ; GRANT SDL_Charstring_Equal ; GRANT SDL_Charstring_Length ; GRANT SDL_Charstring_First ; GRANT SDL_Charstring_Last ; GRANT SDL_Charstring_Concat ; GRANT SDL_Charstring_Extract ; GRANT SDL_Charstring_Modify ; GRANT SDL_Charstring_SubString ; /* SDL NATURAL SYNTYPE Z.100 (03/93) Annex D C.6 */ GRANT SDL_max_int ; GRANT SDL_Natural ; /* SDL REAL Z.100 (03/93) Annex D C.7 */ GRANT SDL_Real ; GRANT SDL_Float ; GRANT SDL_Fix ; GRANT SDL_Fraction ; GRANT SDL_Real_Lit ; GRANT SDL_Real_Equal; GRANT SDL_Real_Neg ; GRANT SDL_Real_Add ; GRANT SDL_Real_Sub ; GRANT SDL_Real_Mul ; GRANT SDL_Real_Div ; GRANT SDL_Real_Lss ; GRANT SDL_Real_Leq ; GRANT SDL_Real_Gtr ; GRANT SDL_Real_Gte ; /* SDL DURATION SORT Z.100 (03/93) Annex D C.11 */ GRANT SDL_Duration ; GRANT SDL_Duration_Lit ; GRANT SDL_Duration_Equal; GRANT SDL_Duration_Add ; GRANT SDL_Duration_Sub ; GRANT SDL_Duration_Neg ; GRANT SDL_Duration_Lss ; GRANT SDL_Duration_Leq ; GRANT SDL_Duration_Gtr ; GRANT SDL_Duration_Gte ; GRANT SDL_Duration_Mul ; GRANT SDL_Duration_Mul2 ; GRANT SDL_Duration_Div ; /* SDL TIME SORT Z.100 (03/93) Annex D C.12 */ GRANT SDL_Time ; GRANT SDL_Time_Lit ; GRANT SDL_Time_Equal ; GRANT SDL_Time_Lss ; GRANT SDL_Time_Leq ; GRANT SDL_Time_Gtr ; GRANT SDL_Time_Gte ; GRANT SDL_Time_Add ; GRANT SDL_Time_Add2 ; GRANT SDL_Time_Sub ; GRANT SDL_Time_Diff ; GRANT SDL_Error_Handler; GRANT Init_SDL_Support; GRANT Error_Type; GRANT i64_zero ; GRANT i64_10 ; GRANT i64_60 ; GRANT i64_100 ; GRANT i64_1000 ; GRANT i64_10_000 ; GRANT i64_100_000 ; GRANT i64_1000_000 ; GRANT i64_10_000_000 ; GRANT i64_1000_000_000; GRANT i64_Max_Int ; GRANT SDL_PTR ; DCL i64_zero SINT64; DCL i64_10 SINT64; DCL i64_60 SINT64; DCL i64_100 SINT64; DCL i64_1000 SINT64; DCL i64_10_000 SINT64; DCL i64_100_000 SINT64; DCL i64_1000_000 SINT64; DCL i64_10_000_000 SINT64; DCL i64_1000_000_000 SINT64; DCL i64_Max_Int SINT64; DCL SDL_Error_Handler Error_Handler_Proc; SYNMODE SDL_PTR = REF CHAR(*); /* *********************************************************** */ /* Error handling routine */ /* Report error and terminate */ /* */ /* *********************************************************** */ NEWMODE Error_Type = SET (SDL_UNDEFINED_ERROR, SDL_DECISION_ERROR, SDL_OPERATOR_ERROR); SYNMODE Error_Handler_Proc = PROC ( Error_Type, REF CHAR(*)); SDL_Fatal_Error: PROC(err_type Error_Type, str REF CHAR(*) ) GENERAL; END SDL_Fatal_Error;
/*---------------------------------------------------------------- */ /* TIMER Z.100 (03/93) chapter 2.8, 5.4.4.1 and 5.4.4.5. */ /* The SDL_Timer_Id mode is used for timer descriptors, which CROS */ /* uses to identify the timers. SDL_Set_Timer returns a descriptor */ /* for the created timer, SDL_Reset_Timer and SDL_Active_Timer */ /* takes a desccriptor as parameter to identify a timer. */ SYNMODE SDL_Timer_Id = INT; /* ************************************************************** */ /* SDL_Set_Timer implements the SDL function SET timer. */ /* In SDL, setting a timer which is already active, */ /* overwrites the original expiration time. */ /* In ECHILL/SCHILL SDL_Set_Timer maps to calling the set_timesig */ /* function of CROS */ /* RETURN VALUES MEANING */ /* > 0 Success, id of registered timer is returned */ /* -4 No available timer id */ /* -5 No available memory */ /* -6 TOD time unit is in wrong status */ /* -7 Illegal time unit */ /* -9 No IPC node */ /* */ /* If the specified timeout is 0 or negative, the timer signal */ /* will be sent immediately. Note that this MAY (or may not) */ /* influence the result of the boolean function */ /* SDL_Timer_Active if called in the same SDL transition as */ /* the setting of the timer. */ /* ************************************************************** */ SDL_Set_Timer: PROC(timer_id SDL_Timer_Id LOC, time SDL_Time, timer INT) GENERAL; END SDL_Set_Timer; SDL_Set_Timer_With_Param: PROC(timer_id SDL_Timer_Id LOC, time SDL_Time, timer INT, msg SDL_PTR, length INT) GENERAL; END SDL_Set_Timer_With_Param; SDL_set_timesig: /* Internal routine */ PROC(units INT, unit INT, timer INT, msg SDL_PTR, length INT) RETURNS(SDL_Timer_Id) GENERAL; END SDL_set_timesig; SDL_Set_Timer_Absolute: PROC(timer_id SDL_Timer_Id LOC, time SDL_Time, timer INT, msg SDL_PTR, length INT) GENERAL; END SDL_Set_Timer_Absolute; SDL_Set_Timer_Relative: PROC(timer_id SDL_Timer_Id LOC, time SDL_Duration, timer INT, msg SDL_PTR, length INT) RETURNS(SDL_Timer_Id) GENERAL; END SDL_Set_Timer_Relative; /* *********************************************************** */ /* SDL_Reset_Timer implements the SDL function RESET timer. */ /* In SDL, a timer can be reset before it expires or while */ /* it is in the input port. */ /* In ECHILL/SCHILL SDL_Reset_Timer maps to calling the */ /* cancel function of CROS */ /* RETURN VALUES MEANING */ /* 0 Executed successfully */ /* -1 Can't find the requested timer id */ /* -2 When unregistered timer id is requested */ /* -3 When the requested timer id is not useful */ /* The range of the timer id is from 0 to 6000*/ /* */ /* cancel removes the specified timer both when it */ /* has not yet reached its timeout point or if it is sent. */ /* *********************************************************** */ SDL_Reset_Timer: PROC(timer SDL_Timer_Id) GENERAL; END SDL_Reset_Timer; SDL_Reset_Timer_With_Param: PROC(timer SDL_Timer_Id, p SDL_PTR) GENERAL; END SDL_Reset_Timer_With_Param; /* *********************************************************** */ /* SDL_Active_Timer implements the SDL function ACTIVE timer */ /* check. In SDL, a timer is active when it is set and not */ /* yet consumed from the input port. */ /* In ECHILL/SCHILL SDL_Active_Timer maps to calling the */ /* check_timer function of CROS */ /* RETURN VALUES MEANING */ /* >0 Success, the remaining time (millisecond) */ /* of the timer is returned */ /* -1 Can't find the requested timer id */ /* -2 When unregistered timer id is requested */ /* -3 When the requested timer id is not useful */ /* The range of the timer id is from 0 to 6000*/ /* */ /* SDL_Active_Timer returns TRUE if the specified timer is set */ /* but has not yet at the timeout point where it is sent OR if */ /* a sent timer signal is sent, but not yet received/consumed. */ /* Else it returns FALSE. */ /* *********************************************************** */ SDL_Active_Timer: PROC(timer SDL_Timer_Id) RETURNS(BOOL) GENERAL; END SDL_Active_Timer; SDL_Active_Timer_With_Param: PROC(timer SDL_Timer_Id, p SDL_PTR) RETURNS(BOOL) GENERAL; END SDL_Active_Timer_With_Param; /* *********************************************************** */ /* Implements the SDL imperative operator NOW. */ /* In ECHILL/SCHILL SDL_Now maps to calling the gettime */ /* function of CROS */ /* SDL_Now returns the value of the system stopwatch. This is */ /* normally the (long) duration since this program started */ /* executing, but may as well be any coordinated value in a */ /* network of distributed SDL application parts, where the */ /* parts may start to execute independently of each other. */ /* *********************************************************** */ SDL_Now: PROC() RETURNS(SDL_Time) GENERAL; END SDL_Now;
/*-------------------------------------------------------------------- */ /* SDL CHARACTER SORT Z.100 (03/93) Annex D C.2 */ SYN SDL_NUL CHAR = H'00; SYN SDL_SOH CHAR = H'01; SYN SDL_STX CHAR = H'02; SYN SDL_ETX CHAR = H'03; SYN SDL_EOT CHAR = H'04; SYN SDL_ENQ CHAR = H'05; SYN SDL_ACK CHAR = H'06; SYN SDL_BEL CHAR = H'07; SYN SDL_BS CHAR = H'08; SYN SDL_HT CHAR = H'09; SYN SDL_LF CHAR = H'0A; SYN SDL_VT CHAR = H'0B; SYN SDL_FF CHAR = H'0C; SYN SDL_CR CHAR = H'0D; SYN SDL_SO CHAR = H'0E; SYN SDL_SI CHAR = H'0F; SYN SDL_DLE CHAR = H'10; SYN SDL_DC1 CHAR = H'11; SYN SDL_DC2 CHAR = H'12; SYN SDL_DC3 CHAR = H'13; SYN SDL_DC4 CHAR = H'14; SYN SDL_NAK CHAR = H'15; SYN SDL_SYN CHAR = H'16; SYN SDL_ETB CHAR = H'17; SYN SDL_CAN CHAR = H'18; SYN SDL_EM CHAR = H'19; SYN SDL_SUB CHAR = H'1A; SYN SDL_ESC CHAR = H'1B; SYN SDL_IS4 CHAR = H'1C; SYN SDL_IS3 CHAR = H'1D; SYN SDL_IS2 CHAR = H'1E; SYN SDL_IS1 CHAR = H'1F; SYN SDL_DEL CHAR = 127; /*-------------------------------------------------------------------- */ /* SDL CHARACTER SORT Z.100 (03/93) Annex D */ SDL_Num: PROC(c CHAR) RETURNS(INT) GENERAL; END SDL_Num; SDL_Chr: PROC(i INT) RETURNS(CHAR) GENERAL; END SDL_Chr;
/*-------------------------------------------------------------------- */ /* SDL CHARSTRING SORT Z.100 (03/93) Annex D C.4 */ SYN SDL_Charstring_max_length INT = 100; NEWMODE SDL_Charstring = STRUCT (length INT(0 : SDL_Charstring_max_length), string CHAR(SDL_Charstring_max_length)); SDL_Charstring_Init: PROC(length INT(0 : SDL_Charstring_max_length), c REF CHAR(*)) RETURNS(SDL_Charstring) GENERAL; END SDL_Charstring_Init; SDL_Charstring_Equal: PROC(l SDL_Charstring, r SDL_Charstring) RETURNS(BOOL) GENERAL; END SDL_Charstring_Equal; SDL_Charstring_MkString: PROC(c CHAR) RETURNS(SDL_Charstring) GENERAL; END SDL_Charstring_MkString; SDL_Charstring_Length: PROC(cs SDL_Charstring) RETURNS(INT) GENERAL; END SDL_Charstring_Length; SDL_Charstring_First: PROC(cs SDL_Charstring) RETURNS(CHAR) GENERAL; END SDL_Charstring_First; SDL_Charstring_Last: PROC(cs SDL_Charstring) RETURNS(CHAR) GENERAL; END SDL_Charstring_Last; SDL_Charstring_Concat: PROC(cs1 SDL_Charstring, cs2 SDL_Charstring) RETURNS(SDL_Charstring); END SDL_Charstring_Concat; SDL_Charstring_Extract: PROC(cs SDL_Charstring, inx INT) RETURNS(CHAR) GENERAL; END SDL_Charstring_Extract; SDL_Charstring_Modify: PROC(cs SDL_Charstring, inx INT, c CHAR) RETURNS(SDL_Charstring) GENERAL; END SDL_Charstring_Modify; SDL_Charstring_SubString: PROC(cs SDL_Charstring, inx INT, length INT) RETURNS(SDL_Charstring) GENERAL; END SDL_Charstring_SubString;
/*------------------------------------------------------------------- */ /* SDL NATURAL SYNTYPE Z.100 (03/93) Annex D C.6 */ SYN SDL_max_int INT = 2_147_483_647; SYNMODE SDL_Natural = INT(0 : SDL_max_int);
/*------------------------------------------------------------------- */ /* SDL REAL Z.100 (03/93) Annex D C.7 */ /* */ /* SDL REAL are mapped on 64-bit integers. We are using a mode SINT64 */ /* to represented 64-bit integers and we have a libray which performs */ /* the most common arithmetic operations on this mode. */ /* The real values are created by a call to SDL_Real_Lit, taking two */ /* parameters, the integer part and the fraction part. The fraction */ /* part is multiplied by 10 ** 9 (in the call). */ /* The representation of a real in a 64-bit integer is as follows: */ /* - the integer part is adjusted up to 9 desimal digit fraction */ /* form. That is, multiplied by 10 ** 9 */ /* - the result is the sum of the adjusted integer part and the */ /* fraction part, and is of sort SDL_Real. */ /*------------------------------------------------------------------- */ SYNMODE SDL_Real = STRUCT (i64 SINT64); /* Fixed 9 desimal digit fraction. */ /* Implements the SDL operator: Float (Integer) Real; */ /* Adjust to 9 desimal digit fraction. */ SDL_Float: PROC(i INT) RETURNS(SDL_Real) GENERAL; END SDL_Float; /* Implements the SDL operator: Fix (Real) Integer; */ /* Truncates the 9 desimal digit fraction. */ SDL_Fix: PROC(x SDL_Real) RETURNS(INT) GENERAL; END SDL_Fix; /* Implements a utility function to get the fraction part */ /* of a Real, Duration or Time value. */ /* Used for debug printouts */ SDL_Fraction: PROC(x SDL_Real) RETURNS(INT) GENERAL; END SDL_Fraction; /* Map SDL Real literal to SDL_Real mode */ /* The parameter `i' denotes the integer part i.e. seconds. */ /* The parameter `f' denotes the fractional part multiplied by 10 ** 9 */ /* The integer part is adjusted up to 9 desimal digit fraction form. */ /* The fraction part is adjusted down to 9 desimal digit fraction form */ /* The result is the sum of the two. */ SDL_Real_Lit: PROC(i INT, f INT) RETURNS(SDL_Real) GENERAL; END SDL_Real_Lit; /* Implements the SDL operator: = (Real, Real)Boolean. */ SDL_Real_Equal: PROC(l SDL_Real, r SDL_Real) RETURNS(BOOL) GENERAL; END SDL_Real_Equal; /* Implements the SDL operator: - (Real)Real. */ SDL_Real_Neg: PROC(r SDL_Real) RETURNS(SDL_Real) GENERAL; END SDL_Real_Neg; /* Implements the SDL operator: + (Real, Real)Real. */ SDL_Real_Add: PROC(l SDL_Real, r SDL_Real) RETURNS(SDL_Real) GENERAL; END SDL_Real_Add; /* Implements the SDL operator: - (Real, Real)Real. */ SDL_Real_Sub: PROC(l SDL_Real, r SDL_Real) RETURNS(SDL_Real) GENERAL; END SDL_Real_Sub; /* Implements the SDL operator: * (Real, Real)Real */ /* Truncates l and r to 4 desimal digit fraction. */ /* Then the product is truncated with 1 desimal digit fraction. */ /* This leaves the two last desimal digits insignificant. */ SDL_Real_Mul: PROC(l SDL_Real, r SDL_Real) RETURNS(SDL_Real) GENERAL; END SDL_Real_Mul; /* Implements the SDL operator: / (Real, Real)Real */ /* `l' is biased before the division with 10_000_000. */ /* This leaves the result in correct representation. */ SDL_Real_Div: PROC(l SDL_Real, r SDL_Real) RETURNS(SDL_Real) GENERAL; END SDL_Real_Div; /* Implements the SDL operator: < (Real, Real)Boolean. */ SDL_Real_Lss: PROC(l SDL_Real, r SDL_Real) RETURNS(BOOL) GENERAL; END SDL_Real_Lss; /* Implements the SDL operator: <= (Real, Real)Boolean. */ SDL_Real_Leq: PROC(l SDL_Real, r SDL_Real) RETURNS(BOOL) GENERAL; END SDL_Real_Leq; /* Implements the SDL operator: > (Real, Real)Boolean. */ SDL_Real_Gtr: PROC(l SDL_Real, r SDL_Real) RETURNS(BOOL) GENERAL; END SDL_Real_Gtr; /* Implements the SDL operator: >= (Real, Real)Boolean. */ SDL_Real_Gte: PROC(l SDL_Real, r SDL_Real) RETURNS(BOOL) GENERAL; END SDL_Real_Gte;
/*------------------------------------------------------------------- */ /* SDL DURATION SORT Z.100 (03/93) Annex D C.11 */ /* */ /* Duration are mapped on 64-bit integers. We are using a mode SINT64 */ /* to represented 64-bit integers and we have a library which performs*/ /* the most common arithmetic operations on this mode. */ /* The Duration values are created by a call to SDL_Duration_Lit, */ /* taking two parameters, the integer part and the fraction part. */ /* The fraction part is multiplied by 10 ** 9 (in the call). */ /* The representation of a duration in a 64-bit integer is as follows:*/ /* - the integer part is adjusted up to 9 desimal digit fraction */ /* form. That is, multiplied by 10 ** 9 */ /* - the result is the sum of the adjusted integer part and the */ /* fraction part, and is of sort SDL_Duration. */ /*------------------------------------------------------------------- */ NEWMODE SDL_Duration = STRUCT (i64 SINT64); /* Map SDL Duration literal to SDL_Duration mode. */ /* The parameter `i' denotes the integer part i.e. seconds. */ /* The parameter `f' denotes the fractional part multiplied by 10 ** 9 */ /* The integer part is adjusted up to 9 desimal digit fraction form. */ /* The fractional part is adjusted down to 9 desimal digit fraction */ /* form. The result is the sum of the two. */ SDL_Duration_Lit: PROC(i INT, f INT) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Lit; /* Implements the SDL operator: = (Duration, Duration)Boolean. */ SDL_Duration_Equal: PROC(l SDL_Duration, r SDL_Duration) RETURNS(BOOL) GENERAL; END SDL_Duration_Equal; /* Implements the SDL operator: + (Duration, Duration)Duration. */ SDL_Duration_Add: PROC(l SDL_Duration, r SDL_Duration) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Add; /* Implements the SDL operator: - (Duration, Duration)Duration. */ SDL_Duration_Sub: PROC(l SDL_Duration, r SDL_Duration) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Sub; /* Implements the SDL operator: - (Duration)Duration. */ SDL_Duration_Neg: PROC(r SDL_Duration) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Neg; /* Implements the SDL operator: < (Duration, Duration)Boolean. */ SDL_Duration_Lss: PROC(l SDL_Duration, r SDL_Duration) RETURNS(BOOL) GENERAL; END SDL_Duration_Lss; /* Implements the SDL operator: <= (Duration, Duration)Boolean. */ SDL_Duration_Leq: PROC(l SDL_Duration, r SDL_Duration) RETURNS(BOOL) GENERAL; END SDL_Duration_Leq; /* Implements the SDL operator: > (Duration, Duration)Boolean. */ SDL_Duration_Gtr: PROC(l SDL_Duration, r SDL_Duration) RETURNS(BOOL) GENERAL; END SDL_Duration_Gtr; /* Implements the SDL operator: >= (Duration, Duration)Boolean. */ SDL_Duration_Gte: PROC(l SDL_Duration, r SDL_Duration) RETURNS(BOOL) GENERAL; END SDL_Duration_Gte; /* Implements the SDL operator: * (Duration, Real)Duration. */ /* Truncates l and r to 4 desimal digit fraction. */ /* Then the product is truncated with 1 desimal digit fraction. */ /* This leaves the two last desimal digits insignificant. */ SDL_Duration_Mul: PROC(l SDL_Duration, r SDL_Real) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Mul; SDL_Duration_Mul2: PROC(l SDL_Real, r SDL_Duration) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Mul2; /* Implements the SDL operator: \ (Duration, Real)Duration. */ /* `l' is biased before the division with 10_000_000. */ /* This leaves the result in correct representation. */ SDL_Duration_Div: PROC(l SDL_Duration, r SDL_Real) RETURNS(SDL_Duration) GENERAL; END SDL_Duration_Div;
/*------------------------------------------------------------------- */ /* SDL TIME SORT Z.100 (03/93) Annex D C.12 */ /* */ /* Time are mapped on 64-bit integers. We are using the mode SINT64 */ /* to represented 64-bit integers and we have a library which performs*/ /* the most common arithmetic operations on this mode. */ /* The Time values are created by a call to SDL_Time_Lit, */ /* taking two parameters, the integer part and the fraction part. */ /* The fraction part is multiplied by 10 ** 9 (in the call). */ /* The representation of a time in a 64-bit integer is as follows: */ /* - the integer part is adjusted up to 9 desimal digit fraction */ /* form. That is, multiplied by 10 ** 9 */ /* - the result is the sum of the adjusted integer part and the */ /* fraction part, and is of sort SDL_Time. */ /*------------------------------------------------------------------- */ NEWMODE SDL_Time = STRUCT (i64 SINT64); /* Map SDL Time literal to SDL_Time mode. */ /* The parameter `i' denotes the integer part i.e. seconds. */ /* The parameter `f' denotes the fractional part multiplied by 10 ** 9 */ /* The integer part is adjusted up to 9 desimal digit fraction form. */ /* The fractional part is adjusted down to 9 desimal digit fraction */ /* form. The result is the sum of the two. */ SDL_Time_Lit: PROC(i INT, f INT) RETURNS(SDL_Time) GENERAL; END SDL_Time_Lit; /* Implements the SDL operator: = (Time, Time)Boolean. */ SDL_Time_Equal: PROC(l SDL_Time, r SDL_Time) RETURNS(BOOL) GENERAL; END SDL_Time_Equal; /* Implements the SDL operator: < (Time, Time)Boolean. */ SDL_Time_Lss: PROC(l SDL_Time, r SDL_Time) RETURNS(BOOL) GENERAL; END SDL_Time_Lss; /* Implements the SDL operator: <= (Time, Time)Boolean. */ SDL_Time_Leq: PROC(l SDL_Time, r SDL_Time) RETURNS(BOOL) GENERAL; END SDL_Time_Leq; /* Implements the SDL operator: > (Time, Time)Boolean. */ SDL_Time_Gtr: PROC(l SDL_Time, r SDL_Time) RETURNS(BOOL) GENERAL; END SDL_Time_Gtr; /* Implements the SDL operator: >= (Time, Time)Boolean. */ SDL_Time_Gte: PROC(l SDL_Time, r SDL_Time) RETURNS(BOOL) GENERAL; END SDL_Time_Gte; /* Implements the SDL operator: + (Time, Duration)Time. */ SDL_Time_Add: PROC(l SDL_Time, r SDL_Duration) RETURNS(SDL_Time) GENERAL; END SDL_Time_Add; SDL_Time_Add2: PROC(l SDL_Duration, r SDL_Time) RETURNS(SDL_Time) GENERAL; END SDL_Time_Add2; /* Implements the SDL operator: - (Time, Duration)Time. */ SDL_Time_Sub: PROC(l SDL_Time, r SDL_Duration) RETURNS(SDL_Time) GENERAL; END SDL_Time_Sub; /* Implements the SDL operator: - (Time, Time)Duration. */ SDL_Time_Diff: PROC(l SDL_Time, r SDL_Time) RETURNS(SDL_Duration) GENERAL; END SDL_Time_Diff;
/* Initialize 64-bit constants */ Init_SDL_Support: PROC() GENERAL; END Init_SDL_Support; END Sdl_support;
The following data types can be handled by sdl2chill:
All the predefined data types, Integer, Natural, Boolean, Character, Charstring, Real, Time, Duration, and PId are completely handled.
The name of these types in the generated CHILL code will be INT, SDL_Natural, BOOL, CHAR, SDL_Charstring, SDL_Real, SDL_Time, SDL_Duration and INSTANCE respectively.
The translation rules for these types and their operators are described in more detail in the SDL Predefined Types.
A sort which is not a struct and which does not contain any inheritance or generator instantiation, but which contains a literal list, is translated to a CHILL set mode, as can be seen in the example below. As in all examples in this subsection, the prefixes, which are added to name strings when they are translated to CHILL, are not shown. The prefixes are used to make sure that no name conflicts occur in the generated program. For more information about prefixes see Names and Prefixes in Generated Code.
NEWTYPE EnumType LITERALS Lit1, Lit2, Lit3; ENDNEWTYPE;
is translated to:
SYNMODE EnumType = SET(Lit1, Lit2, Lit3);
Unfortunately this translation strategy is not always correct. Consider as an example the following sort definition:
NEWTYPE Enum2 LITERALS Lit1, Lit2; OPERATORS Op : Enum2 -> Enum2; AXIOMS Op(Lit1) == Lit2; Op(Op(Lit2)) == Lit1; ENDNEWTYPE;
When evaluating this definition it is fairly easy to see that the value set of this sort contains three values, the value denoted by Lit1, the value denoted by Lit2, and the value obtained by applying Op to Lit2, that is, Op(Lit2). The latter value does not have any explicit literal denoting its value, which means that an implementation of this sort as an enumeration type in CHILL would be incorrect. In general, the set of literals of a sort and the set of values of a sort are two quite different things. Still the translation rule is included in sdl2chill, since it is valid in most situations.
An SDL struct is translated to a CHILL struct, as can be seen in the example below.
NEWTYPE Str STRUCT a Integer; b Boolean; c Character; ENDNEWTYPE;
is translated to:
SYNMODE Str = STRUCT (a INT ,b BOOL ,c CHAR );
All the properties of a struct in SDL are preserved in the CHILL code. The predefined operators Extract! and Modify! are implemented as component selection in the struct in the same way as in SDL, that is, if S is a variable of type Str, then S!a in SDL is translated to S.a in CHILL. The predefined operator Make!, which is a constructor of a struct value, is implemented by means of procedure "yMake_
<struct>()"
in CHILL. This means that the expression "(.12,true,`a'.)"
in SDL is translated to the CHILL call "yMake_mystruct(12, TRUE,`a')"
.
The components of a struct may be of any sort that sdl2chill can handle. A component may, however, not directly or indirectly refer to the struct sort itself.
The sort Str above may not have a component of sort Str. In such a case the translation to a CHILL struct would no longer be valid.
Instantiations of the predefined generator array can be handled by sdl2chill with the following restrictions: The component sort may be any sort that sdl2chill can handle, but may not directly or indirectly refer to the array type itself (see also the previous paragraph on struct). The index sort should be a discrete sort, with one closed interval of values. This means that the following index sorts may be used:
Another way of defining the allowed index sorts is that sdl2chill can handle array generator instantiations with any index sort that maps to a CHILL discrete mode.
SYNTYPE Idx = Integer CONSTANTS 0:10 ENDSYNTYPE; NEWTYPE Arr ARRAY(Idx, Real) ENDNEWTYPE;
is translated to:
SYNMODE Idx = INT(0:10) ,Arr = ARRAY(Idx)SDL_Real ;
All the properties of an array in SDL are preserved in the CHILL code. The predefined operators Extract! and Modify! are implemented as indexing of the array in CHILL in the same way as in component selection is done in SDL, so if My_Var is a variable of type Arr, and My_Index is a valid index expression, then My_Var(My_Index) in SDL maps to My_Var(My_Index) in CHILL.
The predefined operator Make!, which is a constructor of an array value, is implemented by means a procedure.This means that the expression "(. 0.22 .)
" in SDL is translated to the CHILL call:
yMake_MyArray( SDL_Real_Lit(0, 220000000) );
Syntypes may be defined for any sort that sdl2chill can handle, giving a new name for the sort and possibly a new default value for variables of the sort. Range conditions that restrict the allowed range of values are also allowed by sdl2chill provided that the parent sort maps to a CHILL discrete mode and the range condition details map to a CHILL literal range.
The syntype is translated to a type equal to the parent type using SYNMODE definition. The check that a variable of a syntype with range condition is only assigned legal values, is catered for by CHILL semantic conditions. An attempt to assign an illegal value to such a variable will be reported as a CHILL RANGEFAIL exception at run-time9. Similarly, if syntype is specified as index sort in an array, the CHILL semantic conditions will ensure that the index values used in array component selections are within the range conditions specified for the index sort.
SYNTYPE Syn1 = integer CONSTANTS 0:10 ENDSYNTYPE; SYNTYPE Syn2 = integer CONSTANTS 0:255 ENDSYNTYPE; SYNTYPE Arr1 = Arr DEFAULT (. 2.0 .); ENDSYNTYPE; /* Arr is defined in the previous example*/
is translated to:
SYNMODE Syn1 = RANGE(0:10) ,Syn2 = RANGE(0:255) ,Arr1 = Arr ;
In sdl2chill you may initialize a variable by assigning a value to it in the variable definition or by specifying a default value in the sort definition. If neither is done, the initial value for the variable is undefined. The exception to this is that sdl2chill assigns the value NULL to those variables of PId sort that would otherwise contain an undefined initial value.
The default mapping of user defined operators in an SDL sort is as follows:
In User Defined Operators it is described how to include CHILL procedures as implementation of operators.
In sorts that are translated to CHILL set modes, literals are obviously handled by sdl2chill. In sorts that are not translated to CHILL set modes, literals are treated as operators without parameters and are handled exactly in the same way as user defined operators.
Note: Note that sdl2chill does not permit naming of literals using name class literals or character strings. |
Axioms and literal mappings are allowed by sdl2chill in sorts, but are completely ignored.
In the previous subsection the default behavior of sdl2chill concerning operators and literals was described. To make it possible for sdl2chill to generate complete application programs, you should include CHILL procedures implementing the operators and literals. This can be done by means of sdl2chill directives.
An sdl2chill directive is an SDL comment with the first character equal to `#', followed by a sequence of letters identifying the directive. In this case the letters are ADT (for Abstract Data Type) and OP (for operator). An ADT directive and an OP directive should thus look like:
/*#ADT */ /*#OP */
The text is not case sensitive.
OP directives are recognized at two different positions in an abstract data type:
ADT directives are recognized immediately before the reserved word ENDNEWTYPE (or ENDSYNTYPE).
NEWTYPE Str STRUCT a Integer; b Boolean; c Real; ADDING LITERALS Lit1 /*#OP */, Lit2 /*#OP */; OPERATORS Op1 :Str,Integer -> Str; /*#OP */ Op2 :Str,Boolean -> Str; /*#OP */ /*#ADT */ ENDNEWTYPE;
The #OP directive can be used to specify how the applied occurrences of the associated literal or operator should be implemented. In the #ADT directive the actual implementation can be defined e.g. in the form of CHILL procedure definitions.
An OP or ADT directive specifying the implementation details of operators and literals should have the following structure:
/*#OP (B) */ /*#ADT (B) */
The letter between the parentheses should be B (body)10. If B has been specified for an operator or literal, then CHILL code for implementing its intended function must be supplied by the user. This CHILL code should be placed in the ADT directive, according to the following example:
/*#ADT (B) CHILL code in the form of procedure definitions implementing operators and literals. */
The CHILL code must start on a new line.
Note: sdl2chill does not check the consistency between the specification of implementation techniques and the actual CHILL code. This check is, together with checking the CHILL code for syntactic and static semantic errors, left to the CHILL compiler. CHILL comments within the code that is included in a #ADT directive should be in the form of end-of-line comments1. SDL and CHILL use the same symbols for bracketed comments ("/*" and "*/") and if such a comment is included, the SDT Analyzer will consider its closing bracket as the end of the SDL comment. |
In Example 322 the struct Str is defined and there are two literals (Lit1 and Lit2) and two operators (Op1: Str, integer --> Str; and Op2: Str, Boolean --> Str;). The procedures, which should be supplied by the sdl2chill user if B is specified in the OP or ADT directive, are ordinary CHILL procedures.
Lit1: PROC() RETURNS(Str); RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ]; END; Op1: PROC(p1 Str, p2 INT)RETURNS(Str); p1.a +:= p2; RETURN p1; END;
Before it is possible to give a complete example of an abstract data type with implementation of its operators supplied as CHILL procedures it is necessary to look at the problem of names and name strings. When a name string of an entity in SDL is translated to CHILL, a suitable sequence of characters, a prefix, is added to the SDL name string, to make the name unique in the CHILL program, see also Names and Prefixes in Generated Code. This strategy is selected in sdl2chill to avoid name conflicts in the generated code, but it also makes it impossible to predict the actual name string of, for example a mode or a procedure, in the generated program. To handle this problem the user can tell sdl2chill to translate a name string in the user written CHILL code in the same way as SDL name strings are otherwise translated. This is specified by enclosing the SDL name string between "#(" and ")" in the CHILL code. The two procedures in the previous example then become:
#(Lit1): PROC() RETURNS(#(Str)); RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ]; END; #(Op1): PROC(p1 #(Str), p2 INT)RETURNS(#(Str)); p1.a +:= p2; RETURN p1; END;
The facilities enabling the use of SDL defined names in CHILL code is described in more detail in the section Applying SDL Names in CHILL Code -- Directive #SDL. A few observations concerning the example above might be appropriate:
We now give two complete examples of abstract data types.
NEWTYPE Str STRUCT a Integer; b Boolean; c Real; ADDING LITERALS Lit1; OPERATORS Op1 : Str, Integer -> Str; Op2 : Str, Boolean -> Str; /*#ADT (B) #(Lit1): PROC() RETURNS(#(Str)); RETURN [ 2, FALSE, SDL_Real_Lit(2,0) ]; END; #(Op1): PROC(p1 #(Str), p2 INT)RETURNS(#(Str)); p1.a +:= p2; RETURN p1; END; #(Op2): PROC(p1 #(Str), p2 BOOL)RETURNS(#(Str)); IF p2 THEN RETURN p1; ELSE RETURN #(Lit1)(); FI; END; */ ENDNEWTYPE;
SYNTYPE Index = Integer CONSTANTS 1:10 ENDSYNTYPE; NEWTYPE A Array(Index, integer) ADDING LITERALS Zero /*#OP (B) */; OPERATORS Add : A, A -> A; /*#OP (B) */ Sum : A -> Integer; /*#ADT (B) #(Zero): PROC() RETURNS(#(A)); RETURN [ 0,0,0,0,0,0,0,0,0,0 ]; END; #(Add): PROC(p1 #(A), p2 #(A)) RETURNS(#(A)); DCL Result #(A); DCL i #(Index); DO FOR i IN #(Index); Result(i) := p1(i) + p2(i); OD; RETURN Result; END; */ ENDNEWTYPE;
Note that in this example no procedure definition is supplied for the operator Sum. When compiling a generated program where the operator Sum is used, the CHILL compiler will therefore give an error message saying that definition of the name Sum is missing.
For more information about CHILL synonyms, modes and procedures (supplied by the SDL support and used in generated code) that can be useful when implementing operators in CHILL, see SDL Predefined Types, and last in More about Abstract Data Types (below).
Previously under User Defined Operators, the possibility to include implementations of operators and literals in abstract data types was described. Here we will first discuss some additional features concerning operators and then describe how to replace the generated CHILL mode definition for an abstract data type with a user defined mode definition.
For an operator (or literal) in an abstract data type not only B (body) may be specified. The following choices are available:
a+1 a MOD 4 -a
SIZE(a) NUM(a)
Note: As CHILL does not include the possibility to have user defined operators, I (infix) is only adequate together with S (standard). |
For each operator one of the letters B, S and one of the letters P, I should be supplied, either in a #OP directive, or in a #ADT directive, or as the defaults B and P. For literals P and I have no meaning.
Example of usage of S (standard)
REM : Integer,Integer->Integer; /*#ADT (SI) */ SIZE : Real -> Integer; /*#ADT (SP) */
An SDL expression using these operators:
SIZE(a)
will be translated to: SIZE(zh723_a)
These examples show how built-in procedures and standard operators of CHILL can be directly utilized in abstract data types.
In Translation of Sorts it is described which CHILL mode definitions the SDL predefined types, enumeration types, struct, array and syntypes map into. By this translation scheme the general, implementation independent capabilities of the CHILL modes that matches the above SDL types are directly utilized.
When generating applications it is sometimes needed, in parts of a system, to use additional CHILL modes such as pointers, other integer modes than INT and the more implementation oriented capabilities of CHILL such as variant structure modes and packing. This is facilitated by means of the #ADT directive.
By this directive it is possible to suppress the generation of mode definitions for an abstract data type and include a CHILL written mode definition instead. Suppressing the generation of the mode definition, however, does not affect the translation of the actions related to the data type.
The #ADT directive to specify that no mode definition shall
be generated from the SDL sort has the following structure11:
/*#ADT (T)
CHILL code (that replaces the mode definition
otherwise generated by sdl2chill).
*/
The example below shows how the #ADT directive may be used in order to use the imaginary integer mode LONGINT from SDL.
SYNTYPE long /*#NAME 'LONGINT' */ = Integer
/*#ADT (T(S))
*/
ENDSYNTYPE;
...
DCL l1 long
,l2 long := 65536;
...
TASK l1 := l2 + l1;
Maps into the following CHILL code:
...
DCL l1 LONGINT i.e. undefined initial value
,l2 LONGINT := 65536;
...
l1 := l2 + l1;
Below is another example showing how the #ADT directive may be used to facilitate packing of the components of a structure and to build a linked list of data objects by means of a CHILL defined pointer.
SYNTYPE nibble = Integer CONSTANTS 0:15 ENDSYNTYPE; NEWTYPE package STRUCT i nibble; j nibble; ADDING LITERALS NIL OPERATORS SUM: package -> Integer; /*# OP (B) */ DEFAULT NIL; /*#ADT (T) SYNMODE nibble = #(nibble) ,package = #(package) ; NEWMODE #(package) = STRUCT (i nibble PACK ,j nibble PACK ,NEXT REF package ); #(SUM): PROC (p1 package) (INT); DCL p REF package := ->p1 ,sum INT := 0; DO WHILE p /= NULL; sum +:= p->.i + p->.j; p := p->.NEXT; OD; RETURN sum; END; #(NIL): PROC() (package); RETURN [ 0, 0, NULL]; END; */ ENDNEWTYPE;
This is not the whole story, however. The ADT directive allows finger tip control of how the type itself, assignment, equality and initial value are generated.
The following subsections detail the code generation strategy. The SEIZE column shows whether sdl2chill will generate a SEIZE statement for making identifiers visible in separate modules in the CHILL code. The differences in strategy for Samsung and ETRI CHILL is due to somewhat different compiler properties.
ADT(E(x)) | Translation action | SEIZE? |
---|---|---|
E(G) |
Use = if possible1, else generate yEqual_<sort> procedure |
SEIZE if yEqual |
E(S) |
Use = |
no SEIZE |
E(B) |
Use yEqual_<sort>, assume user supplied |
SEIZE |
E(H) |
Use yEqual_<sort>, assume user supplied |
no SEIZE |
E |
= E(B) |
|
- (default) |
= E(G) |
|
Samsung CHILL and ETRI CHILL differ here. The table below shows the decision table used with the "G" letter in the above situations.
X(G) | ETRI | Samsung |
---|---|---|
E(G) |
yEqual_<sort> for array and struct, = otherwise |
Use = |
K(G) |
yMake_<sort> for struct and array |
Tuple for struct, |
A(G) |
Use := |
Use := |
sdl2chill recognizes a number of directives given mainly in SDL comments. The #ADT and #OP used in abstract data types are examples of such directives. These directives were described in the section User Defined Operators in connection with abstract data types and are not further discussed here.
A directive has the general structure:
Upper and lower case letters are considered to be equal in directive names.
Take as an example the directive:
/*#O
P (B) */
This comment will be recognized as a directive only if no other character is inserted in the sequence /*#OP
.12 After this part spaces and carriage returns may be inserted freely.
You may prefix a directive name by "CHILL" or "C" to condition the recognition of the directive to sdl2chill or to the Cadvanced/Cbasic Code Generator respectively.
The #ALT directive placed immediately in an output action makes for a mapping to the CROS initial signals/broadcast facility.
/*#CODE DCL node processorId := ...; */ ... output MySig /*#ALT 'IN node' */;
translates to:
SEND MySig IN node;
The purpose of the separate feature directive is to specify the file structure of the generated program. Both the division of the system into a number of files and the actual file names can be specified. There are two ways this information can be given.
sdl2chill can generate separate files for the system, for a block, and for a process. The #SEPARATE directive should in all cases be placed directly after the first semicolon in the system, block, or process heading; see the following example.
system S; /*#SEPARATE 'filename' */ block B; /*#SEPARATE */ process P1; /*#SEPARATE */ process P2 (1, ); /*#SEPARATE */
As can be seen a file name should be enclosed between quotes. sdl2chill will append appropriate extensions to this name when it generates code.
If no file name is given in the directive, the name of the system, block, or process will be used to obtain a file name. In such a case the file name will be the same as the name of the unit with the appropriate extension (.ch
or .o
) depending on contents. Characters that are not letters, digits or underlines are stripped from the file name.
sdl2chill makes sure identifiers are visible by generating suitable SEIZE statements in the separate modules. Depending on the SDE usage mode, extra context directives should be generated, cf. the environment variable SEPCOM in Samsung/ETRI CHILL. To control whether such context directives are generated, the UNIX environment variable
SDT_USE_INCLUDE
should be set. By default no such context directives are generated.
In the following example a system structure and the #SEPARATE directives are given. This example is then used to show the generated file structure depending on selected generation option.
system S; /*#SEPARATE 'Sfile' */ block B1; /*#SEPARATE */ process P11; /*#SEPARATE 'P11file' */ process P12; block B2; process P21; process P22; /*#SEPARATE */
If full separate generation is selected in the SDT Analyzer interface then the following files will be generated13:
|
B1.ch |
P11file.ch |
P12.ch |
B2.ch |
P21.ch |
P22.ch |
Makefile (SDE dependent) |
The .ch
files contain the CHILL code generated for the corresponding SDL unit and the Makefile
is the makefile for compiling and linking the application program.
If user defined separate generation is selected then the following files will be generated:
|
Contains code for units S, B2, P21 |
|
Contains code for units B1, P12 |
|
Contains code for unit P11 |
|
Contains code for unit P22 |
|
|
The user defined separate generation option thus makes it possible for a user to completely decide the file structure for the generated code. The comments on files and extensions given above are of course also valid in this case.
If you select the "no separate generation" option the following files will be generated:
|
Contains code for all units |
|
|
The comments on files and extensions earlier are valid even here.
Generally a system should be divided into manageable pieces of code, that is, for a large system full separate generation should be used, while for a small system no separate generation ought to be used. The possibility to regenerate and recompile only parts of a system usually compensates for the overhead in generating and compiling several files for a large system
When you write CHILL code that is to be included in a generated program it is often necessary to refer to name strings of objects defined in SDL. The name string of an SDL object is, however, transformed when it is translated to CHILL. A prefix, which is a sequence of characters, is added to the SDL name string to make the CHILL name unique in the CHILL program. Furthermore, all characters in SDL name strings which are not allowed in a CHILL name string are removed. The prefixes are calculated by looking at the structure of definitions in the actual scope and in all scopes above. This means that adding a declaration at the system level might change all prefixes in blocks and processes contained in the system. As a consequence it is almost impossible to know the prefix of an object in advance.
To be able to write CHILL code and use the name string of SDL objects in that code, sdl2chill provides the directive #SDL which is used in CHILL code to translate an SDL name string to the corresponding CHILL name string.
The syntax of the #SDL directive is as follows:
#SDL (SDL name)
or
#SDL (SDL name, entity class name)
There is also a short form for the directive. No characters are allowed between the # character and the (in this form.
#(SDL name)
or
#(SDL name, entity class name)
Replace SDL name
with the name string of an object in the SDL definition and entity class name
by any of the following identifiers (upper and lower case letters are considered to be equal):
This list contains all entity classes, which means that not all of the entries are relevant for practical use. When a #SDL directive is found in included CHILL code, sdl2chill first identifies which SDL object is referred and then replaces the directive by the CHILL name string for that object. The search for the SDL object starts in the current scope (the scope where the CHILL code is included), and follows the scope hierarchy outward to the system definition, until an appropriate SDL object is found. An appropriate SDL name is considered to be found if it has the specified name string and is in the specified entity class. If no entity class name is given the search is performed for all entity classes.
The table in the subsection SDL Predefined Types gives the direct translation between an SDL name and the corresponding CHILL name or expression. For these names the #SDL directive should not be used.
You can include your own CHILL code in tasks by using the #CODE directive. This directive has the following syntax:
/*#CODE CHILL code that should be included in the generated code. */
Type the directive name on the first line and the CHILL code on the following lines up to the end of comment symbol.
A #CODE directive can be placed:
The CHILL code in the directives is textually included in the generated code at the position of the directive. If, for example, a code directive is placed between two assignment statements, the code in the directive is inserted between the translated version of the assignment statements.
Note: sdl2chill handles the CHILL code in directives as text and performs no check that the code is valid CHILL code. |
The code directive is included as a facility in sdl2chill to provide experienced users an escape possibility to the target language CHILL. This increases the application range of sdl2chill.
An example of a possible use of the code directive is: An algorithm for some computation, which in the SDL description is only indicated as task with an informal text, could be implemented in CHILL. In this case the directive #SDL described in the previous subsection probably will become useful to access variables and formal parameters defined in SDL.
Some general hints on how to write CHILL code that can be included into an application program can be found in the last part of the section User Defined Operators.
SDL and CHILL use the same symbols for start and end of comments. To have CHILL comments within the code that is included in any directive, the CHILL end-of-line comment must be used.
The #CODE directive can also be used to include CHILL definitions and declarations, for example mode definitions, locations declarations and procedure definitions into the generated CHILL program. This version of the code directive has the same syntax as the code directive for including CHILL code in task:
/*#CODE CHILL code containing for example: - mode definitions - location declarations - procedure definitions */
Code directives to include CHILL declarations may, generally speaking, be placed immediately after a semicolon that ends a declaration in SDL. More precisely it is allowed to place a #CODE directive after the semicolon that ends:
In the following small PR example the allowed positions are marked with an * followed by a number.
system s; *1 signal s1, s2(integer); *2 channel c1 from env to b1 with s1, s2; *3 newtype n ... endnewtype n; *4 block b1; *5 signalroute sr1 from env to p1 with s1, s2; *6 connect c1 with sr1; *7 process p1 (1,1); *8 signalset s1, s2; *9 dcl a n; *10 start; ... state ...; ... endprocess p1; *11 endblock b1; *12 endsystem s1;
A code directive is considered to belong to the unit where it is defined and the data statements within the directive are thus placed among the other CHILL statements generated for that unit. In the example above directives at positions 1, 2, 3, 4, 12 belong to system s, directives at positions 5, 6, 7, 11 belong to block b1, while directives at positions 8, 9, 10 belong to process p1. Only one code directive may be placed at each available position.
The SDL declarations made in the corresponding unit are available in the code directives and can as usual be reached using the #SDL directive. All definitions and declarations made in code directives are of course available in code directives in tasks in the corresponding unit or in its subunits.
The general hints on how to write CHILL code that fits into a generated CHILL program given in the section User Defined Operators and in the section Applying SDL Names in CHILL Code -- Directive #SDL are also applicable here.
Other possible mechanisms for interfacing existing code include packages, external synonyms and external procedures.
For each sort defined in an SDL system (both predefined sorts and user defined sorts), sdl2chill defines implicitly the prefix operator #CODE with the following signature:
#CODE : Charstring -> S;
where S denotes the actual sort name. This operator or rather these operators make it possible to access e.g. locations, procedures and built-in procedures defined in CHILL using the #CODE directive in SDL expressions without violating the syntactic and static semantic rules of SDL.
During SDL to CHILL translation, sdl2chill will just copy the actual Charstring parameter into the generated CHILL code at the place where the #CODE operator is applied.
Suppose that x
and y
are SDL variables, which are translated to z72_x
and z73_y
, that a
and b
are CHILL locations, and p
is a CHILL procedure defined in #CODE directives.
SDL expression | CHILL expression |
---|---|
|
|
|
|
|
|
|
|
Within the Charstring parameter of a #CODE operator the #SDL directive is available in the same way as in other included CHILL code. This is shown in the expression in the last line of the example above.
As there is one #CODE operator for each sort in the system, it is sometimes necessary to qualify the operator with a sort name to make it possible for the SDL Analyzer to resolve which operator that has been used. If, for example, the question and all answers in a decisions are given as applications of #CODE operators, then it is not possible to determine the type for the decision. One of the #CODE operators should then be qualified with a sort name to resolve the conflict.
DECISION #CODE('a'); (#CODE('1')) : TASK ...; (#CODE('2')) : TASK ...; ENDDECISION;
In this case the sort of the decision cannot be resolved. To overcome this problem the question could be written as
DECISION TYPE integer #CODE('a');
When an SDL name is translated to a CHILL name, a prefix is normally added to the name string given in SDL. This prefix is used to prevent name conflicts in the generated code, as SDL has other scope rules than CHILL and also allow different objects defined in the same scope to have the same name string, if the objects are of different entity classes. It is for example allowed in SDL to have a sort, a variable, and a procedure with the same name string defined in a process. So the purpose of the prefixes is to make each translated SDL name to a unique name in the CHILL program.
A generated CHILL name string for an SDL object contains four parts in the following order:
A CHILL name string may contain letters, digits, and underline "_" and must start with a letter.
The sequence of characters that make the name string unique is determined by the position of the actual declaration in structure of declarations in the system:
0, 1, 2, .. , 9, a, b, .., z
. 00, 10, 20, .., 90, a0, .., z0, 01, 11, 21, .., 91, a1, .., z1, ......, 0z, 1z, 2z, .., 9z, az, .., zz
.The total sequence making a name string unique is now constructed from the "declaration numbers" for the actual unit and its parents, that is the units in which it is defined, starting from the top.
If, for example, a sort is defined as the 5th declaration in a block that in turn is the 12th declaration in the system, then the total sequence will be b4 (if not more than 36 declaration are present on any of the two levels).
Examples of generated name strings:
This strategy for naming objects in the generated code should be used in all normal situations, as it guarantees that no name conflicts occur. sdl2chill offers, however, possibilities to change this strategy. In the user interface of the Analyzer and sdl2chill it is possible to select one of the following strategies: full prefix, entity class prefix, no prefix, or special prefix. Full prefix is default and is the strategy described above. If entity class prefix is selected, then the prefix that is concatenated with the SDL name string will be in accordance with the table below and depends only on the entity class of the object.
Using entity class prefix means that the user must guarantee that no name conflict occurs. It also means, however, that the generated name strings are predictable and thus simplifies writing CHILL code where the SDL names are used. You only have to look for name conflicts within entity classes, for example not having two sorts with the same name string. The entity class prefixes handle the case when two objects of different entity class have the same name string. Note that the table above contains all entity classes. Not all of the items are actually used by sdl2chill.
The third alternative, no prefix, means of course that no prefixes are added to the SDL name string. The name string in the CHILL program will then be the SDL name string with the characters that are not allowed in CHILL name strings (everything except letters, digits, and underline) stripped off. In this case, you must guarantee that no name conflict occurs and that the stripped name string is allowed as a CHILL name string, that is, that it begins with a letter.
In the fourth alternative, special prefix, full prefixes are used for all entity classes except variable, formal parameter, sort, and syntype. For these entity classes no prefix is used.
As was said in the beginning of this subsection, you should have a good reason for selecting anything but the full prefix, as it could be very difficult to spot name conflicts. The compiler will in some cases find a conflict, but may in other cases consider the program as legal and generate an executable program with a possibly unwanted behavior.
When sdl2chill need auxiliary locations, these are usually prefixed with
yAux_<...>
Synthetic procedures (constructors, operator implementations) generated by sdl2chill are also prefixed with a lower case "y", e.g.
yMake_<mode>
If you wish to decide the name string of an object in generated code yourself you can use the #NAME directive. Place the directive directly after the name string in the declaration of the object. It should contain the desired name string to be used in the generated code within quotes.
NEWTYPE S /*#NAME 'S' */ STRUCT a Integer; b Boolean; ADDING OPERATORS Op myTest /*#NAME 'OtherName' */ : S, S -> Boolean; ENDNEWTYPE;
The name string defined in a #NAME directive will be used everywhere that the SDL name is used in the generated code, with one exception: the name of the files for generated code are not affected by the usage of #NAME directives.
Priorities and other OS directives of CROS can be assigned to processes and signals using the directive #PRIO. Exact syntax and how this will affect the behavior of the generated CHILL program is described in the CROS documentation. Effectively, the string in the directive is passed as is to the CHILL code. See also Example 306.
You can assign priority to a process type. The #PRIO directives for processes should be placed directly after the process heading in the definition of the actual process type, as shown in Example 338.
Process P1; /*#PRIO 'PRIORITY 4' */ Process P2(1,1); /*#PRIO 'PRIORITY 2' */ ... Create P1; Create P2;
You can assign a CHILL defined priority to a signal type or to the output of a specific signal value. The #PRIO directives for signals should be placed in the signal definition and in the output actions as shown in Example 338. A #PRIO directive specified in an output action will override a #PRIO directive possibly specified for the actual signal type.
Signal S /*#PRIO 'PRIORITY 6' */; ... Output S; ... Output S /*#PRIO 'PRIORITY 1' */;
The #MAIN directive is used to include initialization code that should be executed before any process transitions are started. The directive should be placed in the system definition directly after the system heading.
System S; /*#MAIN CHILL code for initialization */
The #MAIN directive has exactly the same structure as the #CODE directive for including code in tasks. The included code will, however, be placed in the system initialization procedure "<system>_main()" in the system module
and it will be executed after the initialization of the internal structure, but before any transitions.
Normally, the system module will be labelled "main" which will enable to Samsung/ETRI SDEs to recognize this module as the program main entrypoint. The system initialization procedure "<system>_main()" is then called "inline" in the system module. It may be desirable to have this separate from the SDL (sub)system. The UNIX environment variable
SDT_USE_SEP_MAIN
(when set) will force sdl2chill to use the system name as the module label. It will then be the user's responsibility to start to the SDL system by calling the SDL system initialization procedure
<system>_main()
which is GRANTed out from the system module.
You can specify that a number of user defined and precompiled units (e.g. manually written CHILL modules) shall be linked together with a generated application program. You do this in a #WITH directive that should be placed in the system definition directly after the system or package heading.
System S; /*#WITH 'file1.o' 'file2.o' */
Within the #WITH directive, the names of the object files that are to be included in the link operation should be given between quotes, as in the example above. These file names will then be included literally14 in the call to chmf
, see Building and Running a CHILL Program from SDT.
The makefile will, however, not include any definition of how to compile the corresponding source files, as it is impossible for sdl2chill to know the compilation options or even what compiler the user wants.
To interface CHILL code from outside the SDL system, it may be necessary to use an #ENVIRONMENT directive that should be placed in the system definition directly after the system heading. Combined with SEIZE statements in a #CODE directive this will make such "foreign" identifiers visible in the generated code.
System S; /*#WITH 'file1' 'file2' */ /*#ENVIRONMENT 'file1.sp' 'file2.sp' */
Within the #ENVIRONMENT directive the names of the files should be inside quotes, as in the example above. No extension is added. This generates suitable #include
statements. A user that knows how to interface to routines in other languages in a CHILL program, can with this knowledge and the #ENVIRONMENT directive and the #WITH directive link modules written in another language together with the generated program.
Note: The #ENVIRONMENT directive will only affect the generated CHILL code. There will be no change in the call to |
Note: There may be only one #ENVIRONMENT directive per system or package. |
The #CHILL directive is used with packages to interface system parts which are programmed in CHILL, see Package.
The #PIDLIT directive enables you to identify the PId values of initially created processes. Place the #PIDLIT directive directly after the process heading. It should contain the name of the to be associated synonym within quotes as shown in Example 343 below. In sdl2chill, because output without to is not supported, you may use a #PIDLIT directive to easily get hold of the PId value of an initially created process instance in order to output a signal to it15.
Synonym Pa_lit /*#NAME 'Pa_lit'*/ PId = NULL; ... Process Pa(1,1);/*#PIDLIT 'Pa_lit' */ ... Output my_signal to Pa_lit;
In case you create more than one initial instance of a process, the identifying synonym must be an array of which the item sort is PId and the number of items is equal to the number of initially created instances. See also Example 343.
Syntype index = integer Constants 1:10 Endsyntype; Newtype PId_array Array(index, PId) Endnewtype; Synonym Pb_lits /*#NAME 'Pb_lits' */ PId_array = (. NULL .); ... Process Pb(1,10);/*#PIDLIT 'Pb_lits' */ ... Output my_signal to Pb_lits(10);
The application (or application part) generated with sdl2chill can be viewed as having three components:
In the SDL system processes are created and stopped, transitions are executed, signals are sent from one process to another initiating new transitions, timer signals are sent, and so on. These are examples of internal actions that only affect the execution of the SDL system. An SDL system communicates with its environment by sending signals to the environment and by receiving signals from the environment.
CROS initial signals may also be used to this end.
The SDL system may be viewed as a CHILL module interfaced to via signals. This makes it easy to plug in a system as an application program part anywhere in your CHILL software structure and as the interface definition is also generated by sdl2chill, consistency check is fully catered for by CHILL.
The environment of the SDL system consists of CROS, other application program parts, the hardware, a network of computers and so on. In this world other actions than just signal sending and receiving are required. Examples of some actions that an application may want to perform are:
Such actions can efficiently and reliably be implemented in CHILL.
The system interface module is the place where the two worlds, the SDL system and the environment, meet. Here signals sent from the SDL system to the environment can induce all kinds of events in the environment, and events in the environment might cause signals to be sent into the SDL system. The system interfacing code may be collected in a separate interface module or, if more convenient, embedded in the application program part(s) which the SDL system is connected to. Definitions of the signals connecting the SDL system to its environment is provided by sdl2chill, but the actual functionality of the system interface module, of course, you must provide yourself because sdl2chill has no knowledge of this. How to write the system interface module is described in the next section.
When it comes to system architecture, utilization of the application (parts) generated by sdl2chill is very flexible. In a distributed system an application might consist of several communicating SDL systems. Each SDL system will become one executable program. It might execute either as an operating system process (e.g. UNIX process), or it might execute in a processor of its own, communicating over a network with other processors. There can of course also be combinations of these. Distribution is facilitated by means of the CROS initial signal/broadcast.
With sdl2chill, interfacing to an SDL system as shown in the below example, is very simple:
SDL-PR specification:
system DemonGame; signal Newgame, Probe, Result, Endgame, ... endsystem DemonGame;
Generated CHILL:
#include ... /* If SDT_USE_INCLUDE is set */ DemonGame: MODULE GRANT ALL; ... END DemonGame;
System interface module:
#include ...ApplyDemonGame:
MODULE
SEIZE
Newgame
,Probe
,Result
,Endgame
...
END ApplyDemonGame;
This section is a complete example showing the SDL specification for a system called Demongame, and the CHILL code for connecting to it for the purpose of playing the game by giving commands from the workstation keyboard and showing results on the screen. The generated CHILL code for Demongame is also shown. The latter is not needed in order to write the system interface module, but it is included here anyhow in order to show the actual SDL to CHILL mapping for a non-trivial example.
SPEC MODULE REMOTE unixio; #include "DemonGameMan.sp" #include "signals.sp" ApplyDemonGame: MODULE GRANT ALL; SEIZE /* from DemonGameMan */ Newgame ,Probe ,Result ,Endgame ,Win ,Lose ,Score ,Game_Ack ,Main_P ; NEWMODE Commands = SET (Do_Quit ,S_Newgame ,S_Probe ,S_Result ,S_Endgame ); DCL to_command_tab ARRAY(0:4)Commands := [Do_Quit ,S_Newgame ,S_Probe ,S_Result ,S_Endgame ]; Read_Command: PROC() (Commands); DCL choice_no INT := 0 ; printf("\n"); printf("Newgame: 1 \n"); printf("Probe : 2 \n"); printf("Result : 3 \n"); printf("Endgame: 4 \n"); printf("Quit : 0 \n"); scanf("%d", ->choice_no); IF choice_no < 0 OR choice_no > 4 THEN RETURN Read_Command(); ELSE RETURN to_command_tab(choice_no); FI; END Read_Command; Report_Win: PROC(); printf ("Win \n"); END Report_Win; Report_Lose: PROC(); printf ("Lose \n"); END Report_Lose; Report_Score: PROC(Score INT); printf ("Score is: %d \n", Score); END Report_Score; DemonGameInterface: PROCESS(); DCL Game_P INSTANCE := NULL; DCL int_parm INT; DO WHILE TRUE; CASE Read_Command() OF (S_Newgame): SEND Newgame TO Main_P; RECEIVE CASE (Game_Ack IN Game_P): ; ESAC; (S_Probe): IF Game_P /= NULL THEN SEND Probe TO Game_P; RECEIVE CASE (Win): Report_Win(); (Lose): Report_Lose(); ESAC; FI; (S_Result): IF Game_P /= NULL THEN SEND Result TO Game_P; RECEIVE CASE (Score IN int_parm): Report_Score(int_parm); ESAC; FI; (S_Endgame): SEND Endgame TO Main_P; Game_P := NULL; (Do_Quit): STOP; ESAC; OD; END DemonGameInterface; Start_ApplyDemonGame: PROC(); START DemonGameInterface(); END Start_ApplyDemonGame; END ApplyDemonGame;
system DemonGame; /*#ENVIRONMENT `ApplyDemonGame.sp',`signals.sp' */ signal Newgame, Probe, Result, Endgame, Win, Lose, Score(integer), Game_Ack(PId), Bump, Game_Id(PId); synonym Main_P PId = NULL; synonym Demon_P PId = NULL; /* No prefix assumed to be used, otherwise apply #NAME directive for all names in the System interface. */ procedure Start_ApplyDemonGame; external; channel C1 from env to GameBlock with Newgame, Probe, Result, Endgame; endchannel C1; channel C2 from GameBlock to env with Win, Lose, Score, Game_Ack; endchannel C2; channel C3 from DemonBlock to GameBlock with Bump; from GameBlock to DemonBlock with Game_Id; endchannel C3; block GameBlock referenced; block DemonBlock referenced; endsystem; block DemonBlock; connect C3 and R1, R2; signalroute R2 from env to Demon with Game_Id; signalroute R1 from Demon to env with Bump; process Demon (1, 1) referenced; endblock DemonBlock; process Demon; /*#PIDLIT `Demon_P' */ timer T; dcl game_p PID := NULL; start; set(now + 5, T); nextstate generate; state generate; input T; decision game_p = NULL; (false) : output Bump to game_p; set(now + 0.5, T); nextstate -; (true) : set(now + 10, T); nextstate -; enddecision; input Game_Id(game_p); nextstate -; endprocess Demon; block GameBlock; signal GameOver; connect C1 and R1, R2; connect C2 and R3, R7; connect C3 and R4, R6; signalroute R1 from env to Main with Newgame, Endgame; signalroute R7 from Main to env with Game_Ack; signalroute R3 from Game to env with Win, Lose, Score; signalroute R6 from Game to env with Game_Id; signalroute R5 from Main to Game with GameOver; signalroute R2 from env to Game with Probe, Result; signalroute R4 from env to Game with Bump; process Main (1, 1) referenced; process Game (0, 1) referenced; endblock; process Game; dcl Count Integer; start; task Count := 0; output Game_Id(self) to Demon_P; nextstate Losing; state Losing; input Probe; output Lose to sender; task Count := Count - 1; nextstate -; input Bump; nextstate Winning; state Winning; input Bump; nextstate Losing; input Probe; output Win to sender; task Count := Count + 1; nextstate -; state * ; input Result; output Score(Count) to sender; nextstate -; input Gameover; output Game_Id(NULL) to Demon_P; stop; endprocess; process Main; /*#PIDLIT `Main_P' */ dcl GameP Pid; start; call Start_ApplyDemonGame; nextstate Game_Off; state Game_Off; input Newgame; create Game; task GameP := offspring; output Game_Ack(offspring) to sender; nextstate Game_On; state Game_On; input Endgame; output GameOver to GameP; task GameP := null; nextstate Game_Off; endprocess;
/* Code generated by SDT SDL to ETRI CHILL Translator version 1.0 */
#include "sdl_support.sp"
#include "math64.sp"
#include "ApplyDemonGame.sp"
#include "signals.sp"
main:
MODULE
GRANT ALL;
SEIZE /* external entities defined at this level */
Start_ApplyDemonGame;
/*------------------------- SDL Synonyms ----------------*/
DCL Main_P INSTANCE;
DCL Demon_P INSTANCE;
SIGNAL
Newgame
,Probe
,Result
,Endgame
,Win
,Lose
,Score = (INT)
,Game_Ack = (INSTANCE)
,Bump
,Game_Id = (INSTANCE)
,GameOver
,T
;
/*****
* PROCESS Main
* <<SYSTEM DemonGame/BLOCK GameBlock>>
******/
Main: PROCESS(parent INSTANCE);
NEWMODE
states = SET(start_state, Game_Off, Game_On)
;
DCL
offspring INSTANCE := NULL
,sender INSTANCE := NULL
,state states := start_state
,GameP INSTANCE := NULL
;
DO WHILE TRUE;
CASE state OF
(start_state):
Start_ApplyDemonGame();
state := Game_Off;
GOTO SDL_next_state;
(Game_Off):
RECEIVE CASE NONPERSISTENT SET sender;
(Newgame):
offspring := START Game(THIS) ;
GameP := offspring;
SEND Game_Ack(offspring) TO sender;
state := Game_On;
GOTO SDL_next_state;
ESAC;
(Game_On):
RECEIVE CASE NONPERSISTENT SET sender;
(Endgame):
SEND GameOver TO GameP;
GameP := NULL;
state := Game_Off;
GOTO SDL_next_state;
ESAC;
ESAC;
SDL_next_state: ;
OD;
END Main;
/*****
* PROCESS Game
* <<SYSTEM DemonGame/BLOCK GameBlock>>
******/
Game: PROCESS(parent INSTANCE);
NEWMODE
states = SET(start_state, Losing, Winning)
;
DCL
offspring INSTANCE := NULL
,sender INSTANCE := NULL
,state states := start_state
,Count INT
;
DCL
yAux_INSTANCE INSTANCE
,yAuxTO_INSTANCE INSTANCE
;
DO WHILE TRUE;
CASE state OF
(start_state):
Count := 0;
yAuxTO_INSTANCE := Demon_P;
yAux_INSTANCE := THIS;
SEND Game_Id(yAux_INSTANCE) TO yAuxTO_INSTANCE;
state := Losing;
GOTO SDL_next_state;
(Losing):
RECEIVE CASE NONPERSISTENT SET sender;
(GameOver):
GOTO L_xxLabel2;
(Probe):
SEND Lose TO sender;
Count := Count-1;
GOTO SDL_next_state;
(Result):
GOTO L_xxLabel1;
(Bump):
state := Winning;
GOTO SDL_next_state;
ESAC;
(Winning):
RECEIVE CASE NONPERSISTENT SET sender;
(GameOver):
GOTO L_xxLabel2;
(Probe):
SEND Win TO sender;
Count := Count+1;
GOTO SDL_next_state;
(Result):
GOTO L_xxLabel1;
(Bump):
state := Losing;
GOTO SDL_next_state;
ESAC;
ESAC;
L_xxLabel1: ;
SEND Score(Count) TO sender;
GOTO SDL_next_state;
L_xxLabel2: ;
yAuxTO_INSTANCE := Demon_P;
yAux_INSTANCE := NULL;
SEND Game_Id(yAux_INSTANCE) TO yAuxTO_INSTANCE;
STOP;
SDL_next_state: ;
OD;
END Game;
/*****
* PROCESS Demon
* <<SYSTEM DemonGame/BLOCK DemonBlock>>
******/
Demon: PROCESS(parent INSTANCE);
NEWMODE
states = SET(start_state, generate)
;
DCL
offspring INSTANCE := NULL
,sender INSTANCE := NULL
,state states := start_state
,game_p INSTANCE := NULL
;
DCL
yAux_BOOL BOOL
;
DCL
yTim_T SDL_Timer_Id
;
DO WHILE TRUE;
CASE state OF
(start_state):
SDL_Set_Timer(yTim_T, SDL_Time_Add(SDL_Now(), SDL_Duration_Lit(5, 0)), _T);
state := generate;
GOTO SDL_next_state;
(generate):
RECEIVE CASE NONPERSISTENT SET sender;
(Game_Id IN game_p):
GOTO SDL_next_state;
(T):
IF game_p=NULL
THEN
SDL_Set_Timer(yTim_T, SDL_Time_Add(SDL_Now(), SDL_Duration_Lit(10, 0)), _T);
GOTO SDL_next_state;
ELSE
SEND Bump TO game_p;
SDL_Set_Timer(yTim_T, SDL_Time_Add(SDL_Now(),
SDL_Duration_Lit(0, 500000000)), _T);
GOTO SDL_next_state;
FI;
ESAC;
ESAC;
SDL_next_state: ;
OD;
END Demon;
DemonGame_ModuleInit:
PROC();
Main_P := NULL;
Demon_P := NULL;
Main_P := START Main(NULL);
Demon_P := START Demon(NULL);
END DemonGame_ModuleInit;
Init_SDL_Support();
DemonGame_ModuleInit();
END
main;
sdl2chill translates SDL-92 input to CHILL. There are, however, a set of implementation dependencies and restrictions that are discussed in this section.
The restrictions in the SDT Analyzer, which of course also affect sdl2chill, are summarized below. For more information see The SDT Analyzer.
sdl2chill introduces additional implementation dependencies on the allowed set of SDL concepts:
provided true;
" is usedThe following SDL-92 features are incorporated in sdl2chill:
The following SDL-96 features are incorporated in sdl2chill:
Due to the implementation of Integer using 32-bit integers in CHILL, there is a restriction in range for Integer values. Integers must be in the range [-231,231-1]. There are in the same way restrictions both in range and precision for Real, Time, and Duration. In the interface to the SDL support the literals of Real, Time, and Duration are represented by two 32-bit integers. The first integer of Time, and Duration represents the number of seconds and the second integer represents the number of nanoseconds.
chmf.
sum
is the one explicitly declared in the example.chmf
step, see Generating a CHILL Program.