type-inference #39
2
Makefile
@@ -94,7 +94,7 @@ sextest:
|
|||||||
cp ./tools/sextest/sextest .
|
cp ./tools/sextest/sextest .
|
||||||
|
|
||||||
SEX_TEST_PROGRAMS = hello-world lists comments unicode serialize features \
|
SEX_TEST_PROGRAMS = hello-world lists comments unicode serialize features \
|
||||||
feature-flags lambdas compound-literals
|
feature-flags lambdas compound-literals closures fixpoint
|
||||||
|
|
||||||
# Multi-module linking is checked end to end; see tests/modules/Makefile.
|
# Multi-module linking is checked end to end; see tests/modules/Makefile.
|
||||||
|
|
|||||||
check-modules: sexc
|
check-modules: sexc
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
(fn sum ((a int) (b int)) int
|
(fn sum ((a int) (b int)) int
|
||||||
(return (+ a b)))
|
(return (+ a b)))
|
||||||
|
|
||||||
|
;;; A lambda captures nothing and is a bare function pointer; a closure
|
||||||
|
;;; captures and is a value carrying its own environment
|
||||||
|
(fn make-adder ((a int)) (closure ((int)) int)
|
||||||
|
(return (closure ((b int)) int (a)
|
||||||
|
(return (+ a b)))))
|
||||||
|
|
||||||
(pub fn main () int
|
(pub fn main () int
|
||||||
(var a int 10)
|
(var a int 10)
|
||||||
(var b int 20)
|
(var b int 20)
|
||||||
@@ -36,13 +42,7 @@
|
|||||||
(return (+ 600 (l-2 a)))))
|
(return (+ 600 (l-2 a)))))
|
||||||
(printf "Calling nested lambdas: %d\n" (l-1 6))
|
(printf "Calling nested lambdas: %d\n" (l-1 6))
|
||||||
|
|
||||||
;; Not supported yet -- captures belong to `closure' now, see
|
(var add-10 (closure ((int)) int) (make-adder 10))
|
||||||
;; Function-values.org
|
(var add-20 (closure ((int)) int) (make-adder 20))
|
||||||
;; (fn make-adder ((a int)) (closure ((int)) int)
|
(printf "Calling closures: %d %d\n" (add-10 24) (add-20 24))
|
||||||
;; (return (closure ((b int)) int (a)
|
|
||||||
;; (return (+ a b)))))
|
|
||||||
;;
|
|
||||||
;; (var add-10 (closure ((int)) int) (make-adder 10))
|
|
||||||
;; (var add-20 (closure ((int)) int) (make-adder 20))
|
|
||||||
;; (printf "Calling closures: %d %d\n" (add-10 24) (add-20 24))
|
|
||||||
(return 0))
|
(return 0))
|
||||||
|
|||||||
399
semen.scm
@@ -17,6 +17,7 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
)
|
)
|
||||||
|
|
||||||
(export/rename (process semen-process))
|
(export/rename (process semen-process))
|
||||||
|
(export closure-env-declaration)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
;;; for lambda extraction, docstring processing, macro expansion,
|
;;; for lambda extraction, docstring processing, macro expansion,
|
||||||
;;; injection of module headers, i.e. all things that rearrange code
|
;;; injection of module headers, i.e. all things that rearrange code
|
||||||
@@ -37,8 +38,18 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(macroexpand (car forms) (cdr forms))
|
(macroexpand (car forms) (cdr forms))
|
||||||
acc))
|
acc))
|
||||||
(else
|
(else
|
||||||
(process-rec (cdr forms)
|
;; A closure type's struct is emitted before the toplevel form that
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(match-sex-form (car forms) acc)))))
|
;; first mentioned it, which is why the new forms are lifted off and
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; the structs slide underneath them
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let* ((processed (match-sex-form (car forms) acc))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(new (take-until processed acc)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(process-rec (cdr forms)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(append new (flush-closure-structs!) acc))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (take-until forms tail)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (eq? forms tail)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cons (car forms) (take-until (cdr forms) tail))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
(define (macroexpand macro-form rest-forms)
|
(define (macroexpand macro-form rest-forms)
|
||||||
;; We want to replace macro with its expansion. The problem is,
|
;; We want to replace macro with its expansion. The problem is,
|
||||||
@@ -225,7 +236,7 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(extract-fn-docstring (strip-fn-header-comments sex-fn-raw))))
|
(extract-fn-docstring (strip-fn-header-comments sex-fn-raw))))
|
||||||
(let* ((expanded (macro-expand sex-fn))
|
(let* ((expanded (macro-expand sex-fn))
|
||||||
(env (make-hash-table))
|
(env (make-hash-table))
|
||||||
(processed
|
(lifted
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(walk-form
|
(walk-form
|
||||||
expanded
|
expanded
|
||||||
fn-walker
|
fn-walker
|
||||||
@@ -233,25 +244,133 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(set! (hash-table-ref env :fn-name) (sex-fn-name expanded))
|
(set! (hash-table-ref env :fn-name) (sex-fn-name expanded))
|
||||||
(set! (hash-table-ref env :lambda-counter) 0)
|
(set! (hash-table-ref env :lambda-counter) 0)
|
||||||
(set! (hash-table-ref env :lambda-aux-code) (list))
|
(set! (hash-table-ref env :lambda-aux-code) (list))
|
||||||
env))))
|
(set! (hash-table-ref env :var-types)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(declared-types (sex-fn-arglist expanded)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(processed (rewrite-closure-calls-in-body lifted env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(with-docstring doc processed
|
(with-docstring doc processed
|
||||||
(append (hash-table-ref env :lambda-aux-code) acc)))))
|
(append (hash-table-ref env :lambda-aux-code) acc)))))
|
||||||
|
|
||||||
|
(define (declared-types arglist)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((types (make-hash-table)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(for-each (lambda (param)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(when (and (pair? param) (pair? (cdr param)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-set! types (first param) (second param))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
arglist)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
types))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (aux-name! env make)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((counter (hash-table-ref env :lambda-counter)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! (hash-table-ref env :lambda-counter) (+ counter 1))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(make (hash-table-ref env :fn-name) counter)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (add-aux-code! env forms)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! (hash-table-ref env :lambda-aux-code)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(append forms (hash-table-ref env :lambda-aux-code))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(define (fn-walker form env)
|
(define (fn-walker form env)
|
||||||
(if (eq? 'lambda (car form))
|
(let ((head (car form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(let ((lambda-name (make-lambda-name (hash-table-ref env :fn-name)
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(hash-table-ref env :lambda-counter))))
|
((eq? 'lambda head)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(set! (hash-table-ref env :lambda-aux-code)
|
(let ((name (aux-name! env make-lambda-name)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(append (lift-lambda lambda-name form)
|
(add-aux-code! env (lift-lambda name form))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(hash-table-ref env :lambda-aux-code)))
|
name))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(set! (hash-table-ref env :lambda-counter)
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(+ (hash-table-ref env :lambda-counter) 1))
|
;; a type, not an expression -- becomes the struct for its signature
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
lambda-name)
|
((closure-type? form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
form))
|
(copy-form-source! form `(struct ,(register-closure-type! form form))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((eq? 'closure head)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((base (aux-name! env make-closure-name)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let-values (((construct forms) (lift-closure base form env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(add-aux-code! env (fold match-sex-form (list) forms))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(copy-form-source! form `(,construct ,@(fourth form))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; every binding site is written, so tracking the declarations is
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; enough to know a receiver's type without inference
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((and (eq? 'var head) (>= (length form) 3))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-set! (hash-table-ref env :var-types) (second form) (third form))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else form))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (rewrite-closure-calls-in-body fn-form env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((header (fn-header-length fn-form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(append (take fn-form header)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(map (lambda (form) (rewrite-closure-calls form env))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(drop fn-form header)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (rewrite-closure-calls form env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (not (list? form))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
form
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((type (and (pair? form) (receiver-closure-type (car form) env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(rewrite (lambda (sub) (rewrite-closure-calls sub env))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(copy-form-source!
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
form
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if type
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(,(register-closure-call! type form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,(rewrite (car form))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(map rewrite (cdr form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(map rewrite form))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; A closure type has two spellings: `(closure ...)' as written, and
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `(struct ƛ...)' once resolved -- which is what a struct
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; field holds, since the type database is populated after resolution.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; Both name the same thing, so a receiver is recognised either way.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (as-closure-type type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((closure-type? type) type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((and (list? type) (= 2 (length type)) (eq? 'struct (car type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-ref/default +closure-structs+ (second type) #f))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else #f)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (receiver-closure-type expr env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(as-closure-type (expression-type expr env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; The type of an lvalue path, from known declarations -- a name, and
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; what can be reached from one by subscripting, dereferencing and
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; member access.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (expression-type expr env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((symbol? expr)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-ref/default (hash-table-ref env :var-types) expr #f))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((not (and (list? expr) (>= (length expr) 2))) #f)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(case (car expr)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((¤) (let ((base (expression-type (second expr) env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and (list? base) (>= (length base) 2) (eq? '¤ (car base))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(second base))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((*) (and (= 2 (length expr))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((base (expression-type (second expr) env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and (list? base) (= 2 (length base)) (eq? '* (car base))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(second base)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((dot-access) (member-path-type (expression-type (second expr) env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cddr expr)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((->) (let ((base (expression-type (second expr) env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and (list? base) (= 2 (length base)) (eq? '* (car base))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(member-path-type (second base) (cddr expr)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else #f)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (member-path-type type fields)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (null? fields)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
type
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(member-path-type (field-type type (car fields)) (cdr fields))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (field-type type field)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((name (cond ((symbol? type) type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((and (list? type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(= 2 (length type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(memq (car type) '(struct union)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(second type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else #f))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and name
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let* ((fields (get-fields name))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(entry (and fields (assq field fields))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and entry (second entry))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
(define (make-lambda-name enclosing-fn-name counter)
|
(define (make-lambda-name enclosing-fn-name counter)
|
||||||
(string->symbol
|
(string->symbol
|
||||||
(fmt #f "__lambda_" counter "_" enclosing-fn-name)))
|
(fmt #f "λ" counter "_" enclosing-fn-name)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
(define (lift-lambda name form)
|
(define (lift-lambda name form)
|
||||||
(match form
|
(match form
|
||||||
@@ -260,13 +379,255 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(list)))
|
(list)))
|
||||||
(else (sex-error form "malformed lambda" form))))
|
(else (sex-error form "malformed lambda" form))))
|
||||||
|
|
||||||
|
;;; Closures
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;;
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; A closure is a function pointer and an inline environment, so the
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; value owns its captures and nothing is allocated. The type
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `(closure ((int)) int)' becomes one struct per signature, shared by
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; every closure with that signature. The captures live in `env' as a record
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
alex-eg
commented
Re 347. The type gets what a Re 347. The type gets what a `fn` header gets -- macro expansion and closure resolution, no walk.
```
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) area) -> int (*fp)(int)
```
fe72a10.
|
|||||||
|
;;; only the lifted body knows the shape of, which is why `env' is
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; max_align_t rather than char -- it has to be aligned for whatever
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; ends up in it.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;;
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; The expression becomes three hoisted definitions -- the capture
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; struct, the lifted body, and a constructor -- and is replaced by a
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; call to the constructor, so the captures are evaluated as ordinary
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; arguments at the point the closure is written.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; How much of a closure is environment, in bytes. Counted in bytes
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; so a closure that fits where it was written will also fit
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; elsewhere. Captures are only by value, and never allocated on
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; heap. Anything that is more than 16 bytes should be stored as a
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; pointer, and memory management is entirely up to caller
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define +closure-env-bytes+ 16)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; +closure-env-bytes+ for maximum capacity, max-align-t for
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; effectiveness, hence union
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define +closure-env-type+ 'ƛenv)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (closure-env-declaration)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(union ,+closure-env-type+ ((align max-align-t)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(bytes (¤ char ,+closure-env-bytes+)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define +closure-structs+ (make-hash-table))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define +closure-forwards+ (make-hash-table))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define *pending-closure-structs* (list))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (closure-type? form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(and (pair? form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(eq? 'closure (car form))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(= 3 (length form))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; A type spelling becomes an identifier deterministically, so two
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; translation units have the same signatures for the same closure
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; types: (* const char) -> p_const_char, (closure ((int)) int) ->
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; closure_int_int.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (mangle-type type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((symbol? type) (mangle-word (symbol->string type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((number? type) (number->string type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((null? type) "void")
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((pair? type) (string-intersperse (map mangle-type (mangle-head type)) "_"))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else (sex-error type "cannot mangle type" type))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (mangle-head type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
alex-eg
commented
Re 348. A closure literal answers with its own type. The receiver is walked before the call helper is registered, so the struct is declared ahead of the signature naming it. Re 348. A closure literal answers with its own type. The receiver is walked before the call helper is registered, so the struct is declared ahead of the signature naming it.
```
((closure ((x int)) int () (return x)) 5) -> 5
```
fe72a10.
|
|||||||
|
(case (car type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((*) (cons 'p (cdr type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((¤) (cons 'a (cdr type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (mangle-word word)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list->string
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(map (lambda (c)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (or (char-alphabetic? c) (char-numeric? c)) c #\_))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(string->list word))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (aggregates-in type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((not (list? type)) (list))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((and (= 2 (length type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(memq (car type) '(struct union))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(symbol? (second type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else (append-map aggregates-in type))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; Extract aggregate types from the closure's signature to forward
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; declare them before the closure, so they can be referenced in the
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; closure. Particularly useful for complex cases like fixed point
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; combinator, etc.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (forward-declare-aggregates! type src-form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(for-each
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(lambda (aggregate)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((name (second aggregate)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unless (or (hash-table-exists? +closure-forwards+ name)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(get-tag-info name))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-set! +closure-forwards+ name #t)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! *pending-closure-structs*
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cons (copy-form-source! src-form aggregate)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
*pending-closure-structs*)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(delete-duplicates (aggregates-in type))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (closure-struct-name type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; the glyph says `closure' already, so the tag is just the signature
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(string->symbol (string-append "ƛ"
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(mangle-type (second type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
"_"
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(mangle-type (third type)))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; The code pointer takes the environment first; everything else is
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; the closure's own signature.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (closure-code-type type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(fn (((* void)) ,@(second type)) ,(third type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; Emitted once per signature, before the toplevel form that first
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; needed it.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (register-closure-type! type src-form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((name (closure-struct-name type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unless (hash-table-exists? +closure-structs+ name)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(forward-declare-aggregates! type src-form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-set! +closure-structs+ name type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((form (copy-form-source!
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
src-form
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(struct ,name ((code ,(closure-code-type type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(env (union ,+closure-env-type+)))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(register-aggregate! form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! *pending-closure-structs*
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cons form *pending-closure-structs*))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
name))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; Every closure type in FORM becomes the struct for its signature,
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; registering it on the way. The walker does this for function bodies
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; and headers; globals come through here instead.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (resolve-closure-types form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cond
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((closure-type? form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(copy-form-source! form `(struct ,(register-closure-type! form form))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
((list? form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(copy-form-source! form (map resolve-closure-types form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define +closure-calls+ (make-hash-table))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; The helper a closure call is routed through: `(f 1)' becomes
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `ƛint_int_call(f, 1)', which unpacks the receiver into
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `ƛc.code(&ƛc.env, ƛa0)' inside. The receiver arrives as an argument,
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; so it is evaluated once: unpacked at the call site instead,
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `([table (++ i)] 10)' would read
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; `table[++i].code(&table[++i].env, 10)' and bump `i' twice.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (register-closure-call! type src-form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let* ((closure (closure-struct-name type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(helper (suffixed closure "_call"))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(returns (third type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(params (map (lambda (arg index)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list (string->symbol (fmt #f "ƛa" index))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unwrap-type arg)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(second type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(iota (length (second type))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unless (hash-table-ref/default +closure-calls+ helper #f)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(hash-table-set! +closure-calls+ helper #t)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((call `((dot-access ƛc code)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(& (dot-access ƛc env))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(map first params))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! *pending-closure-structs*
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cons (copy-form-source!
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
src-form
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(fn ,helper ((ƛc (struct ,closure)) ,@params) ,returns
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,(if (eq? 'void returns) call `(return ,call))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
*pending-closure-structs*))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
helper))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; An argument type is written wrapped: `(int)' in `((int) (float))'
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (unwrap-type type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (and (list? type) (= 1 (length type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(car type)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (flush-closure-structs!)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((pending *pending-closure-structs*))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(set! *pending-closure-structs* (list))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
pending))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; Lowering
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (make-closure-name enclosing-fn-name counter)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(string->symbol (fmt #f "ƛ" counter "_" enclosing-fn-name)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (suffixed name suffix)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(string->symbol (string-append (symbol->string name) suffix)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; A capture is a plain name, whose type comes from the declarations
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; the walker has passed. `(name expr)' captures want the type of an
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;;; expression, which is inference, and wait for it.
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (capture-binding capture form env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unless (symbol? capture)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(sex-error form "a closure capture must be a plain name for now" capture))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((type (hash-table-ref/default (hash-table-ref env :var-types) capture #f)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(unless type
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(sex-error form "closure captures an undeclared name" capture))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list capture type)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(define (lift-closure base form env)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(match form
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(('closure arglist ret-type captures . body)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let* ((caps (map (lambda (c) (capture-binding c form env)) captures))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(record (suffixed base "_captures"))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(code (suffixed base "_code"))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(construct (suffixed base "_make"))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(type `(closure ,(map (lambda (p) (list (second p))) arglist)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,ret-type))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(closure (register-closure-type! type form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(values
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
construct
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(map (lambda (f) (copy-form-source! form f))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; C has no empty struct, and a closure over nothing needs
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; no record to point at
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(append
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(if (null? caps)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list `(struct ,record ,caps)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(fn ,code ((ƛe (* void)) ,@arglist) ,ret-type
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(if (null? caps)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`((var ƛcaptures (* (struct ,record)) ƛe)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(map (lambda (cap)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(var ,(first cap) ,(second cap)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(-> ƛcaptures ,(first cap))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
caps)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@body)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(fn ,construct ,caps (struct ,closure)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(var ƛc (struct ,closure))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(if (null? caps)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`((static-assert
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
alex-eg
commented
Re 345. Re 345.
```
(var e _ (¤ p 0)) p : (* int) -> int e = p[0];
(var a _ (¤ pts 1)) pts : (¤ struct point 2) -> struct point, was struct
```
2b73fcf.
|
|||||||
|
(<= (sizeof (struct ,record))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(sizeof (dot-access ƛc env)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
"closure captures do not fit the inline environment")))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(= (dot-access ƛc code) ,code)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(if (null? caps)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(list)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`((var ƛcaptures (* (struct ,record))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cast (& (dot-access ƛc env)) (* (struct ,record))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
,@(map (lambda (cap)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
`(= (-> ƛcaptures ,(first cap)) ,(first cap)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
caps)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(return ƛc))))))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(else (sex-error form "malformed closure" form))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
;;; Structs
|
;;; Structs
|
||||||
|
|
||||||
;;; Record the named structs, unions and enums in the type database
|
;;; Record the named structs, unions and enums in the type database
|
||||||
(define (process-struct sex-struct acc)
|
(define (process-struct sex-struct acc)
|
||||||
(let-values (((doc form) (extract-aggregate-docstring sex-struct)))
|
(let-values (((doc form) (extract-aggregate-docstring sex-struct)))
|
||||||
(register-aggregate! form)
|
;; Resolve before registering: a field of closure type has to reach
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
(with-docstring doc form acc)))
|
;; the type database as the struct it becomes, or member access
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; through it finds nothing
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(let ((form (resolve-closure-types form)))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(register-aggregate! form)
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(with-docstring doc form acc))))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
(define (register-aggregate! form)
|
(define (register-aggregate! form)
|
||||||
(let* ((f (if (eq? (car form) 'pub) (cdr form) form))
|
(let* ((f (if (eq? (car form) 'pub) (cdr form) form))
|
||||||
|
alex-eg
commented
Re 343. sextest wrote Re 343.
```
(&& a b) -> bool (| a b) -> int
(<< l b) l : long -> long (>> c b) c : char -> int
(++ c) c : char -> char
```
sextest wrote `||` escaped, which Sex does not read, so no test could have reached it. Fixed with it. e87463b.
|
|||||||
@@ -280,7 +641,9 @@
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
((enum) (add-enum name form))))))
|
((enum) (add-enum name form))))))
|
||||||
|
|
||||||
(define (process-global-var sex-var acc)
|
(define (process-global-var sex-var acc)
|
||||||
(cons sex-var acc))
|
;; A global is not walked for lambdas, but its type still has to stop
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
;; saying `closure' before the writer sees it
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
(cons (resolve-closure-types sex-var) acc))
|
||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
|
|
||||||
;;; Utils
|
;;; Utils
|
||||||
(define (non-empty-list? form)
|
(define (non-empty-list? form)
|
||||||
|
|||||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
|||||||
25
sexc.scm
@@ -175,17 +175,22 @@ status, which is ours to pass on."
|
|||||||
(semen-process raw-forms))))
|
(semen-process raw-forms))))
|
||||||
|
|
||||||
(define prelude
|
(define prelude
|
||||||
'((include inttypes.h)
|
(append
|
||||||
(include stdbool.h)
|
'((include inttypes.h)
|
||||||
|
(include stdbool.h)
|
||||||
|
(include stddef.h) ; max_align_t, for closure environments
|
||||||
|
(typedef u8 uint8-t)
|
||||||
|
(typedef i8 int8-t)
|
||||||
|
(typedef u16 uint16-t)
|
||||||
|
(typedef i16 int16-t)
|
||||||
|
(typedef u32 uint32-t)
|
||||||
|
(typedef i32 int32-t)
|
||||||
|
(typedef u64 uint64-t)
|
||||||
|
(typedef i64 int64-t))
|
||||||
|
|
||||||
(typedef u8 uint8-t)
|
;; The closure environment is the part of the ABI, so include it in
|
||||||
(typedef i8 int8-t)
|
;; every module
|
||||||
(typedef u16 uint16-t)
|
(list (closure-env-declaration))))
|
||||||
(typedef i16 int16-t)
|
|
||||||
(typedef u32 uint32-t)
|
|
||||||
(typedef i32 int32-t)
|
|
||||||
(typedef u64 uint64-t)
|
|
||||||
(typedef i64 int64-t)))
|
|
||||||
|
|
||||||
(define (main)
|
(define (main)
|
||||||
(let* ((argv (command-line-arguments))
|
(let* ((argv (command-line-arguments))
|
||||||
|
|||||||
@@ -270,4 +270,59 @@ compiles."
|
|||||||
"_Static_assert(sizeof(int) == 4, \"int is four bytes\")"))
|
"_Static_assert(sizeof(int) == 4, \"int is four bytes\")"))
|
||||||
(test-assert "and not the header macro"
|
(test-assert "and not the header macro"
|
||||||
(not (emits? (in-fn "(static-assert (== (sizeof int) 4) \"x\")")
|
(not (emits? (in-fn "(static-assert (== (sizeof int) 4) \"x\")")
|
||||||
"static_assert(")))))
|
"static_assert("))))
|
||||||
|
|
||||||
|
;; A closure is a code pointer beside its captures. The struct is
|
||||||
|
;; named from the signature, so separate translation units agree on
|
||||||
|
;; it, and calling one goes through `code' with `env' passed first.
|
||||||
|
;;
|
||||||
|
;; A closure struct, and the helper its calls go through, are each
|
||||||
|
;; emitted once per signature; the registries deciding that are
|
||||||
|
;; compile-time state like the type databases, and outlive a single
|
||||||
|
;; `sex->c' here. So every case below that looks for a *definition*
|
||||||
|
;; uses a signature of its own -- cases looking at a call site can
|
||||||
|
;; share one.
|
||||||
|
(test-group "closures"
|
||||||
|
(test-assert "the type becomes a struct named for its signature"
|
||||||
|
(emits? "(fn f ((c (closure ((int)) int))) int (return (c 1)))"
|
||||||
|
"struct ƛint_int"))
|
||||||
|
;; The environment is one shared union, declared in the prelude --
|
||||||
|
;; its layout is part of the ABI two units agree on, so it cannot
|
||||||
|
;; depend on what either file contains. `sex->c' has no prelude, so
|
||||||
|
;; what is visible here is the member
|
||||||
|
(test-assert "whose environment is the shared union"
|
||||||
|
(emits? "(fn f ((c (closure ((float)) int))) int (return (c 1.0)))"
|
||||||
|
"union ƛenv env;"))
|
||||||
|
;; The receiver goes through a helper rather than being written
|
||||||
|
;; out twice, so that `[table (++ i)]' evaluates its index once,
|
||||||
|
;; exactly as it would for an array of function pointers
|
||||||
|
(test-assert "a call passes the receiver to a helper"
|
||||||
|
(emits? "(fn f ((c (closure ((int)) int))) int (return (c 1)))"
|
||||||
|
"ƛint_int_call(c, 1)"))
|
||||||
|
(test-assert "and the helper is what dereferences it"
|
||||||
|
(emits? "(fn f ((c (closure ((long)) int))) int (return (c 1)))"
|
||||||
|
"ƛc.code(&ƛc.env, ƛa0)"))
|
||||||
|
(test-assert "a subscript receiver is evaluated once"
|
||||||
|
(emits? "(fn f ((t (¤ (closure ((int)) int) 4)) (i int)) int (return ((¤ t (++ i)) 1)))"
|
||||||
|
"ƛint_int_call(t[++i], 1)"))
|
||||||
|
(test-assert "so is a member receiver"
|
||||||
|
(emits? "(struct h ((cb (closure ((int)) int))))
|
||||||
|
(fn f ((s (struct h))) int (return ((. s cb) 1)))"
|
||||||
|
"ƛint_int_call(s.cb, 1)"))
|
||||||
|
(test-assert "a captured name is rebound in the lifted body"
|
||||||
|
(emits? "(fn f ((n int)) (closure ((char)) int) (return (closure ((x char)) int (n) (return n))))"
|
||||||
|
"int n = ƛcaptures->n;"))
|
||||||
|
(test-assert "captures are checked against the environment"
|
||||||
|
(emits? "(fn f ((n int)) (closure ((short)) int) (return (closure ((x short)) int (n) (return n))))"
|
||||||
|
"_Static_assert(sizeof(struct"))
|
||||||
|
;; A closure over nothing has no record to point at, and C has no
|
||||||
|
;; empty struct to declare for it
|
||||||
|
(test-assert "no captures means no capture record"
|
||||||
|
(not (emits? "(fn f () (closure () int) (return (closure () int () (return 7))))"
|
||||||
|
"_captures {")))
|
||||||
|
;; The receiver is written twice, so a name used as an argument
|
||||||
|
;; must not be mistaken for a call of its own
|
||||||
|
(test-assert "a closure passed as an argument stays a value"
|
||||||
|
(emits? "(fn g ((c (closure ((int)) int))) int (return 0))
|
||||||
|
(fn f ((c (closure ((int)) int))) int (return (g c)))"
|
||||||
|
"g(c)"))))
|
||||||
|
|||||||
@@ -10,14 +10,17 @@
|
|||||||
#
|
#
|
||||||
# It also checks what only a second translation unit can check: that an
|
# It also checks what only a second translation unit can check: that an
|
||||||
# imported type reaches the type database, by expanding a macro that
|
# imported type reaches the type database, by expanding a macro that
|
||||||
# reads the imported struct's fields.
|
# reads the imported struct's fields; and that a closure type crossing
|
||||||
|
# the boundary works both ways -- one built in the module and called
|
||||||
|
# here, one built here and called there, through a code pointer that is
|
||||||
|
# static in the other object.
|
||||||
#
|
#
|
||||||
# The public forms carry comments in their headers, which the reduction
|
# The public forms carry comments in their headers, which the reduction
|
||||||
# to a prototype and to an extern both have to look past.
|
# to a prototype and to an extern both have to look past.
|
||||||
|
|
||||||
SEXC ?= ../../sexc
|
SEXC ?= ../../sexc
|
||||||
|
|
||||||
EXPECTED = hello, world\nhello, sex\n2 greetings\ntext times \ntext times \nmood 1
|
EXPECTED = hello, world\nhello, sex\n2 greetings\ntext times \ntext times \nmood 1\nclosure 15 21 201
|
||||||
|
|
||||||
check:
|
check:
|
||||||
@$(SEXC) greet.sex -c -o greet.o
|
@$(SEXC) greet.sex -c -o greet.o
|
||||||
|
|||||||
@@ -26,4 +26,11 @@
|
|||||||
(printf "\n")
|
(printf "\n")
|
||||||
(var m (enum mood) grumpy)
|
(var m (enum mood) grumpy)
|
||||||
(printf "mood %d\n" m)
|
(printf "mood %d\n" m)
|
||||||
|
|
||||||
|
(var add-10 (closure ((int)) int) (make-adder 10))
|
||||||
|
(printf "closure %d %d" (add-10 5) (apply-twice add-10 1))
|
||||||
|
(var base int 100)
|
||||||
|
(var here (closure ((int)) int)
|
||||||
|
(closure ((x int)) int (base) (return (+ base x))))
|
||||||
|
(printf " %d\n" (apply-twice here 1))
|
||||||
(return 0))
|
(return 0))
|
||||||
|
|||||||
@@ -35,6 +35,19 @@
|
|||||||
(++ greet-count)
|
(++ greet-count)
|
||||||
(printf "hello, %s\n" name))
|
(printf "hello, %s\n" name))
|
||||||
|
|
||||||
|
;;; A closure type crossing the boundary. Both units generate the
|
||||||
|
;;; struct for this signature independently, so they have to agree on
|
||||||
|
;;; its tag and its layout, or the value is passed wrong and nothing
|
||||||
|
;;; says so.
|
||||||
|
(pub fn make-adder ((n int)) (closure ((int)) int)
|
||||||
|
(return (closure ((b int)) int (n)
|
||||||
|
(return (+ n b)))))
|
||||||
|
|
||||||
|
;;; The other direction: a closure built by the importer, whose code
|
||||||
|
;;; pointer is static in *its* object, called from here
|
||||||
|
(pub fn apply-twice ((f (closure ((int)) int)) (x int)) int
|
||||||
|
(return (f (f x))))
|
||||||
|
|
||||||
;;; Not `pub': invisible to importers, and static in the generated C.
|
;;; Not `pub': invisible to importers, and static in the generated C.
|
||||||
(fn unused-helper () void
|
(fn unused-helper () void
|
||||||
(printf "private\n"))
|
(printf "private\n"))
|
||||||
|
|||||||
80
tests/sex-programs/closures.sex
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
(input)
|
||||||
|
(output "Adders: 15 25"
|
||||||
|
"Two captures: 47"
|
||||||
|
"No captures: 7"
|
||||||
|
"Through a parameter: 110"
|
||||||
|
"From an array: 1 2 3"
|
||||||
|
"Index evaluated once: 21 i 1"
|
||||||
|
"Through a struct member: 8"
|
||||||
|
"Nested: 33")
|
||||||
|
(return 0)
|
||||||
|
|
||||||
|
;;; A closure is a code pointer beside its captures, so what this
|
||||||
|
;;; checks is that the captures survive the lifting -- that two
|
||||||
|
;;; closures of one shape keep their own environments, that a closure
|
||||||
|
;;; outlives the call that built it, and that calling one through a
|
||||||
|
;;; parameter, an array element or a struct member resolves the same
|
||||||
|
;;; way as through a local.
|
||||||
|
;;;
|
||||||
|
;;; A receiver is also an ordinary expression: `[table (++ i)]' has to
|
||||||
|
;;; evaluate its index exactly once, the way it would for an array of
|
||||||
|
;;; function pointers.
|
||||||
|
|
||||||
|
(include stdio.h)
|
||||||
|
|
||||||
|
(fn make-adder ((n int)) (closure ((int)) int)
|
||||||
|
(return (closure ((b int)) int (n)
|
||||||
|
(return (+ n b)))))
|
||||||
|
|
||||||
|
(fn make-affine ((k int) (b int)) (closure ((int)) int)
|
||||||
|
(return (closure ((x int)) int (k b)
|
||||||
|
(return (+ (* k x) b)))))
|
||||||
|
|
||||||
|
(fn make-const-7 () (closure () int)
|
||||||
|
(return (closure () int ()
|
||||||
|
(return 7))))
|
||||||
|
|
||||||
|
;;; A closure arriving as a parameter: its type is written, so the call
|
||||||
|
;;; resolves without knowing where it came from
|
||||||
|
(fn apply-twice ((f (closure ((int)) int)) (x int)) int
|
||||||
|
(return (f (f x))))
|
||||||
|
|
||||||
|
(struct handlers ((on-tick (closure ((int)) int))))
|
||||||
|
|
||||||
|
(pub fn main () int
|
||||||
|
(var add-10 (closure ((int)) int) (make-adder 10))
|
||||||
|
(var add-20 (closure ((int)) int) (make-adder 20))
|
||||||
|
(printf "Adders: %d %d\n" (add-10 5) (add-20 5))
|
||||||
|
|
||||||
|
(var affine (closure ((int)) int) (make-affine 5 2))
|
||||||
|
(printf "Two captures: %d\n" (affine 9))
|
||||||
|
|
||||||
|
(var seven (closure () int) (make-const-7))
|
||||||
|
(printf "No captures: %d\n" (seven))
|
||||||
|
|
||||||
|
(printf "Through a parameter: %d\n" (apply-twice (make-adder 50) 10))
|
||||||
|
|
||||||
|
(var table (¤ (closure ((int)) int) 3))
|
||||||
|
(var i int 0)
|
||||||
|
(for (= i 0) (< i 3) (++ i)
|
||||||
|
(= (¤ table i) (make-adder i)))
|
||||||
|
(printf "From an array: %d %d %d\n"
|
||||||
|
((¤ table 0) 1) ((¤ table 1) 1) ((¤ table 2) 1))
|
||||||
|
|
||||||
|
;; the index must be evaluated once, so `i' ends at 1 and not 2 --
|
||||||
|
;; read in a separate statement, since reading and bumping it in one
|
||||||
|
;; printf would be unsequenced whatever the closure did
|
||||||
|
(= i 0)
|
||||||
|
(var once int ([table (++ i)] 20))
|
||||||
|
(printf "Index evaluated once: %d i %d\n" once i)
|
||||||
|
|
||||||
|
(var h (struct handlers) #((struct handlers) : .on-tick (make-adder 5)))
|
||||||
|
(printf "Through a struct member: %d\n" ((. h on-tick) 3))
|
||||||
|
|
||||||
|
;; a closure built inside a closure, capturing that one's capture
|
||||||
|
(var outer (closure ((int)) int)
|
||||||
|
(closure ((x int)) int ()
|
||||||
|
(var inner (closure ((int)) int) (make-adder x))
|
||||||
|
(return (inner 3))))
|
||||||
|
(printf "Nested: %d\n" (outer 30))
|
||||||
|
(return 0))
|
||||||
55
tests/sex-programs/fixpoint.sex
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
(input)
|
||||||
|
(output "direct: 120"
|
||||||
|
"fac: 120 3628800"
|
||||||
|
"fib: 55 6765")
|
||||||
|
(return 0)
|
||||||
|
|
||||||
|
;;; A fixed point built out of closures, which is the hardest thing to
|
||||||
|
;;; ask of them: recursion with no recursive function anywhere, only
|
||||||
|
;;; self-application.
|
||||||
|
;;;
|
||||||
|
;;; Self-application needs `x x' and so a recursive type, which is
|
||||||
|
;;; spelled here by routing it through a named struct whose field is a
|
||||||
|
;;; closure whose own signature mentions that struct. The generated
|
||||||
|
;;; closure struct is written before `struct rec' is, so this only
|
||||||
|
;;; compiles because a forward declaration is emitted ahead of both.
|
||||||
|
;;;
|
||||||
|
;;; Note what `fix' captures: a *pointer* to the knot, not the knot. A
|
||||||
|
;;; closure is a code pointer beside N bytes of environment, so
|
||||||
|
;;; capturing one by value would need N >= 8 + N. No budget makes that
|
||||||
|
;;; true, and the static assertion says so rather than letting it
|
||||||
|
;;; corrupt anything.
|
||||||
|
|
||||||
|
(include stdio.h)
|
||||||
|
|
||||||
|
(struct rec ((f (closure (((* (struct rec))) (int)) int))))
|
||||||
|
|
||||||
|
;;; Takes a step that expects itself, returns an ordinary closure with
|
||||||
|
;;; the self-application hidden inside
|
||||||
|
(fn fix ((step (* (struct rec)))) (closure ((int)) int)
|
||||||
|
(return (closure ((n int)) int (step)
|
||||||
|
(return ((-> step f) step n)))))
|
||||||
|
|
||||||
|
(pub fn main () int
|
||||||
|
(var fac-knot (struct rec))
|
||||||
|
(= (. fac-knot f)
|
||||||
|
(closure ((self (* (struct rec))) (n int)) int ()
|
||||||
|
(if (<= n 1) (return 1))
|
||||||
|
(return (* n ((-> self f) self (- n 1))))))
|
||||||
|
|
||||||
|
;; the knot applied to itself directly, without fix
|
||||||
|
(printf "direct: %d\n" ((. fac-knot f) (& fac-knot) 5))
|
||||||
|
|
||||||
|
(var fib-knot (struct rec))
|
||||||
|
(= (. fib-knot f)
|
||||||
|
(closure ((self (* (struct rec))) (n int)) int ()
|
||||||
|
(if (< n 2) (return n))
|
||||||
|
(return (+ ((-> self f) self (- n 1))
|
||||||
|
((-> self f) self (- n 2))))))
|
||||||
|
|
||||||
|
;; one combinator, two different recursions
|
||||||
|
(var fac (closure ((int)) int) (fix (& fac-knot)))
|
||||||
|
(var fib (closure ((int)) int) (fix (& fib-knot)))
|
||||||
|
(printf "fac: %d %d\n" (fac 5) (fac 10))
|
||||||
|
(printf "fib: %d %d\n" (fib 10) (fib 20))
|
||||||
|
(return 0))
|
||||||
Re 351. One per line, alphabetical.
e87463b.