[JAVA] Kinx Library --REPL

Kinx Library --REPL

Introduction

** "Looks like JavaScript, brain (contents) is Ruby, (stability is AC / DC)" ** Scripting language Kinx ). The library is the life of the language. So how to use the library.

This time it's REPL.

At first, I was pessimistic that I couldn't do REPL, but I'd like to introduce something that works like that.

This is because if you execute ʻevel` obediently, the code area will swell evenly each time you execute it, so I introduced Isolate earlier. / 78cf553b65e286ea39c4) is now executed in a different context. Doing so has dramatically improved memory usage.

However, in this case, the context is different, so ** objects cannot be passed **. I managed to manage this by passing the class definition and function definition to ʻeval` every time. as a result,,,

  1. It has become usable as a calculator.
  2. Functions (function / native), classes, and modules can be used as they are.
  3. Escape sequences ** even on Windows ** colorful.
  4. I also tried to complete keywords with the [TAB] key.
  5. East Asian Width support. UTF8 characters should also be written as [BS] or [DEL]. At least Japanese is OK.

It was completed to the extent that. Worked hard...

What is REPL?

"What is a REPL?", => Read-Eval-Print-Loop. Read the input, ʻeval () `(evaluate), and display the result, and so on.

How to use

starting method

The REPL is built into the Kinx body, similar to SpecTest. Execute as follows.

$ ./kinx --exec:repl
kinx[  0]> _

Since it is described in Markdown here, the color is different, but in reality, prompts and keywords are highlighted and displayed in color (both Windows and Linux).

At first I tried to put up an image so that I could understand it, but since it is still a demo, I tried hard to make a demo. ** Please praise someone **.

repl.gif

You can see that autocomplete (keyword completion) is also working properly. This area is difficult to understand without a demo. seeing is believing.

sample

To get started, try the one listed here (Ruby that starts in 20 minutes) (https://www.ruby-lang.org/en/documentation/quickstart/). It's good, it's done properly at this level.

$ ./kinx --exec:repl
kinx[  0]> "Hello, world"
=> "Hello, world"

kinx[  1]> System.println("Hello, world")
Hello, world
=> (null)

kinx[  2]> 3+2
=> 5

kinx[  3]> 3*2
=> 6

kinx[  4]> 3**2
=> 9

kinx[  5]> Math.sqrt(9)
=> 3

kinx[  6]> a = 3 ** 2
=> 9

kinx[  7]> b = 4 ** 2
=> 16

kinx[  8]> Math.sqrt(a+b)
=> 5

Then it is the main subject.

Command list

All commands start with ..

command Contents
.help View help
.quit End
.history Display command history
.vars List of current variables
.delete name From the current variable listnameDelete variable
.showdef name View function and class definitions
.cursor [*on/off] Turn on cursor display/OFF (default ON)
.fullcode [on/*off] Full input mode (default OFF),.runDo not execute until the command is entered
.time [on/*off] Execution time measurement mode (default OFF), display execution time after execution
.run Used to run in full input mode

Please note that you can also exit with Ctrl-C.

Type .help to get the following help.

kinx[  0]> .help
Kinx REPL Command: * means by default
    .help               Display this help.
    .quit               Quit REPL.
    .history            Display command history.
    .vars               Display variables with its value.
    .delete name        Delete a variable by name.
    .showdef name       Display function/class definition by name.
    .cursor [*on|off]   Set to 'off' to make the cursor invisible.
    .fullcode [on|*off] Set to 'on', and the code will be executed by .run instead of immediately.
    .time [on|*off]     Set to 'on' to measure and display elapsed time.
    .run                Execute the code only with .fullcode 1.

REPL Operation:
    [^] Arrow up        Choose a previous command.
    [v] Arrow down      Choose a next command.
    [<] Arrow left      Move cursor to left.
    [>] Arrow right     Move cursor to right.
    Ctrl+[<]            Move cursor to left by word.
    Ctrl+[>]            Move cursor to right by word.
    [DEL]               Delete character on cursor.
    [BS]                Delete previous character.
    [TAB]               Move to the next tab stop, or auto-complete.

Use the left and right cursor keys to move the cursor, and Ctrl + left and right to move word by word. You can see the history with the up and down keys.

Line editor

Basically, it accepts input with a line editor and immediately executes what you input.

kinx[  0]> 10 * 2
=> 20

Automatic multi-line judgment and automatic indentation

It automatically recognizes { and the corresponding } and continues editor mode until the entire block has been filled. At this time, the indent for 4 blanks is automatically added according to the number of {.

However, you can only edit that line, so you cannot edit it after entering [Enter].

Use this feature to define function, class, module, and so on.

kinx[  0]> function func(...a) {
	[  1]>     return a.reduce(&(r, e) => r + e);
	[  2]> }
=> function func

By doing this, you can use the function as follows.

kinx[  0]> function func(...a) {
    [  1]>     return a.reduce(&(r, e) => r + e);
    [  2]> }
=> function func

kinx[  3]> func(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
=> 55

You can check the registered function as follows.

kinx[  4]> .vars
function func(...a)

kinx[  5]> .showdef func
function func(...a) {
    return a.reduce(&(r, e) => r + e);
}

Keyword completion

Commands and keywords are put into completion mode by pressing the [TAB] key. Completion mode completes a string that may follow the preceding string in light gray. You can check it in the above demo that I tried hard to make. However, it would be troublesome to go back to the top, so I will post it again (because I made it).

repl.gif

If you press the [TAB] key while this candidate is displayed, you can switch to the next candidate. At this time, the following key operations are performed.

Completion candidates change depending on the context of the position. For example, if it is estimated to be an array from the past history, the method of ʻArrayis also added as a candidate. Also, if you assign an object instantiated with thenew` operator in the past history, the class method etc. will be added as candidates.

