Make it as simple as possible, but not simpler. A. Einstein
Oberon is a general-purpose programming language that evolved from Modula-2. Its principal new feature is the concept of type extension. It permits the construction of new data types on the basis of existing ones and provides relations between them.
This report is not intended as a programmer's tutorial. It is intentionally kept concise. Its function is to serve as a reference for programmers, implementors and manual writers. What remains unsaid is mostly left so intentionally, either because it would require one to commit the definition when a general commitment appears as unwise.
A language is an infinite set of sentences, namely the sentences well formed according to its syntax. In Oberon, these sentences are called compilation units. Each unit is a finite sequence of symbols from a finite vocabulary. The vocabulary of Oberon consists of identifiers, numbers, strings, operations, delimiters and comments. They are called lexical symbols and are composed of sequences of characters. (Note the distinction between symbols and characters).
To describe the syntax, an extended Backus-Naur Formalism called EBNF is used. Brackets [ and ] denote optionality of the enclosed sentential form, and braces { and } denote its repetition (possibly 0 times). Syntactic entities (non-terminal symbols) are denoted by English words expressing their intuitive meaning. Symbols of the language vocabulary (terminal symbols) are denoted by strings enclosed in quote marks or words written in capital letters, so-called reserved words. Syntactic rules (productions) are marked by a bar at the left margin of the line.
The representation of symbols in terms of characters is defined using the ASCII set. Symbols are identifiers, numbers, strings, operations, delimiters, and comments. The following lexical rules must be observed. Blanks and line breaks must not occur within symbols (except in comments, and in the case of blanks, in strings). They are ignored unless they are essential to separate two consecutive symbols. Capital and lower-case letters are considered as being distinct.
1. Identifiers are sequences of letters and digits. The first character must be a letter.
$ ident = letter { letter | digit }.Examples include
x scan Oberon GetSymbol firstLetter
2. Numbers are (unsigned) integers or real numbers. Integers are sequences of digits and may be followed by a suffix letter. The type is the minimal type to which the number belongs (see Section 6.1). If no suffix is specified, the representation is decimal. The suffix H indicates hexadecimal representation.
A real number always contains a decimal point. Optionally, it may also contain a decimal scale factor. The letter E (or D) is pronounced as 'times ten to the power of.' A real number is of type REAL, unless it has a scale factor containing the letter D, in which case it is of type LONGREAL.
$ number = integer | real. $ integer = digit {digit} | digit {hexDigit} ``H''. $ real = digit {digit} ``.'' {digit} [ScaleFactor]. $ ScaleFactor = (``E'' | ``D'') [``+'' | ``-''] digit {digit}. $ hexDigit = digit | ``A'' | ``B'' | ``C'' | ``D'' | ``E'' | ``F''. $ digit = ``0'' | ``1'' | ``2'' | ``3'' | ``4'' | ``5'' | ``6'' | ``7'' | ``8'' | ``9''.
Examples include
1987 100H = 256 12.3 4.567E8 = 456700000 0.57712566D-6 = 0.00000057712566
3. Character constants are either denoted by a single character enclosed in quote marks or by the ordinal number of the characters in hexadecimal notation followed by the letter X.
$ CharConstant = ``"'' character ``"'' | digit {hexDigit} ``X''.
4. Strings are sequences of characters enclosed in quote marks ("). A string cannot contain a quote mark. The number of characters in a string is called the length of the string. Strings can be assigned to and compared with arrays of characters (see Sections 9.1 and 8.2.4).
$ string = ``"''{character}``"''.
Examples include
"OBERON" "Don't worry!"
5. Operators and delimiters are the special characters, character pairs, or reserved words listed below. These reserved words consist exclusively of capital letters and cannot be used in the role of identifiers.
+ := ARRAY IS TO - ^ BEGIN LOOP TYPE * = CASE MOD UNTIL / # CONST MODULE VAR ~ < DIV NIL WHILE & > DO OF WITH . <= ELSE OR , >= ELSIF POINTER ; .. END PROCEDURE | : EXIT RECORD ( ) IF REPEAT [ ] IMPORT RETURN { } IN THEN
6. Comments may be inserted between any two symbols in a program. They are arbitrary character sequences opened by the bracket (* and closed by *). Comments do not affect the meaning of a program.
Every identifier occurring in a program must be introduced by a declaration, unless it is a predefined identifier. Declarations also serve to specify certain permanent properties of an object, such as whether it is a constant, a type, a variable or a procedure.
The identifier is the used to refer to the associated object. This is possible only in those parts of a program that are within the scope of the declaration. No identifier may denote more than one object within a given scope. The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local. The scope rule has the following amendments:
In its declaration, an identifier in the global scope may be followed by an export mark (*) to indicate that it is exported from its declaring module. In this case, the identifier may be used in other modules, if they import the declaring module. The identifier is then prefixed by the identifier designating its module (see Section 11). The prefix and the identifier are separated by a period and together are called a qualified identifier.
$ qualident = [ident ``.''] ident. $ identdef = ident [``*''].

A constant expression can be evaluated by a mere textual scan without actually executing the program. Its operands are constants (see Section 8). Examples of constant declarations include
N = 100 limit = 2*N - 1 all = {0..WordSize-1}
A data type determines the set of values that variables of that type may assume, and the operators that are applicable. A type declaration is used to associate an identifier with the type. Such association may be with unstructured (basic) types, or it may be with structured types, in which case it defines the structure of variables of this type and, by implication, the operator that are applicable to the components. There are two different structures, namely arrays and records, with different component selectors.
$ TypeDeclaration = identdef ``='' type. $ type = qualident | ArrayType | RecordType | PointerType | $ ProcedureType.
Examples include
Table = ARRAY N OF REAL Tree = POINTER TO Node Node = RECORD key: INTEGER; left, right: Tree END CenterNode = RECORD (Node) name: ARRAY 32 OF CHAR; subnode: Tree END Function* = PROCEDURE (x: INTEGER): INTEGER
The following basic types are denoted by predeclared identifiers. The associated operators are defined in Section 8.2, and the predeclared function procedures in Section 10.2. The values of a given basic type are as follows:
1. BOOLEAN the truth values TRUE and FALSE. 2. CHAR the characters of the extended ASCII set (0X...0FFX). 3. SHORTINT the integers between MIN(SHORTINT) and MAX(SHORTINT). 4. INTEGER the integers between MIN(INTEGER) and MAX(INTEGER). 5. LONGINT the integers between MIN(LONGINT) and MAX(LONGINT). 6. REAL real numbers between MIN(REAL) and MAX(REAL). 7. LONGREAL real numbers between MIN(LONGREAL) and MAX(LONGREAL). 8. SET the sets of integers between 0 and MAX(SET).
Types 3 to 5 are integer types, 6 and 7 are real types, and together they are called numeric types. They form a hierarchy; the larger type includes (the values of) the smaller type:
LONGREAL )= REAL )= LONGINT )= INTEGER )= SHORTINT
An array is a structure consisting of a fixed number of elements that are all of the same type, called the element type. The number of elements of an array is called its length. The elements of the array are designated by indices, which are integers between 0 and the length minus 1.
$ ArrayType = ARRAY length {``,'' length} OF type. $ length = ConstExpression.
A declaration of the form
ARRAY N0, N1, ... , Nk OF Tis understood as an abbreviation of the declaration
ARRAY N0 OF ARRAY N1 OF ... ARRAY Nk OF T
Examples of array types include
ARRAY N OF INTEGER ARRAY 10, 20 OF REAL
A record type is a structure consisting of a fixed number of elements of possibly different types. The record type declaration specifies for each element, called a field, its type and an identifier that denotes the field. The scope of these field identifiers is the record definition itself, but they are also visible within field designators (see Section 8.1) referring to elements of record variables.
$ RecordType = RECORD [``('' BaseType ``)''] FieldListSequence $ END. $ BaseType = qualident. $ FieldListSequence = FieldList {``;'' FieldList}. $ FieldList = [IdentList ``:'' type]. $ IdentList = identdef {``,'' identdef}.
If a record type is exported, field identifiers that are to be visible outside the declaring module must be marked. They are called public fields; unmarked fields are called private fields.
Record types are extensible; that is, a record type can be defined as an extension of another record type. In the examples above, CenterNode (directly) extends Node, which is the (direct) base type of CenterNode. More specifically, CenterNode extends Node with the fields name and subnode.
Definition: A type T0 extends a type T if it equals T or if it directly extends an extension of T. Conversely, a type T is a base type of T0 if it equals T0 or if it is the direct base type of a base type of T0.
Examples of record type include
RECORD day, month, year: INTEGER END RECORD name, firstname: ARRAY 32 OF CHAR; age: INTEGER; salary: REAL END
Variables of a pointer type P assume as values pointers to variables of some type T. The pointer type P is said to be bound to T, and T is the pointer base type of P. T must be a record or array type. Pointer types inherit the extension relation of their base types. If a type T0 is an extension of T and P0 is a pointer type bound to T0 then P0 is also an extension of P.
$ PointerType = POINTER TO type.
If p is a variable of type P = POINTER TO T then a call of the predefined procedure NEW(p) has the following effect (see Section 10.2): A variable of type T is allocated in free storage, and a pointer to it is assigned to p. This pointer p is of type P; the referenced variable p^ is of type T. Failure of allocation results in p obtaining the value NIL. Any pointer variable may be assigned the value NIL, which points to no variable at all.
Variables of a procedure type T have a procedure (or NIL) as value. If a procedure P is assigned to a procedure variable of type T, the (types of the) formal parameters of P must be the same as those indicated in the formal parameters of T. The same holds for the result type in the case of a function procedure (see Section 10.1). P must not be declared local to another procedure, and neither can it be a predefined procedure.
$ ProcedureType = PROCEDURE [FormalParameters].
Variable declarations serve to introduce variables and associate them with identifiers that must be unique within the given scope. They also serve to associate fixed data types with the variables.
$ VariableDeclaration = IdentList ``:'' type.
Variables whose identifiers appear in the same list are all of the same type. Examples of variable declarations (refer to the examples in Section 6) include
i, j, k: INTEGER x, y: REAL p, q: BOOLEAN s: SET f: Function a: ARRAY 100 OF REAL w: ARRAY 16 OF RECORD ch: CHAR; count: INTEGER END t: Tree
Variables of a pointer type T0 and VAR-parameters of a record type T0 may assume values whose type T1 is an extension of their declared type T0.
Expressions are constructs denoting rules of computation whereby constants and current values of variables are combined to derive other values by the application of operators and function procedures. Expressions consist of operands and operators. Parentheses may be used to express specific associations of operators and operands.
With the exception of sets and literal constants, that is numbers and character strings, operands are denoted by designators. A designator consists of an identifier referring to the constant, variable, or procedure to be designated. This identifier may possibly be qualified by module identifiers (see Sections 4 and 11), and it may be followed by selectors, if the designated object is an element of a structure.
If A designates an array, then A[E] denotes that element of A whose index is the current value of the expression E. Note that E must be of integer type. A designator of the form A[E1, E2, ... , En] stands for A[E1][E2] ... [En]. If p designates a pointer variable, p^ denotes the variable that is referenced by p. If r designates a record then r.f denotes the field f of r. If p designates a pointer, p.f denotes the field of the record p^ (that is, the dot implies dereferencing and p.f stands for p^.f) and p[E] denotes the element of p^ with index E.
The typeguard v(T0) asserts that v is of type T0; that is, it aborts program execution if it is not of type T0. The guard is applicable if
$ designator = qualident {``.'' ident | ``['' ExpList ``]'' | $ ``('' qualident ``)'' | ``^''}. $ ExpList = expression {``,'' expression}.
If the designated object is a variable then the designator refers to the variable's current value. If the object is a procedure, a designator without parameter list refers to that procedure. If it is followed by (possibly empty) parameter list, the designator implies an activation of the procedure and stands for the value resulting from its execution. The (type of the) actual parameters must correspond to the formal parameters as specified in the procedure's declaration (see Section 10).
Examples of designators (see the examples in Section 8) include
i (INTEGER) a[i] (REAL) w[3].ch (CHAR) t.key (INTEGER) t.left.right (Tree) t(CenterNode).subnode (Tree)
The syntax of expressions distinguishes between four classes of operators with different precedences (binding strengths). The operator ~ has the highest precedence, followed by multiplication operators, addition operators and relations. Operators of the same precedence associate from left to right. For example, x - y - z stands for (x - y) - z.
$ expression = SimpleExpression [relation SimpleExpression]. $ relation = ``='' | ``#'' | ``<'' | "<=" | ``>'' | ">=" | IN | IS. $ SimpleExpression = [``+'' | ``-''] term {AddOperator term}. $ AddOperator = ``+'' | ``-'' | OR. $ term = factor {MulOperator factor}. $ MulOperator = ``*'' | ``/'' | DIV | MOD | ``&''. $ factor = number | CharConstant | string | NIL | set | $ designator [ActualParameters] | ``('' expression ``)'' | $ ``~'' factor. $ set = ``{'' [element {``,'' element}] ``}''. $ element = expression [".." expression]. $ ActualParameters = ``('' [ExpList] ``)''.
The available operators are listed in Sections 8.2.1-8.2.4. In some instances, several different operations are designated by the same operator symbol. In these cases, the actual operation is identified by the type of the operands.
____________________________ Symbol Result ____________________________ OR logical disjunction & logical conjunction ~ negation ____________________________
These operators apply to BOOLEAN operands and yield a BOOLEAN result.
p OR q stands for "if p then TRUE, else q" p & q stands for "if p then q, else FALSE" ~ p stands for "not p"
_________________________ Symbol Result _________________________ + sum - difference * product / quotient DIV integer quotient MOD modulus _________________________
The operators +, -, *, and / apply to operands of numeric types. The type of the result is that operand's type which includes the other operand's type, except for division (/), where the result is the real type which includes both operand types. When used as operators with a single operand, - denotes sign inversion and + denotes the identity operation.
The operators DIV and MOD apply to integer operands only. They are related by the following formulas defined for any dividend x and positive divisors y:
x = (x DIV y) * y + (x MOD y) 0 <= (x MOD y) < y
_________________________________ Symbol Result _________________________________ + union - difference * intersection / symmetric set difference _________________________________
Sets are values of type SET. Set operators apply to operands of this type. The monadic minus sign denotes the complement of x; that is, -x denotes the set of integers between 0 and MAX(SET) that are not elements of x.
x - y = x * (- y) x / y = (x - y) + (y - x)
_________________________ Symbol Relation _________________________ = equal # unequal < less <= less or equal > greater >= greater or equal IN set membership IS type test _________________________
Relations are Booleans. The ordering relations <, <=, > and >= apply to the numeric types, CHAR and character arrays (strings). The relations = and # also apply to the type BOOLEAN and to set, pointer and procedure types. x IN s stands for 'x is an element of s.' x must be of an integer type, and s of type SET. v IS T stands for 'v is of type T' and is called a type test. It is applicable if
Assuming, for instance, that T is an extension of T0 and that v is a designator declared of type T0, then the test 'v IS T' determines whether the actually designated variable is (not only a T0, but also) a T. The value of NIL IS T is undefined.
Examples of expressions (refer to the examples in Section 7) include
1987 (INTEGER) i DIV 3 (INTEGER) ~p OR q (BOOLEAN) (i + j) * (i - j) (INTEGER) s - {8, 9, 13} (SET) i + x (REAL) a[i + j] * a[i - j] (REAL) (0 <= i) & (i <= 100) (BOOLEAN) t.key = 0 (BOOLEAN) k IN {i..j-1} (BOOLEAN) t IS CenterNode (BOOLEAN)
Statements denote actions. There are elementary and structured statements. Elementary statements are not composed of any parts that are themselves statements. They are the assignment, the procedure call, and the return and exit statements. Structured statements are composed of parts that are themselves statements. They are used to express sequencing and conditional, selective and repetitive execution. A statement may also be empty, in which case it denotes no action. The empty statement is included in order to relax punctuation rules in statement sequences.
$ statement = [assignment | ProcedureCall | IfStatement | $ CaseStatement | WhileStatement | RepeatStatement | $ LoopStatement | WithStatement | EXIT | $ RETURN [expression]].
The assignment serves to replace the current value of a variable by a new value specified by an expression. The assignment operator is written as ":=" and pronounced as becomes.
$ assignment = designator ":=" expression.
The type of the expression must be included by the type of the variable, or it must extend the type of the variable. The following exceptions hold:
Examples of assignments (see the examples in Section 7) include
i := 0 p := i = j x := i + 1 k := log2(i + j) f := log2 s := {2, 3, 5, 7, 11, 13} a[i] := (x + y) * (x - y) t.key := i w[i + 1].ch := ``A''
A procedure call serves to activate a procedure. The procedure call may contain a list of actual parameters that are substituted in place of their corresponding formal parameters defined in the procedure declaration (see Section 10). The correspondence is established by the positions of the parameters in the lists of actual and formal parameters respectively. There exist two kinds of parameters: variable and value parameters.
In the case of variable parameters, the actual parameter must be a designator denoting a variable. If it designates an element of a structured variable, the selector is evaluated when the formal/actual parameter substitution takes place; that is, before the execution of the procedure. If the parameter is a value parameter, the corresponding actual parameter must be an expression. This expression is evaluated prior to the procedure activation, and the resulting value is assigned to the formal parameter, which now constitutes a local variable (see also Section 10.1).
$ ProcedureCall = designator [ActualParameters].
Examples of procedure calls include
ReadInt(i) (see Section 10) WriteInt(j*2 + 1, 6) INC(w[k].count)
Statement sequences denote the sequence of actions specified by the component statements, which are separated by semicolons.
$ StatementSequence = statement {``;'' statement}.
$ IfStatement = IF expression THEN StatementSequence $ {ELSIF expression THEN StatementSequence} $ [ELSE StatementSequence] $ END.
If statements specify the conditional execution of guarded statements. The Boolean expression preceding a statement is called its guard. The guards are evaluated in sequence of occurrence, until one evaluates to TRUE, whence its associated statement sequence is executed. If no guard is satisfied, the statement sequence following the symbol ELSE is executed, if there is one.
An example is
IF (ch >= ``A'') & (ch <= ``Z'') THEN ReadIdentifier ELSIF (ch >= ``0'') & (ch <= ``9'') THEN ReadNumber ELSIF ch = 22X THEN ReadString END
Case statements specify the selection and execution of a statement sequence according to the value of an expression. First the case expression is evaluated; then the statement sequence is executed whose case label list contains the obtained value. The case expression and all labels must be of the same type, which must be an integer type or CHAR. Case labels are constants, and no value must occur more than once. If the value of the expression does not occur as a label of any case, the statement sequence following the symbol ELSE is selected, if there is one. Otherwise it is considered as an error.
$ CaseStatement = CASE expression OF case {``|'' case} $ [ELSE StatementSequence] END. $ case = [CaseLabelList ``:'' StatementSequence]. $ CaseLabelList = CaseLabels {``,'' CaseLabels}. $ CaseLabels = ConstExpression [".." ConstExpression].
An example is
CASE ch OF ``A''..``Z'': ReadIdentifier | ``0''..``9'': ReadNumber | 22X: ReadString ELSE SpecialCharacter END
While statements specify repetition. If the Boolean expression (guard) yields TRUE, the statement sequence is executed. The expression evaluation and the statement execution are repeated as long as the Boolean expression yields TRUE.
$ WhileStatement = WHILE expression DO StatementSequence END.
Examples include
WHILE j > 0 DO j := j DIV 2; i := i + 1 END WHILE (t # NIL) & (t.key # i) DO t := t.left END
A repeat statement specifies the repeated execution of a statement sequence until a condition is satisfied. The statement sequence is executed at least once.
$ RepeatStatement = REPEAT StatementSequence UNTIL expression.
A loop statement specifies the repeated execution of statement sequence. It is terminated by the execution of any exit statement within that sequence (see Section 9.9).
$ LoopStatement = LOOP StatementSequence END.
An example is
LOOP IF t1 = NIL THEN EXIT END; IF k < t1.key THEN t2 := t1.left; p := TRUE ELSIF k > t1.key THEN t2 := t1.right; p := FALSE ELSE EXIT END; t1 := t2 END
Although while and repeat statements can be expressed by loop statements containing a single exit statement, the use of while and repeat statements is recommended in the most frequently occurring situations, where termination depends on a single condition determined either at the beginning or the end of the repeated statement sequence. The loop statement is useful to express cases with several termination conditions and points.
A return statement consists of the symbol RETURN, possibly followed by an expression. It indicates the termination of a procedure, and the expression specifies the result of a function procedure. Its type must be identical to the result type specified in the procedure heading (see Section 10).
Function procedure require the presence of a return statement indicating the result value. There may be several, although only one will be executed. In proper procedures, a return statement is implied by the end of the procedure body. An explicit return statement therefore appears as an additional (probably exceptional) termination point.
An exit statement consists of the symbol EXIT. It specifies termination of the enclosing loop statement and continuation with the statement following that loop statement. Exit statements are contextually, although not syntactically, bound to the loop statement that contains them.
If a pointer variable or a variable parameter with record structure is of a type T0, it may be designated in the heading of a with clause together with a type T that is an extension of T0. Then the variable is guarded within the with statement as if it had been declared of type T. The with statement assumes a role similar to the type guard, extending the guard over an entire statement sequence. It may be regarded as a regional type guard.
$ WithStatement = WITH qualident ``:'' qualident DO $ StatementSequence END.
An example is
WITH t: CenterNode DO name := t.name; L := t.subnode END;
Procedure declarations consist of a procedure heading and a procedure body. The heading specifies the procedure identifier, the formal parameters and the result type (if any). The body contains declarations and statements. The procedure identifier is repeated at the end of the procedure declaration.
There are two kinds of procedures, namely proper procedures and function procedures. The latter are activated by a function designator as a constituent of an expression, and yield a result that is an operand in the expression. Proper procedures are activated by a procedure call. The function procedure is distinguished in the declaration by indication of the type of its result following the parameter list. Its body must contain a RETURN statement that defines the result of the function procedure.
All constants, variables, types and procedures declared within a procedure body are local to the procedure. The values of local variables are undefined upon entry to the procedure. Since procedures may be declared as local objects too, procedure declarations may be nested.
In addition to its formal parameters and locally declared objects, the objects declared in the environment of the procedure are also visible in the procedure (with the exception of those objects that have the same names as an object declared locally).
The use of the procedure identifier in a call within its declaration implies recursive activation of the procedure.
$ ProcedureDeclaration = $ ProcedureHeading ``;'' ProcedureBody ident. $ ProcedureHeading = $ PROCEDURE [``*''] identdef [FormalParameters]. $ ProcedureBody = $ DeclarationSequence [BEGIN StatementSequence] END. $ ForwardDeclaration = $ PROCEDURE ``^'' identdef [FormalParameters]. $ DeclarationSequence = $ {CONST {ConstantDeclaration ``;''} | $ TYPE {TypeDeclaration ``;''} | $ VAR {VariableDeclaration ``;''}} $ {ProcedureDeclaration ``;'' | ForwardDeclaration ``;''}.
A forward declaration serves to allow forward references to a procedure that appears later in the text in full. The actual declaration -- which specifies the body -- must indicate the same parameters and result type (if any) as the forward declaration, and it must be within the same scope.
An asterisk following the symbol PROCEDURE is a hint to the compiler, and specifies that the procedure is to be usable as a parameter and assignable to variables. (Depending on the implementation, the hint may be optional or required.)
Formal parameters are identifiers that denote actual parameters specified in the procedure call. The correspondence between formal and actual parameters is established when the procedure is called. There are two kinds of parameters, namely value and variable parameters. The kind is indicated in the formal parameter list. Value parameters stand for local variables to which the result of the evaluation of the corresponding actual parameter is assigned as initial value. Variable parameters correspond to actual parameters that are variables, and they stand for these variables. Variable parameters are indicated by the symbol VAR, value parameters by its absence. A function procedure without parameters must have an empty parameter list. It must be called by a function designator whose actual parameter list is empty too.
Formal parameters are local to the procedure; that is, their scope is the program text that constitutes the procedure declaration.
$ FormalParameters = ``('' [FPSection {``;'' FPSection}] ``)'' $ [``:'' qualident]. $ FPSection = [VAR] ident {``,'' ident} ``:'' FormalType. $ FormalType = {ARRAY OF} qualident | ProcedureType.
The type of each formal parameter is specified in the parameter list. For variable parameters, it must be identical to the corresponding actual parameter's type, except in the case of a record, where it must be a base type of the corresponding actual parameter's type. For value parameters, the rule of assignment holds (see Section 9.1). If the formal parameter's type is specified as
ARRAY OF Tthe parameter is said to be an open array parameter, and the corresponding actual parameter may be any array with element type T.
If a formal parameter specifies a procedure type then the corresponding actual parameter must be either a procedure declared globally or a variable (or parameter) of that procedure type. It cannot be a predefined procedure. The result type of a procedure can be neither a record nor an array.
Examples of procedure declarations include
PROCEDURE ReadInt(VAR x: INTEGER); VAR i: INTEGER; ch: CHAR; BEGIN i := 0; Read(ch); WHILE (``0'' <= ch) & (ch <= ``9'') DO i := 10*i + (ORD(ch) - ORD(``0'')); Read(ch) END; x := i END ReadInt PROCEDURE WriteInt(x: INTEGER); (* 0 <= x < 10.0E5 *) VAR i: INTEGER; buf: ARRAY 5 OF INTEGER; BEGIN i := 0; REPEAT buf[i] := x MOD 10; x := x DIV 10; INC(i) UNTIL x = 0; REPEAT DEC(i); Write(CHR(buf[i] + ORD(``0''))) UNTIL i = 0 END WriteInt PROCEDURE log2(x: INTEGER): INTEGER; VAR y: INTEGER; (* assume x > 0 *) BEGIN y := 0; WHILE x > 1 DO x := x DIV 2; INC(y) END; RETURN y END log2
The following tables list the predefined procedures. Some are generic procedures; that is, they apply to several types of operands. v stands for a variable, x and n for expressions, and T for a type.
Function procedures:
______________________________________________________________________________ Name | Argument type | Result type | Function _________|____________________|______________|________________________________ ABS(x) | numeric type | type of x | absolute value _________|____________________|______________|________________________________ ODD(x) | integer type | BOOLEAN | x MOD 2 = 1 _________|____________________|______________|________________________________ CAP(x) | CHAR | CHAR | corresponding capital letter | | | _________|____________________|______________|________________________________ | | | n ASH(x, n)| x, n: integer type| LONGINT | x * 2 , arithmetic shift _________|____________________|______________|________________________________ LEN(v, n)| v: array | LONGINT | the length of v in dimension n | n: integer type | | _________|____________________|______________|________________________________ LEN(v) | array type | LONGINT | LEN(v, 0) _________|____________________|______________|________________________________ MAX(T) | T = basic type | T | maximum value of type T | T = SET | INTEGER | maximum element of sets _________|____________________|______________|________________________________ MIN(T) | T = basic type | T | minimum value of type T | T = SET | INTEGER | 0 _________|____________________|______________|________________________________ SIZE(T) | T = any type | integer type| number of bytes required by T _________|____________________|______________|________________________________
Type conversion procedures:
____________________________________________________________________________ Name | Argument type| Result type| Function _________|_______________|_____________|____________________________________ ORD(x) | CHAR | INTEGER | ordinal number of x _________|_______________|_____________|____________________________________ CHR(x) | integer type | CHAR | character with ordinal number x _________|_______________|_____________|____________________________________ SHORT(x) | LONGINT | INTEGER | identity | INTEGER | SHORTINT | | LONGREAL | REAL | (truncation possible) _________|_______________|_____________|____________________________________ LONG(x) | SHORTINT | INTEGER | identity | INTEGER | LONGINT | | REAL | LONGREAL | _________|_______________|_____________|____________________________________ ENTIER(x)| real type | LONGINT | largest integer not greater than x | | | _________|_______________|_____________|____________________________________Note that ENTIER(i/j) = i DIV j
Proper procedures:
_____________________________________________________________________ Name | Argument types | Function __________|____________________________|_____________________________ INC(v) | integer type | v := v + 1 __________|____________________________|_____________________________ INC(v, x) | integer type | v := v + x __________|____________________________|_____________________________ DEC(v) | integer type | v := v - 1 __________|____________________________|_____________________________ DEC(v, x) | integer type | v := v - x __________|____________________________|_____________________________ INCL(v, x)| v: SET; x: integer type | v := v + {x} __________|____________________________|_____________________________ EXCL(v, x)| v: SET; x: integer type | v := v - {x} __________|____________________________|_____________________________ COPY(x, v)| x: character array, string| v := x | v: character array | __________|____________________________|_____________________________ NEW(v) | pointer type | allocate v^ __________|____________________________|_____________________________ HALT(x) | integer constant | terminate program execution __________|____________________________|_____________________________In HALT(x), x is a parameter whose interpretation is left to the underlying system implementation.
A module is a collection of declarations of constants, types, variables, and procedures, and a sequence of statements for the purpose of assigning initial values to the variables. A module typically constitutes a text that is compilable as a unit.
$ module = MODULE ident ``;'' [ImportList] DeclarationSequence $ [BEGIN StatementSequence] END ident ``.''. $ ImportList = IMPORT import {``,'' import} ``;''. $ import = ident [":=" ident].
The import list specifies the modules of which the module is a client. If an identifier x is exported from a module M, and if M is listed in a module's import list, then x is referred to as M.x. If the form 'M := M1' is used in the import list, that object declared within M1 is referenced as M.x.
Identifiers that are to be visible in client modules, that is outside the declaring module, must be marked by an export mark in their declaration.
The statement sequence following the symbol BEGIN is executed when the module is added to the system (loaded). Individual (parameterless) procedures can thereafter be activated from the system, and these procedures serve as commands.
An example is
MODULE Out; (* exported procedures: Write, WriteInt, WriteLn *) IMPORT Texts, Oberon; VAR W: Texts.Writer; PROCEDURE Write*(ch: CHAR); BEGIN Texts.Write(W, ch) END Write; PROCEDURE WriteInt*(x, n: LONGINT); VAR i: INTEGER; a: ARRAY 16 OF CHAR; BEGIN i := 0; IF x < 0 THEN Texts.Write(W, ``-''); x := -x END; REPEAT a[i] := CHR(x MOD 10 + ORD(``0'')); x := x DIV 10; INC(i); UNTIL x = 0; REPEAT Texts.Write(W, `` ''); DEC(n) UNTIL n <= i; REPEAT DEC(i); Texts.Write(W, a[i]) UNTIL i = 0 END WriteInt; PROCEDURE WriteLn*; BEGIN Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) END WriteLn; BEGIN Texts.OpenWriter(W) END Out.
The module SYSTEM contains definitions that are necessary to program low-level operations referring directly to resources particular to a given computer and/or implementation. These include, for example, facilities for accessing devices that are controlled by the computer, and facilities to break the data type compatibility rules otherwise imposed by the language definition. It is recommended that their use be restricted to specific low-level modules. Such modules are inherently non-portable, but are easily recognized due to the identifier SYSTEM appearing in their import lists. The subsequent definitions are those that hold for the NS32000 implementation, but they are applicable to most modern computers. Individual implementations may differ and include definitions that are particular to the specific, underlying computer.
Module SYSTEM exports the data type BYTE. No representation of values is specified. Instead, certain compatibility rules with other types are given:
The procedures contained in module SYSTEM are listed in the following tables. They correspond to single instructions compiled as in-line code. For details, the reader is referred to the processor manual. v stands for a variable, x, y, a, and n for expressions, and T for a type.
Function procedures:
_____________________________________________________________________________ Name | Argument types | Result type| Function _________|________________________|_____________|____________________________ ADR(v) | any | LONGINT | address of variable v _________|________________________|_____________|____________________________ BIT(a, n)| a: LONGINT | BOOLEAN | bit n of Mem[a] | n: integer type | | _________|________________________|_____________|____________________________ CC(n) | integer constant | BOOLEAN | Condition n _________|________________________|_____________|____________________________ LSH(x, n)| x: integer type of SET| type of x | logical shift | n: integer type | | _________|________________________|_____________|____________________________ ROT(x, n)| x: integer type or SET| type of x | rotation | n: integer type | | _________|________________________|_____________|____________________________ VAL(T, x)| T, x: any type | T | x interpreted as of type T _________|________________________|_____________|____________________________
Proper procedures:
________________________________________________________________________ Name | Argument types | Function _____________|_____________________|____________________________________ GET(a, v) | a: LONGINT | v := Mem[a] | v: any basic type | _____________|_____________________|____________________________________ PUT(a, x) | a: LONGINT | Mem[a] := x | x: any basic type | _____________|_____________________|____________________________________ MOVE(s, d, n)| s, d: LONGINT | Mem[d]...Mem[d+n-1] := | n: integer type | Mem[s]...Mem[s+n-1] _____________|_____________________|____________________________________ NEW(v, n) | v: any pointer type| allocate storage block of n bytes, | n: integer type | assign its address to v _____________|_____________________|____________________________________
This report was taken (with some minor corrections) out of
Martin Reiser, Niklaus Wirth,
"Programming in Oberon", Addison-Wesley, New York, 1992
with the permission of Niklaus Wirth.


