(P && Q => R) stands for ((P && Q) => R) Careful with "==" (precedence) though. -fno-delete-null-pointer-checks -fwrapv formatter paren handling: It would be (unfortunately) a lot easier to yield on just the opening paren and not yield on the closing paren when parsing already. The opening paren will not care so much about precedence - neither when parsing nor when printing, so it's the simpler choice. On the other hand, the closing paren would need special care when parsing and especially when printing (the latter in order to prevent it from printing it as (...])). The downside is that the formatter has to automatically generate the closing paren - but it has to know which are parens already anyway. It's of no use to change that. The formatter has to be able to handle the case anyhow (i.e. handle random user input). Special operations: mut in order to create a mutable slot ? silly naming: "Circumfix" operators are for example parens. Unicode: http://legacy.python.org/dev/peps/pep-3131/#specification-of-language-changes There's even better: two of the possible properties on a codepoint are ID_Start and ID_Continue defined in tr31. ID_Start is a valid first codepoint of an identifier. ID_Continue is a valid continuation codepoint of an identifier. TR31 Allows extension if desired or necessary: http://www.unicode.org/reports/tr31/#Specific_Character_Adjustments Semantics: Maybe list the default bindings in the semantics, too. Make sure to support binding of free variables that are called like constants, such as: 0 0.2 2E3 0x321p22 "hello" true false -2 ?!? +2 ?!?!? 500_000 Use std.typecons : Rebindable for (const) classes. parsing: Make "(a,b) := " do destructuring bind of pairs. The comma is a problem: it will cause a and b to be resolved. Also, the comma shouldn't be resolved either. Alternative: de-resolve (ugly) Alternative: have user do 'a,b' := ... (ugly but explicit) For consistency, also allow 'a' := ... support prefix operators with more than 1 argument. Currently that doesn't work. Reason: automatic gap insertion. Examples: rem, if. `-' in prefix position: auto-introduce extra arg or what?! I'd rather not. MAYBE leave in the AST. Probably not. Distinguish between "\n"-`in' and literal `in' ? constants (thunks): Maybe just store the orig expression together with the result. Test: empty input autotest for all possible combinations! For differential geometry, Einstein summation: Autoquote the indices and/or automatically bind double indices to an invisible sum if there is no sum yet. There have to be explicit conversion possibilities between the index namespace and the normal namespace. From index to normal: (1,2,3)^i From normal to index: If that's even necessary. Better to just have special fn params AND args that are indices only. To be clear, f(x^k) := ... should be f(x,^k) := ... Sums should be able to bind to indices like this and arguably should have an index as running variable in the first place. Optimizations: make sure to remember Name source as well (for 'x' := 'x') move fns out as far as possible, as long as they don't use anything inside. move bindings out as far as possible to merge them if they are the same. If it's not possible to merge the bindings, move them in as far as possible without splitting. for functions marked terminating, reduce them as soon as possible. Warning: each arg needs to be so marked? transform AST to CPS (with OK and error branch, I guess? No.). optimize CPS. delimited continuations let forms: without the (obsolete) "let" keyword we notice too late that the variable is new. That means we have to carry around all the symbols until we know the entire thing. Once we see the ":=" we can finally renumber them! Even better would be to just remember the ranges in the input file, not at all copy. One way or another, it has to remember which run of characters (the content) is which symbol. D: check all the places where int is used for possible overflow. enum PGSQL_UNITTEST_PORT = 5432; immutable PGSQL_UNITTEST_PORT = 5432; type inference: What about functions that are so generic that there are no constants in it? Just infer the most generic "all" type (how does this type exist?). What about structs? Pass field names and only very late have them reduce to offsets, i.e. at runtime depending on type. `in' macro: Detect `a := 2 in a' and transform it to a let form (or similar). Detect `import ... by a in B' and transform it to multiple let forms (or similar). Maybe detect `a := b := 2 in b'. Automatically interpret other things as `in' function call: For example shl ax in shr ax as shl ax; shr ax Also `in' in rem "xxx" in b Make the `in' function auto-defer like all others. MAYBE make `in' automatically mean "&&", as in x = 2 y = 3 but I think that's more a personal thing. The `in' macro just needs special-casing in finishOperation to make it not process its first argument sometimes (as far as `:=' CAN be processed). Think about graceful fallback for `:=' if it appears in the middle of nowhere. maybe rename: `import` `using` `with` maybe: `:=` is `:` infer-type `=` FFI: import (simple) typedefs as far as possible. note that HANDLE = uintptr_t , a number that is not a pointer! rewrite rules: compiler actually has to know the operand types in order to know which operand it is! so the actual rules are like rem "(Groupoid)" `+` :: Integer -> Integer -> Integer ` ` :: Integer -> Integer -> Integer rem "(Semigroup) Associativity" a :: Integer && b :: Integer && c :: Integer && `+` :: Integer -> Integer -> Integer => (a + b) + c = a + (b + c) a :: Integer && b :: Integer && c :: Integer && ` ` :: Integer -> Integer -> Integer => (a b) c = a (b c) rem "(Monoid) Identity" ∃0 (0 :: Integer && `+` :: Integer -> Integer -> Integer && ∀x (x :: Integer => 0 x = x)) ∃1 (1 :: Integer && ` ` :: Integer -> Integer -> Integer && ∀x (x :: Integer => 1 x = x)) rem "(Group) Inverse" a :: Integer => ∃-a (-a :: Integer && `+` :: Integer -> Integer -> Integer && -a + a = 0) a :: Integer => ∃a^(-1) (a^(-1) :: Integer && ` ` :: Integer -> Integer -> Integer && a a^(-1) = a^(-1) a = 1) rem "(Abelian) Commutativity" a :: Integer && b :: Integer && `+` :: Integer -> Integer -> Integer => a + b = b + a a :: Integer && b :: Integer && ` ` :: Integer -> Integer -> Integer => a b = b a rem "(Semiring) Distributivity" a :: Integer && b :: Integer && c :: Integer && `+` :: Integer -> Integer -> Integer && ` ` :: Integer -> Integer -> Integer => a (b + c) = a b + a c a :: Integer && b :: Integer && c :: Integer && `+` :: Integer -> Integer -> Integer && ` ` :: Integer -> Integer -> Integer => (b + c) a = b a + c a rem "(Semiring) Annihilation (Note: automatic for rings)" a :: Integer && b :: Integer && ` ` :: Integer -> Integer -> Integer => 0 a = a 0 = 0 # for rings, that follows. rem "Ring R: R is abelian under addition, R is monoid under multiplication, multiplication distributes" rem "For Lie Rings, associativity is given up." rem "(Field) Multiplicative Inverses exist except for 0" constant syntax: 0 :: Integer 0U :: Natural 0.3f :: Float 0.1p+22 :: Float 1/3 :: Rational 2+3i :: Complex