21 lines
1.4 KiB
Plaintext
21 lines
1.4 KiB
Plaintext
|
1. It is valid for a name to occur in the body of a function.
|
||
|
2. It is valid for a name to occur outside the body of a function as long as there are no cycles of such occurrences.
|
||
|
|
||
|
|
||
|
A simpler version:
|
||
|
1. It is valid for a name to occur in the body of a function.
|
||
|
2. It is valid for a name to occur in the definition of a name that is later in the binding list.
|
||
|
e.g. let a = 5 and b = a in ...
|
||
|
|
||
|
|
||
|
It's actually more complicated than this. The OCaml definition of static constructivity doesn't just specify that a name can only occur in the body of a function; instead, it also specifies a set of valid nesting forms, *none of which is a function call.* Otherwise, you could end up with something like
|
||
|
let rec a = (fun()->b)() and b = (fun()->a)() in a
|
||
|
which is nonsense.
|
||
|
So what I need is approximately this:
|
||
|
1. An expression is valid if it is statically constructive with respect to each defined name and it is not immediately linked to each defined name.
|
||
|
- Statically constructive basically means that the expression doesn't have to compute anything at runtime.
|
||
|
2. An expression is valid if it only refers to names defined before it in the binding list.
|
||
|
- A more flexible rule with a more complex implementation would be to check an occurs graph for cycles.
|
||
|
3. An expression is valid if it only contains valid subexpressions.
|
||
|
OCaml also stipulates something about array constructors with an abstract element type, but I don't understand that one yet.
|