You can see some of this example in the demo shown at the beginning. For example, value and sum are displayed as candidates for s. in the last line.

It may not work well in some cases, but if you enter a string halfway and press the [TAB] key, candidates starting with that string will appear one after another, so try various things. Please give me.

Also, namespace is not supported.

Variable list

The .vars command displays a list of variables that are currently enabled. Note that function names and class names are treated in the same column as variable names, so they cannot be registered with the same name. It will be overwritten with the one defined later.

kinx[ 20]> .vars
class Sample(...a)
a = 10
b = 20
c = 30
d = 40
e = 50
f = 60
g = 70
sample = new Sample(a, b, c, d, e, f, g)

Delete variable

You can specify and delete variables that you no longer need with the .delete command. If you assign it to the same variable name, it will be overwritten, so you may not have much chance to use it. However, there are cases in which a Compile Error occurs when the variable registration order is incorrect due to repeated overwriting, or when the variable dependency is incorrect due to the use of the .delete command. In such a case, delete the variable that has become strange and re-register it so that it can operate correctly.

For example, there are cases where the above variables are registered as follows.

kinx[ 25]> .delete g      //Remove g
kinx[ 26]> sample.sum()   //The sample instance is malformed because g is gone.
=> Error: Compile Error.

kinx[ 27]> .vars
class Sample(...a)
a = 10
b = 20
c = 30
d = 40
e = 50
f = 60
sample = new Sample(a, b, c, d, e, f, g)  // <-Illegal shape because g here is gone.

kinx[ 28]> g = 60         //I want to register a new g, but a compile error occurs.
=> Error: Compile Error.

