| @ -1,795 +0,0 @@ | |||||
| 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 | |||||
|  | |||||
| ### Interpretation | |||||
|  | |||||
| ### Mixed | |||||
|  | |||||
| ### Compilation Overview | |||||
|  | |||||
| # Ch #2 Parsing | |||||
| ## Context-Free Grammars | |||||
| We use CFGs to produce a parse tree from tokens. | |||||
|  | |||||
| ## 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: | |||||
|  | |||||
| ## 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). | |||||
|  | |||||
| # 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: | |||||
|  | |||||
| ## S-Grammar: | |||||
| Only uses synthesized attributes: the grammar above. | |||||
|  | |||||
| ## L-Grammar: | |||||
| A l attribute depends on things above them or besides them in the parse tree. | |||||
|  | |||||
| ## 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: | |||||
|  | |||||
| 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. | |||||
|  | |||||
| ### 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. | |||||
|  | |||||
| # 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 | |||||
|  | |||||
| ```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 | |||||
| } | |||||
| ``` | |||||