Writing LiveC - a C REPL written in V

In this post, I will explain how I wrote LiveC, my latest project. I used V, one of my favourite up-and-coming languages. I like the way the syntax is easy to learn, and the principles logical, but also the fact that compilation to C enhances speed and increases portability. 

I was inspired to make this project by a similar one I saw online, namely crepl. I thought it would be an interesting challenge, and I had also previously thought that a C live shell would be useful. So I set off.

As with most projects I write, the first thing I did was to setup the that we would be working on.

struct Function {
def string
source string
}

struct LiveC {
mut:
functions []Function
main_func string
spaces int
first string
}

Once I had done this, I began to write the methods that we would call on these classes.

My first draft of the code, which didn't use highlighting yet, took input from the user, before checking if it was a function. If so, it entered a mode similar to the Python REPL where it took further input, before adding that to a function. Here is a link to that first iteration.


After the initial setup and proof of concept, I decided to begin work on the syntax highlighter. I thought that syntax highlighting would be a useful feature, fun to implement, and also a test of the V libraries that abstracted terminal raw mode. Having previously worked with raw mode in C (in tedit, my text editor), I was hoping that V would have a syntax for this that got rid of all those pesky flags, and I was not disappointed. In the readline library of V, a builtin, I found an abstraction layer to termios, the Linux terminal struct. This proved to be very useful, though there were still issues with the cursor movement, and even at the final draft I left it one line lower than usual.

After some testing, I setup a rudimentary input function, that worked very similar to os.input in V, input in Python or scanf in C, but live highlighted the user's input. Right from the start, I decided to implement customisable colours, so that anyone who wanted to use my code could more easily tweak it to their own liking. After some research, I had a list of C's keywords and operators, all split into several categories.

    conditionals:=[
"if",
"else",
"while",
"for",
"case",
"default",
"switch",
"list",
"continue"
]
types:=[
"int",
"float",
"double",
"char",
"void",
"signed",
"unsigned",
"size_t",
'atomic_bool',
'atomic_char',
'atomic_schar',
'atomic_uchar',
'atomic_short',
'atomic_ushort',
'atomic_int',
'atomic_uint',
'atomic_long',
'atomic_ulong',
'atomic_llong',
'atomic_ullong',
'atomic_char16_t',
'atomic_char32_t',
'atomic_wchar_t',
'atomic_size_t',
'atomic_ptrdiff_t',
'atomic_intmax_t',
'atomic_uintmax_t'
]
qualifiers:=[
"const",
"volatile",
"restrict",
"auto",
"register",
"static",
"extern",
"thread_local"
]
other_keywords:=[
"struct",
"union",
"typedef",
"enum",
"typedef",
"sizeof"
]
macros:=[
"#define",
"#if",
"#endif",
"#elseif"
"#include"
"#ifdef"
"#ifndef",
"#error",
"#pragma"
]
symbols:=[
"&",
"|",
"!",
"%",
"^",
"*",
":",
";",
"@",
"~"
"<",
">",
"?",
"/",
"=",
"-"
]

Though the names may not strictly obey the correct groupings, I think the gist is there. Also, readers with a keen eye may notice that list, not a keyword has been added to the conditionals array. This was because list was a builtin command to my REPL, which listed the stored source code. I thought why not highlight it, and thus added it.


After I had written the bulk of the code, all that was left to do was to fix the bugs. I won't bother going into all the details here, but I will mention a couple of bugs. First was the running process, which still printed out the output even if it was blank which was fixed. Another more pressing issue was that of appending to the source code, without checking if an error had occurred. This was solved by checking the return code, and if needed restoring a backup made up of the code inserted prior to the error.


To view the latest source code, you can visit github.com/werdl/livec. Below is a little snippet of an example session.

As you can see, one of the key feature is that output is not repeated, achieved by using string slicing in the output display function.

 

 

 

 

 



I hope you enjoyed this post, and be sure to come back to this blog for a post at least once a week!


Comments

Popular posts from this blog

Upcoming Guest Opinions Post!

Why I use the V language

color gets updated!