● Every expression results in a value (+side-effects?): 1+2, str.length(), f(x)+1 Expressions ● Imperative prg : Statements have just vs side-effects, no value: (for, if, break) statements ● Assignment is statement/expression depending on language (a=b=c) ● Often expression can act as a statement, result is discarded (1+2;) ● Functional prg : No side-effects →no statements, just expressions (Haskell: let x = if x>0 then x else -x) 171
● Common subexpressions can usually be optimized, as can constant Expression expressions evaluation ● Intermediate results use memory too! ● Precedence does not determine execution order! ● Side-effects can complicate evaluation (common mistake in C++) 172
● 1: How many – Conditional jump [ goto -statement] ● 2: control – Choice of two control-flows [ if- statement] structures – Logically controlled iteration [ while - are needed statement] at ● Many languages have several minimum? – To improve readability and writability – If the language is large, only some subset is often used 173
● Conditional statements based on equality case- – case labels (possible values) structure ● Design issues: Pascal: case E of – Type of the expression? L1: S1; L2: S2; – Values of the case labels? ... Ln: Sn; • constants? end • Enumerated types? • Mutually exclusive? switch ( E ) { – Other options executed? case L1: S1; C/C++: case L2: S2; break ; • default , else , others -branching ... case Ln: Sn; } 174
• If -statement compiling: – Condition truth value used in conditional Implementing jump conditionals • case -statement: – Small number of case-tags • Compile as if-then-elsif – Reasonable number of tags that cover the set of values • Jump address table • Empty values use the default address – Large number of tags, and even larger set of values • Hash-table or other dictionary 175
r1 := A r2 := B Implementing r1 := r1 > r2 Resulting if r2 := C pseudo- r3 := D assembly: r2 := r2 > r3 r1 := r1 & r2 r2 := E r3 := F r2 := r2 <> r3 Pascal: r1 := r1 | r2 if r1 = 0 goto L2 if ( ( A > B ) and ( C > D ) ) or ( E <> F ) then L1: then_clause then_clause goto L3 else L2: else_clause else_clause L3: 176
● Each case-tag corresponds to an index Jump ● Index points to an address for address jumping when condition evaluates as table the case-tag ● Code is found in the address ... case E of 1 S1 1: S1; 2 S2 2: S2; 3 S3 3: S3; 4 S4 4: S4; ... end 177
● ML and Haskell: piecewise functions Peculiarities – fun fact(0) = 1 | fact(n : int) : int = n * fact(n-1); of choice – fact 0 = 1 fact n = n * fact(n-1) ● Smalltalk boolean objects – Boolean inherited classes True and False – Their methods ifTrue and ifFalse, conditional code as parameter, either executed or not – i < 2 ifTrue: [ Transcript show: 'It is small' ]. 178
● Definite/bounded iteration [counter] Repetition – The number of repetitions is known before starting statements ● Indefinite/unbounded iteration [logical condition] – Number of iterations is determined generalisation (Ada): during the iteration – Test of ending at the end or the loop beginning -- statements exit when cond; -- statements end loop ; 179
● Contains loop index (loop counter) Definite/ for index from expr1 to expr2 do stmt end ● Semantics vary between languages bounded – Is the index value defined after iteration execution? – Can the index value be changed within the body? – Are upper and lower values evaluated only once? Iterating an array 180
● End condition evaluation Pascal: Indefinite/ – beginning s := 0; unbounded • 0 – n iterations Read ( nm ); while nm >= 0 do begin – end iteration s := s + nm; • 1 – n iterations Read ( nm ); end ; ● Ending logic: – while : continue if true s := 0; Read ( nm ); – until : end if true repeat s := s + nm; Read ( nm ); until luku < 0; 181
● Smalltalk iteration is an intermediate method, code block as parameter, with Peculiarities the value of the index as its parameter of iteration – Interval from: 1 to: 10 do: [ i | Transcript show: i ] ● Undefined iteration is a method of a code block – [ Transcript show i. i := i-1. i > 0 ] whileTrue. – [ i > 0 ] whileTrue: [ Transcript show i. i := i-1. ] 182
OUTER_LOOP: Loop for row in 1..max_rows loop INNER_LOOP: control for col in 1..max_cols loop sum := sum + mat ( row, col ); exit OUTER_LOOP when sum > 1000; Ada: end loop INNER_LOOP; end loop OUTER_LOOP; while ( sum < 1000 ) { while ( sum < 1000 ) { C/C++: getnext ( value ); getnext ( value ); if ( value < 0 ) continue ; if ( value < 0 ) break ; sum += value; sum += value; } } 183
type Days is ( Mon, Tue, Wed, Thu, Loops and Fri, Sat, Sun ); Ada: for Index in Days loop ... end loop ; data C++ int[] tbl = {1, 2, 3}; // C++: int tbl[] = {1, 2, 3}; structures for (int i : tbl) { ... } Java: String [ ] strList = { ”Bob”, ”Carol”, ”Ted” }; C#: foreach ( String name in strList ) Console.WriteLine ( ”Name: ”, name ); Lambdas and library functions used as loops let tbl = [1, 2, 3] in Haskell: map (\x -> x*x + 1) tbl 184
● Functions are "single-use": parameters in, return value out Generators/ ● Generators are "multi-use": they can be Coroutines suspended and produce multiple values (when needed) ● In Python, generator is an iterator , which is used to access (and calculate) the values. Generator functions return generators (iterators) ● In C++20, coroutines are a similar concept, with slightly different syntax 185
def factorials(n): Generators, f = 1; i = 1; example while i <= n: yield f i=i+1; f=i*f fact = factorials(10) # print(next(i)) factsq = (x*x for x in fact) for i,f in enumerate(factsq) print(i, ":", f) 186
● Avoid creating big data structures, create values when necessary Benefits of ● Allow lazy evaluation (almost) generators ● Allow pipeline programming: actions (generators) are chained together, feeding values to next action (generator) 187
● Describe computation as a sequence (or tree) of linked steps Pipelines/ ● Becoming more common nowadays Task graphs ● Allows both laziness, concurrency, and parallelism (=asynchrony) ● Ranges + views in C++20 (expanded to coroutines/parallelism in C++23): auto mydata = iota(1) | filter_view(is_prime) | transform_view([](auto x){return x*x;}) | take_view(10) | reverse_view; // Nothing has been executed yet! for (auto& i : mydata) { std::cout << i << std::endl; } 188
Recommend
More recommend