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 std::collections::HashMap;
|
||||
use std::mem;
|
||||
|
||||
pub fn compile(
|
||||
qualified_name: Option<&str>,
|
||||
|
|
@ -39,7 +40,7 @@ pub(crate) fn compile_function(
|
|||
|
||||
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();
|
||||
Ok(chunk)
|
||||
}
|
||||
|
|
@ -51,8 +52,8 @@ pub(crate) fn compile_in_namespace(
|
|||
registry: &mut Registry,
|
||||
) -> Result<(), CompilerErrorAtLine> {
|
||||
let name = namespace.unwrap_or("main");
|
||||
let compiler = Compiler::new(name);
|
||||
let chunk = compiler.compile(ast, symbols, registry, name)?.chunk;
|
||||
let mut compiler = Compiler::new(name);
|
||||
let chunk = compiler.compile(ast, symbols, registry, name)?;
|
||||
let qname = if let Some(namespace) = namespace {
|
||||
format!("{}/{}", namespace, "main")
|
||||
} else {
|
||||
|
|
@ -80,18 +81,20 @@ impl Compiler {
|
|||
}
|
||||
|
||||
pub(crate) fn compile(
|
||||
mut self,
|
||||
&mut self,
|
||||
ast: &Vec<Statement>,
|
||||
symbols: &SymbolTable,
|
||||
registry: &mut Registry,
|
||||
namespace: &str,
|
||||
) -> Result<Self, CompilerErrorAtLine> {
|
||||
) -> Result<Chunk, CompilerErrorAtLine> {
|
||||
for statement in ast {
|
||||
self.compile_statement(statement, symbols, registry, namespace)?;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ pub struct Chunk {
|
|||
pub vars: Vec<(TokenType, String)>,
|
||||
}
|
||||
|
||||
impl Default for Chunk {
|
||||
fn default() -> Self {
|
||||
Chunk::new("")
|
||||
}
|
||||
}
|
||||
|
||||
impl Chunk {
|
||||
pub(crate) fn find_constant(&self, p0: &String) -> Option<usize> {
|
||||
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::errors::CrudLangError;
|
||||
use crate::vm::interpret;
|
||||
use crate::{map_underlying, recompile};
|
||||
use crate::scanner::scan;
|
||||
use crate::vm::{Vm, interpret};
|
||||
use crate::{ast_compiler, bytecode_compiler, map_underlying, recompile, symbol_builder};
|
||||
use arc_swap::ArcSwap;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
|
|
@ -12,6 +13,9 @@ use std::sync::Arc;
|
|||
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!(":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 {
|
||||
print!(">");
|
||||
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 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));
|
||||
|
||||
let result = match interpret(registry.load(), "main") {
|
||||
let result = match vm.run("main", registry.load().get("main").unwrap()) {
|
||||
Ok(value) => value.to_string(),
|
||||
Err(e) => e.to_string(),
|
||||
};
|
||||
println!("{}", result);
|
||||
},
|
||||
Err(e) => {
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// println!("[{}]",input);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ impl Vm {
|
|||
}
|
||||
|
||||
pub(crate) fn run(&mut self, context: &str, chunk: &Chunk) -> Result<Value, RuntimeError> {
|
||||
self.ip = 0;
|
||||
loop {
|
||||
if self.error_occurred {
|
||||
return Err(Something);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue