schala/TODO.md
2022-03-27 22:22:22 -07:00

6.3 KiB

Immediate TODOs / General Code Cleanup

Parsing

Testing

  • Make an automatic (macro-based?) system for numbering compiler errors, this should be every type of error

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)
  • In fact to prove this works, the symbol table shoudl parallelize the process of checking subscopes for local items

  • 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

Typechecking

General code cleanup

Longer-term Ideas

Language Syntax

  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"> -> 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(...),
 }

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

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 <cond-expr>" then <then-expr> else <else-expr> if <half-expr> \n <rest-expr1> then <result1-expr> \n <rest-expr2> then <result-expr2> else <result3-expr> -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 '}'