Commit Graph

35 Commits

Author SHA1 Message Date
a860da6d7e show the cases the comments were describing
All checks were successful
Sex CI / build-linux (pull_request) Successful in 5m18s
2026-09-30 23:51:55 +03:00
fe72a109bf read a var's type as a type, not as a call
`walk-parts' walked the whole `var' form, and a `fn' type's parameter
list is shaped like a call: `(fn ((c int)) int)' came out as
`int (*fp)(c int)'. A closure literal had no type, so calling one in
place missed the rewrite; sextest fed sexc symbols Sex cannot read.
2026-09-30 23:51:55 +03:00
e87463be87 type the operators the walk had no rule for
`&&', the bitwise operators, the shifts and `++' each stopped with
`cannot infer'; an array operand came back as the array; a rank tie
went to whichever operand came first; and a toplevel `_' reached the
writer unsolved.
2026-09-30 23:51:55 +03:00
f5eee71eb7 declare the closure environment in c99
`max_align_t' is C11 and the union goes into every unit, so a program
with no closure in it stopped building under -std=c99. `unify' also
bound a rigid variable one way round only.
2026-09-30 23:51:55 +03:00
024e97553b keep closure signatures apart when mangled
The argument list was flattened with one separator throughout, so
`((long long))' and `((long) (long))' named one struct. A capture
borrowing a name looked only at the local scope chain.
2026-09-30 23:51:55 +03:00
578feb6b73 scope and promote the way C does
A `while' or `switch' body is a block with no `do' around it, and its
declarations landed in the enclosing frame. Two operands of one narrow
type skipped the conversions, so `(+ c c)' answered `char'.
2026-09-30 23:51:55 +03:00
2b73fcf1c4 answer where a written type ends in one place
An arglist entry, an array's bound and its element type ask one
question, and disagreed: `(unsigned int)' was a name plus a type, a
trailing typedef a bound, a subscript the type's second word.
2026-09-30 23:51:55 +03:00
1f445f0f9b implement type inference
Two things out of one mechanism. `_' as a type means "work it out from
the initializer", so (var n _ (strlen s)) stops needing size-t spelled
out; `type-of' hands a macro the type of an expression, so a macro can
dispatch on what it was handed rather than on what was declared. Both
read the same answers from two sides.

Algorithm W's core, intra-procedural, with the extensions C forces:

  - an unknown type, since (include stdio.h) brings in names we never
    parsed. Unification is consistency rather than equality, so
    anything touching an unparsed declaration stops constraining
    instead of rejecting a program that compiled yesterday;
  - the usual arithmetic conversions, since `+' is not a function of
    one type;
  - checking mode for initializers, since #(0 0) has no type of its own
    and takes one from its context. #(T : ...) is the way out of that.

What it wanted on the way:

  - what type a *name* has, which neither the typedef nor the tag
    database recorded. One table serves functions and variables, since
    a function type already has a surface spelling;
  - a scope chain, so a (var c int 9) inside a do ends with the block;
  - form-type, keyed by cons cell, so one form has one type;
  - macros expanded during the walk rather than before it, so type-of
    is answered in the scope the macro was written in.

Closures take the same machinery: a receiver whose type comes from a
call, captures written (name expr) and typed from the expression, and
conversion from a bare function wherever a closure is expected.

