EK9 REPL - Interactive Development

The EK9 REPL (Read-Eval-Print-Loop) is an interactive place to explore the language, prototype code and learn EK9 syntax. It works more like an editor than a bare prompt: syntax highlighting, tab completion, an external editor and sessions you can save and load.

Contents

Starting the REPL

Start it from the command line with -repl:

$ ek9 -repl

EK9 REPL v0.0.1-0 (type :help for commands)
Error level: E0
>>>

Add an error verbosity flag for fuller messages:

$ ek9 -repl -E2

-E2 adds "Did you mean?" suggestions for typos. Error Verbosity Levels shows each level with an example.

Basic Usage

Enter EK9 statements at the prompt. stdout is already declared, so you can start with stdout.println() to show results. A line that declares a variable prints nothing.

Every line you type joins one program, and the REPL compiles and runs that whole program again, so the output of earlier lines appears again. A variable nothing has used yet stops the program running (the unused-variable error, E08090, is hidden in the normal mode and reported by :run), which is why x is printed before the next line is entered:

>>> x <- 42
>>> stdout.println(x)
42
>>> name <- "EK9"
>>> stdout.println(name)
42
EK9
>>> stdout.println(5 + 3)
42
EK9
8

Variables last for the whole session and can be used in later statements. Only lines that compile stay in the session:

>>> x <- 42
>>> stdout.println(x * 2)
84
>>> stdout.println("Value is: " + $x)
84
Value is: 42

Syntax Highlighting

The REPL highlights as you type, in your terminal's colours:

Tab Completion

Press Tab to complete keywords, types, functions, variables and methods.

Keyword and Type Completion

Type the start of a word and press Tab: func completes to function and Int to Integer. With several matches the REPL lists them.

Variable Completion

Variables you have declared complete too: after userName <- "Alice" has been entered, typing user and pressing Tab completes to userName. Entering the declaration prints nothing.

Method Completion After "."

Type a variable name and a dot and press Tab to see the methods of the variable's type, one entry per method name, with its parameters. For stdout that is flush(), print(text as String) and println(text as String); stdout.pri narrows it to the last two. The REPL learns a variable's type from the program it last compiled, so stdout. offers nothing until a line that reads stdout has been entered.

Mode Switching

Each kind of construct has its own mode. Switch with a slash command:

CommandModePrompt
/programProgram statements (default)>>>
/functionFunction definitionsfunction>>>
/classClass definitionsclass>>>
/recordRecord definitionsrecord>>>
/traitTrait definitionstrait>>>
/typeType definitionstype>>>

Example: Defining and Using a Function

>>> /function
Switched to function mode
function>>> square()
function>>>   -> n as Integer
function>>>   <- result as Integer: n * n
function>>>
function>>> /program
Switched to program mode
>>> stdout.println(square(7))
49
>>> stdout.println(square(12))
49
144

In a definition mode, an empty line ends the definition. The REPL compiles it and shows any errors; with none, it prints nothing. Type the indentation yourself (a tab is two spaces); /program goes back to program mode.

Meta-Commands Reference

Meta-commands start with a colon and control the session:

CommandShortDescription
:help:hShow help and the commands
:quit:qLeave the REPL
:clear:cClear every buffer and reset the session
:vars:vShow the names of the functions, types and variables defined so far (names only, no types or values)
:source:sShow the assembled EK9 source
:run:rCompile and run the current program again
:error N:e NSet the error verbosity level (0-3, as -E0 to -E3; any other level is refused)
:strictStrict mode on: report the errors the normal mode hides, such as an unused variable (E08090); :strict off hides them again
:editOpen the source in an external editor
:edit N textReplace line N with the text that follows
:del N:d NDelete line N from the current buffer
:ins N text:i NInsert the text that follows before line N
:save file:w fileSave the session to a file
:load file:l fileLoad a session from a file
:undo:uUndo the last change

External Editor Integration

For bigger edits, enter :edit to open the whole session source in your own editor. The REPL prints Opening editor: and the editor's name, and waits until you save and close it.

It picks the editor from, in order:

  1. $VISUAL, usually a GUI editor
  2. $EDITOR, the standard editor variable
  3. the platform default: vi on Unix and macOS, notepad on Windows

When you save and close the editor, the REPL parses the changed source, loads it into the session buffers and reports what it loaded (for example Loaded: 3 program line(s)). If you changed nothing, or the source does not parse, it prints Source unchanged or parse error - keeping original. and keeps what it had. Loading does not compile: the next line you enter, or :run, does.

Session Management

Saving Sessions

:save writes the assembled program to a file, and :load reads one back into the buffers. The saved file holds the stdout declaration the REPL added, so it loads as one of your own lines. Loading replaces the session, so :vars starts again with no definitions:

