Browse Source

Fixed naming

dockerScript
jrtechs 5 years ago
parent
commit
2b8b962ef8
1 changed files with 795 additions and 0 deletions
  1. +795
    -0
      blogContent/posts/programming/csci-334-final-review.md

+ 795
- 0
blogContent/posts/programming/csci-334-final-review.md View File

@ -0,0 +1,795 @@
A quick review for CSCI-344 (Programming Language Concepts)
# Ch #1 What are Programming Languages
## Types
### Imperative
Most common type of language
- Von Neumann (Fortran, Basic, C)
- Object-oriented (SmallTalk, java)
- Scripting (perl, python, basic)
### Declarative
- Functional (Scheme, ML)
- Logical (Prolog)
## Compilation vs Interpretation
Interpretation is more flexible and gives better diagnostics for debugging.
Compilation provides better performance.
Often there is no clear cut difference between compilation and interpretation because many languages like java and python do a mix of the both.
### Compilation
![](media/plcfinal/compilation.png)
### Interpretation
![](media/plcfinal/interpretation.png)
### Mixed
![](media/plcfinal/mixed.png)
### Compilation Overview
![](media/plcfinal/compOverview.png)
# Ch #2 Parsing
## Context-Free Grammars
We use CFGs to produce a parse tree from tokens.
![](media/plcfinal/cfgEx.png)
## LL Grammar
LL(1) grammar means that it is left right left most derivation parsing with one token look ahead.
In practice we would use a stack to keep track what we expect to see.
In this approach we would build the tree top down.
The LL parsing algorithm uses FIRST/FOLLOW/PREDICT tables.
Ex grammar:
![](media/plcfinal/ll.png)
## LR Grammar
LR (Left to right right most derivation) builds the tree bottom up and is almost always table driven.
## Scanning
A scanner is responsible for tokenizing the source, removing comments, saving text of identifiers, and saving line locations for error messages.
A scanner is most naturally represented as a DFA (Deterministic Finite Automaton).
![](media/plcfinal/scanner.png)
# Ch #10 Object Oriented
Three major OO Components:
- Encapsulation
- Inheritance
- Dynamic method binding
Strict terms for OO lang: everything is an object, inheritance, dynamic method binding.
Since java has primitives, it is not a true OO language.
## Small Talk
Started as a thesis project in the 1960's, has been noted as being one of the best OO language historically.
Basic coding examples on class-inheritance and constructors may be on exam.
### Syntax
Excessively uses parenthesis.
Method calls are in the form: (function:: object parameter1 parameter 2).
NOTICE: the colons in the function name represents how many parameters it has.
Also, there are no commas between parameters.
Basic example class.
```scheme
(class Shape Object
(perimeter area) ; class-level parameters
;constructor
(class-method initalize::shape (per ar)
(init::shape (new self) per ar)
)
(method init::shape (per ar)
(setPerimeter: self per)
(setArea: self ar)
self
)
(method getPerimeter ()
perimeter
)
(method getArea ()
area
)
(method setArea: (a)
(set area a)
)
(method setPerimeter: (p)
(set perimeter p)
)
)
(val shape1 (initalize::shape Shape 12 5))
; area
(getArea shape1)
(setArea: shape1 88)
(getArea shape1)
```
Example with inheritance:
```scheme
(class Circle Shape
(radius)
(class-method initalize:circle (rad)
(init:circle (new self) rad)
)
(method init:circle (rad)
(setRadius: self rad)
self
)
(method setRadius: (rad)
(set radius rad)
(setArea: self (computeArea self))
(setPerimeter: self (computePerimeter self))
)
(method getRadius ()
radius
)
(method computeArea ()
(*
(asFloat (/ 22 7))
(asFloat (squared radius))
)
)
(method computePerimeter ()
(*
(asFloat 2)
(*
(asFloat (/ 22 7))
(asFloat radius)
)
)
)
)
(val circle1 (initalize:circle Circle 5))
(getRadius circle1)
(getArea circle1)
(getPerimeter circle1)
(setRadius: circle1 6)
(getRadius circle1)
(getArea circle1)
(getPerimeter circle1)
```
# Ch #3: Name, Scope, and Binding
A name is a identifier. A binding links a name to an item.
Scope is simply when a binding is active.
# Binding
Binding typically happens at two times:
- Static: before run time
- Dynamic: at run time.
The earlier the binding the greater efficiency you have. The later the binding the greater flexibility you have.
Static scope rules use the structure of the program.
Dynamic scope rules depends on the current state of the program so, the function call sequences can change which bindings are active.
# Lifetime
Key events:
- creation of object
- creation of binding
- references to variables (uses binding)
- deactivation of binding (leave function stack)
- reactivation of bindings
- destruction of bindings
- destruction of object
If object out lives its binding it's garbage.
If binding out lives its object it's a dangling reference.
# Ch #4 Semantic Analysis
The role of semantic analysis is to enforce semantic rules and generate a syntax tree(decorate the parse tree).
To do this we use a attribute grammar.
ex attribute grammar:
![](media/plcfinal/attributeGrammar.png)
## S-Grammar:
Only uses synthesized attributes: the grammar above.
![](media/plcfinal/sgrammar.png)
## L-Grammar:
A l attribute depends on things above them or besides them in the parse tree.
![](media/plcfinal/lgrammar.png)
## Action Routines
Functions used to interleave the parser.
# Ch #11: Functional Programming
Examples:
- Lisp
- Scheme
- FP
- ML
- Haskell
Key Ideas:
- everything is done by composing functions
- no mutable state
- no side effects
- just produces a answer/result
Necessary Features:
- first class and high-order functions (takes in/returns functions)
- polymorphism
- powerful list functionality
- structured function returns
- fully general aggregates
- garbage collection
Since there is no state, it heavily relies on recursion to replace iteration.
## Scheme
Not purely functional because it has some imperative stuff like assignment, I/O, sequencing and IO
Scheme scopes:
- let: calculates all RHS and then assign, can't use prior ones
- let*: evaluates and then assigns
- letrec: evaluates and then assign, this will loop back to fill in missing pieces as they are declared
### Scheme Examples:
Note: cdr is tail of list and car is the first element in the list.
```scheme
; Computes length of list
(define (length lst)
(if (null? lst)
0
(+
1
(length (cdr lst))
)
)
)
; determines if something is in the list
; returns:
; 1 if true(in list)
; 0 if not in list
(define (inList lst n)
(if (null? lst)
0
(if (= n (car lst))
1
(inList (cdr lst) n)
)
)
)
; finds the sum of the list
(define (sumList lst)
(if (null? lst)
0 ; empty list
(+
(car lst)
(sumList (cdr lst))
)
)
)
```
# Ch #6: Control Flow
Types of iteration:
- Sequencing: specifies a linear ordering on statements
- Selection: selects a section of code ie: if statements
- Iteration: for loops, iterates over a well-defined set
- Concurrency
- Exception Handling
- Non-determinacy
Orthogonality: feature can be used in any combination and the meaning is consistent.
# Ch #7: Data Types
Data types are a collection of values from a "domain".
Data types specify the structure of the data and a collection of well-defined operations you can perform on that type.
Data types are useful for implicit context and so that we can avoid meaningless operations.
Strong typing is when language prevents on data that is not appropriate.
Static typing is strong typing that the compiler can do.
Orthogonality: no restriction on how a collection of features can be combined: like python lists.
## Type Systems
A type system has rules for the following:
- type equivalence
- type compatibility: can type A be used in context of type B
- type inference: type of expression given its operands types
## Type Checking
Two major types:
- Structural Equivalence: based on memory layout to determine if same -- can result in unintended equivalencies
- Name equivalence: based on declaration type -- most common
## Coercion
When an expression of one type is used in the context of another. Implicit coercion is when the language does it.
Explicit is when the programmer does it (Casting).
# Ch #12: Logical Programming
Logical programming is based on predicate calculus.
Important concepts:
- Axioms: facts assumed true in knowledge base
- Theorems: things that are provably true
- Hypotheses: things or queries we would like to prove
- ATOM is a constant like a number
Within logical languages, statements can be written many ways.
Logical languages are good for people but bad for people.
Prolog uses backwards chaining to prove things true mathematically.
A horn clause contains a HEAD and a BODY, sll statements must be in this term. The head is a single term, but, the body can be a list of terms.
## Prolog Ex
```Prolog
path(b, f, 6).
path(g, f, 3).
path(e, g, 2).
path(h, g, 4).
% makes paths bi-directional
biPath(A, B, Y) :- path(A, B, Y).
biPath(A, B, Y) :- path(B, A, Y).
% X is starting point
% Y is ending point
% P is a list of the points on the final path if one exists
% N is the distance between X and Y if one exists
% rule for terminal
solveV(X, X, [X], 0, V).
% recursively build out path
solveV(A, B, [A|P], N, V) :- biPath(A, C, CC),
\+member(C, V),
solveV(C, B, P, CCC, [C|V]),
N is CC + CCC.
% expand given definition to helper function
solve(A, B, P, N) :- solveV(A, B, P, N, [A]).
% ex test runs in interpreter
solve(h, c, P, N).
solve(a, e, P, N).
solve(g, c, P, N).
solve(a, a, P, N).
solve(g, h, P, N).
```
# Ch #8: Composite Types
Types:
- Records (Structures)
- Arrays
- Strings
- Pointers
- Lists
- File I/O
## Garbage Collection
Problem with reference counter for garbage collection:
![](media/plcfinal/counter.png)
Mark and Sweep solution:
- Garbage collector walks heap basically marks everything as useless
- starts at outside pointers marking everything it can get to as useful
-walks the heap again placing useless items in the free queue.
## Pointers
### Tombstones
Costly way of dealing with pointers references.
This will create an additional object to maintain the pointer.
![](media/plcfinal/rip.png)
### Lock and Keys
Makes sure that pointers and pointe contains the same lock value before you dereference the object.
Note: this does not prevent attempting to use memory outside of your block resulting in a seg fault.
![](media/plcfinal/lock.png)
# Ch #13: Erlang
Approaches to parallel programming:
- Synchronized access to shared memory
- Message passing between processes (slower)
Race conditions are whe the result depends on the order of the thread actions.
Usually due to bad synchronization but, not always bad.
Synchronization ensures that events in different processes happen in a desired order.
Mutual exclusion: only one can access at a time.
Condition synchronization: wait until some condition is true.
Spin lock - busy-wait mutual exclusion, they waste processing cycles. Semaphores: widely used and uses a scheduler-based methods.
Monitors are used to note who is in a critical region.
## Erlang
Syntax of erlang is very similar to prolog with its pattern matching.
Erlang relies on message passing for concurrency.
Each process contains a "mailbox" where it can receive messages from.
You process by listening for a message of a specific format: ie you can choose to ignore certain messages for a period of time.
### Examples
![](media/plcfinal/erlang.png)
```Erlang
%%%-------------------------------------------------------------------
%%% @author Jeffery Russell
%%% @doc
%%% PLC assignment 4
%%% @end
%%% Created : 16. Nov 2019
%%%-------------------------------------------------------------------
-module(prog4).
-author("jeff").
%% API
-export([start/0, bank/0, client/0]).
% helper function to spawn a specific amount
% of clients
spawn_client(N) when N >= 1 ->
io:fwrite("Spawning a client\n"),
spawn(prog4, client, []),
spawn_client(N -1);
spawn_client(_) ->
io:fwrite("Spawned all clients\n").
% start with random account balance between 2k-3k
% receives message {clientid, number}
% negatives removes from bank, positives add
% returns {<client_id>, balance}
bank() ->
Balance = rand:uniform(1000) + 1999,
io:format("Bank balance starting at: ~w~n", [Balance]),
Client_count = rand:uniform(7) + 2,
Client_left = 1,
spawn_client(Client_count),
loop(Balance, Client_count, Client_left).
% main bank loop which listens for messages and
% processes them
loop(Balance, Client_count, Client_left) ->
receive
%io:format("Bank now has ~w", [balance])
{CLIENT_ID, balance} ->
io:fwrite("~w Requested Balance from the bank\n", [CLIENT_ID]),
CLIENT_ID ! {Balance},
loop(Balance, Client_count, Client_left);
{CLIENT_ID, NUMBER} ->
if
Balance + NUMBER >= 0 ->
CLIENT_ID ! {NUMBER, Balance + NUMBER, successful},
loop(Balance + NUMBER, Client_count, Client_left);
true ->
CLIENT_ID ! {NUMBER, Balance, failed},
loop(Balance, Client_count, Client_left)
end;
goodbye ->
if
Client_left == Client_count ->
io:format("Bank is closing with balance ~w`\n", [Balance]);
true ->
loop(Balance, Client_count, Client_left + 1)
end
end.
% helper function to fetch and print balance of the bank
client_fetch_balance() ->
bank_pid ! {self(), balance},
receive
{Balance} ->
io:format("~w recieved the balance of ~w from the bank~n", [self(), Balance])
end.
% client process loop
% if loop is increment of 5, it requests balance of bank
% withdraws a random amount of money from mank
% and prints the bank's response
% after each withdrawl, it will sleep
client_loop(LoopUntil, CurrentIndex) ->
if
CurrentIndex rem 5 == 0 ->
client_fetch_balance();
true -> pass
end,
if
LoopUntil == CurrentIndex ->
bank_pid ! goodbye,
io:format("~w Client Finished\n", [self()]);
true ->
bank_pid ! {self(), 100-rand:uniform(199) },
receive
{Amount, Balance, Suc} ->
io:format("~w recieved the balance of ~w from the bank after a ~w transation request of ~w~n", [self(), Balance, Suc, Amount])
end,
timer:sleep(rand:uniform(1000) + 499),
client_loop(LoopUntil, CurrentIndex + 1)
end.
% creates random amount of clients
client() ->
Nums = rand:uniform(10) + 9,
client_loop(Nums, 0).
% spawns the bank
start() ->
register(bank_pid, spawn(prog4, bank, [])).
```
# Ch #14: Scripting Languages
Common Characteristics:
- both batch and interactive use
- easy to write high level expressions
- simple scoping rules
- flexible dynamic typing
- easy access to other programs
- sophisticated pattern matching and string manipulation
- high level data types
Often used to glue together other programs.
Need to know bash on the exam.
## Bash
### Shall Parameters
- "$#" is the number of parameters passed
- "$0" is name of the script and its location in filesystem
- "$1" is the first command line parameter. Goes up till 9
- "$*" single word of all the parameters
- "$@" array of all the parameters
ex:
```bash
if [ $# -eq 3 ];
then
if [ -f $1 ]
then
if [ -f $2 ]
then
encode_message $1 $2 $3
else
echo "File $2 does not exist"
fi
else
echo "File $1 does not exist"
fi
else
echo "Usage:"
echo " encoder.sh <plane_text_file> <secret_key_file> <encoded_file>"
fi
```
### Files
```bash
while read line || [ -n "$line" ];
do
for word in $line
do
echo "$word"
done
done < "$1"
```
### Comparisons
Numbers:
- "-eq" equal
- "-ge" greater than or equal
- "-le" less than or equal
- "-ne" not equal
- "-gt" greater
- "-lt" less
ex:
```bash
[n1 -eq n2]
```
Strings:
- "=" equal
- "!=" not equal
- "-n" length is greater than zero
- "-z" length is equal to zero
ex:
```
[ s1 - s2 ]
[ -n s1 ]
```
Files:
- "-d" path is a directory
- "-f" is a file
- "-e" file name exists
- "-r" check of read permission
- "-s" file has length greater than 0
- "-w" write permission
- "-x" execution permission
ex:
```bash
[ -d fname ]
```
### Control Flow
#### If Statements
```bash
if [ expression ];
then
statements
elif [ expression ];
then
statements
else
statements
fi
```
#### Switch Statements
```bash
case $var in
val1)
statements
;;
val2)
statements
;;
*)
statements
;;
esac
```
### Math
To do math you math like this:
```bash
echo "$((124+23))"
# or like this:
VALOR=$[124+23]
# or with let
let X=124+23
```
### Functions
Functions exist in bash.
```bash
#!/bin/bash
hello()
{
echo "Woeie"
}
hello # no parenthesis needed when calling
# you can also declare functions with the keyword
function check()
{
return 42
}
```

Loading…
Cancel
Save