|
Scientific Fortran Tools (SciFT)
1.2
|
Data Types | |
| type | elistiterator |
| Encapsulated IntegerListIterator. More... | |
| type | integerlist |
| The IntegerList class is a template class that provides linked lists. It stores a list of values and provides iterator-based access as well as insertions and removals. IntegerList features both STL-style iterators and Java-style iterators. For developers who already know STL, have the advantage of familiarity. More... | |
| type | integerlistiterator |
| This class use the List template declared into List.h90 file, please take a look to this file for details. More... | |
Public Member Functions | |
| integer function | ssize (this) |
| Returns the number of items in the list. More... | |
| subroutine, public | integerlist_test () |
| Test method. More... | |
Private Member Functions | |
| subroutine | initlist (this) |
| Constructor. More... | |
| subroutine | copylist (this, other) |
| Copy constructor. More... | |
| subroutine | destroylist (this) |
| Destructor. More... | |
| subroutine | show (this, unit, formatted) |
| Show. More... | |
| subroutine | save (this, ofileName) |
| Save the data in two column format in a selected unit. More... | |
| logical function | isempty (this) |
| Returns true if the list contains no items, otherwise returns false. More... | |
| subroutine | appendvalue (this, item) |
| Inserts a value at the end of the list. More... | |
| subroutine | appendfarray (this, array) |
| Inserts values at the end of the list. More... | |
| subroutine | prepend (this, item) |
| Inserts value at the beginning of the list. More... | |
| subroutine | insert (this, before, item) |
| Inserts value in front of the item pointed to by the iterator before. More... | |
| subroutine | erasefromptr (this, ptr) |
| Removes the item pointed to by the iterator ptr from the list. More... | |
| subroutine | erasefrompos (this, pos) |
| Removes the item in pos-th position in the list,. More... | |
| subroutine | eraseallexcept (this, posVec) |
| Removes all the items in the list except those identified with the position given by posVec vector. More... | |
| subroutine | eraseallexceptfirst (this, nItems) |
| Removes all the items in the list except this nItems-th first. More... | |
| subroutine | eraseallexceptlast (this, nItems) |
| Removes all the items in the list except this nItems-th last. More... | |
| subroutine | clear (this) |
| Removes all the items in the list. More... | |
| integer function | atfromptr (this, ptr) |
| Returns the item pointed to by the iterator ptr from the list. More... | |
| integer function | atfrompos (this, pos) |
| Returns the pos-th item from the list. More... | |
| subroutine | replacefromptr (this, ptr, item) |
| Replaces by item the item pointed to by the iterator ptr from the list. More... | |
| subroutine | replacefrompos (this, pos, item) |
| Replaces by item the pos-th item from the list. More... | |
| type(integerlistiterator) function, pointer | ptr (this, pos) |
| Returns the pointer associated to pos-th element. More... | |
| character(:) function, allocatable | str (this, formatted, prefix) |
| Converts to string. More... | |
| subroutine | tofstream (this, ofile) |
| Save the data in two column format in a selected unit. More... | |
| subroutine | showmylist (mylist) |
Definition at line 31 of file IntegerList.f90.
|
private |
Inserts values at the end of the list.
Definition at line 358 of file IntegerList.f90.
|
private |
Inserts a value at the end of the list.
Definition at line 331 of file IntegerList.f90.
|
private |
Returns the pos-th item from the list.
Definition at line 648 of file IntegerList.f90.
|
private |
Returns the item pointed to by the iterator ptr from the list.
Definition at line 637 of file IntegerList.f90.
|
private |
Removes all the items in the list.
Definition at line 610 of file IntegerList.f90.
|
private |
Copy constructor.
Constructs a copy of other
Definition at line 238 of file IntegerList.f90.
|
private |
Destructor.
Destroys the list. References to the values in the list, and all iterators over this list, become invalid.
Definition at line 259 of file IntegerList.f90.
|
private |
Removes all the items in the list except those identified with the position given by posVec vector.
Definition at line 505 of file IntegerList.f90.
|
private |
Removes all the items in the list except this nItems-th first.
Definition at line 549 of file IntegerList.f90.
|
private |
Removes all the items in the list except this nItems-th last.
Definition at line 576 of file IntegerList.f90.
|
private |
Removes the item in pos-th position in the list,.
Definition at line 482 of file IntegerList.f90.
|
private |
Removes the item pointed to by the iterator ptr from the list.
Definition at line 447 of file IntegerList.f90.
|
private |
|
private |
Inserts value in front of the item pointed to by the iterator before.
Definition at line 394 of file IntegerList.f90.
| subroutine, public integerlist::integerlist_test | ( | ) |
Test method.
Definition at line 833 of file IntegerList.f90.
|
private |
Returns true if the list contains no items, otherwise returns false.
Definition at line 321 of file IntegerList.f90.
|
private |
Inserts value at the beginning of the list.
Definition at line 372 of file IntegerList.f90.
|
private |
Returns the pointer associated to pos-th element.
Definition at line 708 of file IntegerList.f90.
|
private |
Replaces by item the pos-th item from the list.
Definition at line 683 of file IntegerList.f90.
|
private |
Replaces by item the item pointed to by the iterator ptr from the list.
Definition at line 672 of file IntegerList.f90.
|
private |
Save the data in two column format in a selected unit.
Definition at line 292 of file IntegerList.f90.
|
private |
Show.
Writes the list to out unit. It's Neccesarry that the method str is implemented in the child class
Definition at line 271 of file IntegerList.f90.
|
private |
Definition at line 817 of file IntegerList.f90.
| integer function integerlist::ssize | ( | class(integerlist), intent(in) | this | ) |
Returns the number of items in the list.
Definition at line 311 of file IntegerList.f90.
|
private |
Converts to string.
Definition at line 737 of file IntegerList.f90.
|
private |
Save the data in two column format in a selected unit.
Definition at line 793 of file IntegerList.f90.