>>> x <- 42
>>> stdout.println(x)
42
>>> :save mysession.ek9
Saved to mysession.ek9
>>> :clear
Session cleared.
>>> :load mysession.ek9
Loaded: 3 program line(s)
>>> :vars
No definitions yet.
>>> :run
42

Persistent History

Your command history is saved to .ek9_repl_history in the directory you start the REPL from, and is there again next time you start it from that directory. Use the up and down arrow keys to move through earlier commands.

Buffer Editing

These commands show and change the code you have entered.

Viewing Source

>>> x <- 42
>>> name <- "EK9"
>>> stdout.println(`${name} is ${x}`)
EK9 is 42
>>> :source
--- program ---
  1(7): x <- 42
  2(8): name <- "EK9"
  3(9): stdout.println(`${name} is ${x}`)

Editing a Line

>>> x <- 42
>>> name <- "EK9"
>>> stdout.println(`${name} is ${x}`)
EK9 is 42
>>> :edit 2 name <- "EK9 Language"
Edited line 2
>>> :source
--- program ---
  1(7): x <- 42
  2(8): name <- "EK9 Language"
  3(9): stdout.println(`${name} is ${x}`)

Deleting and Inserting Lines

>>> x <- 42
>>> name <- "EK9"
>>> stdout.println(`${name} is ${x}`)
EK9 is 42
>>> :del 3
Deleted line 3
>>> :ins 2 count <- 100
Inserted before line 2
>>> :source
--- program ---
  1(6): x <- 42
  2(7): count <- 100
  3(8): name <- "EK9"

Undoing Changes

>>> x <- 42
>>> name <- "EK9"
>>> :ins 2 count <- 100
Inserted before line 2
>>> :undo
Undone
>>> :source
--- program ---
  1(6): x <- 42
  2(7): name <- "EK9"

Error Handling

The REPL reports errors as the compiler does. Set how much it says with :error N, where N is 0 to 3 (any other level is refused):

>>> :error 2
Error level set to 2
>>> count <- 10
>>> stdout.println(count)
10
>>> stdout.println(coutn + 5)
❌ error   :[E50001]: 'coutn' on line 9 position 21: 'coutn': not resolved
        ──▶ repl.ek9:9:22
        │
      9 │       stdout.println(coutn + 5)
        │                      ^^^^^ 'coutn'
        │
        ├─ 💡 help: did you mean 'count'?
        │   ──▶ defined at line 7
        └─ 🔗 See: ek9 -h E50001


>>> stdout.println(count + 5)
10
15

Error Verbosity Levels describes every level and shows sample output for the error formats, -E0 to -E3.

Hover Help (Ctrl+H)

Press Ctrl+H with the cursor on a word. For a keyword or operator you get its help; for a name the last successful compile knows (a variable, function or type) you get its type and where it is defined:

>>> x <- 42
>>> stdout.println(x)
42
>>> x[Ctrl+H]
  x : Integer Kind: Variable Defined at: Line 1 (source line 7) Type defined
  at: org-ek9-lang.ek9 Line n

Complete Example Session

Start the REPL with ek9 -repl and enter these lines. They define a function, use it, make a typo, save the work and leave:

>>> :error 2
Error level set to 2
>>> stdout.println(2 + 3)
5
>>> base <- 5
>>> height <- 10
>>> /function
Switched to function mode
function>>> triangleArea()
function>>>   ->
function>>>     b as Integer
function>>>     h as Integer
function>>>   <- area as Float: Float(b * h) / 2.0
function>>>
function>>> /program
Switched to program mode
>>> stdout.println(triangleArea(base, height))
5
25.0
>>> stdout.println(triangleAera(3, 4))
❌ error   :[E50001]: 'triangleAera' on line 18 position 21: not resolved
        ──▶ repl.ek9:18:22
        │
     18 │       stdout.println(triangleAera(3, 4))
        │                      ^^^^^^^^^^^^ 'triangleAera'
        │
        └─ 🔗 See: ek9 -h E50001


>>> stdout.println(triangleArea(3, 4))
5
25.0
6.0
>>> :save geometry.ek9
Saved to geometry.ek9
>>> :quit
Goodbye!

Tips and Best Practices

Comparison with Other REPLs

If you know another REPL, these EK9 commands do the job of ones you may have used:

EK9Similar to
:edit (your $VISUAL or $EDITOR)IPython's %edit, JShell's /edit
:save / :loadJShell's /save / /open
/function, /class and the other modesScala's :paste, for entering a whole definition

Some are less common in a REPL: line-level buffer editing (:edit N, :del, :ins), :undo, error verbosity levels (:error N) and hover help (Ctrl+H).

Summary

The EK9 REPL gives you:

For command line options and use in build pipelines, see Command Line.