
- resolves #1 - define-type-constructor accepts arbitrary extra "info" that is stored with the type - get-extra-info extras this info - define type stores extra info that is essentially a mu type containing all variant info - match must manually "unfold" this info, ie iso-recursive - all tests passing - mlish tests implements full nqueens example - no explicit instantiation of polymorphic functions - some polymorphic constructors require annotations when no inference possible - a lone nil with no other information - lambda params require annotations - top lvl fns require full signature
338 lines
13 KiB
Plaintext
338 lines
13 KiB
Plaintext
2016-02-29
|
|
Problem: storing variant info as properties
|
|
- when instantiating polymorphic type, need to instantiate properties as well
|
|
Alternate Solution: store variant syntactically in (expanded) type
|
|
- benefit is instantiation "just works"
|
|
- drawbacks:
|
|
- recursive types will expand infinitely
|
|
- quoting the variant stops infinite expansion but breaks the subst
|
|
- ie ids in the quote no longer correspond to the bound id
|
|
- can manually stop expansion but then types will no longer always be
|
|
fully expanded forms
|
|
- tried this a few times previously - can get VERY messy - avoid if possible
|
|
- to make this alternate work, can manually fold/unfold recursive types
|
|
- cant use \mu from stlc+rec-iso bc each type is more than the mu
|
|
so folding/unfolding is a little different
|
|
|
|
2016-02-19
|
|
Implementing algebraic data types
|
|
- macro cannot define type-alias and constructor functions that produce
|
|
variant values
|
|
- not only because adts should be an abstraction (ie not type alias)
|
|
- constructor output will have variant type and not the type defined
|
|
- macro should basically expand to list implementation in stlc+cons.rkt
|
|
- where to store the names of the variants (as stx prop?)
|
|
|
|
|
|
2015-10-09
|
|
TODO: variant case should call current-join?
|
|
|
|
2015-10-09
|
|
Can I get rid of current-type-eval?
|
|
- would have to put "normalize" call in type=?
|
|
- and call normalize in current-promote (before pattern matching)
|
|
|
|
Thus, it's probably better to keep type-eval
|
|
|
|
2015-08-16:
|
|
TODO:
|
|
- generalize binding forms
|
|
- add tags to distinguish different binding forms
|
|
|
|
2015-08-16:
|
|
Paper outline
|
|
|
|
stlc.rkt
|
|
Concepts:
|
|
- #%app
|
|
- lambda
|
|
- user input types must be checked
|
|
|
|
stlc+rec-iso.rkt
|
|
Concept(s): binding form, type=? for binding forms
|
|
|
|
2015-08-13
|
|
Requirements for define-type-constructor syntax:
|
|
- identifier types, like Int
|
|
- basic tuples, like arrow
|
|
- arity
|
|
- nested tuples, like records
|
|
- binding forms, like forall
|
|
|
|
Problem:
|
|
Types must be expanded, to check that they are valid, catch unbound ids, etc.
|
|
But should I attach the expanded type to a term, or the original surface stx?
|
|
- maybe this is just repeating the same thing I wrote below?
|
|
- Related question: fully expand types before calling type=? or typecheck?
|
|
Answer: must only compare fully expanded forms, otherwise these will not work
|
|
- define-type-alias
|
|
Rules:
|
|
- all user-written types must be expanded and checked
|
|
- check for invalid types, unbound ids
|
|
- use expanded types (when available) to create new types
|
|
- expand all types before attaching
|
|
- assume types are expanded in type=? and typechecks
|
|
|
|
2015-07-31
|
|
Problem: pattern-expander not being recognized
|
|
Solution: syntax-parse pattern directives must begin with ~ prefix
|
|
|
|
2015-07-30:
|
|
Problem: How to match against an "expanded" type when I have an unexpanded pat?
|
|
- use the 'orig syntax?
|
|
- this would probably work but now 'orig is used for more than debugging/msgs
|
|
- so dont do this
|
|
- also, wont work because you're only matching part of the type
|
|
- use pattern expanders!
|
|
- a declared literal in define-type-constructor is defined as *both*:
|
|
- and macro that applies a temporary id (defined as void)
|
|
- a pattern-expander that expands into the expanded form:
|
|
((~literal #%plain-app) (~literal tmp-id) . args)
|
|
|
|
Note to self: when getting weird macro pattern matching errors, always check if you're accidentally using a pattern variable!
|
|
|
|
2015-07-28
|
|
Problem: How to handle mixed types, ie combining expanded and unexpanded types.
|
|
Problem: When to eval, ie expand, types into canonical form
|
|
Solution:
|
|
- use two tags, #%type and #%plain-type, representing surface type syntax and
|
|
fully expanded type representation, respectively
|
|
- #%type wrapper automatically added by the define-type- macros
|
|
- #%plain-type wrapper added by type-eval
|
|
- both are macros that expand into their (single) sub-form
|
|
- enables elegant mixing of expanded and unexpanded types
|
|
- mixed types still need to be eval'ed
|
|
- needed to construct other types, eg inferring type of lambda
|
|
- enables easy checking of is-type?
|
|
- only checks outer wrapper
|
|
- rely on each tycon to validate its own arguments
|
|
- eval-type only expands if not #%plain-type, ie not already expanded
|
|
- this solution thus far does not require any awkward "hacks" in implementations
|
|
|
|
2015-07-25
|
|
Problem: types and terms occur in the same space
|
|
What to do about "valid" terms like \x:(void).x or \x:1.x ?
|
|
- adding an is-type? predicate that checks shape and other things will only
|
|
partially work because things like \x:(void).x will still pass
|
|
- define types in a different phase
|
|
- wont work because you need terms to do type checking so the terms have to be
|
|
in the same phase
|
|
- write a separate parser for types
|
|
- wont work because still cant tell with a valid binding is a term or type,
|
|
eg, \x:(void).x still passes
|
|
- unless you hard-code the type names, but then it's not extensible?
|
|
- can extend the reader but then you have code duplication?
|
|
- wrap types with a tag, like #%type ?
|
|
- this might work
|
|
- will this have extensibility problems later, ie with records and variants?
|
|
|
|
2015-07-24
|
|
When to canonicalize (ie, eval) types:
|
|
- calling eval before matching is too late
|
|
- wont catch things like unbound types
|
|
- syntax-class evaling is too eager
|
|
- sometimes get error when you shouldnt or wrong erro
|
|
- eg type (-> 1 2)
|
|
- I think the right place is to have \vdash eval
|
|
- and rackunit testing forms
|
|
|
|
2015-06-30
|
|
when extending a typed language, use prefix-in for identifiers:
|
|
- that are extended, eg #%datum in ext-stlc.rkt
|
|
- rename-out the extended implementation of the form
|
|
- or when you want to use racket's version, eg #%app in ext-stlc.rkt
|
|
- rename-out the prefixed form
|
|
- must except-out the prefixed forms, eg stlc:#%app and stlc:#%datum in ext-stlc
|
|
|
|
2015-06-26
|
|
Random thought: Can kinds be "erased"?
|
|
- first thought is no, since they appear to be needed for type equality?
|
|
- Solution: add them to body of lambda (eg which represents a forall)
|
|
|
|
2015-06-26
|
|
syntax marks problem:
|
|
- in the type created by \Lambda, eg \x.(-> x x), the binding x and body x's
|
|
were free-id= but not bound-id= because the body x's had extra marks
|
|
- this is because (the syntax representing) types are marked going "into" an
|
|
expansion, but do not receive the cancelling mark coming *out of* the
|
|
expansion since they are attached as a syntax-property
|
|
- thus, when this lam goes through another expansion (via \vdash), the binding x
|
|
and body x's become neither free-id nor bound-id=?
|
|
Solution:
|
|
- undo the mark (using syntax-local-introduce) when retrieving the a type
|
|
as a syntax property (ie in \vdash)
|
|
- need one more syntax-local-introduce in infer/tvs+erase
|
|
- i guess the rule is I need as many syntax-local-introduce's as extra
|
|
expanding lambdas that I add
|
|
|
|
|
|
2015-06-18
|
|
Design Decision:
|
|
Types must be fully expanded, if we wish to use expansion to typecheck types
|
|
(i.e., kinding).
|
|
Problems:
|
|
- Type constructors can't be both macro and function
|
|
- solution: macro that expands to tmp function
|
|
- must provide predicate to check
|
|
- Recursive types
|
|
- solution: ???
|
|
- Displaying error msgs
|
|
- need to keep track of surface stx (similar to 'origin prop?)
|
|
- solution: ???
|
|
- repeated expansion of already expanded types
|
|
- solution: ???
|
|
- what to do about tuples, where there may be a string in the fn position
|
|
- solution: add an extra "type constructor" in front of each pair
|
|
- todo: come up with a nicer way to handle "compound" types
|
|
- what is the expansion of forall?
|
|
|
|
2015-06-16
|
|
Problem:
|
|
use expansion for typechecking of terms: ok
|
|
- specifically, ok to go under lambda, since eval happens later
|
|
use expansion for typechecking of types: doesnt work now
|
|
- doesnt work because types currently are not fully-expandable
|
|
- eg a type constructor application (tycon x) is a macro that expands to
|
|
(#%app tycon x), where this expression will error if expanded further
|
|
since tycon cannot be used as an identifier
|
|
- if I define tycon as a regular function, so (tycon x) expands to
|
|
(#%app tycon x), then it wont catch non-app uses of tycon
|
|
- should be fine? - this is a parsing, not typechecking problem
|
|
- but then then parser need to be updated with every new type constructor
|
|
- this kind of monolithic architecture is what the paper is trying
|
|
to avoid
|
|
- alternative: define tycon as a macro where (tycon x) expands to
|
|
(#%app tycon_new x)
|
|
- drawback: can't use ~literal to match/destructure the tycon
|
|
- does this make things like type checking or type=? more difficult?
|
|
- will have to go through a separately-defined interface,
|
|
like a \tau? predicate
|
|
Subproblem: must completely change the representation of types?
|
|
- must use fully-expanded forms instead of surface syntax
|
|
- in particular, will be using *fully expanded identifiers*
|
|
- in this scenario, can I still match with ~literal?
|
|
Subproblem: where/when to expand
|
|
- types now must all be expanded since that is when kind checking occurs
|
|
use expansion for eval of types: not ok
|
|
- dont want to go under binders
|
|
- expand then eval?
|
|
- but then type constructors cant be macros?
|
|
Possible Solution
|
|
- I think eval must be separate
|
|
Subproblem: Do I need a new eval that is different from current-eval?
|
|
- conflict:
|
|
- current-eval must go under forall to check for unbound ids
|
|
- but eval should not go under forall for the case of tyapps
|
|
- maybe tyapp should go into type=?, as in tapl?
|
|
Subproblem: where to eval
|
|
- currently call eval for user type annotations, and in \vdash
|
|
Subproblem: Can type=? assume fully expanded (ie, evaled) types?
|
|
|
|
2015-06-15
|
|
New Thesis: The abstractions provided by macro systems are effective at
|
|
implementing type systems
|
|
|
|
2015-06-08
|
|
Problem: how to represent \rightarrow kind operator
|
|
1) If the kind operator is the same as the function type operator then how do I
|
|
attach a kind to a function arrow, since the arrow is still undefined at the
|
|
time.
|
|
2) If the kind arrow is a different arrow then #%app must be parameterized over
|
|
the arrow
|
|
|
|
2015-05-28
|
|
Problem: how to represent \forall types
|
|
1) (Racket) functions
|
|
- this gets the most linguistic reuse (is this true?)
|
|
- but this does not allow equality comparisons
|
|
- unless perhaps compare two foralls for equality by applying to the same tvar
|
|
- but these type vars would be unbound so it still wouldnt work without
|
|
adding a new special case
|
|
2) syntax
|
|
- easier to compare
|
|
- but still need to manually implement alpha equality
|
|
- would still require a special case for comparing the bodies, which have
|
|
unbound typevars
|
|
|
|
Problem: begin in lambda body gets spliced
|
|
- results in combined syntax properties, eg types
|
|
Solution:
|
|
- wrap lambda body with #%expression to indicate expression, ie non-splicing,
|
|
begin
|
|
|
|
2015-05-29
|
|
Notes: locally-nameless representation of lambdas (and other binding terms)
|
|
- syntactically distinguishes bound names vs free vars
|
|
- combination of debruijn (nameless) for bound vars and names
|
|
- simplifies implementation of capture avoiding substitution
|
|
- I already get around by using Racket's identifiers and free-identifier=
|
|
to easily implement capture-avoiding subst
|
|
- debruijn indices for boundvars avoids having to convert to canonical form
|
|
to compare for alpha-equal
|
|
- using names for free vars avoids "shifting" of indices when adding or
|
|
removing binders, ie free vars dont rely on context
|
|
- two main operations:
|
|
- open: converts some bound vars to free vars
|
|
- eg subst into lambda body
|
|
- conversion and subst can be done in one pass?
|
|
- close: converts some free vars to bound vars
|
|
- eg wrapping a term in a lambda
|
|
- similar to subst
|
|
- both operations involve traversing the term
|
|
- but can do straight-subst (instead of renaming subst) because
|
|
shadowing is not possible
|
|
- multiple binders are more complicated
|
|
- require both depth and offset index
|
|
|
|
Previous: -----------------
|
|
|
|
macro system requirements:
|
|
- depth-first expansion, i.e., localexpand, and stop-lists
|
|
- language form hooks, e.g., #%app, etc
|
|
- literal types, e.g. integer syntax class, ie compile time literal type tag
|
|
- identifiers and free-identifier=?
|
|
- syntax-parse or other pattern matching
|
|
|
|
Type constructors must be prefix (and not infix) and must be functions
|
|
- because in order to support type aliases:
|
|
- types must be expanded,
|
|
- and having a macro identifier (ie, an alias) in the function position
|
|
makes the expander error (constructor is ok bc it is run time identifier)
|
|
|
|
Type expansion problem: what to do about #%app?
|
|
1) use the #%app in scope:
|
|
- may do type checking and error bc types dont have types
|
|
2) use the racket #%app:
|
|
- may work but how to do this without ruining context of other
|
|
identifiers (ie types)
|
|
Solution: do #1, but
|
|
1) stop at the #%app
|
|
2) manually drop it and continue expanding rest
|
|
|
|
Types must be identifiers, but not macros
|
|
- cannot be macros if we want to use expansion for type aliases
|
|
- because then what does a base type like Int expand to?
|
|
- if we define Int as a runtime identifier, then expansion will stop at Int
|
|
|
|
|
|
debugging notes -------------
|
|
- "datum" error:
|
|
|
|
?: literal data is not allowed;
|
|
no #%datum syntax transformer is bound in: #f
|
|
|
|
- likely indicates use of wrong version of some overloaded form
|
|
- eg, using stlc:lambda instead of racket's lambda
|
|
|
|
- vague "bad syntax" error
|
|
- means a syntax-parse #:when or #:with matching failed
|
|
- ideally would have better err msg at that spot
|
|
|
|
- #%datum: keyword used as an expression in: #:with
|
|
- missing a #:when in front of a printf
|
|
|
|
- one of type=? arguments is false
|
|
- term missing a type
|
|
- type missing a kind
|
|
- need to transfer syntax properties, eg subst
|