HTML lists allow web developers to group a set of related items in lists.
An Unordered HTML List
- Coffee
- Tea
- Milk
- Coffee
- Tea
- Milk
Unordered HTML List
An unordered list starts with the
 tag. Each list item starts with the
tag. The list items will be marked with bullets (small black circles) by default:

Coffee

Tea

Milk

Ordered HTML List
An ordered list starts with the
 tag. Each list item starts with the
 tag. The list items will be marked with numbers by default:

Coffee

Tea

Milk


{{ define "main" }}
{{ partial "hero.html" . }}
{{ partial "stories.html" . }}
{{ partial "info.html" . }}
{{ partial "links.html" . }}
{{ partial "contact.html" . }}
{{ end }}
{{ define "footer-scripts" }}
{{ partial "common/google-maps.html" . }}
{{ end }}


Be one of the first members of the club.
We'll be sure to keep you in the loop. Stay tuned!
Request early access to the club for updates and early member benefits.


Diego Simeone hails Atletico draw at Granada as arguably best performance of the season
by FSA EditorDiego Simeone was frustrated not to beat Granada on Saturday given Atletico Madrid produced what he considered a strong performance.
Diego Simeone felt Atletico Madrid played perhaps their best game of the season in Saturday’s 1-1 LaLiga draw with Granada.
Renan Lodi opened the scoring at Nuevo Estadio de Los Carmenes after an hour only for German Sanchez to equalise seven minutes later.
The draw was Atleti’s seventh in their past 10 LaLiga matches and leaves them three points behind Barcelona and Real Madrid at the top of the table, having played a game more.
Simeone was happy with the performance, though, blaming Atletico’s failure to hold on for a win on a “careless moment” that allowed Sanchez to head in from a corner.
“This was our best performance of those away from home and also possibly of those at home too,” the coach told reporters.
“We were very consistent, especially in the first 30 minutes. Granada didn’t get close to our penalty area.
“We played a quite complete match, but we had a careless moment in the goal we conceded. But the team didn’t give up.”
Joao Felix was fit enough only to appear as a second-half substitute, having been struggling with an ankle injury since last month.
Simeone insists the 20-year-old must be given time to regain full fitness before he can be expected to make a significant impact.
“I act as a result of what I see in training,” he said. “He has to keep picking up the pace.
“He has great quality and talent and when he is fully fit he will contribute.”


