Why the word 'dereferencing' in terms of dereferencing pointers? [duplicate] - objective-c

This question will draw information from the draft N1570, so C11 basically.
Colloquially, to dereference a pointer means to apply the unary * operator to a pointer. There is only one place where the word "dereferencing" exists in the draft document (no instance of "dereference"), and it is in a footnote:
102) [...]
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, an address inappropriately aligned for
the type of object pointed to, and the address of an object after the
end of its lifetime
As far as I can see, the unary * operator is actually called the "indirection operator", as evidenced by §6.5.3.2:
6.5.3.2 Address and indirection operators
4 The unary * operator denotes indirection. [...]
Simiarily, it is explicitly called the indirection operator in Annex §J.2:
— The value of an object is accessed by an array-subscript [],
member-access . or −>, address &, or indirection * operator or a
pointer cast in creating an address constant (6.6).
So is it correct to talk about "dereferencing pointers" in C or is this being excessively pedantic? Where does the terminology come from? (I can kinda give a pass on [] being called "deferencing" due to §6.5.2.1)

K&R v1
If one look at The C Programming Language, in first edition, (1978), the term “indirection” is used.
Examples
2.12 Precedence and Order of Evaluation
[…]
Chapter 5 discusses * (indirection) and & (address of).
,
7.2 Unary operators
[…]
The unary * operator means indirection: the expression must be a pointer, and the
result is an lvalue referring to the object to which the expression points.
It is also listed in INDEX as e.g.
* indirection operator 89, 187
A longer excerpt from section 5.1
5.1 Pointers and Addresses
      Since a pointer contains the address of an object, it is possible to access the object “indirectly” through the pointer.
Suppose that x is a variable, say an int, and that px is a
pointer, created in some as yet unspecified way. The unary operator c
gives the address of an object, so the statement
px = &x;
assigns the address of x to the variable px; px is now said to
“point to” x. The & operator can be applied only to variables
and array elements; constructs like &(x+1 ) and &3 are illegal. It
is also illegal to take the address of a register variable.
    The unary operator * treats its operand as the address off the ultimate target, and accesses that address to fetch the contents. Thus
