TODO:
- include spans in ast
- have every node have its own error type
  - why? so you can store stack state, silly!
- dedicated interface/symbol management area
- interactive compiler
- CST and analyses on it
  - import statements and uses?
- figure out procedure and function semantics
  - if distinction is really worth it, and not just convenient

there are three kinds of types:
- parsed types (uninferred, no refs)
- type terms (uninferred, with refs)
- concrete types (inferred completely)

a type inference engine is something that converts an uninferred type to a completely inferred type.


         | Exchange | Weakening | Contraction | Use
:--------|:--------:|:---------:|:-----------:|
Ordered  |    —     |     —     |      —      | Exactly once in order
Linear   | Allowed  |     —     |      —      | Exactly once
Affine   | Allowed  |  Allowed  |      —      | At most once
Relevant | Allowed  |     —     |   Allowed   | At least once
Normal   | Allowed  |  Allowed  |   Allowed   | Arbitrarily 



# Introducing Variables

currently rever only has ordered variables

but after changing to linear, it can't do

	var x := "abc...xyz"
	...
	drop x

because it *needs* a deinit value for the drop, since it can't directly access the init value implicitly anymore. (or can it?)

if you do something like

	let x = "abc...xyz"
	...
	~ implicit drop at end of scope

you'll need a way to drop a let variable when evaluating statements, and figure out some way to drop them when reaching the end of its containing scope.


# Understanding uppercase and lowercase ident conventions

Type context:
- Uppercase: Concrete types, type constructors
- lowercase: type variables

Value/Expression context:
- Uppercase: in-place data, literal, alias for data
- lowercase: location of data, value variables

naming conventions for items:
- Type
- Constant
- Function
- module
- static
- procedure




Store the Result<>s in the AST itself??? because it lets you include error nodes in the parse tree, for better error recovery and error messages!!

formatting library:
- alignment
- min/max width
  - filler character
- min/max height
- min/max depth
  - indentation string


uppercase:
- Functions
- Constants
- Types
- Variants

lowercase:
- modules
- variables
- procedures
- statics
- fields

module.module
module.variable XXXXX
module.procedure
module.static
module.field    XXXXXX
module.Function
module.Constant
module.Type
module.Variant  XXXXXX


-------------------------------------------

Procedure semantics

janus-like: input types are exact same as output types
+ guarantee no loss of info
  + based on principle of functions that don't discard info are always reversible
+ copy-in copy-out semantics
+ modifications are limited to passed parameters
- unnecessarily inflexible; other ways of guaranteeing no-info-loss
- not much room for changes outside given types
  - requires a "dummy" value when constructing a compound type

transformative: input types can be *exchanged* for output types
+ no loss of info
  + guaranteed thru linear type system; every input *must* be used.
+ no dummy values
- probably won't allow as clean `do` and `undo` syntax
  - `do` and `undo` now must be expressions, not statements
- how would it work for non-linear types? values that can be copied?
  - 
