repl keeps its state
This commit is contained in:
parent
bcd81677bb
commit
d2106ccf96
4 changed files with 34 additions and 14 deletions
|
|
@ -15,6 +15,7 @@ use crate::vm::{
|
||||||
};
|
};
|
||||||
use crate::{Registry, SymbolTable};
|
use crate::{Registry, SymbolTable};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
qualified_name: Option<&str>,
|
qualified_name: Option<&str>,
|
||||||
|
|
@ -39,7 +40,7 @@ pub(crate) fn compile_function(
|
||||||
|
|
||||||
compiler.vars.insert(name, var_index);
|
compiler.vars.insert(name, var_index);
|
||||||
}
|
}
|
||||||
let mut chunk = compiler.compile(&function.body, symbols, registry, namespace)?.chunk;
|
let mut chunk = compiler.compile(&function.body, symbols, registry, namespace)?;
|
||||||
chunk.function_parameters = function.parameters.to_vec();
|
chunk.function_parameters = function.parameters.to_vec();
|
||||||
Ok(chunk)
|
Ok(chunk)
|
||||||
}
|
}
|
||||||
|
|
@ -51,8 +52,8 @@ pub(crate) fn compile_in_namespace(
|
||||||
registry: &mut Registry,
|
registry: &mut Registry,
|
||||||
) -> Result<(), CompilerErrorAtLine> {
|
) -> Result<(), CompilerErrorAtLine> {
|
||||||
let name = namespace.unwrap_or("main");
|
let name = namespace.unwrap_or("main");
|
||||||
let compiler = Compiler::new(name);
|
let mut compiler = Compiler::new(name);
|
||||||
let chunk = compiler.compile(ast, symbols, registry, name)?.chunk;
|
let chunk = compiler.compile(ast, symbols, registry, name)?;
|
||||||
let qname = if let Some(namespace) = namespace {
|
let qname = if let Some(namespace) = namespace {
|
||||||
format!("{}/{}", namespace, "main")
|
format!("{}/{}", namespace, "main")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -80,18 +81,20 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile(
|
pub(crate) fn compile(
|
||||||
mut self,
|
&mut self,
|
||||||
ast: &Vec<Statement>,
|
ast: &Vec<Statement>,
|
||||||
symbols: &SymbolTable,
|
symbols: &SymbolTable,
|
||||||
registry: &mut Registry,
|
registry: &mut Registry,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
) -> Result<Self, CompilerErrorAtLine> {
|
) -> Result<Chunk, CompilerErrorAtLine> {
|
||||||
for statement in ast {
|
for statement in ast {
|
||||||
self.compile_statement(statement, symbols, registry, namespace)?;
|
self.compile_statement(statement, symbols, registry, namespace)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit_byte(OP_RETURN);
|
self.emit_byte(OP_RETURN);
|
||||||
Ok(self)
|
let chunk = self.chunk.clone();
|
||||||
|
self.chunk.code.clear(); // in case the compiler is reused, clear it for the next compilation. This is for the REPL
|
||||||
|
Ok(chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raise(&self, error: CompilerError) -> CompilerErrorAtLine {
|
fn raise(&self, error: CompilerError) -> CompilerErrorAtLine {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@ pub struct Chunk {
|
||||||
pub vars: Vec<(TokenType, String)>,
|
pub vars: Vec<(TokenType, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Chunk {
|
||||||
|
fn default() -> Self {
|
||||||
|
Chunk::new("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub(crate) fn find_constant(&self, p0: &String) -> Option<usize> {
|
pub(crate) fn find_constant(&self, p0: &String) -> Option<usize> {
|
||||||
for (i, constant) in self.constants.iter().enumerate() {
|
for (i, constant) in self.constants.iter().enumerate() {
|
||||||
|
|
|
||||||
26
src/repl.rs
26
src/repl.rs
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::errors::CrudLangError;
|
use crate::errors::CrudLangError;
|
||||||
use crate::vm::interpret;
|
use crate::scanner::scan;
|
||||||
use crate::{map_underlying, recompile};
|
use crate::vm::{Vm, interpret};
|
||||||
|
use crate::{ast_compiler, bytecode_compiler, map_underlying, recompile, symbol_builder};
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
@ -12,6 +13,9 @@ use std::sync::Arc;
|
||||||
pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudLangError> {
|
pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudLangError> {
|
||||||
println!("REPL started -- Type ctrl-c to exit (both the repl and the server)");
|
println!("REPL started -- Type ctrl-c to exit (both the repl and the server)");
|
||||||
println!(":h for help");
|
println!(":h for help");
|
||||||
|
let mut symbol_table = HashMap::new();
|
||||||
|
let mut vm = Vm::new(®istry.load());
|
||||||
|
let mut bytecode_compiler = bytecode_compiler::Compiler::new("main");
|
||||||
loop {
|
loop {
|
||||||
print!(">");
|
print!(">");
|
||||||
io::stdout().flush().map_err(map_underlying())?;
|
io::stdout().flush().map_err(map_underlying())?;
|
||||||
|
|
@ -27,21 +31,27 @@ pub fn start(registry: Arc<ArcSwap<HashMap<String, Chunk>>>) -> Result<(), CrudL
|
||||||
_ => {
|
_ => {
|
||||||
let registry_copy = registry.load().clone();
|
let registry_copy = registry.load().clone();
|
||||||
let mut registry_copy = registry_copy.deref().clone();
|
let mut registry_copy = registry_copy.deref().clone();
|
||||||
match recompile(input, &mut registry_copy){
|
|
||||||
Ok(_)=> {
|
let tokens = scan(input)?;
|
||||||
|
|
||||||
|
let ast = ast_compiler::compile(None, tokens, &mut symbol_table)?;
|
||||||
|
symbol_builder::build("", &ast, &mut symbol_table);
|
||||||
|
|
||||||
|
match bytecode_compiler.compile(&ast, &symbol_table, &mut registry_copy, "") {
|
||||||
|
Ok(chunk) => {
|
||||||
|
registry_copy.insert("main".to_string(), chunk);
|
||||||
registry.store(Arc::new(registry_copy));
|
registry.store(Arc::new(registry_copy));
|
||||||
|
|
||||||
let result = match interpret(registry.load(), "main") {
|
let result = match vm.run("main", registry.load().get("main").unwrap()) {
|
||||||
Ok(value) => value.to_string(),
|
Ok(value) => value.to_string(),
|
||||||
Err(e) => e.to_string(),
|
Err(e) => e.to_string(),
|
||||||
};
|
};
|
||||||
println!("{}", result);
|
println!("{}", result);
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{}", e);
|
println!("{}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println!("[{}]",input);
|
// println!("[{}]",input);
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ impl Vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(&mut self, context: &str, chunk: &Chunk) -> Result<Value, RuntimeError> {
|
pub(crate) fn run(&mut self, context: &str, chunk: &Chunk) -> Result<Value, RuntimeError> {
|
||||||
|
self.ip = 0;
|
||||||
loop {
|
loop {
|
||||||
if self.error_occurred {
|
if self.error_occurred {
|
||||||
return Err(Something);
|
return Err(Something);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue