diff --git a/src/bytecode_compiler.rs b/src/bytecode_compiler.rs index d98b008..694ea72 100644 --- a/src/bytecode_compiler.rs +++ b/src/bytecode_compiler.rs @@ -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, symbols: &SymbolTable, registry: &mut Registry, namespace: &str, - ) -> Result { + ) -> Result { 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 { diff --git a/src/chunk.rs b/src/chunk.rs index 01bc33a..22df4f1 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -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 { for (i, constant) in self.constants.iter().enumerate() { diff --git a/src/repl.rs b/src/repl.rs index bf888c1..37031ec 100644 --- a/src/repl.rs +++ b/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>>) -> 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>>) -> 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); diff --git a/src/vm.rs b/src/vm.rs index b76bfb4..c01070c 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -81,6 +81,7 @@ impl Vm { } pub(crate) fn run(&mut self, context: &str, chunk: &Chunk) -> Result { + self.ip = 0; loop { if self.error_occurred { return Err(Something);