# Immediate TODOs / General Code Cleanup ## Testing * Get a test library for running many unit tests working ## Symbols * Add some good printf-debugging impls for SymbolTable-related items * the symbol table should probably *only* be for global definitions (maybe rename it to reflect this?) * dealing with variable lookup w/in functions/closures should probably happen in AST -> ReducedAST * b/c that's where we go from a string name to a canonical ID (for e.g. 2nd param in 3rd enclosing scope) * Old notes on a plan of attack: 1. modify visitor so it can handle scopes -this is needed both to handle import scope correctly -and also to support making FQSNs aware of function parameters 2. Once FQSNs are aware of function parameters, most of the Rc things in eval.rs can go away ## Parser * I think I can restructure the parser to get rid of most instances of expect!, at least at the beginning of a rule ## Typechecking * make a type to represent types rather than relying on string comparisons * look at https://rickyhan.com/jekyll/update/2018/05/26/hindley-milner-tutorial-rust.html ## General code cleanup * standardize on an error type that isn't String * implement a visitor pattern for the use of scope_resolver * maybe implement this twice: 1) the value-returning, no-default one in the haoyi blogpost, * look at * https://gitlab.haskell.org/ghc/ghc/wikis/pattern-synonyms * the non-value-returning, default one like in rustc (cf. https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md) # Longer-term Ideas ## Language Syntax * the `type` declaration should have some kind of GADT-like syntax * use `let` sigil to indicate a variable in a pattern explicitly: ``` q is MyStruct(let a, Chrono::Trigga) then { // a is in scope here } ``` * if you have a pattern-match where one variant has a variable and the other lacks it instead of treating this as a type error, promote the bound variable to an option type * what if there was something like React jsx syntas built in? i.e. a way to automatically transform some kind of markup into a function call, cf. `

` -> h1(prop=arg) * implement and test open/use statements * Include extensible scala-style `html"string ${var}"` string interpolations * A neat idea for pattern matching optimization would be if you could match on one of several things in a list ex: ``` if x { is (comp, LHSPat, RHSPat) if comp in ["==, "<"] -> ... } ``` * Schala should have both currying *and* default arguments! ``` fn a(b: Int, c:Int, d:Int = 1) -> Int a(1,2) : Int a(1,2,d=2): Int a(_,1,3) : Int -> Int a(1,2, c=_): Int -> Int a(_,_,_) : Int -> Int -> Int -> Int ``` * scoped types - be able to define a quick enum type scoped to a function or other type for something, that only is meant to be used as a quick bespoke interface between two other things ex. ``` type enum { type enum MySubVariant { SubVariant1, SubVariant2, etc. } Variant1(MySubVariant), Variant2(...), } ``` * inclusive/exclusive range syntax like .. vs ..= ## Typechecking * cf. the notation mentioned in the cardelli paper, the debug information for the `typechecking` pass should * print the generated type variable for every subexpression in an expression * think about idris-related ideas of multiple implementations of a type for an interface (+ vs * impl for monoids, for preorder/inorder/postorder for Foldable) * should have an Idris-like `cast To From` function * something like the swift `Never` type ( https://nshipster.com/never/ ) in the stdlib ## Compilation * look into Inkwell for rust LLVM bindings * https://cranelift.readthedocs.io/en/latest/?badge=latest * look at https://gluon-lang.org/doc/nightly/book/embedding-api.html # Syntax Playground ## Trying if-syntax again ``` //simple if expr if x == 10 then "a" else "z" //complex if expr if x == 10 then { let a = 1 let b = 2 a + b } else { 55 } // different comparison ops if x { == 1 then "a" .isPrime() then "b" else "c" } /* for now disallow `if x == { 1 then ... }`, b/c hard to parse //simple pattern-matching if x is Person("Ivan", age) then age else 0 //match-block equivalent if x { is Person("Ivan", _) then "Ivan" is Person(_, age) if age > 13 then "barmitzvah'd" else "foo" } ``` ## (OLD) Playing around with conditional syntax ideas - if/match playground simple if `if x == 1.0 { "a" } else { "b" }` one comparison multiple targets: `if x == { 1.0 -> "a", 2.0 -> "b", else -> "c" }` different comparison operators/ method calls: `if x { == 1.0 -> "a", eq NaN -> "n", .hella() -> "h", else -> "z" }` pattern matching/introducing bindings: `if alice { .age < 18 -> "18", is Person("Alice", age) -> "${age}", else -> "none" }` pattern matching w/ if-let: `if person is Person("Alice", age) { "${age}" } else { "nope" }` -https://soc.github.io/languages/unified-condition-syntax syntax: `if " then else ` `if \n then \n then else ` -and rest-exprs (or "targets") can have 'is' for pattern-matching, actually so can a full cond-expr UNIFIED IF EXPRESSIONS FINAL WORK: basic syntax: `if_expr := if discriminator '{' (guard_expr)* '}'` `guard_expr := pattern 'then' block_or_expr'` `pattern := rhs | is_pattern` `is_pattern := 'is' ???` `rhs := expression | ???` if the only two guard patterns are true and false, then the abbreviated syntax: `'if' discriminator 'then' block_or_expr 'else' block_or_expr` can replace `'if' discriminator '{' 'true' 'then' block_or_expr; 'false' 'then' block_or_expr '}'`