Skip to content

Latest commit

 

History

History
451 lines (315 loc) · 8.69 KB

cli.md

File metadata and controls

451 lines (315 loc) · 8.69 KB

Command-line Interface

milone command is the standard CLI for milone-lang projects.

Subcommands

Less important:

run

Run a project.

milone run <PROJECT-DIR> [-- ARGS...]

Examples:

milone run ./MiloneProject
milone run ./MiloneProject -- --flag arg1 arg2

Requirements:

Options:

  • -- ARGS...
    • Arguments for generated executable.
    • Note that -- is required to pass some args.
  • --release
    • Compile in release mode.
  • --target-dir <DIR> (defaults to target/<PROJECT-NAME>)
    • Specify target directory.
    • That directory contains intermediate files and output files.
    • Note that <PROJECT-NAME> is basename of project directory.

Output:

  • Code:
    • 1 if compile failed.
    • Exit code that executed program returned.
  • Stdout: Inherited to executed program.
  • Stderr: Compile progress and compile errors. Inherited to executed program too.
  • Files: Same as build

build

Build a project for an executable.

milone build <PROJECT-DIR>

Examples:

milone build ./MiloneProject
milone build ./MiloneProject --release --target-dir ../build

Options:

  • --release
    • Compile in release mode.
  • --target-dir <DIR> (defaults to target/<PROJECT-NAME>)
    • Specify target directory.
    • That directory contains intermediate files and output files.
    • Note that <PROJECT-NAME> is basename of project directory.
  • --output <FILE>, -o <FILE>
    • Copy the output file to specified destination after successful build.