Search For
The Search for... dialog allows the user to specify what they want to find, how the matching is to be done, and where and what files are to be searched.
Find This is the text to be searched for. It can be either a literal search string or a regular expression. Multiple search arguments can be specified here by using a vertical bar | to separate the arguments. To search for a vertical bar, place two vertical bars together like this ||.
Get Find Text From Specified File Specifies that the search strings are to be loaded from the specified file. Enter multiple search strings, one per line, in a simple text file and supply that filename to search for the specified strings.
Case Sensitive Specifies that the search is to be case-sensitive.
Exclude Comment Lines Specifies that matches which occur only within a Clarion comment are to be excluded from the search results. Only certain files, identified on the Options dialog, receive this special Clarion processing.
Match Pattern at Start of Line Matches the pattern if at the beginning of a line.
Match Pattern at End of Line Matches the pattern if at the end of a line.
Exact Match Only lines that match exactly.
Exclude Matching Lines Only lines that do not contain a match.
Use Regular Expressions The Find string as a regular expression. The search engine interprets all metacharacters as regular expressions.
Press this button to get regular expression help
Filenames Only Select this option to return one result line for each file that contains a match. All matches are not identified, only that the file contains a match.
Read File List from Specified File Specifies that the list of files to be searched is contained in a text file. Specify the full path and filename of files to be searched, one per line, in a simple text file and supply that file name to have the program search only the files in the supplied list.
Paths Search a semicolon delimited list of directories. The user can enter or paste directories into the path, select from the drop down list, or use the two buttons located to the right of the path. The ellipsis [...] button displays the Windows File Dialog and replaces the path with the selected folder. The plus [+] button displays the Windows File Dialog and appends a semicolon and the selected folder to the path.
Search Subdirectories Searches for matching files in the current directory and all subdirectories.
Levels Specifies how many subdirectory levels are to be searched. If the level is blank then all subdirectory levels are searched.
Files Specifies a file or files to search. Separate the file names with a semicolon, vertical bar, or space. Wildcards can be used in the filenames.
Exclude Specifies a file or files to exclude from the Results List. Separate the file names with a semicolon, vertical bar, or space. Wildcards can be used in the filenames.
Load Saved Results The Save Results dialog allows the user to save the results to a re-loadable result list file. This button is used to re-load a previously saved re-loadable result list file.
Search New Tab Press this button to begin the search and display the results on a new tab.
Search Press this button to begin the search.
Cancel Press this button to close the dialog and return to the main window without doing a search.