if y is alos an int,
y = *px;
assigns to y the contents of whatever px points to. So the
sequence
px = &x;
y = *px;
assigns the same value to y as does
y = x;
K&R v2
In second edition the term dereferencing comes in.
5.1 Pointers and Addresses
The unary operator * is the indirection or dereferencing operator; when applied to a pointer, it accesses the object the pointer points to. Suppose that x and y are integers and ip is a pointer to int. This artificial sequence shows how to declare a pointer and how to use & and *:
[…]
Prior usage
The term is however ("much") older as can be seen in e.g.
A survey of some issues concerning abstract data types, 1974. E.g pp24/25. Here stated in the connection with ALGOL 68, PASCAL, SIMULA 67.
The mechanism by which pointers are transformed into values by a language is
known as 'dereferencing', a form of coercion (discussed later). Consider the statement
p := q;
Depending upon the types of p and q, there are several possible interpretations.
Let '#' be a dereferencing operator (i.e. if p points to j , then #p is the same as j) and
'#' be a referencing operation (i.e. if p points to j , then p is the same as #j). The
following table indicates the possible actions a language might take to perform the
assignment:
|
| type of p
|
| t ref t ref ref t . . .
|
---------------------------------------------------------
|
t | p←q p←#q p←##q
| #p←q #p←#q
| ##p←q
type |
of |
q ref t | p←#q p←q p←#q
| #p←#q #p←q
| ##p←#q
|
|
ref ref t | p←##q p←#q p←q
. | #p←##q #p←#q
. | ##p←##q
. |
|
|
[…]
Coining
There are several other examples of its usage. Exactly where and when it was coined I am not able to find though (at least not yet). (The 1974 paper is at least interesting.)
For the fun of it it can also often be useful to look at mailing lists such as net.unix-wizards. An example from Peter Lamb at Melbourne Uni (11/28/83):
Dereferencing NULL pointers is yet another example of idiots who
write 'portable' code, assuming however, that THEIR machine is the
only one on which it will ever run: the same sorts of people who designed
cpio with binary headers.
Even on a VAX, dereferencing NULL will get you garbage: sure, *(char *)NULL
and *(short *)NULL return you 0, but *(int *)NULL will give you
1024528128 !!!!.
[…]
Ed1. Addition
Not mentioning “dereferencing” but still; An interesting read is Ritchie: The Development of the C Language ✝
Here the term “indirection” is also consistently used – but/and/etc. the connection between the languages are somewhat detailed. The use of the term is thus interesting in view of e.g. papers like the 1974 one mentioned above.
As an example on indirection as concept and the syntax read e.g. pp 12 ev.
    An accident of syntax contributed to the perceived complexity of the language. The indirection operator, spelled * in C, is syntactically a unary prefix operator, just as in BCPL and B. This works well in simple expressions, but in more complex cases, parentheses are required to direct the parsing.
[…]
There are two effects occurring. Most important, C has a relatively rich set of ways of describing types (compared, say, with Pascal). Declarations in languages as expressive as C– Algol 68, for example – describe objects equally hard to understand, simply because the objects themselves are complex. A second effect owes to details of the syntax. Declarations in C must be read in an ‘inside-out’ style that many find difficult to grasp [Anderson 80].
In this conjunction it is likely also worth mentioning ANSI C89 and mentions like:
3.1.2.5 Types
A pointer to void may not be dereferenced, although such a pointer may be converted to a normal pointer type which may be dereferenced.
Draft ANSI C Standard (ANSI X3J11/88-090), (Courtesy of Wikipedia)
Rationale for American National Standard for Information Systems – Programming Language – C
Among the invalid values for dereferencing a pointer by the unary * operator are
a null pointer, an address inappropriately aligned for the type of
object pointed to, or the address of an object that has automatic
storage duration when execution of the block in which the object is
declared and of all enclosed blocks has terminated.
(I have to re-read some of these documents now.)

Because in the good old days of K&R C, the language only passed parameters by value. So pointers were used to simulate a pass parameters by reference. And people (incorrectly) spoke of taking a reference to a variable for constructing a pointer to a variable.
And the dereferencing of a pointer was the opposite operation.
Now C++ uses true references that are distinct from pointers, but the word dereference is still used (even if it is not really correct).

I do not know the exact etymology, but one can consider a pointer value (in the generic sense, not the C/C++-specific meaning) as "referencing" another object in memory; that is, p refers to x. When we use p to obtain the value stored in x, we are bypassing that reference, or de-referencing p.

Kernighan and Ritchie, The C Programming Language, 2nd ed., 5.1:
The unary operator * is the indirection or dereferencing operator; [...] ''pointer to void'' is used to hold any type of pointer but cannot be dereferenced itself.

Related

Does Perl 6 have an infinite Int?

I had a task where I wanted to find the closest string to a target (so, edit distance) without generating them all at the same time. I figured I'd use the high water mark technique (low, I guess) while initializing the closest edit distance to Inf so that any edit distance is closer:
use Text::Levenshtein;
my #strings = < Amelia Fred Barney Gilligan >;
for #strings {
put "$_ is closest so far: { longest( 'Camelia', $_ ) }";
}
sub longest ( Str:D $target, Str:D $string ) {
state Int $closest-so-far = Inf;
state Str:D $closest-string = '';
if distance( $target, $string ) < $closest-so-far {
$closest-so-far = $string.chars;
$closest-string = $string;
return True;
}
return False;
}
However, Inf is a Num so I can't do that:
Type check failed in assignment to $closest-so-far; expected Int but got Num (Inf)
I could make the constraint a Num and coerce to that:
state Num $closest-so-far = Inf;
...
$closest-so-far = $string.chars.Num;
However, this seems quite unnatural. And, since Num and Int aren't related, I can't have a constraint like Int(Num). I only really care about this for the first value. It's easy to set that to something sufficiently high (such as the length of the longest string), but I wanted something more pure.
Is there something I'm missing? I would have thought that any numbery thing could have a special value that was greater (or less than) all the other values. Polymorphism and all that.
{new intro that's hopefully better than the unhelpful/misleading original one}
#CarlMäsak, in a comment he wrote below this answer after my first version of it:
Last time I talked to Larry about this {in 2014}, his rationale seemed to be that ... Inf should work for all of Int, Num and Str
(The first version of my answer began with a "recollection" that I've concluded was at least unhelpful and plausibly an entirely false memory.)
In my research in response to Carl's comment, I did find one related gem in #perl6-dev in 2016 when Larry wrote:
then our policy could be, if you want an Int that supports ±Inf and NaN, use Rat instead
in other words, don't make Rat consistent with Int, make it consistent with Num
Larry wrote this post 6.c. I don't recall seeing anything like it discussed for 6.d.
{and now back to the rest of my first answer}
Num in P6 implements the IEEE 754 floating point number type. Per the IEEE spec this type must support several concrete values that are reserved to stand in for abstract concepts, including the concept of positive infinity. P6 binds the corresponding concrete value to the term Inf.
Given that this concrete value denoting infinity already existed, it became a language wide general purpose concrete value denoting infinity for cases that don't involve floating point numbers such as conveying infinity in string and list functions.
The solution to your problem that I propose below is to use a where clause via a subset.
A where clause allows one to specify run-time assignment/binding "typechecks". I quote "typecheck" because it's the most powerful form of check possible -- it's computationally universal and literally checks the actual run-time value (rather than a statically typed view of what that value can be). This means they're slower and run-time, not compile-time, but it also makes them way more powerful (not to mention way easier to express) than even dependent types which are a relatively cutting edge feature that those who are into advanced statically type-checked languages tend to claim as only available in their own world1 and which are intended to "prevent bugs by allowing extremely expressive types" (but good luck with figuring out how to express them... ;)).
A subset declaration can include a where clause. This allows you to name the check and use it as a named type constraint.
So, you can use these two features to get what you want:
subset Int-or-Inf where Int:D | Inf;
Now just use that subset as a type:
my Int-or-Inf $foo; # ($foo contains `Int-or-Inf` type object)
$foo = 99999999999; # works
$foo = Inf; # works
$foo = Int-or-Inf; # works
$foo = Int; # typecheck failure
$foo = 'a'; # typecheck failure
1. See Does Perl 6 support dependent types? and it seems the rough consensus is no.

menhir - associate AST nodes with token locations in source file

I am using Menhir to parse a DSL. My parser builds an AST using an elaborate collection of nested types. During later typecheck and other passes in error reports generated for a user, I would like to refer to source file position where it occurred. These are not parsing errors, and they generated after parsing is completed.
A naive solution would be to equip all AST types with additional location information, but that would make working with them (e.g. constructing or matching) unnecessary clumsy. What are the established practices to do that?
I don't know if it's a best practice, but I like the approach taken in the abstract syntax tree of the Frama-C system; see https://github.com/Frama-C/Frama-C-snapshot/blob/master/src/kernel_services/ast_data/cil_types.mli
This approach uses "layers" of records and algebraic types nested in each other. The records hold meta-information like source locations, as well as the algebraic "node" you can match on.
For example, here is a part of the representation of expressions:
type ...
and exp = {
eid: int; (** unique identifier *)
enode: exp_node; (** the expression itself *)
eloc: location; (** location of the expression. *)
}
and exp_node =
| Const of constant (** Constant *)
| Lval of lval (** Lvalue *)
| UnOp of unop * exp * typ
| BinOp of binop * exp * exp * typ
...
So given a variable e of type exp, you can access its source location with e.eloc, and pattern match on its abstract syntax tree in e.enode.
So simple, "top-level" matches on syntax are very easy:
let rec is_const_expr e =
match e.enode with
| Const _ -> true
| Lval _ -> false
| UnOp (_op, e', _typ) -> is_const_expr e'
| BinOp (_op, l, r, _typ) -> is_const_expr l && is_const_expr r
To match deeper in an expression, you have to go through a record at each level. This adds some syntactic clutter, but not too much, as you can pattern match on only the one record field that interests you:
let optimize_double_negation e =
match e.enode with
| UnOp (Neg, { enode = UnOp (Neg, e', _) }, _) -> e'
| _ -> e
For comparison, on a pure AST without metadata, this would be something like:
let optimize_double_negation e =
match e.enode with
| UnOp (Neg, UnOp (Neg, e', _), _) -> e'
| _ -> e
I find that Frama-C's approach works well in practice.
You need somehow to attach the location information to your nodes. The usual solution is to encode your AST node as a record, e.g.,
type node =
| Typedef of typdef
| Typeexp of typeexp
| Literal of string
| Constant of int
| ...
type annotated_node = { node : node; loc : loc}
Since you're using records, you can still pattern match without too much syntactic overhead, e.g.,
match node with
| {node=Typedef t} -> pp_typedef t
| ...
Depending on your representation, you may choose between wrapping each branch of your type individually, wrapping the whole type, or recursively, like in Frama-C example by #Isabelle Newbie.
A similar but more general approach is to extend a node not with the location, but just with a unique identifier and to use a final map to add arbitrary data to nodes. The benefit of this approach is that you can extend your nodes with arbitrary data as you actually externalize node attributes. The drawback is that you can't actually guarantee the totality of an attribute since finite maps are no total. Thus it is harder to preserve an invariant that, for example, all nodes have a location.
Since every heap allocated object already has an implicit unique identifier, the address, it is possible to attach data to the heap allocated objects without actually wrapping it in another type. For example, we can still use type node as it is and use finite maps to attach arbitrary pieces of information to them, as long as each node is a heap object, i.e., the node definition doesn't contain constant constructors (in case if it has, you can work around it by adding a bogus unit value, e.g., | End can be represented as | End of unit.
Of course, by saying an address, I do not literally mean the physical or virtual address of an object. OCaml uses a moving GC so an actual address of an OCaml object may change during a program execution. Moreover, an address, in general, is not unique, as once an object is deallocated its address can be grabbed by a completely different entity.
Fortunately, after ephemera were added to the recent version of OCaml it is no longer a problem. Moreover, an ephemeron will play nicely with the GC, so that if a node is no longer reachable its attributes (like file locations) will be collected by the GC. So, let's ground this with a concrete example. Suppose we have two nodes c1 and c2:
let c1 = Literal "hello"
let c2 = Constant 42
Now we can create a location mapping from nodes to locations (we will represent the latter as just strings)
module Locations = Ephemeron.K1.Make(struct
type t = node
let hash = Hashtbl.hash (* or your own hash if you have one *)
let equal = (=) (* or a specilized equal operator *)
end)
The Locations module provides an interface of a typical imperative hash table. So let's use it. In the parser, whenever you create a new node you should register its locations in the global locations value, e.g.,
let locations = Locations.create 1337
(* somewhere in the semantics actions, where c1 and c2 are created *)
Locations.add c1 "hello.ml:12:32"
Locations.add c2 "hello.ml:13:56"
And later, you can extract the location:
# Locations.find locs c1;;
- : string = "hello.ml:12:32"
As you see, although the solution is nice in the sense, that it doesn't touch the node data type, so the rest of your code can pattern match on it nice and easy, it is still a little bit dirty, as it requires global mutable state, that is hard to maintain. Also, since we are using an object address as a key, every newly created object, even if it was logically derived from the original object, will have a different identity. For example, suppose you have a function, that normalizes all literals:
let normalize = function
| Literal str -> Literal (normalize_literal str)
| node -> node
It will create a new Literal node from the original nodes, so all the location information will be lost. That means, that you need to update the location information, every time you derive one node from another.
Another issue with ephemera is that they can't survive the marshaling or serialization. I.e., if you store your AST somewhere in a file, and then you restore it, all nodes will loose their identity, and the location table will become empty.
Speaking of the "monadic approach" that you mentioned in comments. Though monads are magic, they still can't magically solve all the problems. They are not silver bullets :) In order to attach something to a node we still need to extend it with an extra attribute - either a location information directly or an identity through which we can attach properties indirectly. The monad can be useful for the latter though, as instead of having a global reference to the last assigned identifier, we can use a state monad, to encapsulate our id generator. And for the sake of completeness, instead of using a state monad or a global reference to generate unique identifiers, you can use UUID and get identifiers that are not only unique in a program run, but are also universally unique, in the sense that there are no other objects in the world with the same identifier, no matter how often you run your program (in the sane world). And although it looks like that generating the UUID doesn't use any state, underneath the hood it still uses an imperative random number generator, so it is sort of cheating, but still can seen as pure functional, as it doesn't contain observable effects.

Fortran serialization using C_LOC and C_F_POINTER

I'm looking for a Fortran Library or preferred method of serializing data to a memory buffer in Fortran.
After researching the topic, I found examples using the EQUIVALENCE statement and the TRANSFER intrinsic function. I wrote code to test them and they both worked. In my limited testing, the transfer function seems to be quite a bit slower than the equivalence statement. However, I have found several references stating that in general not to use the equivalence statement.
So, I've been trying to come up with another way to serialize data efficiently. After ready up on the Fortran 2003 spec I discovered that I could use the C_LOC and C_F_POINTER together to cast my "byte" array into the desired data type (int, real, etc..). Initial testing shows that it is working and is faster than the transfer function. An example program is listed below. I was wondering if this is valid use of the C_LOC and C_F_POINTER functions.
Thanks!
program main
use iso_c_binding
implicit none
real(c_float) :: a, b, c
integer(c_int8_t), target :: buf(12)
a = 12345.6789_c_float
b = 4567.89123_c_float
c = 9079.66788_c_float
call pack_float( a, c_loc(buf(1)) )
call pack_float( b, c_loc(buf(5)) )
call pack_float( c, c_loc(buf(9)) )
print '(A,12I5)', 'Bin: ', buf
contains
subroutine pack_float( src, dest )
implicit none
real(c_float), intent(in) :: src
type(c_ptr), intent(in) :: dest
real(c_float), pointer :: p
call c_f_pointer(dest, p)
p = src
end subroutine
end program
Output:
Bin: -73 -26 64 70 33 -65 -114 69 -84 -34 13 70
I also coded this up in Python to double check the answer above. The code and output is listed below.
import struct
a = struct.pack( '3f', 12345.6789, 4567.89123, 9079.66788)
b = struct.unpack('12b', a)
print b
Output:
(-73, -26, 64, 70, 33, -65, -114, 69, -84, -34, 13, 70)
Practically, use of C_LOC and C_F_POINTER in this way is likely to work, but formally it is not standard conforming. The type and type parameters of the Fortran pointer passed to C_F_POINTER must either be interoperable with the object nominated by the C address or be the same as the type and type parameters of the object that was originally passed to C_LOC (see the description of the FPTR argument in F2008 15.2.3.3). Depending on what you are trying to serialize, you may also find that formal restrictions on the C_LOC argument (which are progressively less restrictive in later standards than F2003) come into play.
(The C equivalent requires use of unsigned char for this sort of trick - which is not necessarily the same thing as int8_t.)
There are constraints on the items in an EQUIVALENCE set that make that approach not generally applicable (see constraints C591 through C594 in F2008). Interpreting the internal representation of an object through equivalence is also formally subject to the rules around definition and undefinition of variables - see F2008 16.6.6 item 1 in particular.
The conforming way to access the representation of one object as a different type in Fortran is through TRANSFER. Be mindful that serialization of the internal representation of derived types with allocatable or pointer components (is that what you mean by dynamic fields?) may not be useful.
Depending on circumstance, it may be simpler and more robust to simply store your real time results in an array of the type of the thing to be stored.

What are Free and Bound variables?

I've been programming for a long time (too long, actually), but I'm really struggling to get a handle on the terms "Free Variables" and "Bound Variables".
Most of the "explanations" I've found online start by talking about topics like Lambda calculus and Formal logic, or Axiomatic Semantics. which makes me want to reach for my revolver.
Can someone explain these two terms, ideally from an implementation perspective. Can they exist in compiled languages, and what low-level code do they translate to?
A free variable is a variable used in some function that its value depends on the context where the function is invoked, called or used. For example, in math terms, z is a free variable because is not bounded to any parameter. x is a bounded variable:
f(x) = x * z
In programming languages terms, a free variable is determined dynamically at run time searching the name of the variable backwards on the function call stack.
A bounded variable evaluation does not depend on the context of the function call. This is the most common modern programming languages variable type. Local variables, global variables and parameters are all bounded variables.
A free variable is somewhat similar to the "pass by name" convention of some ancient programming languages.
Let's say you have a function f that just prints some variable:
def f():
print(X)
This is Python. While X is not a local variable, its value follows the Python convention: it searches upwards on the chain of the blocks where the function is defined until it reaches the top level module.
Since in Python the value of X is determined by the function declaration context, we say that X is a bounded variable.
Hypothetically, if X were a free variable, this should print 10:
X = 2
def f():
print(X)
def g():
# X is a local variable to g, shadowing the global X
X = 10
f()
In Python, this code prints 2 because both X variables are bounded. The local X variable on g is bounded as a local variable, and the one on f is bounded to the global X.
Implementation
The implementation of a programming language with free variables needs to take care the context on where each function is called, and for every free variable use some reflection to find which variable to use.
The value of a free variable can not be generally determined at compile time, since is heavily determined by the run time flow and the call stack.
Whether a variable is free or bound is relative; it depends on the fragment of code you are looking at.
In this fragment, x is bound:
function(x) {return x + x;};
And here, x occurs free:
return x + x;
In other words, freeness is a property of the context. You don't say "x is a free variable" or "x is a bound variable," but instead identify the context you are talking about: "x is free in the expression E." For this reason, the same variable x can be either free or bound depending on which fragment of code you are talking about. If the fragment contains the variable's binding site (for example, it is listed in the function arguments) then it is bound, if not, it is free.
Where the free/bound distinction is important from an implementation perspective is when you are implementing how variable substitution works (e.g. what happens when you apply arguments to a function.) Consider the evaluation steps:
(function(x) {return x + x;})(3);
=> 3 + 3
=> 6
This works fine because x is free in the body of the function. If x was bound in the body of the function, however, our evaluation would need to be careful:
(function(x) {return (function(x){return x * 2;})(x + x);})(3);
=> (function(x){return x * 2;})(3 + 3); // careful to leave this x alone for now!
=> (function(x){return x * 2;})(6);
=> 6 * 2
=> 12
If our implementation didn't check for bound occurrences, it could have replaced the bound x for 3 and given us the wrong answer:
(function(x) {return (function(x){return x * 2;})(x + x);})(3);
=> (function(x){return 3 * 2;})(3 + 3); // Bad! We substituted for a bound x!
=> (function(x){return 3 * 2;})(6);
=> 3 * 2
=> 6
Also, it should be clarified that free vs. bound is a property of the syntax (i.e. the code itself), not a property of how a the code is evaluated at run-time. vz0 talks about dynamically scoped variables, which are somewhat related to, but not synonymous with, free variables. As vz0 correctly describes, dynamic variable scope is a language feature that allows expressions that contains free variables to be evaluated by looking at the run-time call-stack to find the value of a variable that shares the same name. However, It still makes sense to talk about free occurrences of variables in languages that don't allow dynamic scope: you would just get an error (like "x is not defined") if you were to try to evaluate an such expression in these languages.
And I can't restrain myself: I hope one day you can find the strength to put your revolvers away when people mention lambda calculus! Lambda calculus is a good tool for thinking about variables and bindings because it is an extremely minimal programming language that supports variables and substitution and nothing else. Real-world programming languages contain a lot of other junk (like dynamic scope, for example) that obscures the essence.

First and follow of the non-terminals in two grammars

Given the following grammar:
S -> L=L
s -> L
L -> *L
L -> id
What are the first and follow for the non-terminals?
If the grammar is changed into:
S -> L=R
S -> R
L -> *R
L -> id
R -> L
What will be the first and follow ?
When I took a compiler course in college I didn't understand FIRST and FOLLOWS at all. I implemented the algorithms described in the Dragon book, but I had no clue what was going on. I think I do now.
I assume you have some book that gives a formal definition of these two sets, and the book is completely incomprehensible. I'll try to give an informal description of them, and hopefully that will help you make sense of what's in your book.
The FIRST set is the set of terminals you could possibly see as the first part of the expansion of a non-terminal. The FOLLOWS set is the set of terminals you could possibly see following the expansion of a non-terminal.
In your first grammar, there are only three kinds of terminals: =, *, and id. (You might also consider $, the end-of-input symbol, to be a terminal.) The only non-terminals are S (a statement) and L (an Lvalue -- a "thing" you can assign to).
Think of FIRST(S) as the set of non-terminals that could possibly start a statement. Intuitively, you know you do not start a statement with =. So you wouldn't expect that to show up in FIRST(S).
So how does a statement start? There are two production rules that define what an S looks like, and they both start with L. So to figure out what's in FIRST(S), you really have to look at what's in FIRST(L). There are two production rules that define what an Lvalue looks like: it either starts with a * or with an id. So FIRST(S) = FIRST(L) = { *, id }.
FOLLOWS(S) is easy. Nothing follows S because it is the start symbol. So the only thing in FOLLOWS(S) is $, the end-of-input symbol.
FOLLOWS(L) is a little trickier. You have to look at every production rule where L appears, and see what comes after it. In the first rule, you see that = may follow L. So = is in FOLLOWS(L). But you also notice in that rule that there is another L at the end of the production rule. So another thing that could follow L is anything that could follow that production. We already figured out that the only thing that can follow the S production is the end-of-input. So FOLLOWS(L) = { =, $ }. (If you look at the other production rules, L always appears at the end of them, so you just get $ from those.)
Take a look at this Easy Explanation, and for now ignore all the stuff about ϵ, because you don't have any productions which contain the empty-string. Under "Rules for First Sets", rules #1, #3, and #4.1 should make sense. Under "Rules for Follows Sets", rules #1, #2, and #3 should make sense.
Things get more complicated when you have ϵ in your production rules. Suppose you have something like this:
D -> S C T id = V // Declaration is [Static] [Const] Type id = Value
S -> static | ϵ // The 'static' keyword is optional
C -> const | ϵ // The 'const' keyword is optional
T -> int | float // The Type is mandatory and is either 'int' or 'float'
V -> ... // The Value gets complicated, not important here.
Now if you want to compute FIRST(D) you can't just look at FIRST(S), because S may be "empty". You know intuitively that FIRST(D) is { static, const, int, float }. That intuition is codified in rule #4.2. Think of SCT in this example as Y1Y2Y3 in the "Easy Explanation" rules.
If you want to compute FOLLOWS(S), you can't just look at FIRST(C), because that may be empty, so you also have to look at FIRST(T). So FOLLOWS(S) = { const, int, float }. You get that by applying "Rules for follow sets" #2 and #4 (more or less).
I hope that helps and that you can figure out FIRST and FOLLOWS for the second grammar on your own.
If it helps, R represents an Rvalue -- a "thing" you can't assign to, such as a constant or a literal. An Lvalue can also act as an Rvalue (but not the other way around).
a = 2; // a is an lvalue, 2 is an rvalue
a = b; // a is an lvalue, b is an lvalue, but in this context it's an rvalue
2 = a; // invalid because 2 cannot be an lvalue
2 = 3; // invalid, same reason.
*4 = b; // Valid! You would almost never write code like this, but it is
// grammatically correct: dereferencing an Rvalue gives you an Lvalue.