Output:

  • Code: 0 if success. 1 if error.
  • Stdout: Compilation progress and compile errors.
  • Files:
    • <TARGET-DIR>/*.c: C files (if success)
    • <TARGET-DIR>/<PROJECT-NAME>.exe: Executable (if success)
    • where TARGET-DIR is specified by --target-dir option
    • <FILE> specified by -o/--output (if success)
    • On linux:
      • <TARGET-DIR>/build.ninja
    • On windows:
      • <TARGET-DIR>/<PROJECT-NAME>.sln
      • <TARGET-DIR>/<PROJECT-NAME>/<PROJECT-NAME>.vcxproj
      • <TARGET-DIR>/<PROJECT-NAME>/target/** (generated by MSBuild)

eval

Compute an expression.

milone eval <EXPRESSION>

Examples:

milone eval '40 + 2'
#=> 42
milone eval '
let rec fact n =
  if n <= 1 then 1 else n * fact (n - 1)
fact 5'
#=> 120

Options: None.

Output:

  • Code: 0 if success. 1 if error.
  • Stdout: Evaluation result.
  • Files:
    • target/Eval/**: Intermediate files.

Remarks:

  • Expression must be of a type that can convert to string.
  • Line numbers in compile error are incorrect.
  • milone eval - reads an expression from standard input that ends with an EOF character.

check

Check if a project is valid.

milone check <PROJECT-DIR>

Examples:

milone check ./MiloneProject

Description:

  • Valid means:
    • well-formed (parsing is okay), and
    • well-typed (type checking is okay).
  • Report compile errors.
  • Unlike build subcommand, code generation is skipped for faster feedback.

Output:

  • Code: 0 if okay.
  • Stdout: Compile errors if any.

parse

Parse a source file.

Examples:

milone parse <FILE...>
milone parse src/Std/StdChar.milone

Output:

  • Code: 0 if success. 1 if IO error or syntax error in any input.
  • Stdout: JSON text including syntax tree and syntax errors (described later -> #syntax-tree-json-format).
  • Files: None.

Read from Standard Input

- can be specified instead of an input file to read from standard input:

milone parse - <<'EOF'
let main _ = 0
EOF

compile

Compile a project to C source files.

Examples:

milone compile <PROJECT-DIR>
milone compile ./MiloneProject

Output:

  • Code: 0 if success. 1 if error.
  • Stdout: Compilation progress and compile errors.
  • Files:
    • <TARGET-DIR>/*.c: C files (if success)

help

Print help text of the milone command.

milone help

Equivalent:

milone
milone -h
milone --help

Output:

  • Code: 0.
  • Stdout: Help text.

version

Print version number of the milone command.

milone version

Equivalent:

milone -V
milone --version

Output:

  • Code: 0.
  • Stdout: 0.0.0\n for example.

Global Options

These options works in any subcommands. Currently you want none of them.

    -v, --verbose   Enable verbose logging for debug
        --profile   Enable profile logging
    -q, --quiet     Disable logging (default)
        --parallel  Enable parallel compilation (experimental)

Requirements

Some of subcommands require something on runtime environment.

require-GCC

(On linux only.)

Install GCC 7.5.0.

Notes:

  • Installation process varies.
    • I did sudo apt install build-essential on Ubuntu.
  • clang is also okay. Set CC environment variable to clang.

require-ninja-build

(On linux only.)

Install ninja-build 1.10.2.

Notes:

  • ninja command (also known as ninja-build) is a build tool.
  • It runs subprocesses and provides some profits. Ninja does:
    • print progress messages nicely
    • run subprocesses in parallel
    • skip unnecessary jobs

require-MSBuild

(On windows only.)

Install Visual Studio 2022 Build Tools.

Notes:

  • MSBuild.exe is a build tool that is used to compile C (MSVC) project on windows.

Less Important Features

  • --project <PROJECT-DIR>
    • Subcommands that take <PROJECT-DIR> as positional argument also support --project option instead.
    • That's to match behavior with dotnet run.
  • --release and --target-dir
    • check and compile subcommands accept these flags but ignore. (So that you can replace build subcommand with check without changing other args.)
  • --debug (inversion of --release) is accepted but ignored.

Misc Notes

  • I'm NOT familiar with external tools; please teach me.
  • Interface is similar to cargo (in Rust).
  • On linux: consider to install mold for faster linking.

Syntax Tree JSON Format

(See also #parse subcommand.)

This section consists of three steps:

  • Provide a small example of input code and output JSON text
  • Describe underlying data model of syntax tree
  • Describe mapping from data model to JSON

Note the output format is subject to change.

Example:
    f (x + 1) // comment
[
{"file": "FILE",
 "root":

["Root", "1:1..2:1", [
  ["Blank", "1:1..1:5"],
  ["ExprDecl", "1:5..1:25", [
    ["AppExpr", "1:5..1:25", [
      ["NameExpr", "1:5..1:7", [
        ["Ident", "1:5..1:6", "f"],
        ["Blank", "1:6..1:7"]
      ]],
      ["ParenExpr", "1:7..1:25", [
        ["LeftParen", "1:7..1:8"],
        ["BinaryExpr", "1:8..1:13", [
          ["NameExpr", "1:8..1:10", [
            ["Ident", "1:8..1:9", "x"],
            ["Blank", "1:9..1:10"]
          ]],
          ["Plus", "1:10..1:11"],
          ["Blank", "1:11..1:12"],
          ["LiteralExpr", "1:12..1:13", [
            ["Int", "1:12..1:13", 1]
          ]]
        ]],
        ["RightParen", "1:13..1:14"],
        ["Blank", "1:14..1:15"],
        ["Comment", "1:15..1:25"]
      ]]
    ]]
  ]],
  ["Newlines", "1:25..2:1", "\n"]
]]}
]
Data model:

Syntax tree is a data structure that consists of tokens and syntax nodes. It's well-known as component of compiler and can be learned with text books and web pages about tokenizer and parser.

Token is a division of source text.

Syntax node is a group of tokens and other nodes.

Mapping:

Range is mapped to a string:

    "y1:x1...y2:x2"

where y1, x1 are start positions and y2, x2 are (exclusive) end positions. y's are 1-origin row numbers. x's are 1-origin column numbers (computed in UTF-8 encoding.)

Token is mapped to either a 2-element array:

    [kind, range]

or a 3-element array:

    [kind, range, value]

where value is a string, number or boolean.

Node is mapped to a three-element array:

    [kind, range, children]

where children is an array of tokens and nodes.

Error is mapped to a string that represents an error.

Toplevel is an array of files. Each file is an object like this:

    { "file": pathname, "root": node, "errors"?: error[] }

where errors can be omit if empty.

See milone_syntax_tree.ungram for more detailed structure.