Employment
The Delaware Chester Community School (DCCS) leadership board is inviting candidates interested in teaching at DCCS to join its dedicated group of teachers.
DCCS offers training and devlepoment opportunities to all of its instructors. The following is a list of general area topics in need of instructors:
- Mandarin as a heritage language
- Mandarin as a second language
- Math (Pre-MathCounts, MathCounts, AMC8, AMC10)
- English Reading & Writing
- Public Speaking
- Debating
- Robotics
- Coding
- Chess
- Music Instruments
- Singing
- Dancing
- Drawing
- Arts & Crafts


In the Netherlands alone 1.8 million animals die every day for the food industry ... DAILY! Worldwide there are more than 60 billion animals kept for the food industry, on an unprecedented scale which will only continue to increase by one still growing world population.
In the Netherlands 40% of the total climate load is caused by the animal food industry. Worldwide this is about 20% which makes this a greater polluter than the whole transport sector with all its aircraft and oil tankers. It is simply bizarre how much water and food must be produced to feed a cow to ultimately achieve 1 kg of meat. Many meat eaters say the soybean industry is so bad for the environment, and yes that's right. However, more needs to be done when 75% of all soy nutrition goes to the animal industry. The result is one enormous attack on nature, acidification from farmland by the huge amounts of manure and massive deforestation.
Everything seems to indicate that one plant-based diet is many times healthier for us than an animal-based diet with proteins and fats. What a recognized fact is that processed meat like ham, salami, burgers and sausages, is carcinogenic and in the same WHO category such as smoking and asbestos. Also eating a lot of meat ensures more fat deposits in the blood vessels (cholesterol) which later in life can lead to various heart and vascular disease. I think that many of us are ready are for the next step. I like the concept of flexitarian whereas at least three vegan days a week must be completed. So no meat, no fish and no dairy, from breakfast until dinner, a completely vegetable day.


This section includes more detailed information on how to create and configure a SQL Server 2005 database for use with DotNetNuke.
1. In SQL Server Management Studio, in the Object Explorer, Select Databases for the SQL Server instance you wish to use, right-click and select the New Database option.
2. In the New Database dialog give the Database a name (in the example below the Databse is called Website), and click OK.
3. If you decide to use SQL Server Authorization then you will need to use a SQL Server Login. If you do not already have one created then you can create one by selecting Logins under Security, right click and select New Login.
4. Once you have created a Login you need to add that "Login" as a User for your new Database. To do this select the Database you just created, select the Users section, right click on Users and select the New Database User option. In the example shown below we are using the Database - DotNetNuke.
5. Enter the Login name in the text box, or choose the login name by clicking the elipsis button (...), make sure that the db_owner role, and Schema are selected, and click OK
Your database is now ready to be installed.
Back to Welcome page.


Test prototype
Prepare focus group objectives
Create Market research findings
Desgin production process
Develop initial marketing plan
Project management activities
Design quality assurance tests
Desgin document review


