211 lines
6.1 KiB
Markdown
211 lines
6.1 KiB
Markdown
# Immediate TODOs / General Code Cleanup
|
|
|
|
|
|
## 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<String> things in eval.rs can go away
|
|
|
|
## Semantics
|
|
|
|
* Use annotations to indicate builtin functions
|
|
|
|
## 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
|
|
|
|
* a type like `type Klewos = Klewos { <fields> }` (i.e. a type with exactly one record-like variant) should be writeable as
|
|
`type Klewos = { <fields> }` as a shorthand, and should not require explicit matching.
|
|
* 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">` -> 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 ..=
|
|
|
|
* Nameable patterns/ pattern synonyms cf. https://gitlab.haskell.org/ghc/ghc/-/wikis/pattern-synonyms
|
|
|
|
|
|
## 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<Paste>
|
|
|
|
* 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 <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 '}'`
|
|
|