vua/repl.v
2025-06-19 22:38:38 -05:00

97 lines
1.8 KiB
V

module repl
import tokenizer as _ { Token, Tokenizer, VuaToken }
import readline { read_line }
pub struct Repl {
pub:
welcome_msg string = "Welcome to the REPL!"
}
/**
* Caller owns returned memory.
*/
pub fn (r Repl) read(input string) ![]Token {
mut tokens := []Token{
len: 0,
cap: 128,
init: Token{0, .eof},
}
mut tokenizer := Tokenizer{input: input}
for !tokenizer.end_of_input() {
token := tokenizer.parse_all()!
if token.tag == .eof { break }
if token.tag == .newline {
if tokens.len > 0 {
break
} else {
continue // skip empty lines
}
}
tokens << token
}
if tokens.len == 0 {
return error('No input whatsoever')
}
return tokens
}
pub fn (r Repl) eval(ast []Token, input string) string {
mut s := []string{len: 0, cap: 4096, init: ''}
for token in ast {
s << ', '
match token.tag {
.eof { s << 'EOF' }
.nil { s << 'nil' }
.string { s << 'string' }
.number { s << 'number' }
.decimal { s << 'decimal' }
.true { s << 'true' }
.false { s << 'false' }
.table_start { s << '{' }
.table_end { s << '}' }
.identifier { s << 'identifier' }
.comma { s << ',' }
.newline { s << '\n' }
.equal { s << '=' }
.dot { s << '.' }
.angle_bracket_left { s << '[' }
.angle_bracket_right { s << ']' }
.reserved_keyword { s << 'reserved_keyword' }
.operator, .operator_len2, .operator_len3{ s << 'operator' }
}
}
if s.len == 0 {
return 'No output'
}
return s.join(' ')
}
//fn (r Repl) print(t VuaType) {
pub fn (r Repl) print(t string) string {
return t
}
pub fn (r Repl) loop() ! {
for {
input := read_line('vua>> ') or {
println('\nGoodbye')
break
}
if input.trim_space() == 'exit' {
println('\nGoodbye')
break
}
tokens := r.read(input.str())!
expr := r.eval(tokens, input.str())
output := r.print(expr)
println(output)
}
}