type-inference #39
@@ -381,11 +381,13 @@ forms, and what remains."
|
||||
;; are not part of it: ((* const char)), (int)
|
||||
(walk-type (maybe-unwrap-type arg))))
|
||||
|
||||
;;; A parameter reaches fmt-c as `(type name)' and nothing else: it
|
||||
;;; reads the name out with `cadr', so a nameless one is the type and
|
||||
;;; an explicit #f. Handing it the bare type instead made it read the
|
||||
;;; type's own second word as the name -- `(* const char)' lost its
|
||||
;;; star -- and a one-word type had no second word to read at all.
|
||||
;;; fmt-c reads a parameter as `(type name)', taking the name with
|
||||
;;; `cadr'. A nameless one is the type and an explicit #f:
|
||||
;;;
|
||||
;;; (* const char) -> const char the star read as the name
|
||||
;;; ((* const char) #f) -> const char *
|
||||
;;; (int) -> (cadr) error
|
||||
;;; (int #f) -> int
|
||||
(define (walk-arglist form)
|
||||
;; E.g.:
|
||||
;; ((float) (int) (const char) (* const char) (¤ (* const struct res) 32))
|
||||
|
||||
@@ -509,9 +509,9 @@
|
||||
((eq? a b) #t)
|
||||
((unknown-type? a) #t)
|
||||
((unknown-type? b) #t)
|
||||
;; Whichever side is free takes the binding, so that a rigid
|
||||
;; variable is solved *to* rather than solved, in either order.
|
||||
;; Both rigid and distinct is the mismatch `eq?' above let through.
|
||||
;; Whichever side is free takes the binding: `(unify a r)' and
|
||||
;; `(unify r a)' both leave `a' bound to `r'. Two rigid and
|
||||
;; distinct is the mismatch `eq?' above let through.
|
||||
((and (tvar? a) (not (tvar-rigid? a))) (bind-tvar! a b form))
|
||||
((and (tvar? b) (not (tvar-rigid? b))) (bind-tvar! b a form))
|
||||
((or (tvar? a) (tvar? b)) (type-mismatch a b form))
|
||||
|
||||
131
semen.scm
@@ -299,12 +299,15 @@
|
||||
|
|
||||
;;;
|
||||
;;; `(do (var c int 9) ...)' declares a `c' that ends with the block, so
|
||||
;;; a closure-typed `c' outside it is still a closure after it. Every
|
||||
;;; form whose body C brackets opens a frame; innermost 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.
|
||||
;;; form whose body C brackets opens a frame; innermost 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.
|
||||
;;;
|
||||
;;; One frame per form is enough, rather than one per arm: a `case' label
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; opens no scope in C either, and a declaration is not a statement, so
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 only way to write one in an `if' arm is the `do' that already
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; brings its own.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 v double 3.75)
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; (while (< v 0) (var v char 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.
|
||||
;;; (var m _ (+ v 1)) ; double, not char
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; One frame per form, not one per arm: a `case' label opens no scope
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; in C, and an `if' arm can only declare inside a `do', which brings
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; its own.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 (declare-name! env name type)
|
||||
(hash-table-set! (car (hash-table-ref env :scopes)) name type))
|
||||
@@ -383,10 +386,11 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
|
||||
((var)
|
||||
|
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.
|
||||
;; the initializer is walked before the name it binds is in
|
||||
;; scope; the type is resolved rather than walked, a `fn' type's
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; parameter list being indistinguishable from a call -- walking
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 ((c int)) int)' with a closure named `c' in scope would
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 the parameter as a call of 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.
|
||||
;; scope; the type is resolved rather than walked, a parameter
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 being shaped like a 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.
|
||||
;;
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 (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.
|
||||
;; (var fp (fn ((c int)) int) ...) ; int (*fp)(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.
|
||||
(let* ((prefix (if (>= (length form) 3)
|
||||
(append (take form 2)
|
||||
(list (resolve-closure-types
|
||||
@@ -427,9 +431,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.
|
||||
(else
|
||||
(let ((closure (receiver-closure-type (car form) env)))
|
||||
(if closure
|
||||
;; the receiver is walked first: a closure written where 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.
|
||||
;; is called registers its struct on the way, and the 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.
|
||||
;; helper's signature mentions that 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.
|
||||
;; the receiver is walked first: `((closure ((x 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.
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.
|
||||
;; () ...) 5)' registers `struct ƛint_int' on the way, 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.
|
||||
;; the call helper's signature names 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.
|
||||
(let ((receiver (walk-statement (car form) env)))
|
||||
(copy-form-source!
|
||||
form
|
||||
@@ -530,10 +534,12 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 (pair (cdr params) (- remaining 1)
|
||||
(cons (unwrap-type (car params)) acc))))))
|
||||
|
||||
;;; A `fn' header has its macros expanded and its closure 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.
|
||||
;;; resolved without being walked; a `var' type is the same thing 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.
|
||||
;;; same position, and gets the same two. A macro standing in for a 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.
|
||||
;;; may still ask `(type-of x)' while it does so.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 a `fn' header gets, a `var' type gets -- macro expansion 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.
|
||||
;;; closure resolution, no walk:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; (defmacro (ty) 'int) (var x (ty) 0) -> int x = 0;
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; and the macro may ask `(type-of x)' while it stands in for a 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 (expand-type type env)
|
||||
(let ((expanded
|
||||
(parameterize ((current-type-of
|
||||
@@ -594,8 +600,8 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
(and (symbol? (car expr)) (get-return-type (car expr))))
|
||||
(else
|
||||
(case (car expr)
|
||||
;; subscripting an array gives its element type, and a pointer
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; subscripts the same 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.
|
||||
;; (¤ pts 1), pts : (¤ struct point 2) -> (struct 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.
|
||||
;; (¤ p 1), p : (* 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.
|
||||
((¤) (let ((base (expression-type (second expr) env)))
|
||||
|
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.
|
||||
(or (array-element-type base) (pointer-target base))))
|
||||
;; unary `&' takes an address; with two operands it is bitwise and
|
||||
@@ -613,9 +619,8 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
(cddr expr)))
|
||||
((cast) (and (= 3 (length expr)) (third expr)))
|
||||
((sizeof) 'size-t)
|
||||
;; a closure literal is its own type: the first three elements
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; already spell one, so calling one where it is written resolves
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; like calling one through a 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.
|
||||
;; `(closure ((x int)) int () ...)' is a `(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.
|
||||
;; so `((closure ((x int)) int () (return x)) 5)' is a 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.
|
||||
((closure) (and (closure-expression? expr)
|
||||
`(closure ,(arglist-types (second expr)) ,(third expr))))
|
||||
;; `c-and' and `c-or' are the names from before `&&' and `||'
|
||||
@@ -623,11 +628,11 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
((+ - / %) (arithmetic-type expr env))
|
||||
;; the bitwise operators join like the arithmetic ones
|
||||
((^ |\||) (arithmetic-type expr env))
|
||||
;; a shift does not join: the result is the promoted left operand,
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 the right one says only how far
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 shift is the promoted left operand, not a join:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; (<< l b), l : long -> long; (>> c b), c : char -> 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.
|
||||
((<< >>) (promoted-type (expression-type (second expr) env)))
|
||||
|
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.
|
||||
;; ...and an increment is not a join either -- it is the operand,
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; unpromoted, being what is written back to 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.
|
||||
;; ...and an increment is the operand unpromoted:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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), c : char -> char
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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-type (second expr) env))
|
||||
;; otherwise a call: a closure answers with its own return type,
|
||||
;; anything else with what its signature says
|
||||
@@ -661,37 +666,36 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
(cond
|
||||
((or (ptr-type? l) (array-type? l)) (decayed left l))
|
||||
((or (ptr-type? r) (array-type? r)) (decayed right r))
|
||||
;; one type on both sides needs no ranking, which is the only 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.
|
||||
;; a name we never parsed a declaration for joins at all
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; one type on both sides needs no ranking:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; (+ n n), n : size-t -> size-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.
|
||||
((and (prim-type? l) (prim-type? r) (equal? (prim-name l) (prim-name r)))
|
||||
(promoted left l))
|
||||
((or (unrankable? l) (unrankable? r)) '?)
|
||||
((< (conversion-rank l) (conversion-rank r)) (promoted right r))
|
||||
((> (conversion-rank l) (conversion-rank r)) (promoted left l))
|
||||
;; at equal rank C takes the unsigned one, whichever side it 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.
|
||||
;; written 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.
|
||||
;; (+ i u) and (+ u i) are both unsigned 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.
|
||||
((unsigned-type? r) (promoted right r))
|
||||
(else (promoted left l)))))))
|
||||
|
||||
;;; A name we never parsed a declaration for -- `size-t', `GLuint' --
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; has no rank we can know, so a join that would have to compare one
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; answers `?' instead of taking whichever operand came 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.
|
||||
;;; `resolve-wildcard' turns that into "write it out", which is the only
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; honest thing to say about 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.
|
||||
;;; `size-t', `GLuint': no declaration parsed, so no rank to compare.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; (var m _ (+ 1 n)) n : size-t -> type of this is unknown
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 m size-t (+ 1 n)) -> size_t m = 1 + n;
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 (unrankable? type)
|
||||
(and (prim-type? type) (not (c-primitive? type))))
|
||||
|
||||
(define (unsigned-type? type)
|
||||
(and (prim-type? type) (memq 'unsigned (prim-name type)) #t))
|
||||
|
||||
;;; Anything narrower than `int' is promoted to one before 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.
|
||||
;;; arithmetic happens, so two `char's join as `int' and not as `char'.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; Operands of the same type reach here too, which is the whole 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.
|
||||
;;; `(+ c c)' is where the promotion is invisible and the truncation 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.
|
||||
;;; not. `unsigned' alone is `unsigned int' and stays as 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.
|
||||
;;; An array is a pointer to its first element the moment it is 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.
|
||||
;;; operand, so `(+ a 1)' is a `(* int)' and not the `(¤ int 4)' 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.
|
||||
;;; `a' was declared as -- which is not a type an initializer can have.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; Narrower than `int' promotes to one:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; (+ c c) c : char 100 -> int 200, not char -56
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; (+ h h) h : short 30000 -> int 60000, not short -5536
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; (+ u u) u : unsigned -> unsigned -- `unsigned' is unsigned 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.
|
||||
;;; An array operand is a pointer to its first element:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
;;; (var p _ (+ a 1)) a : (¤ int 4) -> int * p = a + 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.
|
||||
;;; not int p[4] = a + 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.
|
||||
(define (decayed written type)
|
||||
|
alex-eg
commented
Re 344. Re 344. `decay` has its caller.
```
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1)) -> int * p = a + 1;
```
e87463b.
|
||||
(if (array-type? type) (unparse-type (decay type)) written))
|
||||
|
||||
@@ -776,11 +780,11 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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)
|
||||
|
||||
;;; +closure-env-bytes+ for maximum capacity, and an alignment wide
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 for anything that fits in them, hence union. `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.
|
||||
;;; would say that in one word, but it is C11 and the target is C99, so
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 widest built-ins say it instead: a union is aligned for 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.
|
||||
;;; strictest of its members.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 capacity, the widest built-ins 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.
|
||||
;;; alignment, hence union -- a union takes the strictest alignment of
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; its members. `max_align_t' would say the second in one 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.
|
||||
;;; sexc hello-world.sex -- -std=c99 unknown type name '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.
|
||||
(define +closure-env-type+ 'ƛenv)
|
||||
|
||||
(define (closure-env-declaration)
|
||||
@@ -854,15 +858,14 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
*pending-closure-structs*)))))
|
||||
(delete-duplicates (aggregates-in type))))
|
||||
|
||||
;;; Where one argument ends and the next begins has to survive 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.
|
||||
;;; flattening, or `((long long))' and `((long) (long))' mangle alike 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.
|
||||
;;; the second signature silently reuses the first one's struct. Words
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; within an argument keep the single separator; the arguments take 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.
|
||||
;;; doubled one.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 words inside an argument take the single separator, 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.
|
||||
;;; arguments a doubled one:
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 proof against a type name that mangles to a trailing `_' of its
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; own -- for that the arguments would have to carry their lengths, 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.
|
||||
;;; the name in the C is worth more than the last of the ambiguity.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 ((long long)) int) -> ƛlong_long_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 ((long) (long)) int) -> ƛlong__long_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.
|
||||
;;;
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 word whose first character mangles to `_' still aliases 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.
|
||||
;;; doubled separator: `((a -b))' and `((a) (b))' are both `a__b'.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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-arglist args)
|
||||
(if (null? args)
|
||||
"void"
|
||||
@@ -1040,8 +1043,8 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 ((name (capture-name capture)))
|
||||
(unless (symbol? name)
|
||||
(sex-error form "a closure capture needs a name" capture))
|
||||
;; the same lookup either way: a capture that borrows a name can
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; borrow a global's or a function's, not only a local's
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 same lookup either way, so `(closure ((x int)) int (scale)
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; ...)' borrows a global's `scale' as readily as a local's
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 (expression-type (capture-argument capture) env)))
|
||||
(unless type
|
||||
(sex-error form "cannot infer what is captured as" name))
|
||||
@@ -1128,23 +1131,21 @@
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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.
|
||||
((union) (add-union name form))
|
||||
((enum) (add-enum name form))))))
|
||||
|
||||
;;; A toplevel form has no function around it and so no scope chain. 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.
|
||||
;;; name in a global's initializer is another global's or a function's,
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;;; which `get-name-type' answers without one.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 function around a toplevel form, so no scope chain: what 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.
|
||||
;;; global's initializer names comes from `get-name-type' alone.
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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-toplevel-env)
|
||||
(let ((env (make-hash-table)))
|
||||
(set! (hash-table-ref env :scopes) (list))
|
||||
env))
|
||||
|
||||
(define (process-global-var 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.
|
||||
;; saying `closure' before the writer sees it, and a `_' still has to
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; be written out: the writer has no spelling for one 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.
|
||||
;; A global is not walked for lambdas, but the writer spells neither
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function 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 346. Solved from Re 346. Solved from `get-name-type` alone, so a global names only what is declared above it.
```
(var n _ 1) -> static int n = 1;
(var s _ "hi") -> static const char * s = "hi";
```
e87463b.
|
||||
;; `closure' nor `_': `(var n _ 1)' has to reach it as `int n = 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.
|
||||
(let* ((resolved (resolve-closure-types sex-var))
|
||||
(qualifier (and (memq (car resolved) '(pub extern)) (car resolved)))
|
||||
(core (if qualifier (cdr resolved) resolved))
|
||||
;; `extern' declares without initializing, so there is 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.
|
||||
;; for a `_' to be worked out from
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; `(extern var n int)' has no initializer to work a `_' out
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
;; from
|
||||
|
pkulev
commented
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source. With
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With `n` a `size-t` (an unparsed name, rank 1, same as `int`):
```c
int m1 = 1 + n;
size_t m2 = n + 1;
```
`cc` accepts both. C types `1 + n` as `size_t`, and the `int` declaration narrows. The same tie makes `(+ i u)` an `int` and `(+ u i)` an `unsigned int`. `char + char` is declared `char`.
`size-t` never reaches the `long` rank because it is not a typedef Sex has parsed, so the `strlen` example's `(+ 1 n)` lands here.
pkulev
commented
The forms that reach this walk are
The forms that reach this walk are `&&`, `||`, `|`, `&`, `<<`, `>>`, `++`. `c-and` and `c-or` are the names from before those spellings. The writer already emits `a && b` from `(&& a b)`.
`(var ok _ (&& a b))` and `(var x _ (<< a b))` and `(var x _ (++ a))` all stop with `cannot infer the type of`.
pkulev
commented
An array operand is returned as the array. emits An array operand is returned as the array. `decay` in `infer.scm` is the conversion this comment describes, and nothing in the walk calls it.
```sex
(var a (¤ int 4) #(1 2 3 4))
(var p _ (+ a 1))
```
emits `int p[4] = a + 1`. `cc`: `invalid initializer`.
pkulev
commented
A subscript types only when the base's surface form is already stops with A subscript types only when the base's surface form is already `(¤ ...)`. An `(* int)` is not, so
```sex
(fn f ((p (* int))) int
(var e _ (¤ p 0))
(return e))
```
stops with `cannot infer the type of`. This is the other use named on `decay`.
pkulev
commented
`resolve-closure-types` runs here and `resolve-wildcard` does not. `(var n _ 1)` at toplevel emits `static _ n = 1`. `cc`: `unknown type name '_'`. The same form inside a function becomes `int n = 1`.
pkulev
commented
`walk-parts` walks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside a `fn` type.
```sex
(var c (closure ((int)) int) (make-adder 1))
(var fp (fn ((c int)) int) (lambda ((c int)) int (return c)))
```
`-m` shows `(var fp (fn ((ƛint_int_call c int)) int) ...)`, and the C is `int (*fp)(c int)`. With no closure named `c`, the same declaration emits `int (*fp)(int)`.
pkulev
commented
The callee is typed before it is walked, so a closure literal has no type yet and falls through to
The callee is typed before it is walked, so a closure literal has no type yet and falls through to `convert-arguments`. After the walk the form is a call of the constructor:
```c
return ƛ0_f_make()(5);
```
`cc`: `called object is not a function or function pointer`. `((lambda ((x int)) int (return x)) 5)` works, because the lifted function is registered before the call is typed. `((make-adder 20) 22)` works, because the callee is already a call with a closure return type.
|
||||
(core (if (eq? 'extern qualifier)
|
||||
core
|
||||
(resolve-wildcard core (make-toplevel-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.
|
||||
@@ -87,10 +87,9 @@
|
||||
;; `process' returns one record; `process-input-port' is named from
|
||||
;; the child's side, so it is the port we write to.
|
||||
;;
|
||||
;; Sex has no symbol escaping -- `|' is an operator there, not a
|
||||
;; quote -- so the forms go out the way they were written. Left to
|
||||
;; escape, `||' would leave here as `|\|\||' and reach sexc as a
|
||||
;; different symbol.
|
||||
;; Sex reads no symbol escaping -- `|' is an operator there. Left
|
||||
;; on, `(|| a b)' leaves here as `(|\|\|| a b)' and reaches sexc
|
||||
;; as a different symbol.
|
||||
(let* ((proc (process compiler (append (list "-o" compiled-file) flags)))
|
||||
(sexc-stdin (process-input-port proc)))
|
||||
(symbol-escape #f)
|
||||
|
||||
34
types.scm
@@ -240,14 +240,14 @@
|
||||
|
||||
;;; The shape of a written type
|
||||
;;;
|
||||
;;; Three places have to tell a type from something that merely
|
||||
;;; contains one: an arglist entry is either `(name type)' or a bare
|
||||
;;; type, and an array's last element is either a bound or the last
|
||||
;;; word of its element type. They used to answer it separately, and
|
||||
;;; disagreed.
|
||||
;;; Where a type ends, asked by an arglist and by an array bound:
|
||||
;;;
|
||||
;;; (f1 float) a name and a type (unsigned int) a type
|
||||
;;; (¤ int 4) four of int (¤ const t) unsized, of const t
|
||||
;;; (¤ mytype N) N of mytype (¤ * size-t) unsized, of (* size-t)
|
||||
|
||||
;;; A qualifier can never end a type, which is what tells `(¤ const t)'
|
||||
;;; -- an unsized array of `t' -- from `(¤ int 4)'.
|
||||
;;; A qualifier cannot end a type: `(¤ const t)' is unsized, `(¤ int 4)'
|
||||
;;; is four of int.
|
||||
(define +c-qualifiers+ '(const volatile restrict _Atomic))
|
||||
|
||||
(define +c-specifiers+
|
||||
@@ -271,20 +271,22 @@
|
||||
(pair? (cdr arg)) ; 1 element args are always type
|
||||
(not (type-head? arg))))
|
||||
|
||||
;;; Is NAME a typedef, as opposed to a `define'd constant? Both live in
|
||||
;;; the same table, and only the first is part of a type.
|
||||
;;; A typedef and a `define' share +type-db+; only the typedef is part
|
||||
;;; of a type:
|
||||
;;;
|
||||
;;; (typedef small int) -> (¤ small N) is N of small
|
||||
;;; (define CAP 4) -> (¤ int CAP) is CAP of int
|
||||
(define (typedef-name? name)
|
||||
(let ((info (and (symbol? name) (get-type-info name))))
|
||||
(and info (memq (car info) '(typedef struct union enum)) #t)))
|
||||
|
||||
;;; `(¤ int N)' is N of int
|
||||
;;; `(¤ unsigned int)' is an unsized array of unsigned int
|
||||
;;; The last element is a bound only where what precedes it already
|
||||
;;; spells a whole type -- a specifier, a tag after its keyword, or a
|
||||
;;; typedef we have seen declared:
|
||||
;;;
|
||||
;;; The last element is a bound only if what precedes it is already a
|
||||
;;; complete type, so `(¤ const mytype)' and `(¤ * size-t)' end in the
|
||||
;;; last word of their element type and not in a bound. A type is
|
||||
;;; complete when it ends in a specifier, in a tag following its
|
||||
;;; keyword, or in a typedef we have seen declared.
|
||||
;;; (¤ int 4) four of int (¤ unsigned int) unsized
|
||||
;;; (¤ mytype CAP) CAP of mytype (¤ struct point) unsized
|
||||
;;; (¤ const mytype) unsized (¤ * size-t) unsized
|
||||
;;;
|
||||
;;; TYPE is the whole `(¤ ...)' form.
|
||||
(define (array-bound? type)
|
||||
|
||||
When the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With
nasize-t(an unparsed name, rank 1, same asint):ccaccepts both. C types1 + nassize_t, and theintdeclaration narrows. The same tie makes(+ i u)anintand(+ u i)anunsigned int.char + charis declaredchar.size-tnever reaches thelongrank because it is not a typedef Sex has parsed, so thestrlenexample's(+ 1 n)lands here.The forms that reach this walk are
&&,||,|,&,<<,>>,++.c-andandc-orare the names from before those spellings. The writer already emitsa && bfrom(&& a b).(var ok _ (&& a b))and(var x _ (<< a b))and(var x _ (++ a))all stop withcannot infer the type of.An array operand is returned as the array.
decayininfer.scmis the conversion this comment describes, and nothing in the walk calls it.emits
int p[4] = a + 1.cc:invalid initializer.A subscript types only when the base's surface form is already
(¤ ...). An(* int)is not, sostops with
cannot infer the type of. This is the other use named ondecay.resolve-closure-typesruns here andresolve-wildcarddoes not.(var n _ 1)at toplevel emitsstatic _ n = 1.cc:unknown type name '_'. The same form inside a function becomesint n = 1.walk-partswalks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside afntype.-mshows(var fp (fn ((ƛint_int_call c int)) int) ...), and the C isint (*fp)(c int). With no closure namedc, the same declaration emitsint (*fp)(int).The callee is typed before it is walked, so a closure literal has no type yet and falls through to
convert-arguments. After the walk the form is a call of the constructor:cc:called object is not a function or function pointer.((lambda ((x int)) int (return x)) 5)works, because the lifted function 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 the ranks tie this keeps the left operand, so the declared type depends on the order of the source.
With
nasize-t(an unparsed name, rank 1, same asint):ccaccepts both. C types1 + nassize_t, and theintdeclaration narrows. The same tie makes(+ i u)anintand(+ u i)anunsigned int.char + charis declaredchar.size-tnever reaches thelongrank because it is not a typedef Sex has parsed, so thestrlenexample's(+ 1 n)lands here.The forms that reach this walk are
&&,||,|,&,<<,>>,++.c-andandc-orare the names from before those spellings. The writer already emitsa && bfrom(&& a b).(var ok _ (&& a b))and(var x _ (<< a b))and(var x _ (++ a))all stop withcannot infer the type of.An array operand is returned as the array.
decayininfer.scmis the conversion this comment describes, and nothing in the walk calls it.emits
int p[4] = a + 1.cc:invalid initializer.A subscript types only when the base's surface form is already
(¤ ...). An(* int)is not, sostops with
cannot infer the type of. This is the other use named ondecay.resolve-closure-typesruns here andresolve-wildcarddoes not.(var n _ 1)at toplevel emitsstatic _ n = 1.cc:unknown type name '_'. The same form inside a function becomesint n = 1.walk-partswalks the type as well as the initializer. A list whose head is an in-scope closure is rewritten as a closure call, including a parameter name inside afntype.-mshows(var fp (fn ((ƛint_int_call c int)) int) ...), and the C isint (*fp)(c int). With no closure namedc, the same declaration emitsint (*fp)(int).The callee is typed before it is walked, so a closure literal has no type yet and falls through to
convert-arguments. After the walk the form is a call of the constructor:cc:called object is not a function or function pointer.((lambda ((x int)) int (return x)) 5)works, because the lifted function is registered before the call is typed.((make-adder 20) 22)works, because the callee is already a call with a closure return type.