kinx[ 29> .delete sample  //A malformed instance is interfering with execution, so I removed that as well.
kinx[ 30]> g = 60         //g can be re-registered.
=> 60

kinx[ 31]> var sample = new Sample(a, b, c, d, e, f, g)  //sample is also re-registered.
=> (null)

kinx[ 32]> sample.sum() //Can be executed using the new g.
=> 270

View function, class and module definitions

In .vars, the function name and class name are displayed in the list display, but the definition is not displayed. You can then use the .showdef command to see the contents of the definition.

kinx[ 33]> .showdef Sample
class Sample(...a) {
    @value = a;
    public sum() {
        return @value.reduce(&(r, e) => r + e);
    }
}

Execution history

You can check the execution history so far with the .history command. For example, the following display is displayed (the number is different from the above example, but it is a sample).

[  0]: class Sample(...a) {
[  1]:     @value = a;
[  2]:     public sum() {
[  3]:         return @value.reduce(&(r, e) => r + e);
[  4]:     }
[  5]: }
[  6]: a = new Sample(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
[  7]: .vars
[  8]: System.println(a.sum());
[  9]: a = 10
[ 10]: b = 20
[ 11]: c = 30
[ 12]: d = 40
[ 13]: e = 50
[ 14]: f = 60
[ 15]: g = 70
[ 16]: .vars
[ 17]: var sample = new Sample(a, b, c, d, e, f, g)
[ 18]: sample.sum()
[ 19]: .vars
[ 20]: sample.sum()
[ 21]: .showdef System
[ 22]: .showdef Sample
[ 23]: .vars
[ 24]: sample.sum()
[ 25]: .delete g
[ 26]: sample.sum()
[ 27]: .vars
[ 28]: g = 60
[ 29]: g = 60
[ 30]: .vars
[ 31]: .delete sample
[ 32]: g = 60
[ 33]: var sample = new Sample(a, b, c, d, e, f, g)
[ 34]: sample.sum()
[ 35]: .history

From the past history, you can also refer to it using ! As shown below.

kinx[ 36]> !34
=> "sample.sum();"
=> 270

You can also use the up and down cursor keys to select the history as a re-entry target.

Execution time measurement

If you set .time on, the execution result will be displayed. Since the measurement result is simply the elapsed time until it is returned as ʻeval`, various overheads are included, but it will be a guide.

kinx[  0]> native fib(n) {
    [  1]>     return n if (n < 3);
    [  2]>     return fib(n-2) + fib(n-1);
    [  3]> }
=> native<int> fib

kinx[  4]> .time on
.time: on

kinx[  5]> fib(39)
=> 102334155

elapsed:    1.238 s

kinx[  6]> fib(34)
=> 9227465

elapsed:    0.131 s

Full input mode

With .fullcode on, just pressing the[Enter]key will not execute it. Continue typing until you enter the .run command. However, at the moment, in full input mode, variables and class definitions are not ** registered **. All will be a one-shot execution of only that input.

kinx[  0]> .fullcode on
.fullcode: on

kinx[  1]> class Something() {
    [  2]>         public println(...a) {
    [  3]>                 System.println(a);
    [  4]>         }
    [  5]> }
    [  6]> s = new Something();
    [  7]> s.println(1, 2, 3, 4, 5, 6, 7, 8);
    [  8]> .run
[1, 2, 3, 4, 5, 6, 7, 8]
=> {"s":null}

kinx[  9]> .vars

kinx[ 10]>

Read external file

Use the .load command to import an external file. Modules that are ʻusing as normal libraries are also loaded with .load. You can enable some method name completion by loading it with .load`.

For example, if you use DateTime, you can do the following:

kinx[  0]> .load DateTime
=> Successfully loaded.

kinx[  1]> var dt = new DateTime(2020, 1, 1, 9, 30, 0)
=> (null)

kinx[  2]> .vars
dt = new DateTime(2020, 1, 1, 9, 30, 00)

kinx[  3]> dt.weekday()
=> 3

kinx[  4]> System.println(dt)
2020/01/01 09:30:00

The search file name is specified name.kx. The search target is performed in the following order. So you can also refer to the standard library.

  1. Current directory
  2. In the lib folder under the folder containing the kinx executable file
  3. In the lib / std folder under the folder containing the kinx executable file
  4. In the ../lib folder as seen from the folder containing the kinx executable file
  5. In the kinxlib folder under the folder containing the kinx executable file
  6. In the kinxlib / std folder under the folder containing the kinx executable file

Excuse me, with the v0.9.2 release I missed the consideration (5 and 6 were needed for Linux but not implemented) and on Linux I get an error .load DateTime. Specify .load /usr/bin/kinxlib/std/DateTime as the workaround. It's hard. I'm sorry.

However, there are currently two caveats regarding DateTime. It may improve in future versions.

East Asian Width

Supports UTF8 input. Since the cursor is moved according to the definition of East Asian Width, full-width characters are moved by that width. In the following example, aiueo also moves the cursor one character at a time in full-width, and Aiueo moves the cursor in half-width. Also, deleting with the [DEL] and [BS] keys works correctly.

$ ./kinx --exec:repl
kinx[  0]> a = "Aiueo Aiueo";
=> "Aiueo Aiueo"

kinx[  1]> System.println(a);
Aiueo Aiueo
=> (null)

kinx[  2]> a = "That kind of aio";  //On "U"[DEL]And on "O"[BS]Press.
=> "That kind of aio"

kinx[  3]> System.println(a);
That kind of aio
=> (null)

in conclusion

I read somewhere that the programming language was ** half-serving without REPL **, so I tried my best to make it (it was hard ...). That said, it's still developing. With this as the first edition, I would like to make improvements if requested.

It would be great if more people could take this opportunity. We have also released a release build, so if you like.

See you next time.

Recommended Posts

Kinx Library --REPL
Kinx Library --Getopt
Kinx Library --DateTime
Kinx Library --Process
Kinx Library-JIT Compiler Library
Kinx Library-JIT Compiler Library (Extra Edition)