diff --git a/src/compiler/backend.rs b/src/compiler/backend.rs index f202c80..ee471bf 100644 --- a/src/compiler/backend.rs +++ b/src/compiler/backend.rs @@ -5,7 +5,7 @@ use super::representation::CoreAST; use super::CompilationUnit; use crate::compiler::source::Registry; -use code_generator::{CodeGenerator, Target}; +use code_generator::CodeGenerator; #[derive(Debug)] pub struct Backend {} @@ -21,7 +21,7 @@ impl Backend { ast: &CoreAST, registry: &Registry, ) -> std::result::Result { - let mut code_gen = CodeGenerator::new(Target::TopLevel, None, registry); - Ok(code_gen.generate(ast)?) + let unit = CodeGenerator::generate(registry, ast)?; + Ok(unit) } } diff --git a/src/compiler/backend/code_generator.rs b/src/compiler/backend/code_generator.rs index bad4114..a4b1fe0 100644 --- a/src/compiler/backend/code_generator.rs +++ b/src/compiler/backend/code_generator.rs @@ -80,7 +80,10 @@ impl Context { } impl<'a> CodeGenerator<'a> { - pub fn new( + /// constructor is private since we don't want external callers + /// to hold an instance of `CodeGenerator`. It has internal state + /// that shouldn't be shared across multiple generation invocations. + fn new( target: Target, parent_variables: Option, source_registry: &'a Registry, @@ -96,16 +99,17 @@ impl<'a> CodeGenerator<'a> { } } - pub fn generate(&mut self, ast: &CoreAST) -> Result { + /// Main entry point to generate the VM byte code + pub fn generate(registry: &Registry, ast: &CoreAST) -> Result { let proc = Self::generate_procedure( - self.source_registry, + registry, None, Target::TopLevel, &Expression::body(ast.expressions.clone()), &Formals::empty(), )?; - Ok(CompilationUnit::new(Closure::new(proc, vec![]))) + Ok(CompilationUnit::new(Closure::new(proc))) } pub fn generate_procedure( @@ -215,8 +219,8 @@ impl<'a> CodeGenerator<'a> { Ok(()) } - // This is the main entry-point that turns Expressions into instructions, which - // are then written to the current chunk. + /// This is the main entry-point that turns Expressions into instructions, which + /// are then written to the current chunk. fn emit_instructions(&mut self, ast: &Expression, context: &Context) -> Result<()> { match ast { Expression::Identifier(id) => self.emit_get_variable(id)?, diff --git a/src/compiler/frontend/parser.rs b/src/compiler/frontend/parser.rs index cccdd2d..5608287 100644 --- a/src/compiler/frontend/parser.rs +++ b/src/compiler/frontend/parser.rs @@ -22,15 +22,24 @@ pub mod quotation; pub mod result; pub mod sequence; +/// The `Expression` type encodes scheme core forms. #[derive(Clone, PartialEq, Debug)] pub enum Expression { + /// A scheme identifier, which is a special symbol Identifier(identifier::Identifier), + /// Any scheme literal value Literal(literal::LiteralExpression), + /// A definition Define(define::DefinitionExpression), + /// A lambda expression Lambda(lambda::LambdaExpression), + /// A set! expression Assign(assignment::SetExpression), + /// An if expression If(conditional::IfExpression), + /// An expression for function application Apply(apply::ApplicationExpression), + /// A begin expression to sequence other expressions Begin(sequence::BeginExpression), } @@ -63,6 +72,19 @@ impl Parser { } } + /// Expand and parse `ast` into the `CoreAST` representation. + /// This process interleaves macro expansion and parsing of forms. + /// + /// ``` + /// use braces::compiler::frontend::parser::Parser; + /// use braces::compiler::representation::SexpAST; + /// use braces::compiler::frontend::reader::datum::Datum; + /// let mut parser = Parser::new(); + /// // just a very simple s-expression which will be parsed to a literal + /// let sexps = SexpAST::new(vec![Datum::boolean(true, 0..2)]); + /// + /// parser.parse(&sexps).unwrap(); + /// ``` pub fn parse(&mut self, ast: &SexpAST) -> Result { let expressions: Result> = ast.to_vec().iter().map(|d| self.do_parse(d)).collect(); diff --git a/src/compiler/source/location.rs b/src/compiler/source/location.rs index ec25a56..7eaeb3b 100644 --- a/src/compiler/source/location.rs +++ b/src/compiler/source/location.rs @@ -44,5 +44,6 @@ impl> From for Location { /// /// Examples of this are `Datum` and various `Expression`s. pub trait HasSourceLocation { + /// return `Location` information for this value fn source_location(&self) -> &Location; } diff --git a/src/vm/value.rs b/src/vm/value.rs index e15028a..ab652a1 100644 --- a/src/vm/value.rs +++ b/src/vm/value.rs @@ -157,7 +157,6 @@ impl SchemeEqual for Value { #[derive(Debug, Clone)] pub struct Factory { strings: StringTable, - symbols: StringTable, true_value: Value, false_value: Value, nil_value: Value, @@ -168,7 +167,6 @@ impl Default for Factory { fn default() -> Factory { Factory { strings: StringTable::default(), - symbols: StringTable::default(), true_value: Value::Bool(true), false_value: Value::Bool(false), nil_value: Value::ProperList(list::List::Nil), @@ -203,7 +201,7 @@ impl Factory { } pub fn sym>(&mut self, v: T) -> Symbol { - let k = self.symbols.get_or_intern(v.into()); + let k = self.strings.get_or_intern(v.into()); Symbol(k) } @@ -250,7 +248,7 @@ impl Factory { } pub fn closure(&mut self, v: procedure::native::Procedure) -> Value { - Value::Closure(closure::Closure::new(v, vec![])) + Value::Closure(closure::Closure::new(v)) } pub fn from_datum(&mut self, d: &Datum) -> Value { @@ -277,15 +275,6 @@ impl Factory { } } - pub fn interned_symbols(&self) -> Vec { - self.symbols - .interned_vec() - .iter() - .cloned() - .map(Symbol) - .collect() - } - pub fn interned_strings(&self) -> Vec { self.strings .interned_vec() diff --git a/src/vm/value/closure.rs b/src/vm/value/closure.rs index e242d27..2c01d39 100644 --- a/src/vm/value/closure.rs +++ b/src/vm/value/closure.rs @@ -12,15 +12,12 @@ pub struct Closure { } impl Closure { - pub fn new(proc: procedure::native::Procedure, up_values: Vec) -> Self { - Self::from_rc(Rc::new(proc), up_values) + pub fn new(proc: procedure::native::Procedure) -> Self { + Self::from_rc(Rc::new(proc), vec![]) } pub fn from_rc(proc: Rc, up_values: Vec) -> Self { - Self { - proc: proc, - up_values, - } + Self { proc, up_values } } pub fn code(&self) -> &Chunk {