* You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { SnapshotVersion } from '../core/snapshot_version'; import { Timestamp } from '../core/timestamp'; import { assert, fail } from '../util/assert'; import * as misc from '../util/misc'; import { Document, MaybeDocument, NoDocument } from './document'; import { DocumentKey } from './document_key'; import { FieldValue, ObjectValue, ServerTimestampValue } from './field_value'; import { FieldPath } from './path'; /** * Provides a set of fields that can be used to partially patch a document. * FieldMask is used in conjunction with ObjectValue. * Examples: * foo - Overwrites foo entirely with the provided value. If foo is not * present in the companion ObjectValue, the field is deleted. * foo.bar - Overwrites only the field bar of the object foo. * If foo is not an object, foo is replaced with an object * containing foo */ export class FieldMask { constructor(readonly fields: FieldPath[]) { // TODO(dimond): validation of FieldMask } isEqual(other: FieldMask): boolean { return misc.arrayEquals(this.fields, other.fields); } } /** Represents a transform within a TransformMutation. */ export interface TransformOperation { isEqual(other: TransformOperation): boolean; } /** Transforms a value into a server-generated timestamp. */ export class ServerTimestampTransform implements TransformOperation { private constructor() {} static instance = new ServerTimestampTransform(); isEqual(other: TransformOperation): boolean { return other instanceof ServerTimestampTransform; } } /** A field path and the TransformOperation to perform upon it. */ export class FieldTransform { constructor( readonly field: FieldPath, readonly transform: TransformOperation ) {} isEqual(other: FieldTransform): boolean { return ( this.field.isEqual(other.field) && this.transform.isEqual(other.transform) ); } } /** The result of successfully applying a mutation to the backend. */ export class MutationResult { constructor( /** * The version at which the mutation was committed or null for a delete. */ readonly version: SnapshotVersion | null, /** * The resulting fields returned from the backend after a * TransformMutation has been committed. Contains one FieldValue for each * FieldTransform that was in the mutation. * * Will be null if the mutation was not a TransformMutation. */ readonly transformResults: FieldValue[] | null ) {} } export enum MutationType { Set, Patch, Transform, Delete } /** * Encodes a precondition for a mutation. This follows the model that the * backend accepts with the special case of an explicit "empty" precondition * (meaning no precondition). */ export class Precondition { static readonly NONE = new Precondition(); private constructor( readonly updateTime?: SnapshotVersion, readonly exists?: boolean ) { assert( updateTime === undefined || exists === undefined, 'Precondition can specify "exists" or "updateTime" but not both' ); } /** Creates a new Precondition with an exists flag. */ static exists(exists: boolean) { return new Precondition(undefined, exists); } /** Creates a new Precondition based on a version a document exists at. */ static updateTime(version: SnapshotVersion) { return new Precondition(version); } /** Returns whether this Precondition is empty. */ get isNone(): boolean { return this.updateTime === undefined && this.exists === undefined; } /** * Returns true if the preconditions is valid for the given document * (or null if no document is available). */ isValidFor(maybeDoc: MaybeDocument | null) { Iif (this.updateTime !== undefined) { return ( maybeDoc instanceof Document && maybeDoc.version.isEqual(this.updateTime) ); } else if (this.exists !== undefined) { Eif (this.exists) { return maybeDoc instanceof Document; } else { return maybeDoc === null || maybeDoc instanceof NoDocument; } } else { assert(this.isNone, 'Precondition should be empty'); return true; } } isEqual(other: Precondition) { return ( misc.equals(this.updateTime, other.updateTime) && this.exists === other.exists ); } } /** * A mutation describes a self-contained change to a document. Mutations can * create, replace, delete, and update subsets of documents. * * Mutations not only act on the value of the document but also it version. * In the case of Set, Patch, and Transform mutations we preserve the existing * version. In the case of Delete mutations, we reset the version to 0. * * Here's the expected transition table. * * MUTATION APPLIED TO RESULTS IN * * SetMutation Document(v3) Document(v3) * SetMutation NoDocument(v3) Document(v0) * SetMutation null Document(v0) * PatchMutation Document(v3) Document(v3) * PatchMutation NoDocument(v3) NoDocument(v3) * PatchMutation null null * TransformMutation Document(v3) Document(v3) * TransformMutation NoDocument(v3) NoDocument(v3) * TransformMutation null null * DeleteMutation Document(v3) NoDocument(v0) * DeleteMutation NoDocument(v3) NoDocument(v0) * DeleteMutation null NoDocument(v0) * * Note that TransformMutations don't create Documents (in the case of being * applied to a NoDocument), even though they would on the backend. This is * because the client always combines the TransformMutation with a SetMutation * or PatchMutation and we only want to apply the transform if the prior * mutation resulted in a Document (always true for a SetMutation, but not * necessarily for a PatchMutation). * * ## Subclassing Notes * * Subclasses of Mutation need to implement applyToRemoteDocument() and * applyToLocalView() to implement the actual behavior of applying the mutation * to some source document. */ export abstract class Mutation { readonly type: MutationType; readonly key: DocumentKey; readonly precondition: Precondition; /** * Applies this mutation to the given MaybeDocument or null for the purposes * of computing a new remote document. Both the input and returned documents * can be null. * * @param maybeDoc The document to mutate. The input document can be null if * the client has no knowledge of the pre-mutation state of the document. * @param mutationResult The result of applying the mutation from the backend. * @return The mutated document. The returned document may be null, but only * if maybeDoc was null and the mutation would not create a new document. */ abstract applyToRemoteDocument( maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument | null; /** * Applies this mutation to the given MaybeDocument or null for the purposes * of computing the new local view of a document. Both the input and returned * documents can be null. * * @param maybeDoc The document to mutate. The input document can be null if * the client has no knowledge of the pre-mutation state of the document. * @param baseDoc The state of the document prior to this mutation batch. The * input document can be null if the client has no knowledge of the * pre-mutation state of the document. * @param localWriteTime A timestamp indicating the local write time of the * batch this mutation is a part of. * @return The mutated document. The returned document may be null, but only * if maybeDoc was null and the mutation would not create a new document. */ abstract applyToLocalView( maybeDoc: MaybeDocument | null, baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null; abstract isEqual(other: Mutation): boolean; protected verifyKeyMatches(maybeDoc: MaybeDocument | null): void { if (maybeDoc != null) { assert( maybeDoc.key.isEqual(this.key), 'Can only apply a mutation to a document with the same key' ); } } /** * Returns the version from the given document for use as the result of a * mutation. Mutations are defined to return the version of the base document * only if it is an existing document. Deleted and unknown documents have a * post-mutation version of SnapshotVersion.MIN. */ protected static getPostMutationVersion( maybeDoc: MaybeDocument | null ): SnapshotVersion { if (maybeDoc instanceof Document) { return maybeDoc.version; } else { return SnapshotVersion.MIN; } } } /** * A mutation that creates or replaces the document at the given key with the * object value contents. */ export class SetMutation extends Mutation { constructor( readonly key: DocumentKey, readonly value: ObjectValue, readonly precondition: Precondition ) { super(); } readonly type: MutationType = MutationType.Set; applyToRemoteDocument( maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); assert( mutationResult.transformResults == null, 'Transform results received by SetMutation.' ); // Unlike applyToLocalView, if we're applying a mutation to a remote // document the server has accepted the mutation so the precondition must // have held. const version = Mutation.getPostMutationVersion(maybeDoc); return new Document(this.key, version, this.value, { hasLocalMutations: false }); } applyToLocalView( maybeDoc: MaybeDocument | null, baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); Iif (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } const version = Mutation.getPostMutationVersion(maybeDoc); return new Document(this.key, version, this.value, { hasLocalMutations: true }); } isEqual(other: Mutation): boolean { return ( other instanceof SetMutation && this.key.isEqual(other.key) && this.value.isEqual(other.value) && this.precondition.isEqual(other.precondition) ); } } /** * A mutation that modifies fields of the document at the given key with the * given values. The values are applied through a field mask: * * * When a field is in both the mask and the values, the corresponding field * is updated. * * When a field is in neither the mask nor the values, the corresponding * field is unmodified. * * When a field is in the mask but not in the values, the corresponding field * is deleted. * * When a field is not in the mask but is in the values, the values map is * ignored. */ export class PatchMutation extends Mutation { constructor( readonly key: DocumentKey, readonly data: ObjectValue, readonly fieldMask: FieldMask, readonly precondition: Precondition ) { super(); } readonly type: MutationType = MutationType.Patch; applyToRemoteDocument( maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); assert( mutationResult.transformResults == null, 'Transform results received by PatchMutation.' ); // TODO(mcg): Relax enforcement of this precondition // // We shouldn't actually enforce the precondition since it already passed on // the backend, but we may not have a local version of the document to // patch, so we use the precondition to prevent incorrectly putting a // partial document into our cache. if (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } const version = Mutation.getPostMutationVersion(maybeDoc); const newData = this.patchDocument(maybeDoc); return new Document(this.key, version, newData, { hasLocalMutations: false }); } applyToLocalView( maybeDoc: MaybeDocument | null, baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); if (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } const version = Mutation.getPostMutationVersion(maybeDoc); const newData = this.patchDocument(maybeDoc); return new Document(this.key, version, newData, { hasLocalMutations: true }); } isEqual(other: Mutation): boolean { return ( other instanceof PatchMutation && this.key.isEqual(other.key) && this.fieldMask.isEqual(other.fieldMask) && this.precondition.isEqual(other.precondition) ); } /** * Patches the data of document if available or creates a new document. Note * that this does not check whether or not the precondition of this patch * holds. */ private patchDocument(maybeDoc: MaybeDocument | null): ObjectValue { let data: ObjectValue; if (maybeDoc instanceof Document) { data = maybeDoc.data; } else { data = ObjectValue.EMPTY; } return this.patchObject(data); } private patchObject(data: ObjectValue): ObjectValue { for (const fieldPath of this.fieldMask.fields) { const newValue = this.data.field(fieldPath); if (newValue !== undefined) { data = data.set(fieldPath, newValue); } else { data = data.delete(fieldPath); } } return data; } } /** * A mutation that modifies specific fields of the document with transform * operations. Currently the only supported transform is a server timestamp, but * IP Address, increment(n), etc. could be supported in the future. * * It is somewhat similar to a PatchMutation in that it patches specific fields * and has no effect when applied to a null or NoDocument (see comment on * Mutation for rationale). */ export class TransformMutation extends Mutation { readonly type: MutationType = MutationType.Transform; // NOTE: We set a precondition of exists: true as a safety-check, since we // always combine TransformMutations with a SetMutation or PatchMutation which // (if successful) should end up with an existing document. readonly precondition = Precondition.exists(true); constructor( readonly key: DocumentKey, readonly fieldTransforms: FieldTransform[] ) { super(); } applyToRemoteDocument( maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); assert( mutationResult.transformResults != null, 'Transform results missing for TransformMutation.' ); const transformResults = mutationResult.transformResults!; // TODO(mcg): Relax enforcement of this precondition // // We shouldn't actually enforce the precondition since it already passed on // the backend, but we may not have a local version of the document to // patch, so we use the precondition to prevent incorrectly putting a // partial document into our cache. if (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } const doc = this.requireDocument(maybeDoc); const newData = this.transformObject(doc.data, transformResults); return new Document(this.key, doc.version, newData, { hasLocalMutations: false }); } applyToLocalView( maybeDoc: MaybeDocument | null, baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); if (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } const doc = this.requireDocument(maybeDoc); const transformResults = this.localTransformResults( localWriteTime, baseDoc ); const newData = this.transformObject(doc.data, transformResults); return new Document(this.key, doc.version, newData, { hasLocalMutations: true }); } isEqual(other: Mutation): boolean { return ( other instanceof TransformMutation && this.key.isEqual(other.key) && misc.arrayEquals(this.fieldTransforms, other.fieldTransforms) && this.precondition.isEqual(other.precondition) ); } /** * Asserts that the given MaybeDocument is actually a Document and verifies * that it matches the key for this mutation. Since we only support * transformations with precondition exists this method is guaranteed to be * safe. */ private requireDocument(maybeDoc: MaybeDocument | null): Document { assert( maybeDoc instanceof Document, 'Unknown MaybeDocument type ' + maybeDoc ); const doc = maybeDoc! as Document; assert( doc.key.isEqual(this.key), 'Can only transform a document with the same key' ); return doc; } /** * Creates a list of "transform results" (a transform result is a field value * representing the result of applying a transform) for use when applying a * TransformMutation locally. * * @param localWriteTime The local time of the transform mutation (used to * generate ServerTimestampValues). * @param baseDoc The document prior to applying this mutation batch. * @return The transform results list. */ private localTransformResults( localWriteTime: Timestamp, baseDoc: MaybeDocument | null ): FieldValue[] { const transformResults = [] as FieldValue[]; for (const fieldTransform of this.fieldTransforms) { const transform = fieldTransform.transform; Eif (transform instanceof ServerTimestampTransform) { let previousValue: FieldValue | null = null; if (baseDoc instanceof Document) { previousValue = baseDoc.field(fieldTransform.field) || null; } transformResults.push( new ServerTimestampValue(localWriteTime, previousValue) ); } else { return fail('Encountered unknown transform: ' + transform); } } return transformResults; } private transformObject( data: ObjectValue, transformResults: FieldValue[] ): ObjectValue { assert( transformResults.length === this.fieldTransforms.length, 'TransformResults length mismatch.' ); for (let i = 0; i < this.fieldTransforms.length; i++) { const fieldTransform = this.fieldTransforms[i]; const transform = fieldTransform.transform; const fieldPath = fieldTransform.field; Eif (transform instanceof ServerTimestampTransform) { data = data.set(fieldPath, transformResults[i]); } else { return fail('Encountered unknown transform: ' + transform); } } return data; } } /** A mutation that deletes the document at the given key. */ export class DeleteMutation extends Mutation { constructor(readonly key: DocumentKey, readonly precondition: Precondition) { super(); } readonly type: MutationType = MutationType.Delete; applyToRemoteDocument( maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); assert( mutationResult.transformResults == null, 'Transform results received by DeleteMutation.' ); // Unlike applyToLocalView, if we're applying a mutation to a remote // document the server has accepted the mutation so the precondition must // have held. return new NoDocument(this.key, SnapshotVersion.MIN); } applyToLocalView( maybeDoc: MaybeDocument | null, baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null { this.verifyKeyMatches(maybeDoc); Iif (!this.precondition.isValidFor(maybeDoc)) { return maybeDoc; } if (maybeDoc) { assert( maybeDoc.key.isEqual(this.key), 'Can only apply mutation to document with same key' ); } return new NoDocument(this.key, SnapshotVersion.forDeletedDoc()); } isEqual(other: Mutation): boolean { return ( other instanceof DeleteMutation && this.key.isEqual(other.key) && this.precondition.isEqual(other.precondition) ); } } |


class Net::POP3
What is This Library?¶ ↑
This library provides functionality for retrieving email via POP3, the Post Office Protocol version 3. For details of POP3, see [RFC1939] (www.ietf.org/rfc/rfc1939.txt).
Examples¶ ↑
Retrieving Messages¶ ↑
This example retrieves messages from the server and deletes them on the server.
Messages are written to files named 'inbox/1', 'inbox/2', .… Replace 'pop.example.com' with your POP3 server address, and 'YourAccount' and 'YourPassword' with the appropriate account details.
require 'net/pop' pop = Net::POP3.new('pop.example.com') pop.start('YourAccount', 'YourPassword') # (1) if pop.mails.empty? puts 'No mail.' else i = 0 pop.each_mail do |m| # or "pop.mails.each ..." # (2) File.open("inbox/#{i}", 'w') do |f| f.write m.pop end m.delete i += 1 end puts "#{pop.mails.size} mails popped." end pop.finish # (3)
-
Call #start and start POP session.
-
Access messages by using #each_mail and/or #mails.
-
Close POP session by calling #finish or use the block form of start.
Shortened Code¶ ↑
The example above is very verbose. You can shorten the code by using some utility methods. First, the block form of ::start can be used instead of ::new, #start and #finish.
require 'net/pop' Net::POP3.start('pop.example.com', 110, 'YourAccount', 'YourPassword') do |pop| if pop.mails.empty? puts 'No mail.' else i = 0 pop.each_mail do |m| # or "pop.mails.each ..." File.open("inbox/#{i}", 'w') do |f| f.write m.pop end m.delete i += 1 end puts "#{pop.mails.size} mails popped." end end
#delete_all is an alternative for each_mail and delete.
require 'net/pop' Net::POP3.start('pop.example.com', 110, 'YourAccount', 'YourPassword') do |pop| if pop.mails.empty? puts 'No mail.' else i = 1 pop.delete_all do |m| File.open("inbox/#{i}", 'w') do |f| f.write m.pop end i += 1 end end end
And here is an even shorter example.
require 'net/pop' i = 0 Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| File.open("inbox/#{i}", 'w') do |f| f.write m.pop end i += 1 end
Memory Space Issues¶ ↑
All the examples above get each message as one big string. This example avoids this.
require 'net/pop' i = 1 Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| File.open("inbox/#{i}", 'w') do |f| m.pop do |chunk| # get a message little by little. f.write chunk end i += 1 end end
Using APOP¶ ↑
The net/pop library supports APOP authentication. To use APOP, use the Net::APOP class instead of the Net::POP3 class. You can use the utility method, Net::POP3.APOP(). For example:
require 'net/pop' # Use APOP authentication if $isapop == true pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110) pop.start(YourAccount', 'YourPassword') do |pop| # Rest of the code is the same. end
Fetch Only Selected Mail Using 'UIDL' POP Command¶ ↑
If your POP server provides UIDL functionality, you can grab only selected mails from the POP server. e.g.
def need_pop?( id ) # determine if we need pop this mail... end Net::POP3.start('pop.example.com', 110, 'Your account', 'Your password') do |pop| pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m| do_something(m.pop) end end
The Net::POPMail#unique_id method returns the unique-id of the message as a String. Normally the unique-id is a hash of the message.
Constants
- Revision
svn revision of this library
Attributes
The address to connect to.
Seconds to wait until a connection is opened. If the POP3 object cannot open a connection within this time, it raises a Net::OpenTimeout exception. The default value is 30 seconds.
Seconds to wait until reading one block (by one read(1) call). If the POP3 object cannot complete a read() within this time, it raises a Net::ReadTimeout exception. The default value is 60 seconds.
Public Class Methods
Returns the APOP class if isapop
is
true; otherwise, returns the POP class. For example:
# Example 1 pop = Net::POP3::APOP($is_apop).new(addr, port) # Example 2 Net::POP3::APOP($is_apop).start(addr, port) do |pop| .... end
# File lib/net/pop.rb, line 238 def POP3.APOP(isapop) isapop ? APOP : POP3 end
Opens a POP3 session, attempts authentication, and quits.
This method raises POPAuthenticationError if authentication fails.
Example: normal POP3¶ ↑
Net::POP3.auth_only('pop.example.com', 110, 'YourAccount', 'YourPassword')
Example: APOP¶ ↑
Net::POP3.auth_only('pop.example.com', 110, 'YourAccount', 'YourPassword', true)
# File lib/net/pop.rb, line 305 def POP3.auth_only(address, port = nil, account = nil, password = nil, isapop = false) new(address, port, isapop).auth_only account, password end
returns the :ca_file or :ca_path from ::ssl_params
# File lib/net/pop.rb, line 377 def POP3.certs return @ssl_params[:ca_file] || @ssl_params[:ca_path] end
Constructs proper parameters from arguments
# File lib/net/pop.rb, line 337 def POP3.create_ssl_params(verify_or_params = {}, certs = nil) begin params = verify_or_params.to_hash rescue NoMethodError params = {} params[:verify_mode] = verify_or_params if certs if File.file?(certs) params[:ca_file] = certs elsif File.directory?(certs) params[:ca_path] = certs end end end return params end
The default port for POP3 connections, port 110
# File lib/net/pop.rb, line 210 def POP3.default_pop3_port 110 end
The default port for POP3S connections, port 995
# File lib/net/pop.rb, line 215 def POP3.default_pop3s_port 995 end
returns the port for POP3
# File lib/net/pop.rb, line 205 def POP3.default_port default_pop3_port() end
Starts a POP3 session and deletes all messages on the server. If a block is given, each POPMail object is yielded to it before being deleted.
This method raises a POPAuthenticationError if authentication fails.
Example¶ ↑
Net::POP3.delete_all('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| file.write m.pop end
# File lib/net/pop.rb, line 283 def POP3.delete_all(address, port = nil, account = nil, password = nil, isapop = false, &block) start(address, port, account, password, isapop) {|pop| pop.delete_all(&block) } end
Disable SSL for all new instances.
# File lib/net/pop.rb, line 355 def POP3.disable_ssl @ssl_params = nil end
Enable SSL for all new instances. params
is passed to
OpenSSL::SSLContext#set_params.
# File lib/net/pop.rb, line 332 def POP3.enable_ssl(*args) @ssl_params = create_ssl_params(*args) end
Starts a POP3 session and iterates over each POPMail object, yielding it to the
block
. This method is equivalent to:
Net::POP3.start(address, port, account, password) do |pop| pop.each_mail do |m| yield m end end
This method raises a POPAuthenticationError if authentication fails.
Example¶ ↑
Net::POP3.foreach('pop.example.com', 110, 'YourAccount', 'YourPassword') do |m| file.write m.pop m.delete if $DELETE end
# File lib/net/pop.rb, line 262 def POP3.foreach(address, port = nil, account = nil, password = nil, isapop = false, &block) # :yields: message start(address, port, account, password, isapop) {|pop| pop.each_mail(&block) } end
Creates a new POP3 object.
address
is the hostname or ip address of your POP3 server.
The optional port
is the port to connect to.
The optional isapop
specifies whether this connection is going
to use APOP authentication; it defaults to
false
.
This method does not open the TCP connection.
# File lib/net/pop.rb, line 417 def initialize(addr, port = nil, isapop = false) @address = addr @ssl_params = POP3.ssl_params @port = port @apop = isapop @command = nil @socket = nil @started = false @open_timeout = 30 @read_timeout = 60 @debug_output = nil @mails = nil @n_mails = nil @n_bytes = nil end
returns the SSL Parameters
see also ::enable_ssl
# File lib/net/pop.rb, line 362 def POP3.ssl_params return @ssl_params end
Creates a new POP3 object and open the connection. Equivalent to
Net::POP3.new(address, port, isapop).start(account, password)
If block
is provided, yields the newly-opened POP3 object to it, and automatically closes it at the
end of the session.
Example¶ ↑
Net::POP3.start(addr, port, account, password) do |pop| pop.each_mail do |m| file.write m.pop m.delete end end
# File lib/net/pop.rb, line 401 def POP3.start(address, port = nil, account = nil, password = nil, isapop = false, &block) # :yield: pop new(address, port, isapop).start(account, password, &block) end
returns true
if ::ssl_params is set
# File lib/net/pop.rb, line 367 def POP3.use_ssl? return<EMAIL_ADDRESS>end
returns whether verify_mode is enable from ::ssl_params
# File lib/net/pop.rb, line 372 def POP3.verify return @ssl_params[:verify_mode] end
Public Instance Methods
Does this instance use APOP authentication?
# File lib/net/pop.rb, line 436 def apop? @apop end
Starts a pop3 session, attempts authentication, and quits. This method must not be called while POP3 session is opened. This method raises POPAuthenticationError if authentication fails.
# File lib/net/pop.rb, line 314 def auth_only(account, password) raise IOError, 'opening previously opened POP session' if started? start(account, password) { ; } end
Deletes all messages on the server.
If called with a block, yields each message in turn before deleting it.
Example¶ ↑
n = 1 pop.delete_all do |m| File.open("inbox/#{n}") do |f| f.write m.pop end n += 1 end
This method raises a POPError if an error occurs.
# File lib/net/pop.rb, line 686 def delete_all # :yield: message mails().each do |m| yield m if block_given? m.delete unless m.deleted? end end
Disable SSL for all new instances.
# File lib/net/pop.rb, line 463 def disable_ssl @ssl_params = nil end
Yields each message to the passed-in block in turn. Equivalent to:
pop3.mails.each do |popmail| .... end
This method raises a POPError if an error occurs.
# File lib/net/pop.rb, line 664 def each_mail(&block) # :yield: message mails().each(&block) end
Enables SSL for this instance. Must be called before the connection is
established to have any effect. +params+ is port to
establish the SSL connection on; Defaults to 995. params
(except :port) is passed to OpenSSL::SSLContext#set_params.
# File lib/net/pop.rb, line 452 def enable_ssl(verify_or_params = {}, certs = nil, port = nil) begin @ssl_params = verify_or_params.to_hash.dup @port = @ssl_params.delete(:port) || @port rescue NoMethodError @ssl_params = POP3.create_ssl_params(verify_or_params, certs) @port = port || @port end end
Finishes a POP3 session and closes TCP connection.
# File lib/net/pop.rb, line 585 def finish raise IOError, 'POP session not yet started' unless started? do_finish end
Provide human-readable stringification of class state.
# File lib/net/pop.rb, line 468 def inspect "#<#{self.class} #{@address}:#{@port} open=#{@started}>" end
debugging output for msg
# File lib/net/pop.rb, line 711 def logging(msg) @debug_output << msg + "\n" if @debug_output end
Returns an array of Net::POPMail objects, representing all the messages on the server. This array is renewed when the session restarts; otherwise, it is fetched from the server the first time this method is called (directly or indirectly) and cached.
This method raises a POPError if an error occurs.
# File lib/net/pop.rb, line 642 def mails return @mails.dup if @mails if n_mails() == 0 # some popd raises error for LIST on the empty mailbox. @mails = [] return [] end @mails = command().list.map {|num, size| POPMail.new(num, size, self, command()) } @mails.dup end
Returns the total size in bytes of all the messages on the POP server.
# File lib/net/pop.rb, line 630 def n_bytes return @n_bytes if @n_bytes @n_mails, @n_bytes = command().stat @n_bytes end
Returns the number of messages on the POP server.
# File lib/net/pop.rb, line 623 def n_mails return @n_mails if @n_mails @n_mails, @n_bytes = command().stat @n_mails end
The port number to connect to.
# File lib/net/pop.rb, line 493 def port return @port || (use_ssl? ? POP3.default_pop3s_port : POP3.default_pop3_port) end
Set the read timeout.
# File lib/net/pop.rb, line 508 def read_timeout=(sec) @command.socket.read_timeout = sec if @command @read_timeout = sec end
Resets the session. This clears all “deleted” marks from messages.
This method raises a POPError if an error occurs.
# File lib/net/pop.rb, line 696 def reset command().rset mails().each do |m| m.instance_eval { @deleted = false } end end
WARNING: This method causes a serious security hole. Use this method only for debugging.
Set an output stream for debugging.
Example¶ ↑
pop = Net::POP.new(addr, port) pop.set_debug_output $stderr pop.start(account, passwd) do |pop| .... end
# File lib/net/pop.rb, line 485 def set_debug_output(arg) @debug_output = arg end
Starts a POP3 session.
When called with block, gives a POP3 object to the block and closes the session after block call finishes.
This method raises a POPAuthenticationError if authentication fails.
# File lib/net/pop.rb, line 526 def start(account, password) # :yield: pop raise IOError, 'POP session already started' if @started if block_given? begin do_start account, password return yield(self) ensure do_finish end else do_start account, password return self end end
true
if the POP3 session has started.
# File lib/net/pop.rb, line 514 def started? @started end
does this instance use SSL?
# File lib/net/pop.rb, line 441 def use_ssl? return<EMAIL_ADDRESS>end


QrAtt
QrAtt
☰
Start
Status
About
QrAtt
Let's Start
⇣
Select Role
Teacher
Student
QrAtt
version: 1.0
Testing
About QrAtt


Inherits MonoBehaviour.
◆ gameEnd()
| void GameUIManager.gameEnd |
( |
| ) |
|
Toggle gameOverScreen, pauseButton, and scoreCounter
◆ gameReset()
| void GameUIManager.gameReset |
( |
| ) |
|
Toggle UI of gameOverScreen, startScreen, and countdown
◆ setScore()
| void GameUIManager.setScore |
( |
int |
score | ) |
|
◆ startCountdown()
| IEnumerator GameUIManager.startCountdown |
( |
| ) |
|
Start the timer for the UI to show the User
◆ toggleGameUI()
| void GameUIManager.toggleGameUI |
( |
GameObject |
UIObject | ) |
|
◆ countdown
| GameObject GameUIManager.countdown |
◆ endScore
| GameObject GameUIManager.endScore |
◆ gameOverScreen
| GameObject GameUIManager.gameOverScreen |
◆ pauseButton
| GameObject GameUIManager.pauseButton |
◆ pauseScreen
| GameObject GameUIManager.pauseScreen |
◆ scoreCounter
| GameObject GameUIManager.scoreCounter |
◆ startScreen
| GameObject GameUIManager.startScreen |
The documentation for this class was generated from the following file:


I acquired some 4-Hydroxy-DiPT from a friend, he bought them of the internet just before they became illegal (around may last year I think). I had also gotten a hit of acid from him, which was my first trip.
this is in the summer and I was 18 years of age.I take the bus to a friend of mine, he's home alone and I plan to ingest my 4hodipt while my 2 friends smoke pot and watch over me. my friend rolls a few joints for the night.
I take the 4-ho-dipt. they are in pill form and each pill is 15 mg. one of the pills is only about 3/4 of its original size so I assume I ingest about 25 mg. we sit around and eat some food and talk. after about 20 minutes my legs start to feel tingly and weird. I look at a plate on which we had eaten and it seems to become deeper when I look at it. I laugh a bit at it, then I look at the floor. The floor looks weird, it seems as if the patterns in the material moves, yet they do not. I think I see faces in the floor. I honestly see a flash of none other than Bob Marley himself in the floor. I definitely feel the drug now.
I notice after a while that I am really tripping, I dont talk as I usually do. we go outside into the summers evening. I look into the sky and the sunset looks beautiful, not a lot of people are around so I can relax and focus on the beauty around me. we walk down a road which seems to last for 20 minutes when in reality it only took us 30 seconds to go down. we go to a place by a lake/pond and my friends light up a joint. I dont smoke any of it, I am too busy looking at the lake. a green 'light' or hue surrounds the whole place. it feels as if the whole place is breathing this warm green colour.
I look down on my legs. I am sitting in a very weird position but I think my legs look beautiful in this position. I tell my friends that my legs look pretty and they just laugh.
we continue our walk through the sleepy neighbourhood. ( I have difficulties remembering when things happened so some of this might have happened before or after they are presented in this report)
we walk up a small mountain. we sit down on a bench and light a joint, which I take 2 tokes of. I cannot sit still so I start to walk around. I see a green light in the sky, it looks like a firework of some sort but I know it's not.
I start talking to a tree, it doesnt really respond but I can 'feel' its spirit. we embrace eachother. my friends laugh at me, I go on to tell the tree that they are only laughing because they dont understand our 'language'. right there I have a very weird experience. I 'see/feel' a dream I dreamed the night before and forgot about, I didnt really see it but I 'feel' a window in the air that displays this dream to me. a very weird moment.
I go back to the bench where my friends are smoking ganja. I look at a rock beside us and see a beautiful woman, she is composed of small stripes of light blue and green. she looks a bit like a cartoon. it is a very peaceful and pretty image, it looks as if she is sleeping inside a spacepod or something. when I come closer the image dissolves into other things. we head on.
we walk back to my friends house and roll some joints. I am very glad to be in this state, and I give the remaining pill to my friend. the dose I have in me is well enough for me, I'm not even peaking at this point. we go out for another walk. we come to a football field. I point at a star which we all look at. it looks as if a spiral is surrounding it and we all see it. we have a wonderful moment of togetherness. we smoke a joint and are glad for each other. this far the trip has been really nice to me. from this point on the night takes a darker mood, not necessarily in a bad way but still. I begin to 'peak'. we decide to take a much longer walk than before, through some dark woods. looking back on it, it was a bit crazy to go there tripping but I really dont regret it for I saw/felt some really amazing things.
at this point my mind is bombarded with messages and weird thoughtpatterns I have never experienced. it is very hard to explain but I am able to 'see' my personality from an objective perspective, and I see things in myself that I have to change to become a better person. as awesome as this is I feel that this is just the beginning of the larger change. I have to change my whole being to get where I want to be. but this change in personality is the first one I have to go through, and now I see it in front of me.
I feel as if my mind is expanding, it goes way outside my body. it's as if I have a new sense.
we continue our walk. we come to a road that is next to a dark forest which seems really threatening. I now have an interesting experience: the road and the forest tilt towards each other. it's as if we're walking on a wall and the forest is a wall on the other side of the 'room' we're in. I dont remember what happens next, but we're in some sort of park and I see castle on a mountain a couple of hundred yards away. I dont know if it's real or not.
There are a lot of small bushes here with pretty flowers. I lay down beside one of these and start talking to it and caressing it. I look up in the sky and see a luminous geometrical pattern all over it. we walk away from the park and come to a field. it feels lonely and scary there, but we walk past it. my friend who also took 4-ho-dipt begins to talk about the grass around us being evil. he has been pretty silent this far. I am a little scared at this point. we get across the field and in front of us is another area of woods, I have a bad feeling about it but we walk in to it and up a path. as soon as we start to walk up the path it starts to rain and the wind starts to blow.
I know 'something' is warning us or doesnt want us to go this way, I tell my friends that something is wrong here but they insist we head on. as we reach the end of the path the wind and rain stops but I still feel a very nasty presence around us. beside us now is a big, recently built house, with a planted lawn around it. it is lit up inside with dim lights, for some reason it looks and feels horrible. I am very afraid to stay there any longer and we continue to walk. we come out on the asphalt road beside the house and here I can 'feel' death. I feel Death as a being, he/she/it is very present.
I look to my left down the road, and a couple of yards away from us he is standing, Death. Death stands under a street light, he is very tall and very big. Imagine three fully grown men put together. I only see his outer shapes because his whole being is luminous. he is of a very bright blue colour. it lookes as if he is carrying a scythe or something on his back but its hard to see as I only see his outer lining, its like looking at a shadow. but it is glowing of blue. beside him he has a dog, also glowing blue. this dog is the largest beast I have ever seen, it is sitting down but is still taller than Death and Death is taller than any man I've seen. The Dog's ears are huge, 1,5 foot long perhaps. They just stand there, but I can feel them strongly. surprisingly I'm scared, I just say to my friends: lets get out of here. a Very profound moment for me.
we're almost home again, back in the neighbourhood. we're sitting next to a road that leads up to my friends house. we decide to light the last joint. it is a rather strong joint. my friend who is tripping falls asleep for a while and then wakes up and asks for the spliff. we all laugh. my other friend who is only smoking pot tonight starts to look very much like a lizard when he is smoking the joint. this joint boosts my trip.. we begin to walk up the road to my friends house. walking up this road takes about 1 hour. I'm not sure if it just feels like one hour or if it really is one hour but damn am I high. at this point my mouth is extremely dry, I have never been so dry in my throat before.
I begin to hear all sorts of weird and scary sounds. I feel sounds reverberating inside my body, as I talk my mouth starts to feel the way guitar-effects-pedals sound. If you know what a tremolo is: imagine that sound inside your mouth. very weird. I see ghosts inside the asphalt coming at me. it's pretty scary especially since I feel like I'm moving in slowmotion. Next thing I know we're in my friends kitchen, my friend is telling me to stop shouting. I am pretty outraged by the fact that I am hearing eerie echoes in my head and that my face is feeling like sound effects. my friend starts to feel ill and goes to the bathroom to vomit. I feel shitty, my friend demands we turn all music off and I become pissed off because the music really soothes me and I need it cause I am freaking out.
I listen to my friend vomit for half an hour (which feels like 3 hours) and his floor starts to look REALLY creepy. I see a bunch of genitalia-resembling stuff moving around inside it. then all I remember is seeing my friends sleeping and thinking I should go to bed too. I wake up the next day feeling weird, takes me a while to comprehend all of what has happened to me.
these were the biggest moments of this trip but there was alot more that happened that I have forgotten about. everything is a bit hazy when I think about it, feels like one big moment instead of several different moments. hard to explain. I do remember seeing a whole bunch of 60's and 70's musicians inside a mountain and that the forest was alive and breathing and I was part of it.
this was a really great night that left a huge impression on me. I cant really explain all the stuff that happened.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.