type-match grew `_' on the pattern side, since (closure ((int)) int)
and (closure ((float)) int) were separate clauses for one case.
2026-09-30 00:09:32 +03:00
53f92727a5 mark multi-form macro expansions with $
A bare list was read as several forms, so a macro returning
`((make-adder 10) 5)' -- a call of what make-adder returns -- was
spliced into two. Add a new $ char to denote splicing, so ($ form ...)
splices.
2026-09-30 00:08:33 +03:00
8a3f51e833 implement closures 2026-09-29 21:07:16 +03:00
aa5cfc1b7d remove capture list from lambdas, they are always pure
Explicitly rename capturing lambdas to closures, they will be
implemented later
2026-09-29 16:09:51 +03:00
26e8e6c374 fix lambdas and add a test to prevent rotting
Lambdas rotted because there wasn't any test for them, and after
return type moved to the end, lambdas stayed assumning it in the
front. We fix this and add test program
2026-09-27 16:11:05 +03:00
62316e1e3d enable includes to have multiple targets
All checks were successful
Sex CI / build-linux (pull_request) Successful in 4m47s
Sex CI / build-linux (push) Successful in 4m47s
2026-09-26 16:54:51 +03:00
ee053e35c9 look past comments in a public form's header 2026-09-23 14:35:55 +03:00
e0a228c66e make feature guard produce nothing on eof/closing bracket/paren
A dropped datum is replaced by whatever follows it, but what follows
may be the end of the file or the paren closing the list we are
in. Hand the token back to the caller instead: read-list closes its
list with it and the toplevel loop stops.

A `;' comment between a guard and the form it guards was also taken for
the guarded datum, so the form stayed unconditional and the guard did
nothing. Skip comments when reading the guard.

comment-form? was defined three times over; it moves to utils.
2026-09-23 14:31:38 +03:00
Pavel Kulyov
d0e2c699e3 semen: fix premature negative cases merge hehe
All checks were successful
Sex CI / build-linux (pull_request) Successful in 4m47s
Sex CI / build-linux (push) Successful in 4m50s
2026-09-22 23:40:16 +03:00
Pavel Kulyov
1685b0c31f semen: process fn docstrings 2026-09-21 22:24:04 +03:00
Pavel Kulyov
720bff3437 semen: add and use fn core prototype getter 2026-09-20 15:40:29 +03:00
Pavel Kulyov
8588f5a531 semen: extract counting header length into a function 2026-09-20 15:33:09 +03:00
d0d0ea8e84 process imported forms as toplevel, not as text
1. register imported types
2. protect against multiple imports (diamond, circular)
2026-09-16 16:57:34 +03:00
0b2b97a0c6 add type database and compile-time reflection 2026-09-15 21:28:41 +03:00
28ad33ca38 add sex-error reporting 2026-09-15 21:28:41 +03:00
d83ee32f12 add source line number preservation
Some checks failed
Sex CI / build-macos (pull_request) Has been cancelled
Sex CI / build-linux (pull_request) Failing after 3m34s
For source-level debug. Add --line-directives option, defaulted to
statement. Disabled when used with -C. Explicit non-none value
overrides disabling when -C is present
2026-09-09 14:16:32 +03:00
1ca77aaf59 replace Scheme read with our tokenizer and parser
Also implement . as field access operator and preserve ;-comments in
generated C
2026-09-09 12:44:52 +03:00
196694f18e modularize sex
Also rename macros to sex-macros, module-system to sex-modules for
clarity, uniformity, and to avoid name clashes with Chicken's
units/modules named "macros" and "modules"
2026-04-29 22:48:55 +03:00
0ad1d01fec enable semen-walk-form to embed results (for macro processing) 2025-10-30 18:05:44 +03:00
b4145255bd move recons to utils 2025-10-30 18:05:44 +03:00
951f96f340 add define support 2025-10-30 18:05:44 +03:00
a6348b7b5a add enum support 2025-10-30 18:05:44 +03:00
47affc449f add typedef support 2025-10-30 18:05:44 +03:00
775e321597 add support for nested lambdas 2025-10-01 14:10:42 +03:00
442f663635 add initial lambda support
No closures for now, but solid groundwork is laid.
2025-09-30 09:35:16 +03:00
06892e1afa re-implement macro-expansion using new semantic walker 2025-09-29 15:56:51 +03:00
532487d713 implement semantic code walking framework 2025-09-29 15:56:51 +03:00
b1744bb6af split semantic processing and fmt-c code generation
Introducing Sex SEMantic ENgine: the semen.
Also split reader to other file (it can be replaced in the future).
Macro expansion inside Sex code doesn't work yet, and it must be done
in semen, not during fmt-c generation as before.
2025-09-29 15:50:01 +03:00