Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import/Export Additions #4

Closed
jchitel opened this issue Nov 9, 2017 · 3 comments
Closed

Import/Export Additions #4

jchitel opened this issue Nov 9, 2017 · 3 comments
Assignees
Projects

Comments

@jchitel
Copy link
Owner

jchitel commented Nov 9, 2017

Import/Export Additions

Description:

Exports are weird right now because they are sort of tacked on to declarations. They have their own scope for names, which sort of makes sense, but it can be done more intuitively.
Also, as of now, exports are the only way to declare constants. It turned out that way because we wanted to be able to export expressions but had no way to declare non-exported expressions.
We have an entire framework to support them, so we may as well just do it.

So these are the import forms we need to support:

  1. import from "module": ImportName: import default
  2. import from "module": { {name}, {name} as {alias}, ... }: import named
  3. import from "module": ImportName, { {name}, {name} as {alias}, ... }: import named and default
  4. import from "module": * as {namespace}: wildcard import
  5. import from "module": { {name}, {name} as {alias}, * as {namespace} }: import named and wildcard
  6. import from "module": ImportName, * as {namespace}: default and wildcard import
  7. import from "module": ImportName, { {name}, {name} as {alias}, * as {namespace} }: default, named and wildcard import

Currently 1 and 2 are already supported, and 3-7 are not yet supported.

And these are the export forms we need to support:

  1. export default {named declaration}: export default in place declaration
  2. export default {anon declaration}: export default anonymous declaration
  3. export default {name}: export default already declared declaration
  4. export {named declaration}: export declaration with declaration name
  5. export {name} = {named declaration}: export declaration with another name
  6. export {name} = {expression}: export constant under name
  7. export { {name}, {name} as {alias}, ... }: export already declared declaration(s)

Currently 1 and 3 are already supported, and 2 and 4 are not yet supported.
5 and 6 are currently supported and will be removed.
7 currently exists in a different form for single exports, it will be redone to support multiple exports.

And these are fusion import/export declarations (export forwarding):

  1. export from "module": ExportName: Default from another -> Named from yours
  2. export default from "module": Default from another -> Default from yours
  3. export default from "module": { {name} }: Named from another -> Default from yours
  4. export from "module:" { {name}, {name} as {alias}, ... }: Named from another -> Named from yours
  5. export default from "module": *: All from another -> Default from yours (grouped under a namespace object)
  6. export from "module": * as {name}: All from another -> Named from yours (grouped under a namepsace object)
  7. export from "module": *: All from another -> All from yours (ungrouped, just a 1:1 forward)

Currently none of these are supported.

With the above, all possible kinds of imports and exports should be supported.

New syntactic features:

New Tokens

CONST ::= "const"

New NonTerminals:

ConstantDeclaration ::= CONST IDENT EQUALS Expression
AnonDeclaration ::= AnonTypeDeclaration | AnonFunctionDeclaration | Expression
AnonTypeDeclaration ::= TYPE EQUALS Type
AnonFunctionDeclaration ::= FUNC Type TypeParamList? ParameterList FAT_ARROW (Expression | Block)
NamedExports ::= LBRACE (IDENT | IDENT AS IDENT) (+ sep COMMA) RBRACE
ExportForwards ::= ImportList
                 | MULTIPLY
DefaultExportForwards ::= LBRACE IDENT RBRACE
                        | MULTIPLY

Extended NonTerminals:

Program ::= ImportDeclaration* (Declaration | ExportDeclaration)*
Declaration ::= TypeDeclaration | FunctionDeclaration | ConstantDeclaration
ImportDeclaration ::= IMPORT FROM STRING_LITERAL COLON ImportList
ImportList ::= IDENT
              | NamedImports
              | IDENT COMMA NamedImports
              | MULTIPLY AS IDENT
              | IDENT COMMA MULTIPLY AS IDENT
NamedImports ::= LBRACE (IDENT | IDENT AS IDENT | MULTIPLY AS IDENT) (+ sep COMMA) RBRACE
ExportDeclaration ::= EXPORT DEFAULT (Declaration | AnonDeclaration | IDENT)
                    | EXPORT (Declaration | NamedExports)
                    | EXPORT FROM STRING_LITERAL COLON ExportForwards
                    | EXPORT DEFAULT FROM STRING_LITERAL (COLON DefaultExportForwards)?
Type ::= ... | Type DOT IDENT

New semantic features:

  • All this basically boils down to the existing framework we have, except wildcards and rest imports, which I will address at the end
  • The new import types just add imports the same way they did before, the existing framework already supports it
  • Exports must always have a name. If there is a default export with a named declaration, the declaration is processed normally and the default export is set to that name.
  • Anonymous default exports are only exposed at typecheck time, not to the developer, under a special identifier for type checking.
  • Named exports with a separate name are no longer possible unless it is an already declared value, in which case there is an alias that points to the module scoped value.
  • All named exports are pointers to some other declaration. Export names still have their own scope.
  • Export forwarding is just sugar for an import combined with an export. The export names are just linked directly to the imported declarations.
  • Now for wildcards and rest imports.
  • Wildcard imports will take all exports of a module and group them on a namespace, which is a special sort of readonly struct.
  • The type of namespaces is not accessible from code, but it does have a type (this may change in the future).
  • Rest imports work the same way with namespaces, but they have to be more complex because they need to determine which exports haven't been explicitly imported.
  • If the default export is not explicitly imported, the wildcard will include the default export as a field.

Transformation:

  • Type checking resolves all exports to a common framework, so transformation will likely need no changes.
  • Namespace imports may require changes.
@jchitel jchitel self-assigned this Nov 9, 2017
@jchitel jchitel added this to To Do in Ren v0.1 via automation Nov 9, 2017
@jchitel jchitel moved this from To Do to In Progress in Ren v0.1 Nov 10, 2017
@jchitel
Copy link
Owner Author

jchitel commented Nov 15, 2017

Ok, the syntax (all parser-impl, CST, and AST logic) is done.

The remaining work:

  • Refactor the TypeChecker to use the new import/export formats
  • Add type checking logic for namespaces
  • Rework translator logic to handle new constant declarations and namespace accesses
  • Fix/add tests for the new syntax

Things to address:

  • Because of how translation works, it may be necessary to replace Expression in exports with an actual AnonConstantDeclaration. Yes, this made things way simpler.

@jchitel
Copy link
Owner Author

jchitel commented Nov 15, 2017

Additional problem:

  • The results of namespace accesses can have type parameters, so it's no longer just identifier types that can have type arguments. This means we need to rework specific types to be a left-recursive suffix instead of a simple kind of type.

This will actually be nice for several reasons:

  • The logic for resolving the types of identifiers doesn't need to be duplicated between identifiers and specific types.
  • It opens the door to be able to easily make other types generic as well (if that makes sense).

@jchitel
Copy link
Owner Author

jchitel commented Dec 4, 2017

Ok, tests are done and all passing. We could probably use more coverage, but we're fine for the time being. Closing my first feature!

@jchitel jchitel closed this as completed Dec 4, 2017
Ren v0.1 automation moved this from In Progress to Done Dec 4, 2017
@jchitel jchitel mentioned this issue Dec 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Ren v0.1
  
Done
Development

No branches or pull requests

1 participant