kmruiz/sonata

Module System

Open

#1 opened on Feb 26, 2020

 (0 comments) (0 reactions) (0 assignees)C++ (0 forks)auto 404
compilerdiscoveryhelp wantedlanguage

Repository metrics

Stars
 (25 stars)
PR merge metrics
 (PR metrics pending)

Description

Context

Sonata does not implement, yet, any modularization system that allows hiding internal state to a module. Right now the compiler will let you use any defined class, and this class will be stored in the top-level scope.

Sonata, however, does implement a way to import files with source code based on a include path.

Motivation

Any modern language should contain a painless module system that allows developers to reuse code enforcing their best practices:

  • Importing external modules from the include path safely.
  • Importing only chosen classes from a file.

Requirements

Sonata is meant to be a simple language, so the module system should be also as simple as possible and opinionated on best practices. There is a minimum set of requirements:

  • The developer is responsible of hiding any declaration that is not useful outside the module.
  • Importing/exporting definitions should not pollute the language, if possible.

Approach

A suggested approach would be:

  • All files in Sonata pertain to a module, by default it will be related to the directory where they are. This would work similar to a Java package.
  • Modules have a hierarchy: Given the module std.lib
    • The module std is parent of std.lib
    • The module std.lob is sibling of std.lib
    • The module std.lib.streams is child of std.lib
  • Any declaration in a module, is by default public and visible to all modules.
  • Declarations marked as internal can only be seen by the same module, siblings and children.

Examples

; src/my/module/foo.sn :: module: my.module.foo
internal let foo() = 1

; src/my/module/bar.sn :: module: my.module.bar
requires my.module.foo
let bar() = foo() + 1 ; visible because my.module.bar is sibling of my.module.foo

; src/my/module/foo/fooer.sn :: module: my.module.foo.fooer
requires my.module.foo
let fooer() = foo() ; visible because my.module.foo.fooer is child of my.module.foo

; src/main.sn :: module: main
requires my.module.foo

foo() ; does not compile, foo() is internal to module my.module.foo

Affected Modules

  • The standard library needs to be changed to use the new module system.
  • The compiler should enforce visibility rules.

Contributor guide